From 6a2792ea8e79e799d0eacc732127dc3ca7d1ce80 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 12 Sep 2021 23:07:29 +0100 Subject: [PATCH] Add documentation extension to Jupyter Lab (#745) * Add documentation extension to Jupyter Lab * Fix lint * fix pyupgrade * Change label from Documentation to Gamestonk Documentation * Improve code after review --- .pre-commit-config.yaml | 2 +- jupyterlab/documentation/.eslintignore | 5 ++ jupyterlab/documentation/.eslintrc.js | 53 ++++++++++++ jupyterlab/documentation/MANIFEST.in | 22 +++++ jupyterlab/documentation/README.md | 17 ++++ jupyterlab/documentation/RELEASE.md | 3 + .../__init__.py | 13 +++ .../_version.py | 2 + jupyterlab/documentation/install.json | 5 ++ jupyterlab/documentation/package.json | 80 +++++++++++++++++ jupyterlab/documentation/pyproject.toml | 17 ++++ jupyterlab/documentation/schema/plugin.json | 25 ++++++ jupyterlab/documentation/setup.py | 86 +++++++++++++++++++ jupyterlab/documentation/src/index.ts | 77 +++++++++++++++++ jupyterlab/documentation/src/svg.d.ts | 4 + jupyterlab/documentation/style/base.css | 0 jupyterlab/documentation/style/docs.svg | 9 ++ jupyterlab/documentation/style/index.css | 1 + jupyterlab/documentation/style/index.js | 1 + jupyterlab/documentation/tsconfig.json | 24 ++++++ jupyterlab/gst-settings/package.json | 4 +- jupyterlab/gst-settings/src/index.ts | 2 +- jupyterlab/gst/package.json | 4 +- 23 files changed, 450 insertions(+), 6 deletions(-) create mode 100644 jupyterlab/documentation/.eslintignore create mode 100644 jupyterlab/documentation/.eslintrc.js create mode 100644 jupyterlab/documentation/MANIFEST.in create mode 100644 jupyterlab/documentation/README.md create mode 100644 jupyterlab/documentation/RELEASE.md create mode 100644 jupyterlab/documentation/gamestonk_terminal_documentation/__init__.py create mode 100644 jupyterlab/documentation/gamestonk_terminal_documentation/_version.py create mode 100644 jupyterlab/documentation/install.json create mode 100644 jupyterlab/documentation/package.json create mode 100644 jupyterlab/documentation/pyproject.toml create mode 100644 jupyterlab/documentation/schema/plugin.json create mode 100644 jupyterlab/documentation/setup.py create mode 100644 jupyterlab/documentation/src/index.ts create mode 100644 jupyterlab/documentation/src/svg.d.ts create mode 100644 jupyterlab/documentation/style/base.css create mode 100644 jupyterlab/documentation/style/docs.svg create mode 100644 jupyterlab/documentation/style/index.css create mode 100644 jupyterlab/documentation/style/index.js create mode 100644 jupyterlab/documentation/tsconfig.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c39d42d3267..ce0dd7dcbc7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: rev: 'v0.812' hooks: - id: mypy - args: [ --ignore-missing-imports --exclude '/setup\.py$' ] + args: [ --ignore-missing-imports ] - repo: https://github.com/pre-commit/mirrors-pylint rev: 'v3.0.0a4' hooks: diff --git a/jupyterlab/documentation/.eslintignore b/jupyterlab/documentation/.eslintignore new file mode 100644 index 00000000000..8bd31f70bec --- /dev/null +++ b/jupyterlab/documentation/.eslintignore @@ -0,0 +1,5 @@ +node_modules +dist +coverage +**/*.d.ts +ui-tests diff --git a/jupyterlab/documentation/.eslintrc.js b/jupyterlab/documentation/.eslintrc.js new file mode 100644 index 00000000000..c23757866cb --- /dev/null +++ b/jupyterlab/documentation/.eslintrc.js @@ -0,0 +1,53 @@ +module.exports = { + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:jsdoc/recommended', + 'plugin:prettier/recommended', + 'plugin:react/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + sourceType: 'module', + }, + plugins: ['@typescript-eslint', 'jsdoc'], + rules: { + '@typescript-eslint/naming-convention': [ + 'error', + { + selector: 'interface', + format: ['PascalCase'], + custom: { + regex: '^I[A-Z]', + match: true, + }, + }, + ], + '@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }], + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/quotes': [ + 'error', + 'single', + { avoidEscape: true, allowTemplateLiterals: false }, + ], + curly: ['error', 'all'], + eqeqeq: 'error', + 'jsdoc/require-param-type': 'off', + 'jsdoc/require-property-type': 'off', + 'jsdoc/require-returns-type': 'off', + 'jsdoc/no-types': 'warn', + 'prefer-arrow-callback': 'error', + }, + settings: { + jsdoc: { + mode: 'typescript', + }, + react: { + version: 'detect', + }, + }, +}; diff --git a/jupyterlab/documentation/MANIFEST.in b/jupyterlab/documentation/MANIFEST.in new file mode 100644 index 00000000000..fd16a90a831 --- /dev/null +++ b/jupyterlab/documentation/MANIFEST.in @@ -0,0 +1,22 @@ +include LICENSE +include README.md +include pyproject.toml +include jupyter-config/gamestonk_terminal_documentation.json + +include package.json +include ts*.json + +graft gamestonk_terminal_documentation/labextension + +# Javascript files +graft src +graft style +prune **/node_modules +prune lib + +# Patterns to exclude from any directory +global-exclude *~ +global-exclude *.pyc +global-exclude *.pyo +global-exclude .git +global-exclude .ipynb_checkpoints diff --git a/jupyterlab/documentation/README.md b/jupyterlab/documentation/README.md new file mode 100644 index 00000000000..633a4106809 --- /dev/null +++ b/jupyterlab/documentation/README.md @@ -0,0 +1,17 @@ +# Gamestonk Teminal Documentation + +This extensions adds a button into the Gamestonk Terminal category of the Jupyter Lab launcher panel. + +## Install, Use and Develop + +```bash +pip install -e . +jlpm +jlpm run build:prod +jupyter labextension install . + +# Rebuild Typescript source after making changes +jlpm build +# Rebuild JupyterLab after making any changes +jupyter lab build +``` diff --git a/jupyterlab/documentation/RELEASE.md b/jupyterlab/documentation/RELEASE.md new file mode 100644 index 00000000000..4603959c9af --- /dev/null +++ b/jupyterlab/documentation/RELEASE.md @@ -0,0 +1,3 @@ +# Making a new release of gamestonk-settings + +Check out the [workflow documentation](https://github.com/jupyter-server/jupyter_releaser#typical-workflow) for information. diff --git a/jupyterlab/documentation/gamestonk_terminal_documentation/__init__.py b/jupyterlab/documentation/gamestonk_terminal_documentation/__init__.py new file mode 100644 index 00000000000..65fd31bee52 --- /dev/null +++ b/jupyterlab/documentation/gamestonk_terminal_documentation/__init__.py @@ -0,0 +1,13 @@ +import json +import os.path as osp + +from ._version import __version__ # noqa: F401 + +HERE = osp.abspath(osp.dirname(__file__)) + +with open(osp.join(HERE, "labextension", "package.json")) as fid: + data = json.load(fid) + + +def _jupyter_labextension_paths(): + return [{"src": "labextension", "dest": data["name"]}] diff --git a/jupyterlab/documentation/gamestonk_terminal_documentation/_version.py b/jupyterlab/documentation/gamestonk_terminal_documentation/_version.py new file mode 100644 index 00000000000..ee864fc9e71 --- /dev/null +++ b/jupyterlab/documentation/gamestonk_terminal_documentation/_version.py @@ -0,0 +1,2 @@ +version_info = (0, 1, 0) +__version__ = ".".join(map(str, version_info)) diff --git a/jupyterlab/documentation/install.json b/jupyterlab/documentation/install.json new file mode 100644 index 00000000000..bd03dceabd2 --- /dev/null +++ b/jupyterlab/documentation/install.json @@ -0,0 +1,5 @@ +{ + "packageManager": "python", + "packageName": "gamestonk_terminal_documentation", + "uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package gamestonk_terminal_documentation" +} diff --git a/jupyterlab/documentation/package.json b/jupyterlab/documentation/package.json new file mode 100644 index 00000000000..6b6f563098f --- /dev/null +++ b/jupyterlab/documentation/package.json @@ -0,0 +1,80 @@ +{ + "name": "@gamestonk/documentation", + "version": "0.1.0", + "description": "Gamestonk terminal documentation", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/GamestonkTerminal/GamestonkTerminal", + "bugs": { + "url": "https://github.com/GamestonkTerminal/GamestonkTerminal/issues" + }, + "license": "MIT", + "author": { + "name": "Project Jupyter Contributors", + "email": "dro.lopes@campus.fct.unl.pt" + }, + "files": [ + "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", + "style/**/*.{css,eot,js,gif,html,jpg,json,png,svg,woff2,ttf}", + "schema/**/*.json" + ], + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "repository": { + "type": "git", + "url": "https://github.com/GamestonkTerminal/GamestonkTerminal.git" + }, + "scripts": { + "build": "jlpm run build:lib && jlpm run build:labextension:dev", + "build:all": "jlpm run build:lib && jlpm run build:labextension", + "build:labextension": "jupyter labextension build .", + "build:labextension:dev": "jupyter labextension build --development True .", + "build:lib": "tsc", + "build:prod": "jlpm run clean && jlpm run build:lib && jlpm run build:labextension", + "clean": "jlpm run clean:lib", + "clean:all": "jlpm run clean:lib && jlpm run clean:labextension", + "clean:labextension": "rimraf gamestonk_terminal_documentation/labextension", + "clean:lib": "rimraf lib tsconfig.tsbuildinfo", + "eslint": "eslint . --ext .ts,.tsx --fix", + "eslint:check": "eslint . --ext .ts,.tsx", + "install:extension": "jlpm run build", + "prepare": "jlpm run clean && jlpm run build:prod", + "watch": "run-p watch:src watch:labextension", + "watch:labextension": "jupyter labextension watch .", + "watch:src": "tsc -w" + }, + "dependencies": { + "@jupyterlab/application": "^3.1.0", + "@jupyterlab/launcher": "^3.1.0", + "@jupyterlab/mainmenu": "^3.1.7" + }, + "devDependencies": { + "@jupyterlab/builder": "^3.1.0", + "@typescript-eslint/eslint-plugin": "^4.8.1", + "@typescript-eslint/parser": "^4.8.1", + "eslint": "^7.14.0", + "eslint-config-prettier": "^6.15.0", + "eslint-plugin-jsdoc": "^36.0.0", + "eslint-plugin-prettier": "^3.1.4", + "eslint-plugin-react": "^7.18.3", + "npm-run-all": "^4.1.5", + "prettier": "^2.1.1", + "rimraf": "^3.0.2", + "typescript": "~4.1.3" + }, + "sideEffects": [ + "style/*.css", + "style/*.svg", + "style/index.js" + ], + "jupyterlab": { + "extension": true, + "outputDir": "gamestonk_terminal_documentation/labextension", + "schemaDir": "schema" + }, + "styleModule": "style/index.js" +} diff --git a/jupyterlab/documentation/pyproject.toml b/jupyterlab/documentation/pyproject.toml new file mode 100644 index 00000000000..dd4cdf63e73 --- /dev/null +++ b/jupyterlab/documentation/pyproject.toml @@ -0,0 +1,17 @@ +[build-system] +requires = ["jupyter_packaging~=0.10,<2", "jupyterlab~=3.1"] +build-backend = "jupyter_packaging.build_api" + +[tool.jupyter-packaging.options] +skip-if-exists = ["gamestonk_terminal_documentation/labextension/static/style.js"] +ensured-targets = ["gamestonk_terminal_documentation/labextension/static/style.js", "gamestonk_terminal_documentation/labextension/package.json"] + +[tool.jupyter-packaging.builder] +factory = "jupyter_packaging.npm_builder" + +[tool.jupyter-packaging.build-args] +build_cmd = "build:prod" +npm = ["jlpm"] + +[tool.check-manifest] +ignore = ["gamestonk_terminal_documentation/labextension/**", "yarn.lock", ".*", "package-lock.json"] diff --git a/jupyterlab/documentation/schema/plugin.json b/jupyterlab/documentation/schema/plugin.json new file mode 100644 index 00000000000..32ce33f6a97 --- /dev/null +++ b/jupyterlab/documentation/schema/plugin.json @@ -0,0 +1,25 @@ +{ + "title": "Gamestonk Terminal Documentation", + "description": "Gamestonk Terminal Documentation.", + "jupyter.lab.menus": { + "main": [ + { + "id": "jp-mainmenu-file", + "items": [ + { + "type": "submenu", + "id": "jp-mainmenu-file-new", + "items": [ + { + "command": "gamestonk:documentation", + "rank": 30 + } + ] + } + ] + } + ] + }, + "additionalProperties": false, + "type": "object" +} diff --git a/jupyterlab/documentation/setup.py b/jupyterlab/documentation/setup.py new file mode 100644 index 00000000000..1389ea6588a --- /dev/null +++ b/jupyterlab/documentation/setup.py @@ -0,0 +1,86 @@ +""" +gamestonk_terminal_documentation setup +""" +import json +import sys +from pathlib import Path + +import setuptools + +HERE = Path(__file__).parent.resolve() + +# The name of the project +name = "gamestonk_terminal_documentation" + +lab_path = HERE / name.replace("-", "_") / "labextension" + +# Representative files that should exist after a successful build +ensured_targets = [str(lab_path / "package.json"), str(lab_path / "static/style.js")] + +labext_name = "@gamestonk/documentation" + +data_files_spec = [ + ( + "share/jupyter/labextensions/%s" % labext_name, + str(lab_path.relative_to(HERE)), + "**", + ), + ("share/jupyter/labextensions/%s" % labext_name, ".", "install.json"), +] + +long_description = (HERE / "README.md").read_text() + +# Get the package info from package.json +pkg_json = json.loads((HERE / "package.json").read_bytes()) + +setup_args = dict( + name=name, + version=pkg_json["version"], + url=pkg_json["homepage"], + author=pkg_json["author"]["name"], + author_email=pkg_json["author"]["email"], + description=pkg_json["description"], + license=pkg_json["license"], + long_description=long_description, + long_description_content_type="text/markdown", + packages=setuptools.find_packages(), + install_requires=[], + zip_safe=False, + include_package_data=True, + python_requires=">=3.6", + platforms="Linux, Mac OS X, Windows", + keywords=["Jupyter", "JupyterLab", "JupyterLab3"], + classifiers=[ + "License :: OSI Approved :: BSD License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Framework :: Jupyter", + ], +) + +try: + from jupyter_packaging import wrap_installers, npm_builder, get_data_files + + post_develop = npm_builder( + build_cmd="install:extension", source_dir="src", build_dir=lab_path + ) + setup_args["cmdclass"] = wrap_installers( + post_develop=post_develop, ensured_targets=ensured_targets + ) + setup_args["data_files"] = get_data_files(data_files_spec) +except ImportError as e: + import logging + + logging.basicConfig(format="%(levelname)s: %(message)s") + logging.warning( + "Build tool `jupyter-packaging` is missing. Install it with pip or conda." + ) + if not ("--name" in sys.argv or "--version" in sys.argv): + raise e + +if __name__ == "__main__": + setuptools.setup(**setup_args) diff --git a/jupyterlab/documentation/src/index.ts b/jupyterlab/documentation/src/index.ts new file mode 100644 index 00000000000..21e1ef86657 --- /dev/null +++ b/jupyterlab/documentation/src/index.ts @@ -0,0 +1,77 @@ +import { + JupyterFrontEnd, + JupyterFrontEndPlugin, +} from '@jupyterlab/application'; + +import { ICommandPalette } from '@jupyterlab/apputils'; + +import { ILauncher } from '@jupyterlab/launcher'; + +import { IMainMenu } from "@jupyterlab/mainmenu"; + +import { LabIcon } from '@jupyterlab/ui-components'; + +import docsIconStr from '../style/docs.svg'; + +const CATEGORY = "Gamestonk Terminal"; + +namespace CommandIDs { + export const createNew = 'jlab-examples:create-new-python-file'; +} + +const extension: JupyterFrontEndPlugin = { + id: 'documentation', + autoStart: true, + optional: [ILauncher, ICommandPalette], + activate: ( + app: JupyterFrontEnd, + launcher: ILauncher | null, + menu: IMainMenu | null, + palette: ICommandPalette | null + ) => { + const { commands } = app; + const command = CommandIDs.createNew; + const icon = new LabIcon({ + name: 'documentation:docs-icon', + svgstr: docsIconStr, + }); + + commands.addCommand(command, { + label: 'Gamestonk Documentation', + icon: icon, + execute: (args: any) => { + window.open( + 'https://gamestonkterminal.github.io/GamestonkTerminal/', + '_blank' + ); + }, + }); + + // Add the command to the launcher + if (launcher) { + launcher.add({ + command, + category: CATEGORY, + rank: 3, + }); + } + + // Add the command to the palette + if (palette) { + palette.addItem({ + command, + args: { isPalette: true }, + category: CATEGORY, + }); + } + + // Add the command to the menu + if (menu) { + menu.fileMenu.newMenu.addGroup([{ command }], 30); + } + console.log("Added Gamestonk Settings Extension."); + + }, +}; + +export default extension; diff --git a/jupyterlab/documentation/src/svg.d.ts b/jupyterlab/documentation/src/svg.d.ts new file mode 100644 index 00000000000..9348424371f --- /dev/null +++ b/jupyterlab/documentation/src/svg.d.ts @@ -0,0 +1,4 @@ +declare module '*.svg' { + const value: string; + export default value; +} diff --git a/jupyterlab/documentation/style/base.css b/jupyterlab/documentation/style/base.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jupyterlab/documentation/style/docs.svg b/jupyterlab/documentation/style/docs.svg new file mode 100644 index 00000000000..1dcf4eaf781 --- /dev/null +++ b/jupyterlab/documentation/style/docs.svg @@ -0,0 +1,9 @@ + + + docs + + + + + + diff --git a/jupyterlab/documentation/style/index.css b/jupyterlab/documentation/style/index.css new file mode 100644 index 00000000000..8a7ea29e694 --- /dev/null +++ b/jupyterlab/documentation/style/index.css @@ -0,0 +1 @@ +@import url('base.css'); diff --git a/jupyterlab/documentation/style/index.js b/jupyterlab/documentation/style/index.js new file mode 100644 index 00000000000..a028a76408b --- /dev/null +++ b/jupyterlab/documentation/style/index.js @@ -0,0 +1 @@ +import './base.css'; diff --git a/jupyterlab/documentation/tsconfig.json b/jupyterlab/documentation/tsconfig.json new file mode 100644 index 00000000000..81139f5447e --- /dev/null +++ b/jupyterlab/documentation/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "composite": true, + "declaration": true, + "esModuleInterop": true, + "incremental": true, + "jsx": "react", + "module": "esnext", + "moduleResolution": "node", + "noEmitOnError": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "preserveWatchOutput": true, + "resolveJsonModule": true, + "outDir": "lib", + "rootDir": "src", + "strict": true, + "strictNullChecks": false, + "target": "es2017", + "types": [] + }, + "include": ["src/*"] +} diff --git a/jupyterlab/gst-settings/package.json b/jupyterlab/gst-settings/package.json index 360a4c79e72..0f11462d90e 100644 --- a/jupyterlab/gst-settings/package.json +++ b/jupyterlab/gst-settings/package.json @@ -11,10 +11,10 @@ "bugs": { "url": "https://github.com/GamestonkTerminal/GamestonkTerminal/issues" }, - "license": "BSD-3-Clause", + "license": "MIT", "author": { "name": "Gamestonk Contributors", - "email": "" + "email": "dro.lopes@campus.fct.unl.pt" }, "files": [ "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", diff --git a/jupyterlab/gst-settings/src/index.ts b/jupyterlab/gst-settings/src/index.ts index e5170ea004f..78d875665c8 100644 --- a/jupyterlab/gst-settings/src/index.ts +++ b/jupyterlab/gst-settings/src/index.ts @@ -83,7 +83,7 @@ const extension: JupyterFrontEndPlugin = { if (menu) { menu.fileMenu.newMenu.addGroup([{ command }], 30); } - console.log("Added Gamestonk Settings Exstension."); + console.log("Added Gamestonk Settings Extension."); }, }; diff --git a/jupyterlab/gst/package.json b/jupyterlab/gst/package.json index 39e0b93101c..3d14e591970 100644 --- a/jupyterlab/gst/package.json +++ b/jupyterlab/gst/package.json @@ -11,10 +11,10 @@ "bugs": { "url": "https://github.com/GamestonkTerminal/GamestonkTerminal/issues" }, - "license": "BSD-3-Clause", + "license": "MIT", "author": { "name": "Gamestonk Contibuters", - "email": "" + "email": "dro.lopes@campus.fct.unl.pt" }, "files": [ "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",