commit
ddcf687a78
@ -0,0 +1,22 @@
|
||||
lint-staged.config.js
|
||||
.eslintrc.js
|
||||
|
||||
node_modules
|
||||
**/build
|
||||
**/lib
|
||||
**/node_modules
|
||||
**/mock_packages
|
||||
**/static
|
||||
**/typings
|
||||
**/schemas
|
||||
**/themes
|
||||
coverage
|
||||
*.map.js
|
||||
*.bundle.js
|
||||
|
||||
# jetbrains IDE stuff
|
||||
.idea/
|
||||
|
||||
# ms IDE stuff
|
||||
.history/
|
||||
.vscode/
|
||||
@ -0,0 +1,56 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
commonjs: true,
|
||||
node: true,
|
||||
'jest/globals': true
|
||||
},
|
||||
root: true,
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:jest/recommended'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.eslint.json',
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'jest'],
|
||||
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-var-requires': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-empty-interface': 'off',
|
||||
'@typescript-eslint/quotes': [
|
||||
'error',
|
||||
'single',
|
||||
{ avoidEscape: true, allowTemplateLiterals: false }
|
||||
],
|
||||
curly: ['error', 'all'],
|
||||
eqeqeq: 'error',
|
||||
'prefer-arrow-callback': 'error'
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect'
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,116 @@
|
||||
*.bundle.*
|
||||
lib/
|
||||
node_modules/
|
||||
*.egg-info/
|
||||
.ipynb_checkpoints
|
||||
*.tsbuildinfo
|
||||
|
||||
# Created by https://www.gitignore.io/api/python
|
||||
# Edit at https://www.gitignore.io/?templates=python
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# OS X stuff
|
||||
*.DS_Store
|
||||
|
||||
# End of https://www.gitignore.io/api/python
|
||||
|
||||
_temp_extension
|
||||
junit.xml
|
||||
[uU]ntitled*
|
||||
jupyterlab_classic/static
|
||||
@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
**/node_modules
|
||||
**/lib
|
||||
**/package.json
|
||||
**/static
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"singleQuote": true
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2020, Jeremy Tuloup
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@ -0,0 +1,21 @@
|
||||
include LICENSE
|
||||
include README.md
|
||||
include pyproject.toml
|
||||
include jupyter-config/jupyterlab-classic.json
|
||||
|
||||
include package.json
|
||||
include install.json
|
||||
include ts*.json
|
||||
|
||||
# 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
|
||||
@ -0,0 +1,60 @@
|
||||
# jupyterlab-classic
|
||||
|
||||
The next gen old-school Notebook UI.
|
||||
|
||||
## Install
|
||||
|
||||
With `pip`:
|
||||
|
||||
```bash
|
||||
pip install jupyterlab-classic
|
||||
```
|
||||
|
||||
With `conda`:
|
||||
|
||||
```bash
|
||||
conda install -c conda-forge jupyterlab-classic
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
`jupyterlab-classic` can be started as a standalone app with:
|
||||
|
||||
```bash
|
||||
python -m jupyterlab_classic
|
||||
```
|
||||
|
||||
Existing federated JupyterLab extensions listed via:
|
||||
|
||||
```bash
|
||||
jupyter labextension list
|
||||
```
|
||||
|
||||
Should also be available when starting `jupyterlab-classic`.
|
||||
|
||||
## Motivation
|
||||
|
||||
JupyterLab is the next-gen UI for Project Jupyter. Approaching version 3.0, it is becoming more mature and provides and advanced computation environment, that can sometimes be compared to what traditional IDEs offer.
|
||||
|
||||
However in some cases, having a leaner, simpler, and more focused interface to work on a notebook is really useful.
|
||||
|
||||
The single document mode as currently implemented in JupyterLab helps address this issue, but still displays a couple of visual cues to the users that can be distracting.
|
||||
|
||||
The goal of the `jupyterlab-classic` project is to look as close to the classic notebook UI as possible, while leveraging the efforts put in the development of JupyterLab itself and its extension system.
|
||||
|
||||
Technically speaking, `jupyterlab-classic` reuses **many** of the existing plugins for JupyterLab (notebook, toolbar), and also supports pre-built (federated) third-party extensions using the new distribution system added in 3.0. That way, extensions built for JupyterLab should also be compatible with `jupyterlab-classic`, as long as they can be added to the application.
|
||||
|
||||
## Prior art
|
||||
|
||||
This project is mostly a reboot of the two previous attempts at making something similar:
|
||||
|
||||
- [simplest-notebook](https://github.com/yuvipanda/simplest-notebook)
|
||||
- [jupyterlab-clarity-mode](https://github.com/jupytercalpoly/jupyterlab-clarity-mode)
|
||||
|
||||
These projects real expressed the need for a stripped down, minimal version of the Jupyter Notebook UI.
|
||||
|
||||
`jupyterlab-classic` contributes to that space With the added:
|
||||
|
||||
- Support for existing federated (prebuilt) JupyterLab extensions
|
||||
- Repo structure, similar to JupyterLab
|
||||
- Reusing as much as possible from upstream JupyterLab
|
||||
@ -0,0 +1,154 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
||||
|
||||
// Promise.allSettled polyfill, until our supported browsers implement it
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
|
||||
if (Promise.allSettled === undefined) {
|
||||
Promise.allSettled = promises =>
|
||||
Promise.all(
|
||||
promises.map(promise =>
|
||||
promise.then(
|
||||
value => ({
|
||||
status: 'fulfilled',
|
||||
value
|
||||
}),
|
||||
reason => ({
|
||||
status: 'rejected',
|
||||
reason
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
require('./style.css');
|
||||
|
||||
function loadScript(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const newScript = document.createElement('script');
|
||||
newScript.onerror = reject;
|
||||
newScript.onload = resolve;
|
||||
newScript.async = true;
|
||||
document.head.appendChild(newScript);
|
||||
newScript.src = url;
|
||||
});
|
||||
}
|
||||
async function loadComponent(url, scope) {
|
||||
await loadScript(url);
|
||||
|
||||
// From MIT-licensed https://github.com/module-federation/module-federation-examples/blob/af043acd6be1718ee195b2511adf6011fba4233c/advanced-api/dynamic-remotes/app1/src/App.js#L6-L12
|
||||
// eslint-disable-next-line no-undef
|
||||
await __webpack_init_sharing__('default');
|
||||
const container = window._JUPYTERLAB[scope];
|
||||
// Initialize the container, it may provide shared modules and may need ours
|
||||
// eslint-disable-next-line no-undef
|
||||
await container.init(__webpack_share_scopes__.default);
|
||||
}
|
||||
|
||||
async function createModule(scope, module) {
|
||||
try {
|
||||
const factory = await window._JUPYTERLAB[scope].get(module);
|
||||
return factory();
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`Failed to create module: package: ${scope}; module: ${module}`
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main function
|
||||
*/
|
||||
async function main() {
|
||||
const App = require('@jupyterlab-classic/application').App;
|
||||
const app = new App();
|
||||
const mods = [
|
||||
require('@jupyterlab-classic/application-extension'),
|
||||
require('@jupyterlab/apputils-extension').default.filter(({ id }) =>
|
||||
['@jupyterlab/apputils-extension:settings'].includes(id)
|
||||
),
|
||||
require('@jupyterlab/codemirror-extension').default.filter(({ id }) =>
|
||||
['@jupyterlab/codemirror-extension:services'].includes(id)
|
||||
),
|
||||
require('@jupyterlab/mainmenu-extension'),
|
||||
require('@jupyterlab/rendermime-extension'),
|
||||
require('@jupyterlab/notebook-extension').default.filter(({ id }) =>
|
||||
[
|
||||
'@jupyterlab/notebook-extension:factory',
|
||||
'@jupyterlab/notebook-extension:widget-factory',
|
||||
'@jupyterlab/notebook-extension:tracker'
|
||||
].includes(id)
|
||||
)
|
||||
];
|
||||
|
||||
const extension_data = JSON.parse(
|
||||
PageConfig.getOption('federated_extensions')
|
||||
);
|
||||
|
||||
const federatedExtensionPromises = [];
|
||||
const federatedMimeExtensionPromises = [];
|
||||
const federatedStylePromises = [];
|
||||
|
||||
const extensions = await Promise.allSettled(
|
||||
extension_data.map(async data => {
|
||||
await loadComponent(
|
||||
`${URLExt.join(
|
||||
PageConfig.getOption('fullLabextensionsUrl'),
|
||||
data.name,
|
||||
data.load
|
||||
)}`,
|
||||
data.name
|
||||
);
|
||||
return data;
|
||||
})
|
||||
);
|
||||
|
||||
extensions.forEach(p => {
|
||||
if (p.status === 'rejected') {
|
||||
// There was an error loading the component
|
||||
console.error(p.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = p.value;
|
||||
if (data.extension) {
|
||||
federatedExtensionPromises.push(createModule(data.name, data.extension));
|
||||
}
|
||||
if (data.mimeExtension) {
|
||||
federatedMimeExtensionPromises.push(
|
||||
createModule(data.name, data.mimeExtension)
|
||||
);
|
||||
}
|
||||
if (data.style) {
|
||||
federatedStylePromises.push(createModule(data.name, data.style));
|
||||
}
|
||||
});
|
||||
|
||||
// Add the federated extensions.
|
||||
const federatedExtensions = await Promise.allSettled(
|
||||
federatedExtensionPromises
|
||||
);
|
||||
federatedExtensions.forEach(p => {
|
||||
if (p.status === 'fulfilled') {
|
||||
mods.push(p.value);
|
||||
} else {
|
||||
console.error(p.reason);
|
||||
}
|
||||
});
|
||||
|
||||
// Load all federated component styles and log errors for any that do not
|
||||
(await Promise.allSettled(federatedStylePromises))
|
||||
.filter(({ status }) => status === 'rejected')
|
||||
.forEach(({ reason }) => {
|
||||
console.error(reason);
|
||||
});
|
||||
|
||||
app.registerPluginModules(mods);
|
||||
|
||||
await app.start();
|
||||
}
|
||||
|
||||
window.addEventListener('load', main);
|
||||
@ -0,0 +1,207 @@
|
||||
{
|
||||
"name": "@jupyterlab-classic/builder",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"build:prod": "webpack --mode=production",
|
||||
"clean": "rimraf build",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"watch": "webpack --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jupyterlab-classic/application": "^0.1.0",
|
||||
"@jupyterlab-classic/application-extension": "^0.1.0",
|
||||
"@jupyterlab-classic/ui-components": "^0.1.0",
|
||||
"@jupyterlab/apputils-extension": "^3.0.0-rc.10",
|
||||
"@jupyterlab/codemirror-extension": "^3.0.0-rc.10",
|
||||
"@jupyterlab/mainmenu-extension": "^3.0.0-rc.10",
|
||||
"@jupyterlab/notebook-extension": "^3.0.0-rc.10",
|
||||
"@jupyterlab/rendermime-extension": "^3.0.0-rc.10",
|
||||
"@jupyterlab/theme-light-extension": "^3.0.0-rc.10",
|
||||
"@jupyterlab/coreutils": "~5.0.0-rc.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jupyterlab/builder": "^3.0.0-rc.10",
|
||||
"css-loader": "~3.2.0",
|
||||
"file-loader": "~5.0.2",
|
||||
"fs-extra": "^8.1.0",
|
||||
"glob": "~7.1.6",
|
||||
"mini-css-extract-plugin": "~0.9.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"raw-loader": "~4.0.0",
|
||||
"rimraf": "~3.0.2",
|
||||
"style-loader": "~1.0.1",
|
||||
"svg-url-loader": "~6.0.0",
|
||||
"url-loader": "~4.1.1",
|
||||
"watch": "~1.0.2",
|
||||
"webpack": "^5.7.0",
|
||||
"webpack-bundle-analyzer": "^4.1.0",
|
||||
"webpack-cli": "^4.2.0",
|
||||
"webpack-merge": "^5.1.2",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@jupyterlab/application": "~3.0.0-rc.10",
|
||||
"@jupyterlab/application-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/apputils": "~3.0.0-rc.10",
|
||||
"@jupyterlab/apputils-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/attachments": "~3.0.0-rc.10",
|
||||
"@jupyterlab/cells": "~3.0.0-rc.10",
|
||||
"@jupyterlab/celltags": "~3.0.0-rc.10",
|
||||
"@jupyterlab/celltags-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/codeeditor": "~3.0.0-rc.10",
|
||||
"@jupyterlab/codemirror": "~3.0.0-rc.10",
|
||||
"@jupyterlab/codemirror-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/completer": "~3.0.0-rc.10",
|
||||
"@jupyterlab/completer-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/console": "~3.0.0-rc.10",
|
||||
"@jupyterlab/console-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/coreutils": "~5.0.0-rc.10",
|
||||
"@jupyterlab/csvviewer": "~3.0.0-rc.10",
|
||||
"@jupyterlab/csvviewer-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/debugger": "~3.0.0-rc.10",
|
||||
"@jupyterlab/debugger-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/docmanager": "~3.0.0-rc.10",
|
||||
"@jupyterlab/docmanager-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/docregistry": "~3.0.0-rc.10",
|
||||
"@jupyterlab/documentsearch": "~3.0.0-rc.10",
|
||||
"@jupyterlab/documentsearch-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/extensionmanager": "^3.0.0-rc.10",
|
||||
"@jupyterlab/extensionmanager-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/filebrowser": "~3.0.0-rc.10",
|
||||
"@jupyterlab/filebrowser-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/fileeditor": "~3.0.0-rc.10",
|
||||
"@jupyterlab/fileeditor-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/help-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/htmlviewer": "~3.0.0-rc.10",
|
||||
"@jupyterlab/htmlviewer-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/hub-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/imageviewer": "~3.0.0-rc.10",
|
||||
"@jupyterlab/imageviewer-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/inspector": "~3.0.0-rc.10",
|
||||
"@jupyterlab/inspector-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/javascript-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/json-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/launcher": "~3.0.0-rc.10",
|
||||
"@jupyterlab/launcher-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/logconsole": "~3.0.0-rc.10",
|
||||
"@jupyterlab/logconsole-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/mainmenu": "~3.0.0-rc.10",
|
||||
"@jupyterlab/mainmenu-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/markdownviewer-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/mathjax2": "~3.0.0-rc.10",
|
||||
"@jupyterlab/mathjax2-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/metapackage": "~3.0.0-rc.10",
|
||||
"@jupyterlab/nbconvert-css": "~3.0.0-rc.10",
|
||||
"@jupyterlab/nbformat": "~3.0.0-rc.10",
|
||||
"@jupyterlab/notebook": "~3.0.0-rc.10",
|
||||
"@jupyterlab/notebook-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/observables": "~4.0.0-rc.10",
|
||||
"@jupyterlab/outputarea": "~3.0.0-rc.10",
|
||||
"@jupyterlab/pdf-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/property-inspector": "~3.0.0-rc.10",
|
||||
"@jupyterlab/rendermime": "~3.0.0-rc.10",
|
||||
"@jupyterlab/rendermime-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/rendermime-interfaces": "~3.0.0-rc.10",
|
||||
"@jupyterlab/running": "~3.0.0-rc.10",
|
||||
"@jupyterlab/running-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/services": "~6.0.0-rc.10",
|
||||
"@jupyterlab/settingeditor": "~3.0.0-rc.10",
|
||||
"@jupyterlab/settingeditor-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/settingregistry": "~3.0.0-rc.10",
|
||||
"@jupyterlab/shortcuts-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/statedb": "~3.0.0-rc.10",
|
||||
"@jupyterlab/statusbar": "~3.0.0-rc.10",
|
||||
"@jupyterlab/statusbar-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/terminal": "~3.0.0-rc.10",
|
||||
"@jupyterlab/terminal-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/theme-dark-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/theme-light-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/toc": "~5.0.0-rc.10",
|
||||
"@jupyterlab/toc-extension": "~5.0.0-rc.10",
|
||||
"@jupyterlab/tooltip": "~3.0.0-rc.10",
|
||||
"@jupyterlab/tooltip-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/translation": "~3.0.0-rc.10",
|
||||
"@jupyterlab/translation-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/ui-components": "~3.0.0-rc.10",
|
||||
"@jupyterlab/ui-components-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/vdom": "~3.0.0-rc.10",
|
||||
"@jupyterlab/vdom-extension": "~3.0.0-rc.10",
|
||||
"@jupyterlab/vega5-extension": "~3.0.0-rc.10",
|
||||
"@lumino/algorithm": "^1.2.3",
|
||||
"@lumino/application": "^1.8.4",
|
||||
"@lumino/commands": "^1.10.1",
|
||||
"@lumino/coreutils": "^1.4.3",
|
||||
"@lumino/disposable": "^1.3.5",
|
||||
"@lumino/domutils": "^1.1.7",
|
||||
"@lumino/dragdrop": "^1.5.1",
|
||||
"@lumino/messaging": "^1.3.3",
|
||||
"@lumino/properties": "^1.1.6",
|
||||
"@lumino/signaling": "^1.3.5",
|
||||
"@lumino/virtualdom": "^1.6.1",
|
||||
"@lumino/widgets": "^1.14.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1"
|
||||
},
|
||||
"jupyterlab": {
|
||||
"name": "JupyterLab Classic",
|
||||
"version": "0.1.0",
|
||||
"extensions": {
|
||||
"@jupyterlab-classic/application-extension": ""
|
||||
},
|
||||
"buildDir": "./static",
|
||||
"outputDir": ".",
|
||||
"singletonPackages": [
|
||||
"@jupyterlab/application",
|
||||
"@jupyterlab/apputils",
|
||||
"@jupyterlab/codeeditor",
|
||||
"@jupyterlab/codemirror",
|
||||
"@jupyterlab/completer",
|
||||
"@jupyterlab/console",
|
||||
"@jupyterlab/coreutils",
|
||||
"@jupyterlab/debugger",
|
||||
"@jupyterlab/docmanager",
|
||||
"@jupyterlab/documentsearch",
|
||||
"@jupyterlab/extensionmanager",
|
||||
"@jupyterlab/filebrowser",
|
||||
"@jupyterlab/fileeditor",
|
||||
"@jupyterlab/imageviewer",
|
||||
"@jupyterlab/inspector",
|
||||
"@jupyterlab/launcher",
|
||||
"@jupyterlab/logconsole",
|
||||
"@jupyterlab/mainmenu",
|
||||
"@jupyterlab/markdownviewer",
|
||||
"@jupyterlab/notebook",
|
||||
"@jupyterlab/rendermime",
|
||||
"@jupyterlab/rendermime-interfaces",
|
||||
"@jupyterlab/services",
|
||||
"@jupyterlab/settingeditor",
|
||||
"@jupyterlab/settingregistry",
|
||||
"@jupyterlab/statedb",
|
||||
"@jupyterlab/statusbar",
|
||||
"@jupyterlab/terminal",
|
||||
"@jupyterlab/tooltip",
|
||||
"@jupyterlab/translation",
|
||||
"@jupyterlab/ui-components",
|
||||
"@lumino/algorithm",
|
||||
"@lumino/application",
|
||||
"@lumino/commands",
|
||||
"@lumino/coreutils",
|
||||
"@lumino/disposable",
|
||||
"@lumino/domutils",
|
||||
"@lumino/dragdrop",
|
||||
"@lumino/messaging",
|
||||
"@lumino/properties",
|
||||
"@lumino/signaling",
|
||||
"@lumino/virtualdom",
|
||||
"@lumino/widgets",
|
||||
"react",
|
||||
"react-dom"
|
||||
],
|
||||
"linkedPackages": {
|
||||
"@jupyterlab-classic/application": "../packages/application",
|
||||
"@jupyterlab-classic/application-extension": "../packages/application-extension"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
// We dynamically set the webpack public path based on the page config
|
||||
// settings from the JupyterLab app. We copy some of the pageconfig parsing
|
||||
// logic in @jupyterlab/coreutils below, since this must run before any other
|
||||
// files are loaded (including @jupyterlab/coreutils).
|
||||
|
||||
/**
|
||||
* Get global configuration data for the Jupyter application.
|
||||
*
|
||||
* @param name - The name of the configuration option.
|
||||
*
|
||||
* @returns The config value or an empty string if not found.
|
||||
*
|
||||
* #### Notes
|
||||
* All values are treated as strings.
|
||||
* For browser based applications, it is assumed that the page HTML
|
||||
* includes a script tag with the id `jupyter-config-data` containing the
|
||||
* configuration as valid JSON. In order to support the classic Notebook,
|
||||
* we fall back on checking for `body` data of the given `name`.
|
||||
*/
|
||||
function getOption(name) {
|
||||
let configData = Object.create(null);
|
||||
// Use script tag if available.
|
||||
if (typeof document !== 'undefined' && document) {
|
||||
const el = document.getElementById('jupyter-config-data');
|
||||
|
||||
if (el) {
|
||||
configData = JSON.parse(el.textContent || '{}');
|
||||
}
|
||||
}
|
||||
return configData[name] || '';
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
__webpack_public_path__ = getOption('fullStaticUrl') + '/';
|
||||
@ -0,0 +1,7 @@
|
||||
@import url('~@jupyterlab-classic/application-extension/style/index.css');
|
||||
@import url('~@jupyterlab-classic/ui-components/style/index.css');
|
||||
|
||||
@import url('~@jupyterlab/codemirror-extension/style/index.css');
|
||||
@import url('~@jupyterlab/rendermime-extension/style/index.css');
|
||||
@import url('~@jupyterlab/notebook-extension/style/index.css');
|
||||
@import url('~@jupyterlab/theme-light-extension/style/index.css');
|
||||
@ -0,0 +1,88 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
// Heavily inspired (and slightly tweaked) from:
|
||||
// https://github.com/jupyterlab/jupyterlab/blob/master/examples/federated/core_package/webpack.config.js
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const merge = require('webpack-merge').default;
|
||||
const { ModuleFederationPlugin } = webpack.container;
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
|
||||
.BundleAnalyzerPlugin;
|
||||
|
||||
const Build = require('@jupyterlab/builder').Build;
|
||||
const baseConfig = require('@jupyterlab/builder/lib/webpack.config.base');
|
||||
|
||||
const data = require('./package.json');
|
||||
|
||||
const names = Object.keys(data.dependencies).filter(name => {
|
||||
const packageData = require(path.join(name, 'package.json'));
|
||||
return packageData.jupyterlab !== undefined;
|
||||
});
|
||||
|
||||
// Ensure a clear build directory.
|
||||
const buildDir = path.resolve(__dirname, 'build');
|
||||
if (fs.existsSync(buildDir)) {
|
||||
fs.removeSync(buildDir);
|
||||
}
|
||||
fs.ensureDirSync(buildDir);
|
||||
|
||||
// Copy extra files
|
||||
const index = path.resolve(__dirname, 'index.js');
|
||||
const cssImports = path.resolve(__dirname, 'style.css');
|
||||
fs.copySync(index, path.resolve(buildDir, 'index.js'));
|
||||
fs.copySync(cssImports, path.resolve(buildDir, 'style.css'));
|
||||
|
||||
const extras = Build.ensureAssets({
|
||||
packageNames: names,
|
||||
output: buildDir
|
||||
});
|
||||
|
||||
const singletons = {};
|
||||
|
||||
data.jupyterlab.singletonPackages.forEach(element => {
|
||||
singletons[element] = { singleton: true };
|
||||
});
|
||||
|
||||
// Make a bootstrap entrypoint
|
||||
const entryPoint = path.join(buildDir, 'bootstrap.js');
|
||||
const bootstrap = 'import("./index.js");';
|
||||
fs.writeFileSync(entryPoint, bootstrap);
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
baseConfig.mode = 'production';
|
||||
}
|
||||
|
||||
if (process.argv.includes('--analyze')) {
|
||||
extras.push(new BundleAnalyzerPlugin());
|
||||
}
|
||||
|
||||
module.exports = [
|
||||
merge(baseConfig, {
|
||||
mode: 'development',
|
||||
entry: ['./publicpath.js', './' + path.relative(__dirname, entryPoint)],
|
||||
output: {
|
||||
path: path.resolve(__dirname, '..', 'jupyterlab_classic/static/'),
|
||||
library: {
|
||||
type: 'var',
|
||||
name: ['_JUPYTERLAB', 'CORE_OUTPUT']
|
||||
},
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new ModuleFederationPlugin({
|
||||
library: {
|
||||
type: 'var',
|
||||
name: ['_JUPYTERLAB', 'CORE_LIBRARY_FEDERATION']
|
||||
},
|
||||
name: 'CORE_FEDERATION',
|
||||
shared: {
|
||||
...data.resolutions,
|
||||
...singletons
|
||||
}
|
||||
})
|
||||
]
|
||||
})
|
||||
].concat(extras);
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"ServerApp": {
|
||||
"jpserver_extensions": {
|
||||
"jupyterlab_classic": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
from ._version import __version__
|
||||
from .app import ClassicApp
|
||||
from .serverextension import load_jupyter_server_extension
|
||||
|
||||
|
||||
def _jupyter_server_extension_paths():
|
||||
return [
|
||||
{
|
||||
'module': 'jupyterlab'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def _jupyter_server_extension_points():
|
||||
return [{"module": "jupyterlab_classic", "app": ClassicApp}]
|
||||
@ -0,0 +1,4 @@
|
||||
from jupyterlab_classic.app import main
|
||||
import sys
|
||||
|
||||
sys.exit(main())
|
||||
@ -0,0 +1 @@
|
||||
__version__ = "0.1.0"
|
||||
@ -0,0 +1,58 @@
|
||||
import os
|
||||
|
||||
from jupyter_server.base.handlers import JupyterHandler
|
||||
from jupyter_server.extension.handler import (
|
||||
ExtensionHandlerMixin,
|
||||
ExtensionHandlerJinjaMixin,
|
||||
)
|
||||
from jupyterlab import LabApp
|
||||
from jupyter_server.utils import url_path_join as ujoin
|
||||
from tornado import web
|
||||
|
||||
from ._version import __version__
|
||||
|
||||
HERE = os.path.dirname(__file__)
|
||||
version = __version__
|
||||
|
||||
|
||||
class ClassicHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):
|
||||
@web.authenticated
|
||||
def get(self):
|
||||
config_data = {
|
||||
"appVersion": version,
|
||||
"baseUrl": self.base_url,
|
||||
"token": self.settings["token"],
|
||||
"fullStaticUrl": ujoin(self.base_url, "static", self.name),
|
||||
"frontendUrl": ujoin(self.base_url, "classic/"),
|
||||
}
|
||||
return self.write(
|
||||
self.render_template(
|
||||
"index.html",
|
||||
static=self.static_url,
|
||||
base_url=self.base_url,
|
||||
token=self.settings["token"],
|
||||
page_config=config_data,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ClassicApp(LabApp):
|
||||
|
||||
extension_url = '/classic'
|
||||
app_url = "/classic"
|
||||
load_other_extensions = True
|
||||
name = __name__
|
||||
app_name = 'JupyterLab Classic'
|
||||
static_dir = os.path.join(HERE, 'static')
|
||||
templates_dir = os.path.join(HERE, 'templates')
|
||||
app_version = version
|
||||
|
||||
def initialize_handlers(self):
|
||||
super().initialize_handlers()
|
||||
self.handlers.append(('/classic', ClassicHandler))
|
||||
|
||||
|
||||
main = launch_new_instance = ClassicApp.launch_instance
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -0,0 +1,10 @@
|
||||
from .app import ClassicApp
|
||||
|
||||
|
||||
def load_jupyter_server_extension(serverapp):
|
||||
extension = ClassicApp()
|
||||
extension.serverapp = serverapp
|
||||
extension.load_config_file()
|
||||
extension.update_config(serverapp.config)
|
||||
extension.parse_command_line(serverapp.extra_args)
|
||||
extension.initialize()
|
||||
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (c) Jupyter Development Team.
|
||||
Distributed under the terms of the Modified BSD License.
|
||||
-->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>{% block title %}{{page_title | e}}{% endblock %}</title>
|
||||
|
||||
{% block favicon %}<link rel="shortcut icon" type="image/x-icon" href="/static/favicons/favicon.ico">{% endblock %}
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
{% block stylesheet %}
|
||||
<style type="text/css">
|
||||
/* disable initial hide */
|
||||
div#header, div#site {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block site %}
|
||||
|
||||
<div class="error">
|
||||
{% block h1_error %}
|
||||
<h1>{{status_code | e}} : {{status_message | e}}</h1>
|
||||
{% endblock h1_error %}
|
||||
{% block error_detail %}
|
||||
{% if message %}
|
||||
<p>The error was:</p>
|
||||
<div class="traceback-wrapper">
|
||||
<pre class="traceback">{{message | e}}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</header>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type='text/javascript'>
|
||||
window.onload = function () {
|
||||
var tb = document.getElementsByClassName('traceback')[0];
|
||||
tb.scrollTop = tb.scrollHeight;
|
||||
{% if message %}
|
||||
console.error("{{message | e}}")
|
||||
{% endif %}
|
||||
};
|
||||
</script>
|
||||
{% endblock script %}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{page_config['appName'] | e}}</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{# Copy so we do not modify the page_config with updates. #}
|
||||
{% set page_config_full = page_config.copy() %}
|
||||
|
||||
{# Set a dummy variable - we just want the side effect of the update. #}
|
||||
{% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
|
||||
|
||||
<script id="jupyter-config-data" type="application/json">
|
||||
{{ page_config_full | tojson }}
|
||||
</script>
|
||||
<script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
/* Remove token from URL. */
|
||||
(function () {
|
||||
var parsedUrl = new URL(window.location.href);
|
||||
if (parsedUrl.searchParams.get('token')) {
|
||||
parsedUrl.searchParams.delete('token');
|
||||
window.history.replaceState({ }, '', parsedUrl.href);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"npmClient": "yarn",
|
||||
"version": "2.0.0",
|
||||
"useWorkspaces": true
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
const escape = require('shell-quote').quote;
|
||||
const fs = require('fs');
|
||||
const isWin = process.platform === 'win32';
|
||||
|
||||
const escapeFileNames = filenames =>
|
||||
filenames
|
||||
.filter(filename => fs.existsSync(filename))
|
||||
.map(filename => `"${isWin ? filename : escape([filename])}"`)
|
||||
.join(' ');
|
||||
|
||||
module.exports = {
|
||||
'**/*{.css,.json,.md}': filenames => {
|
||||
const escapedFileNames = escapeFileNames(filenames);
|
||||
return [
|
||||
`prettier --write ${escapedFileNames}`,
|
||||
`git add -f ${escapedFileNames}`
|
||||
];
|
||||
},
|
||||
'**/*{.ts,.tsx,.js,.jsx}': filenames => {
|
||||
const escapedFileNames = escapeFileNames(filenames);
|
||||
return [
|
||||
`prettier --write ${escapedFileNames}`,
|
||||
`eslint --fix ${escapedFileNames}`,
|
||||
`git add -f ${escapedFileNames}`
|
||||
];
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,161 @@
|
||||
{
|
||||
"private": true,
|
||||
"homepage": "https://github.com/jtpio/jupyterlab-classic",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jtpio/jupyterlab-classic"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/jtpio/jupyterlab-classic/issues"
|
||||
},
|
||||
"license": "BSD-3-Clause",
|
||||
"author": "Jeremy Tuloup",
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"builder",
|
||||
"packages/*"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build": "lerna run build",
|
||||
"build:prod": "lerna run build:prod",
|
||||
"build:test": "lerna run build:test",
|
||||
"clean": "lerna run clean",
|
||||
"install": "lerna bootstrap",
|
||||
"eslint": "eslint . --ext .ts,.tsx --fix",
|
||||
"eslint:check": "eslint . --ext .ts,.tsx",
|
||||
"prettier": "prettier --write \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"",
|
||||
"prettier:check": "prettier --list-different \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"",
|
||||
"publish": "yarn run clean && yarn run build && lerna publish",
|
||||
"test": "lerna run test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^4.2.0",
|
||||
"@typescript-eslint/parser": "^4.2.0",
|
||||
"eslint": "^7.10.0",
|
||||
"eslint-plugin-jest": "^24.1.3",
|
||||
"eslint-config-prettier": "^6.15.0",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"eslint-plugin-react": "^7.21.5",
|
||||
"husky": "^3",
|
||||
"jest": "^26.4.2",
|
||||
"jest-junit": "^11.1.0",
|
||||
"jest-raw-loader": "^1.0.1",
|
||||
"jest-summary-reporter": "^0.0.2",
|
||||
"lerna": "^3.22.1",
|
||||
"lint-staged": "^10.4.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^1.19.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"shell-quote": "^1.7.2",
|
||||
"typescript": "~4.0.3"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"resolutions": {
|
||||
"@jupyterlab/application": "3.0.0-rc.10",
|
||||
"@jupyterlab/application-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/apputils": "3.0.0-rc.10",
|
||||
"@jupyterlab/apputils-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/attachments": "3.0.0-rc.10",
|
||||
"@jupyterlab/cells": "3.0.0-rc.10",
|
||||
"@jupyterlab/celltags": "3.0.0-rc.10",
|
||||
"@jupyterlab/celltags-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/codeeditor": "3.0.0-rc.10",
|
||||
"@jupyterlab/codemirror": "3.0.0-rc.10",
|
||||
"@jupyterlab/codemirror-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/completer": "3.0.0-rc.10",
|
||||
"@jupyterlab/completer-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/console": "3.0.0-rc.10",
|
||||
"@jupyterlab/console-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/coreutils": "5.0.0-rc.10",
|
||||
"@jupyterlab/csvviewer": "3.0.0-rc.10",
|
||||
"@jupyterlab/csvviewer-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/debugger": "3.0.0-rc.10",
|
||||
"@jupyterlab/debugger-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/docmanager": "3.0.0-rc.10",
|
||||
"@jupyterlab/docmanager-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/docregistry": "3.0.0-rc.10",
|
||||
"@jupyterlab/documentsearch": "3.0.0-rc.10",
|
||||
"@jupyterlab/documentsearch-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/extensionmanager": "3.0.0-rc.10",
|
||||
"@jupyterlab/extensionmanager-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/filebrowser": "3.0.0-rc.10",
|
||||
"@jupyterlab/filebrowser-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/fileeditor": "3.0.0-rc.10",
|
||||
"@jupyterlab/fileeditor-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/help-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/htmlviewer": "3.0.0-rc.10",
|
||||
"@jupyterlab/htmlviewer-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/hub-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/imageviewer": "3.0.0-rc.10",
|
||||
"@jupyterlab/imageviewer-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/inspector": "3.0.0-rc.10",
|
||||
"@jupyterlab/inspector-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/javascript-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/json-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/launcher": "3.0.0-rc.10",
|
||||
"@jupyterlab/launcher-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/logconsole": "3.0.0-rc.10",
|
||||
"@jupyterlab/logconsole-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/mainmenu": "3.0.0-rc.10",
|
||||
"@jupyterlab/mainmenu-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/markdownviewer-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/mathjax2": "3.0.0-rc.10",
|
||||
"@jupyterlab/mathjax2-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/metapackage": "3.0.0-rc.10",
|
||||
"@jupyterlab/nbconvert-css": "3.0.0-rc.10",
|
||||
"@jupyterlab/nbformat": "3.0.0-rc.10",
|
||||
"@jupyterlab/notebook": "3.0.0-rc.10",
|
||||
"@jupyterlab/notebook-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/observables": "4.0.0-rc.10",
|
||||
"@jupyterlab/outputarea": "3.0.0-rc.10",
|
||||
"@jupyterlab/pdf-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/property-inspector": "3.0.0-rc.10",
|
||||
"@jupyterlab/rendermime": "3.0.0-rc.10",
|
||||
"@jupyterlab/rendermime-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/rendermime-interfaces": "3.0.0-rc.10",
|
||||
"@jupyterlab/running": "3.0.0-rc.10",
|
||||
"@jupyterlab/running-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/services": "6.0.0-rc.10",
|
||||
"@jupyterlab/settingeditor": "3.0.0-rc.10",
|
||||
"@jupyterlab/settingeditor-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/settingregistry": "3.0.0-rc.10",
|
||||
"@jupyterlab/shortcuts-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/statedb": "3.0.0-rc.10",
|
||||
"@jupyterlab/statusbar": "3.0.0-rc.10",
|
||||
"@jupyterlab/statusbar-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/terminal": "3.0.0-rc.10",
|
||||
"@jupyterlab/terminal-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/theme-dark-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/theme-light-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/toc": "5.0.0-rc.10",
|
||||
"@jupyterlab/toc-extension": "5.0.0-rc.10",
|
||||
"@jupyterlab/tooltip": "3.0.0-rc.10",
|
||||
"@jupyterlab/tooltip-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/translation": "3.0.0-rc.10",
|
||||
"@jupyterlab/translation-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/ui-components": "3.0.0-rc.10",
|
||||
"@jupyterlab/ui-components-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/vdom": "3.0.0-rc.10",
|
||||
"@jupyterlab/vdom-extension": "3.0.0-rc.10",
|
||||
"@jupyterlab/vega5-extension": "3.0.0-rc.10",
|
||||
"@lumino/algorithm": "^1.2.3",
|
||||
"@lumino/application": "^1.8.4",
|
||||
"@lumino/commands": "^1.10.1",
|
||||
"@lumino/coreutils": "^1.4.3",
|
||||
"@lumino/disposable": "^1.3.5",
|
||||
"@lumino/domutils": "^1.1.7",
|
||||
"@lumino/dragdrop": "^1.5.1",
|
||||
"@lumino/messaging": "^1.3.3",
|
||||
"@lumino/properties": "^1.1.6",
|
||||
"@lumino/signaling": "^1.3.5",
|
||||
"@lumino/virtualdom": "^1.6.1",
|
||||
"@lumino/widgets": "^1.14.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "@jupyterlab-classic/application-extension",
|
||||
"version": "0.1.0",
|
||||
"description": "JupyterLab Classic - Application Extension",
|
||||
"homepage": "https://github.com/jtpio/jupyterlab-classic",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jtpio/jupyterlab-classic/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jtpio/jupyterlab-classic.git"
|
||||
},
|
||||
"license": "BSD-3-Clause",
|
||||
"author": "Project Jupyter",
|
||||
"sideEffects": [
|
||||
"style/**/*.css"
|
||||
],
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"style": "style/index.css",
|
||||
"directories": {
|
||||
"lib": "lib/"
|
||||
},
|
||||
"files": [
|
||||
"lib/*.d.ts",
|
||||
"lib/*.js.map",
|
||||
"lib/*.js",
|
||||
"schema/*.json",
|
||||
"style/**/*.css"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"clean": "rimraf lib && rimraf tsconfig.tsbuildinfo",
|
||||
"docs": "typedoc src",
|
||||
"prepublishOnly": "npm run build",
|
||||
"watch": "tsc -b --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jupyterlab-classic/application": "0.1.0",
|
||||
"@jupyterlab-classic/ui-components": "0.1.0",
|
||||
"@jupyterlab/application": "^3.0.0-rc.10",
|
||||
"@jupyterlab/apputils": "^3.0.0-rc.10",
|
||||
"@jupyterlab/codeeditor": "^3.0.0-rc.10",
|
||||
"@jupyterlab/codemirror": "^3.0.0-rc.10",
|
||||
"@jupyterlab/docregistry": "^3.0.0-rc.10",
|
||||
"@jupyterlab/docmanager": "^3.0.0-rc.10",
|
||||
"@jupyterlab/notebook": "^3.0.0-rc.10",
|
||||
"@jupyterlab/translation": "^3.0.0-rc.10",
|
||||
"@lumino/widgets": "^1.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "~3.0.0",
|
||||
"typescript": "~4.0.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"jupyterlab": {
|
||||
"extension": true
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,367 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import {
|
||||
IRouter,
|
||||
JupyterFrontEnd,
|
||||
JupyterFrontEndPlugin,
|
||||
Router
|
||||
} from '@jupyterlab/application';
|
||||
|
||||
import {
|
||||
sessionContextDialogs,
|
||||
ISessionContextDialogs,
|
||||
DOMUtils
|
||||
} from '@jupyterlab/apputils';
|
||||
|
||||
import { PageConfig } from '@jupyterlab/coreutils';
|
||||
|
||||
import {
|
||||
DocumentManager,
|
||||
IDocumentManager,
|
||||
renameDialog
|
||||
} from '@jupyterlab/docmanager';
|
||||
|
||||
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
||||
|
||||
import { NotebookPanel } from '@jupyterlab/notebook';
|
||||
|
||||
import { ITranslator, TranslationManager } from '@jupyterlab/translation';
|
||||
|
||||
import {
|
||||
App,
|
||||
ClassicShell,
|
||||
IClassicShell
|
||||
} from '@jupyterlab-classic/application';
|
||||
|
||||
import { jupyterIcon } from '@jupyterlab-classic/ui-components';
|
||||
|
||||
import { Widget } from '@lumino/widgets';
|
||||
|
||||
/**
|
||||
* The default notebook factory.
|
||||
*/
|
||||
const NOTEBOOK_FACTORY = 'Notebook';
|
||||
|
||||
/**
|
||||
* The command IDs used by the application plugin.
|
||||
*/
|
||||
namespace CommandIDs {
|
||||
export const open = 'open';
|
||||
}
|
||||
|
||||
/**
|
||||
* A minimal document manager plugin.
|
||||
* TODO: move to @jupyterlab-classic/docmanager-extension
|
||||
*/
|
||||
const doc: JupyterFrontEndPlugin<IDocumentManager> = {
|
||||
id: '@jupyterlab-classic/application-extension:docmanager',
|
||||
provides: IDocumentManager,
|
||||
autoStart: true,
|
||||
activate: (app: JupyterFrontEnd) => {
|
||||
const opener = {
|
||||
open: (widget: Widget, options: DocumentRegistry.IOpenOptions) => {
|
||||
app.shell.add(widget, 'main', options);
|
||||
}
|
||||
};
|
||||
const docManager = new DocumentManager({
|
||||
registry: app.docRegistry,
|
||||
manager: app.serviceManager,
|
||||
opener
|
||||
});
|
||||
|
||||
app.commands.addCommand(CommandIDs.open, {
|
||||
label: 'Open a document',
|
||||
execute: (args: any) => {
|
||||
const path = args['path'] as string;
|
||||
const factory = args['factory'] as string;
|
||||
const options = args['options'] as DocumentRegistry.IOpenOptions;
|
||||
const closable = args['closable'] as boolean;
|
||||
const widget = docManager.open(path, factory, undefined, options);
|
||||
if (widget) {
|
||||
widget.title.closable = closable ?? true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return docManager;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The kernel logo plugin.
|
||||
*/
|
||||
const kernelLogo: JupyterFrontEndPlugin<void> = {
|
||||
id: '@jupyterlab-classic/application-extension:kernelLogo',
|
||||
autoStart: true,
|
||||
requires: [IClassicShell],
|
||||
activate: (app: JupyterFrontEnd, shell: IClassicShell) => {
|
||||
const { serviceManager } = app;
|
||||
const baseUrl = PageConfig.getBaseUrl();
|
||||
|
||||
let widget: Widget;
|
||||
// TODO: this signal might not be needed if we assume there is always only
|
||||
// one notebook in the main area
|
||||
shell.currentChanged.connect(async () => {
|
||||
if (widget) {
|
||||
widget.dispose();
|
||||
widget.parent = null;
|
||||
}
|
||||
const current = shell.currentWidget;
|
||||
if (!(current instanceof NotebookPanel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await current.sessionContext.ready;
|
||||
|
||||
const name = current.sessionContext.session?.kernel?.name ?? '';
|
||||
const spec = serviceManager.kernelspecs?.specs?.kernelspecs[name];
|
||||
if (!spec) {
|
||||
return;
|
||||
}
|
||||
|
||||
let kernelIconUrl = spec.resources['logo-64x64'];
|
||||
if (!kernelIconUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = kernelIconUrl.indexOf('kernelspecs');
|
||||
kernelIconUrl = baseUrl + kernelIconUrl.slice(index);
|
||||
const node = document.createElement('div');
|
||||
const img = document.createElement('img');
|
||||
img.src = kernelIconUrl;
|
||||
img.title = spec.display_name;
|
||||
node.appendChild(img);
|
||||
widget = new Widget({ node });
|
||||
widget.addClass('jp-ClassicKernelLogo');
|
||||
app.shell.add(widget, 'top', { rank: 10_010 });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The logo plugin.
|
||||
*/
|
||||
const logo: JupyterFrontEndPlugin<void> = {
|
||||
id: '@jupyterlab-classic/application-extension:logo',
|
||||
autoStart: true,
|
||||
activate: (app: JupyterFrontEnd) => {
|
||||
const logo = new Widget();
|
||||
jupyterIcon.element({
|
||||
container: logo.node,
|
||||
elementPosition: 'center',
|
||||
padding: '2px 2px 2px 8px',
|
||||
height: '28px',
|
||||
width: 'auto'
|
||||
});
|
||||
logo.id = 'jp-ClassicLogo';
|
||||
app.shell.add(logo, 'top', { rank: 0 });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The main plugin.
|
||||
*/
|
||||
const main: JupyterFrontEndPlugin<void> = {
|
||||
id: '@jupyterlab-classic/application-extension:main',
|
||||
autoStart: true,
|
||||
activate: () => {
|
||||
console.log(main.id, 'activated');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The default paths for a JupyterLab Classic app.
|
||||
*/
|
||||
const paths: JupyterFrontEndPlugin<JupyterFrontEnd.IPaths> = {
|
||||
id: '@jupyterlab-classic/application-extension:paths',
|
||||
activate: (app: JupyterFrontEnd): JupyterFrontEnd.IPaths => {
|
||||
if (!(app instanceof App)) {
|
||||
throw new Error(`${paths.id} must be activated in JupyterLab Classic.`);
|
||||
}
|
||||
return app.paths;
|
||||
},
|
||||
autoStart: true,
|
||||
provides: JupyterFrontEnd.IPaths
|
||||
};
|
||||
|
||||
/**
|
||||
* The default URL router provider.
|
||||
*/
|
||||
const router: JupyterFrontEndPlugin<IRouter> = {
|
||||
id: '@jupyterlab-classic/application-extension:router',
|
||||
requires: [JupyterFrontEnd.IPaths],
|
||||
activate: (app: JupyterFrontEnd, paths: JupyterFrontEnd.IPaths) => {
|
||||
const { commands } = app;
|
||||
const base = paths.urls.base;
|
||||
const router = new Router({ base, commands });
|
||||
void app.started.then(() => {
|
||||
// Route the very first request on load.
|
||||
void router.route();
|
||||
|
||||
// Route all pop state events.
|
||||
window.addEventListener('popstate', () => {
|
||||
void router.route();
|
||||
});
|
||||
});
|
||||
return router;
|
||||
},
|
||||
autoStart: true,
|
||||
provides: IRouter
|
||||
};
|
||||
|
||||
/**
|
||||
* The default session dialogs plugin
|
||||
*/
|
||||
const sessionDialogs: JupyterFrontEndPlugin<ISessionContextDialogs> = {
|
||||
id: '@jupyterlab-classic/application-extension:sessionDialogs',
|
||||
provides: ISessionContextDialogs,
|
||||
autoStart: true,
|
||||
activate: () => sessionContextDialogs
|
||||
};
|
||||
|
||||
/**
|
||||
* The default JupyterLab Classic application shell.
|
||||
*/
|
||||
const shell: JupyterFrontEndPlugin<IClassicShell> = {
|
||||
id: '@jupyterlab-classic/application-extension:shell',
|
||||
activate: (app: JupyterFrontEnd) => {
|
||||
if (!(app.shell instanceof ClassicShell)) {
|
||||
throw new Error(`${shell.id} did not find a ClassicShell instance.`);
|
||||
}
|
||||
return app.shell;
|
||||
},
|
||||
autoStart: true,
|
||||
provides: IClassicShell
|
||||
};
|
||||
|
||||
/**
|
||||
* A plugin to provide a spacer at rank 10000 for flex panels
|
||||
*/
|
||||
const spacer: JupyterFrontEndPlugin<void> = {
|
||||
id: '@jupyterlab-classic/application-extension:spacer',
|
||||
autoStart: true,
|
||||
activate: (app: JupyterFrontEnd) => {
|
||||
const spacer = new Widget();
|
||||
spacer.id = DOMUtils.createDomID();
|
||||
spacer.addClass('jp-ClassicSpacer');
|
||||
app.shell.add(spacer, 'top', { rank: 10000 });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A plugin to display the title of the notebook
|
||||
*/
|
||||
const title: JupyterFrontEndPlugin<void> = {
|
||||
id: '@jupyterlab-classic/application-extension:title',
|
||||
autoStart: true,
|
||||
requires: [IClassicShell],
|
||||
optional: [IDocumentManager, IRouter],
|
||||
activate: (
|
||||
app: JupyterFrontEnd,
|
||||
shell: IClassicShell,
|
||||
docManager: IDocumentManager | null,
|
||||
router: IRouter | null
|
||||
) => {
|
||||
// TODO: this signal might not be needed if we assume there is always only
|
||||
// one notebook in the main area
|
||||
const widget = new Widget();
|
||||
widget.id = 'jp-title';
|
||||
app.shell.add(widget, 'top', { rank: 10 });
|
||||
|
||||
shell.currentChanged.connect(async () => {
|
||||
const current = shell.currentWidget;
|
||||
if (!(current instanceof NotebookPanel)) {
|
||||
return;
|
||||
}
|
||||
const h = document.createElement('h1');
|
||||
h.textContent = current.title.label;
|
||||
widget.node.appendChild(h);
|
||||
widget.node.style.marginLeft = '10px';
|
||||
if (docManager) {
|
||||
widget.node.onclick = async () => {
|
||||
const result = await renameDialog(
|
||||
docManager,
|
||||
current.sessionContext.path
|
||||
);
|
||||
if (result) {
|
||||
h.textContent = result.path;
|
||||
if (router) {
|
||||
// TODO: better handle this
|
||||
router.navigate(`/classic/tree/${result.path}`, {
|
||||
skipRouting: true
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A simplified Translator
|
||||
*/
|
||||
const translator: JupyterFrontEndPlugin<ITranslator> = {
|
||||
id: '@jupyterlab-classic/application-extension:translator',
|
||||
activate: (app: JupyterFrontEnd<JupyterFrontEnd.IShell>): ITranslator => {
|
||||
const translationManager = new TranslationManager();
|
||||
return translationManager;
|
||||
},
|
||||
autoStart: true,
|
||||
provides: ITranslator
|
||||
};
|
||||
|
||||
/**
|
||||
* The default tree route resolver plugin.
|
||||
*/
|
||||
const tree: JupyterFrontEndPlugin<void> = {
|
||||
id: '@jupyterlab-classic/application-extension:tree-resolver',
|
||||
autoStart: true,
|
||||
requires: [IRouter],
|
||||
activate: (app: JupyterFrontEnd, router: IRouter): void => {
|
||||
const { commands } = app;
|
||||
const treePattern = new RegExp('/tree/(.*)');
|
||||
|
||||
const command = 'router:tree';
|
||||
commands.addCommand(command, {
|
||||
execute: (args: any) => {
|
||||
const parsed = args as IRouter.ILocation;
|
||||
const matches = parsed.path.match(treePattern);
|
||||
if (!matches) {
|
||||
return;
|
||||
}
|
||||
const [, path] = matches;
|
||||
|
||||
app.restored.then(() => {
|
||||
commands.execute(CommandIDs.open, {
|
||||
path,
|
||||
factory: NOTEBOOK_FACTORY
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
router.register({ command, pattern: treePattern });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Export the plugins as default.
|
||||
*/
|
||||
const plugins: JupyterFrontEndPlugin<any>[] = [
|
||||
doc,
|
||||
kernelLogo,
|
||||
logo,
|
||||
main,
|
||||
paths,
|
||||
router,
|
||||
sessionDialogs,
|
||||
shell,
|
||||
spacer,
|
||||
title,
|
||||
translator,
|
||||
tree
|
||||
];
|
||||
|
||||
export default plugins;
|
||||
@ -0,0 +1,38 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
| Copyright (c) Jupyter Development Team.
|
||||
|
|
||||
| Distributed under the terms of the Modified BSD License.
|
||||
|----------------------------------------------------------------------------*/
|
||||
|
||||
.jp-ClassicSpacer {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
.jp-ClassicKernelLogo {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.jp-ClassicKernelLogo img {
|
||||
max-width: 28px;
|
||||
max-height: 28px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#jp-title h1 {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
color: var(--jp-ui-font-color0);
|
||||
font-family: var(--jp-ui-font-family);
|
||||
line-height: calc(1.5 * var(--jp-private-title-panel-height));
|
||||
}
|
||||
|
||||
#jp-title h1:hover {
|
||||
background: var(--jp-layout-color2);
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
@import url('~@jupyterlab-classic/application/style/index.css');
|
||||
@import url('~@lumino/widgets/style/index.css');
|
||||
|
||||
@import url('./base.css');
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../../tsconfigbase",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src/*"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../application"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
module.exports = require('@jupyterlab/testutils/lib/babel.config');
|
||||
@ -0,0 +1,22 @@
|
||||
const func = require('@jupyterlab/testutils/lib/jest-config');
|
||||
const upstream = func(__dirname);
|
||||
|
||||
let local = {
|
||||
preset: 'ts-jest/presets/js-with-babel',
|
||||
transformIgnorePatterns: ['/node_modules/(?!(@jupyterlab/.*)/)'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: './tsconfig.test.json'
|
||||
}
|
||||
},
|
||||
transform: {
|
||||
'\\.(ts|tsx)?$': 'ts-jest',
|
||||
'\\.svg$': 'jest-raw-loader'
|
||||
}
|
||||
};
|
||||
|
||||
Object.keys(local).forEach(option => {
|
||||
upstream[option] = local[option];
|
||||
});
|
||||
|
||||
module.exports = upstream;
|
||||
@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "@jupyterlab-classic/application",
|
||||
"version": "0.1.0",
|
||||
"description": "JupyterLab Classic - Application",
|
||||
"homepage": "https://github.com/jtpio/jupyterlab-classic",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jtpio/jupyterlab-classic/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jtpio/jupyterlab-classic.git"
|
||||
},
|
||||
"license": "BSD-3-Clause",
|
||||
"author": "Project Jupyter",
|
||||
"sideEffects": [
|
||||
"style/*.css"
|
||||
],
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"style": "style/index.css",
|
||||
"directories": {
|
||||
"lib": "lib/"
|
||||
},
|
||||
"files": [
|
||||
"lib/*.d.ts",
|
||||
"lib/*.js.map",
|
||||
"lib/*.js",
|
||||
"style/*.css"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"build:test": "tsc --build tsconfig.test.json",
|
||||
"clean": "rimraf lib && rimraf tsconfig.tsbuildinfo",
|
||||
"docs": "typedoc src",
|
||||
"prepublishOnly": "npm run build",
|
||||
"test": "jest",
|
||||
"test:cov": "jest --collect-coverage",
|
||||
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
|
||||
"test:debug:watch": "node --inspect-brk node_modules/.bin/jest --runInBand --watch",
|
||||
"watch": "tsc -b --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jupyterlab/application": "^3.0.0-rc.10",
|
||||
"@jupyterlab/docregistry": "^3.0.0-rc.10",
|
||||
"@jupyterlab/coreutils": "^5.0.0-rc.10",
|
||||
"@jupyterlab/ui-components": "^3.0.0-rc.10",
|
||||
"@lumino/algorithm": "^1.3.3",
|
||||
"@lumino/coreutils": "^1.5.3",
|
||||
"@lumino/messaging": "^1.4.3",
|
||||
"@lumino/signaling": "^1.4.3",
|
||||
"@lumino/widgets": "^1.14.0",
|
||||
"es6-promise": "~4.2.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.6",
|
||||
"@babel/preset-env": "^7.12.1",
|
||||
"@jupyterlab/testutils": "^3.0.0-rc.10",
|
||||
"@types/jest": "^26.0.10",
|
||||
"jest": "^26.4.2",
|
||||
"rimraf": "~3.0.0",
|
||||
"ts-jest": "^26.3.0",
|
||||
"typescript": "~4.0.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,129 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import {
|
||||
JupyterFrontEnd,
|
||||
JupyterFrontEndPlugin
|
||||
} from '@jupyterlab/application';
|
||||
|
||||
import { PageConfig } from '@jupyterlab/coreutils';
|
||||
|
||||
import { IClassicShell, ClassicShell } from './shell';
|
||||
|
||||
/**
|
||||
* App is the main application class. It is instantiated once and shared.
|
||||
*/
|
||||
export class App extends JupyterFrontEnd<IClassicShell> {
|
||||
/**
|
||||
* Construct a new App object.
|
||||
*
|
||||
* @param options The instantiation options for an application.
|
||||
*/
|
||||
constructor(options: App.IOptions = { shell: new ClassicShell() }) {
|
||||
super({
|
||||
shell: options.shell
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the application.
|
||||
*/
|
||||
readonly name = 'JupyterLab Custom App';
|
||||
|
||||
/**
|
||||
* A namespace/prefix plugins may use to denote their provenance.
|
||||
*/
|
||||
readonly namespace = this.name;
|
||||
|
||||
/**
|
||||
* The version of the application.
|
||||
*/
|
||||
readonly version = 'unknown';
|
||||
|
||||
/**
|
||||
* The JupyterLab application paths dictionary.
|
||||
*/
|
||||
get paths(): JupyterFrontEnd.IPaths {
|
||||
return {
|
||||
urls: {
|
||||
base: PageConfig.getOption('baseUrl'),
|
||||
notFound: PageConfig.getOption('notFoundUrl'),
|
||||
app: PageConfig.getOption('appUrl'),
|
||||
static: PageConfig.getOption('staticUrl'),
|
||||
settings: PageConfig.getOption('settingsUrl'),
|
||||
themes: PageConfig.getOption('themesUrl'),
|
||||
doc: PageConfig.getOption('docUrl'),
|
||||
translations: PageConfig.getOption('translationsApiUrl'),
|
||||
hubHost: PageConfig.getOption('hubHost') || undefined,
|
||||
hubPrefix: PageConfig.getOption('hubPrefix') || undefined,
|
||||
hubUser: PageConfig.getOption('hubUser') || undefined,
|
||||
hubServerName: PageConfig.getOption('hubServerName') || undefined
|
||||
},
|
||||
directories: {
|
||||
appSettings: PageConfig.getOption('appSettingsDir'),
|
||||
schemas: PageConfig.getOption('schemasDir'),
|
||||
static: PageConfig.getOption('staticDir'),
|
||||
templates: PageConfig.getOption('templatesDir'),
|
||||
themes: PageConfig.getOption('themesDir'),
|
||||
userSettings: PageConfig.getOption('userSettingsDir'),
|
||||
serverRoot: PageConfig.getOption('serverRoot'),
|
||||
workspaces: PageConfig.getOption('workspacesDir')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugins from a plugin module.
|
||||
*
|
||||
* @param mod - The plugin module to register.
|
||||
*/
|
||||
registerPluginModule(mod: App.IPluginModule): void {
|
||||
let data = mod.default;
|
||||
// Handle commonjs exports.
|
||||
if (!Object.prototype.hasOwnProperty.call(mod, '__esModule')) {
|
||||
data = mod as any;
|
||||
}
|
||||
if (!Array.isArray(data)) {
|
||||
data = [data];
|
||||
}
|
||||
data.forEach(item => {
|
||||
try {
|
||||
this.registerPlugin(item);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the plugins from multiple plugin modules.
|
||||
*
|
||||
* @param mods - The plugin modules to register.
|
||||
*/
|
||||
registerPluginModules(mods: App.IPluginModule[]): void {
|
||||
mods.forEach(mod => {
|
||||
this.registerPluginModule(mod);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace for App statics.
|
||||
*/
|
||||
export namespace App {
|
||||
/**
|
||||
* The instantiation options for an App application.
|
||||
*/
|
||||
export type IOptions = JupyterFrontEnd.IOptions<IClassicShell>;
|
||||
|
||||
/**
|
||||
* The interface for a module that exports a plugin or plugins as
|
||||
* the default value.
|
||||
*/
|
||||
export interface IPluginModule {
|
||||
/**
|
||||
* The default export.
|
||||
*/
|
||||
default: JupyterFrontEndPlugin<any> | JupyterFrontEndPlugin<any>[];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
export * from './app';
|
||||
export * from './shell';
|
||||
@ -0,0 +1,237 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import { JupyterFrontEnd } from '@jupyterlab/application';
|
||||
|
||||
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
||||
|
||||
import { ArrayExt, IIterator, iter } from '@lumino/algorithm';
|
||||
import { Token } from '@lumino/coreutils';
|
||||
|
||||
import { Message, MessageLoop, IMessageHandler } from '@lumino/messaging';
|
||||
|
||||
import { ISignal, Signal } from '@lumino/signaling';
|
||||
|
||||
import { Panel, Widget, BoxLayout } from '@lumino/widgets';
|
||||
|
||||
/**
|
||||
* The JupyterLab Classic application shell token.
|
||||
*/
|
||||
export const IClassicShell = new Token<IClassicShell>(
|
||||
'@jupyterlab-classic/application:IClassicShell'
|
||||
);
|
||||
|
||||
/**
|
||||
* The JupyterLab Classic application shell interface.
|
||||
*/
|
||||
export interface IClassicShell extends ClassicShell {}
|
||||
|
||||
/**
|
||||
* The default rank for ranked panels.
|
||||
*/
|
||||
const DEFAULT_RANK = 900;
|
||||
|
||||
/**
|
||||
* The application shell.
|
||||
*/
|
||||
export class ClassicShell extends Widget implements JupyterFrontEnd.IShell {
|
||||
constructor() {
|
||||
super();
|
||||
this.id = 'main';
|
||||
|
||||
const rootLayout = new BoxLayout();
|
||||
|
||||
this._topHandler = new Private.PanelHandler();
|
||||
this._menu = new Panel();
|
||||
this._main = new Panel();
|
||||
|
||||
this._topHandler.panel.id = 'top-panel';
|
||||
this._menu.id = 'menu-panel';
|
||||
this._main.id = 'main-panel';
|
||||
|
||||
BoxLayout.setStretch(this._topHandler.panel, 0);
|
||||
BoxLayout.setStretch(this._menu, 0);
|
||||
BoxLayout.setStretch(this._main, 1);
|
||||
|
||||
const spacer = new Widget();
|
||||
spacer.node.style.minHeight = '16px';
|
||||
|
||||
rootLayout.spacing = 0;
|
||||
rootLayout.addWidget(this._topHandler.panel);
|
||||
rootLayout.addWidget(this._menu);
|
||||
rootLayout.addWidget(spacer);
|
||||
rootLayout.addWidget(this._main);
|
||||
|
||||
this.layout = rootLayout;
|
||||
}
|
||||
|
||||
activateById(id: string): void {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a widget to the application shell.
|
||||
*
|
||||
* @param widget - The widget being added.
|
||||
*
|
||||
* @param area - Optional region in the shell into which the widget should
|
||||
* be added.
|
||||
*
|
||||
* @param options - Optional open options.
|
||||
*
|
||||
*/
|
||||
add(
|
||||
widget: Widget,
|
||||
area?: Shell.Area,
|
||||
options?: DocumentRegistry.IOpenOptions
|
||||
): void {
|
||||
if (area === 'top') {
|
||||
const rank = options?.rank ?? DEFAULT_RANK;
|
||||
return this._topHandler.addWidget(widget, rank);
|
||||
}
|
||||
if (area === 'menu') {
|
||||
return this._menu.addWidget(widget);
|
||||
}
|
||||
this._main.widgets.forEach(w => {
|
||||
w.close();
|
||||
});
|
||||
this._main.addWidget(widget);
|
||||
this._main.update();
|
||||
this._currentChanged.emit(void 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* A signal emitted when the current widget changes.
|
||||
*/
|
||||
get currentChanged(): ISignal<ClassicShell, void> {
|
||||
return this._currentChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current widget in the shell's main area.
|
||||
*/
|
||||
get currentWidget(): Widget {
|
||||
return this._main.widgets[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of widgets for the given area.
|
||||
*
|
||||
* @param area The area
|
||||
*/
|
||||
widgets(area: Shell.Area): IIterator<Widget> {
|
||||
if (area === 'top') {
|
||||
return iter(this._topHandler.panel.widgets);
|
||||
}
|
||||
if (area === 'menu') {
|
||||
return iter(this._menu.widgets);
|
||||
}
|
||||
return iter(this._main.widgets);
|
||||
}
|
||||
|
||||
private _topHandler: Private.PanelHandler;
|
||||
private _menu: Panel;
|
||||
private _main: Panel;
|
||||
private _currentChanged = new Signal<this, void>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace for Shell statics
|
||||
*/
|
||||
export namespace Shell {
|
||||
/**
|
||||
* The areas of the application shell where widgets can reside.
|
||||
*/
|
||||
export type Area = 'main' | 'top' | 'menu';
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace for private module data.
|
||||
*/
|
||||
namespace Private {
|
||||
/**
|
||||
* An object which holds a widget and its sort rank.
|
||||
*/
|
||||
export interface IRankItem {
|
||||
/**
|
||||
* The widget for the item.
|
||||
*/
|
||||
widget: Widget;
|
||||
|
||||
/**
|
||||
* The sort rank of the widget.
|
||||
*/
|
||||
rank: number;
|
||||
}
|
||||
/**
|
||||
* A less-than comparison function for side bar rank items.
|
||||
*/
|
||||
export function itemCmp(first: IRankItem, second: IRankItem): number {
|
||||
return first.rank - second.rank;
|
||||
}
|
||||
|
||||
/**
|
||||
* A class which manages a panel and sorts its widgets by rank.
|
||||
*/
|
||||
export class PanelHandler {
|
||||
constructor() {
|
||||
MessageLoop.installMessageHook(this._panel, this._panelChildHook);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the panel managed by the handler.
|
||||
*/
|
||||
get panel(): Panel {
|
||||
return this._panel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a widget to the panel.
|
||||
*
|
||||
* If the widget is already added, it will be moved.
|
||||
*/
|
||||
addWidget(widget: Widget, rank: number): void {
|
||||
widget.parent = null;
|
||||
const item = { widget, rank };
|
||||
const index = ArrayExt.upperBound(this._items, item, Private.itemCmp);
|
||||
ArrayExt.insert(this._items, index, item);
|
||||
this._panel.insertWidget(index, widget);
|
||||
}
|
||||
|
||||
/**
|
||||
* A message hook for child add/remove messages on the main area dock panel.
|
||||
*/
|
||||
private _panelChildHook = (
|
||||
handler: IMessageHandler,
|
||||
msg: Message
|
||||
): boolean => {
|
||||
switch (msg.type) {
|
||||
case 'child-added':
|
||||
{
|
||||
const widget = (msg as Widget.ChildMessage).child;
|
||||
// If we already know about this widget, we're done
|
||||
if (this._items.find(v => v.widget === widget)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, add to the end by default
|
||||
const rank = this._items[this._items.length - 1].rank;
|
||||
this._items.push({ widget, rank });
|
||||
}
|
||||
break;
|
||||
case 'child-removed':
|
||||
{
|
||||
const widget = (msg as Widget.ChildMessage).child;
|
||||
ArrayExt.removeFirstWhere(this._items, v => v.widget === widget);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
private _items = new Array<Private.IRankItem>();
|
||||
private _panel = new Panel();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
| Copyright (c) Jupyter Development Team.
|
||||
| Distributed under the terms of the Modified BSD License.
|
||||
|----------------------------------------------------------------------------*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: var(--jp-layout-color2);
|
||||
}
|
||||
|
||||
#main {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
#top-panel {
|
||||
display: flex;
|
||||
border-bottom: var(--jp-border-width) solid var(--jp-border-color0);
|
||||
background: var(--jp-layout-color1);
|
||||
min-height: calc(1.5 * var(--jp-private-menubar-height));
|
||||
}
|
||||
|
||||
#menu-panel {
|
||||
display: flex;
|
||||
min-height: var(--jp-private-menu-panel-height);
|
||||
background: var(--jp-layout-color1);
|
||||
border-bottom: var(--jp-border-width) solid var(--jp-border-color0);
|
||||
box-shadow: var(--jp-elevation-z1);
|
||||
}
|
||||
|
||||
#main-panel {
|
||||
box-shadow: var(--jp-elevation-z4);
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
| Copyright (c) Jupyter Development Team.
|
||||
| Distributed under the terms of the Modified BSD License.
|
||||
|----------------------------------------------------------------------------*/
|
||||
|
||||
@import url('~@jupyterlab/application/style/index.css');
|
||||
@import url('~@jupyterlab/mainmenu/style/index.css');
|
||||
@import url('~@jupyterlab/ui-components/style/index.css');
|
||||
|
||||
@import url('./base.css');
|
||||
@ -0,0 +1,13 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import { Shell } from '@jupyterlab-classic/application';
|
||||
|
||||
describe('Shell', () => {
|
||||
describe('#constructor()', () => {
|
||||
it('should create a LabShell instance', () => {
|
||||
const shell = new Shell();
|
||||
expect(shell).toBeInstanceOf(Shell);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfigbase",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfigbase.test",
|
||||
"include": ["src/**/*", "test/**/*"],
|
||||
"references": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
module.exports = require('@jupyterlab/testutils/lib/babel.config');
|
||||
@ -0,0 +1,2 @@
|
||||
const func = require('@jupyterlab/testutils/lib/jest-config');
|
||||
module.exports = func(__dirname);
|
||||
@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "@jupyterlab-classic/ui-components",
|
||||
"version": "0.1.0",
|
||||
"description": "JupyterLab Classic - UI components",
|
||||
"homepage": "https://github.com/jtpio/jupyterlab-classic",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jtpio/jupyterlab-classic/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jtpio/jupyterlab-classic.git"
|
||||
},
|
||||
"license": "BSD-3-Clause",
|
||||
"author": "Project Jupyter",
|
||||
"sideEffects": [
|
||||
"style/**/*"
|
||||
],
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"style": "style/index.css",
|
||||
"directories": {
|
||||
"lib": "lib/"
|
||||
},
|
||||
"files": [
|
||||
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
|
||||
"style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"build:test": "tsc --build tsconfig.test.json",
|
||||
"clean": "rimraf lib && rimraf tsconfig.tsbuildinfo",
|
||||
"cleansvg": "svgo --config svgo.yaml",
|
||||
"docs": "typedoc src",
|
||||
"docs:init": "bash docs/build.sh",
|
||||
"prepublishOnly": "npm run build",
|
||||
"storybook": "start-storybook -p 9001 -c .storybook",
|
||||
"test": "jest",
|
||||
"test:cov": "jest --collect-coverage",
|
||||
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
|
||||
"test:debug:watch": "node --inspect-brk node_modules/.bin/jest --runInBand --watch",
|
||||
"watch": "tsc -b --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jupyterlab/ui-components": "^3.0.0-rc.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.2",
|
||||
"@babel/preset-env": "^7.10.2",
|
||||
"@jupyterlab/testutils": "^3.0.0-rc.10",
|
||||
"@types/jest": "^26.0.10",
|
||||
"babel-loader": "^8.0.6",
|
||||
"jest": "^26.4.2",
|
||||
"rimraf": "~3.0.0",
|
||||
"ts-jest": "^26.3.0",
|
||||
"typescript": "~4.0.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
| Copyright (c) Jupyter Development Team.
|
||||
| Distributed under the terms of the Modified BSD License.
|
||||
|----------------------------------------------------------------------------*/
|
||||
|
||||
import { LabIcon } from '@jupyterlab/ui-components';
|
||||
|
||||
import jupyterSvgstr from '../../style/icons/jupyter.svg';
|
||||
|
||||
export const jupyterIcon = new LabIcon({
|
||||
name: 'classic-ui-components:jupyter',
|
||||
svgstr: jupyterSvgstr
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
export * from './iconimports';
|
||||
@ -0,0 +1,4 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
export * from './icon';
|
||||
@ -0,0 +1,7 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
declare module '*.svg' {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
|
After Width: | Height: | Size: 9.8 KiB |
@ -0,0 +1,6 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
| Copyright (c) Jupyter Development Team.
|
||||
| Distributed under the terms of the Modified BSD License.
|
||||
|----------------------------------------------------------------------------*/
|
||||
|
||||
@import url('./base.css');
|
||||
@ -0,0 +1,10 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
describe('foo', () => {
|
||||
describe('bar', () => {
|
||||
it('should pass', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfigbase",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfigbase.test",
|
||||
"include": ["src/**/*", "test/**/*"],
|
||||
"references": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
[build-system]
|
||||
requires = ["jupyter_packaging~=0.7.0", "jupyterlab>=3.0.0rc10,==3.*", "setuptools>=40.8.0", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
@ -0,0 +1,59 @@
|
||||
"""
|
||||
jupyterlab-classic setup
|
||||
"""
|
||||
import os
|
||||
|
||||
from jupyter_packaging import get_version
|
||||
import setuptools
|
||||
|
||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
# The name of the project
|
||||
NAME = "jupyterlab-classic"
|
||||
PACKAGE_NAME = NAME.replace("-", "_")
|
||||
|
||||
# Get our version
|
||||
version = get_version(os.path.join(PACKAGE_NAME, "_version.py"))
|
||||
|
||||
with open("README.md", "r") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
setup_args = dict(
|
||||
name=NAME,
|
||||
version=version,
|
||||
url="https://github.com/jtpio/jupyterlab-classic",
|
||||
author="Jeremy Tuloup",
|
||||
description="The next gen old-school Notebook UI",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
data_files=[
|
||||
(
|
||||
"etc/jupyter/jupyter_server_config.d",
|
||||
["jupyter-config/jupyter_server_config.d/jupyterlab_classic.json"],
|
||||
),
|
||||
],
|
||||
packages=setuptools.find_packages(),
|
||||
install_requires=[
|
||||
"jupyterlab>=3.0.0rc10,==3.*",
|
||||
],
|
||||
zip_safe=False,
|
||||
include_package_data=True,
|
||||
python_requires=">=3.6",
|
||||
license="BSD-3-Clause",
|
||||
platforms="Linux, Mac OS X, Windows",
|
||||
keywords=["Jupyter", "JupyterLab", "Notebook"],
|
||||
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",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
setuptools.setup(**setup_args)
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "./tsconfigbase",
|
||||
"include": ["packages/**/*", "builder/**/*"],
|
||||
"types": ["jest"]
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"noEmitOnError": true,
|
||||
"noUnusedLocals": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es2015",
|
||||
"lib": [
|
||||
"es2015",
|
||||
"es2015.collection",
|
||||
"dom",
|
||||
"es2015.iterable",
|
||||
"es2017.object"
|
||||
],
|
||||
"types": ["jest"],
|
||||
"jsx": "react",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
{
|
||||
"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,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
"target": "es2017",
|
||||
"types": []
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"noImplicitAny": true,
|
||||
"noEmitOnError": true,
|
||||
"noUnusedLocals": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es2015",
|
||||
"outDir": "lib",
|
||||
"lib": [
|
||||
"es2015",
|
||||
"es2015.collection",
|
||||
"dom",
|
||||
"es2015.iterable",
|
||||
"es2017.object"
|
||||
],
|
||||
"types": ["jest", "node"],
|
||||
"jsx": "react",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"strictNullChecks": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue