diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index e651ab2..f223fe1 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -39,5 +39,6 @@ jobs:
run: |
source "$CONDA/etc/profile.d/conda.sh"
conda activate jupyterlab-module-federation
+ pip install jupyterlab==2.1.5
python run.py
diff --git a/.gitignore b/.gitignore
index fc7225e..2302e97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,3 @@ stats.json
node_modules
core_package/build
md_package/build
-log.json
diff --git a/build-ext.js b/build-ext.js
index aa42959..fa26df1 100644
--- a/build-ext.js
+++ b/build-ext.js
@@ -36,7 +36,9 @@ commander
const webpack = require.resolve('webpack-cli');
let cmdText = `${webpack} --config webpack.config.ext.js`;
- run(cmdText, { env: { ...process.env, OUTPUT_PATH: output, PACKAGE_PATH: packagePath, NODE_ENV: node_env } });
+ const env = { OUTPUT_PATH: output, PACKAGE_PATH: packagePath, NODE_ENV: node_env };
+ console.log(env);
+ run(cmdText, { env: { ...process.env, ...env } });
}
);
diff --git a/core_package/package.json b/core_package/package.json
index 445d6c6..2d8ab94 100644
--- a/core_package/package.json
+++ b/core_package/package.json
@@ -54,7 +54,6 @@
"@jupyterlab/logconsole-extension": "~3.0.0-alpha.4",
"@jupyterlab/mainmenu": "~3.0.0-alpha.4",
"@jupyterlab/mainmenu-extension": "~3.0.0-alpha.4",
- "@jupyterlab/markdownviewer": "~3.0.0-alpha.4",
"@jupyterlab/mathjax2": "~3.0.0-alpha.4",
"@jupyterlab/mathjax2-extension": "~3.0.0-alpha.4",
"@jupyterlab/metapackage": "~3.0.0-alpha.4",
@@ -145,7 +144,6 @@
"@jupyterlab/launcher",
"@jupyterlab/logconsole",
"@jupyterlab/mainmenu",
- "@jupyterlab/markdownviewer",
"@jupyterlab/notebook",
"@jupyterlab/rendermime",
"@jupyterlab/rendermime-interfaces",
diff --git a/main.py b/main.py
index fdaa254..2e8dc15 100644
--- a/main.py
+++ b/main.py
@@ -3,6 +3,7 @@
from jupyterlab_server import LabServerApp, LabConfig
from jupyterlab_server.server import FileFindHandler, APIHandler
+
from notebook.utils import url_path_join as ujoin, url_escape
import json
import os
@@ -10,7 +11,7 @@
from tornado.web import StaticFileHandler
-HERE = os.path.dirname(__file__)
+HERE = os.path.abspath(os.path.dirname(__file__))
# Turn off the Jupyter configuration system so configuration files on disk do
# not affect this app. This helps this app to truly be standalone.
@@ -24,10 +25,24 @@ class SettingHandler(APIHandler):
def get(self, schema_name=""):
path = os.path.join(HERE, 'node_modules/@jupyterlab/markdownviewer-extension/schema/plugin.json')
+
with open(path) as fid:
- data = fid.read()
- return self.finish(data)
+ schema = fid.read()
+
+ # copy-pasta of typical response for now.
+ result = {"id":"@jupyterlab/markdownviewer-extension:plugin","raw":"{}","schema":{"jupyter.lab.setting-icon":"ui-components:markdown","jupyter.lab.setting-icon-label":"Markdown Viewer","title":"Markdown Viewer","description":"Markdown viewer settings.","definitions":{"fontFamily":{"type":["string","null"]},"fontSize":{"type":["integer","null"],"minimum":1,"maximum":100},"lineHeight":{"type":["number","null"]},"lineWidth":{"type":["number","null"]},"hideFrontMatter":{"type":"boolean"},"renderTimeout":{"type":"number"}},"properties":{"fontFamily":{"title":"Font Family","description":"The font family used to render markdown.\nIf `null`, value from current theme is used.","$ref":"#/definitions/fontFamily","default":None},"fontSize":{"title":"Font Size","description":"The size in pixel of the font used to render markdown.\nIf `null`, value from current theme is used.","$ref":"#/definitions/fontSize","default":None},"lineHeight":{"title":"Line Height","description":"The line height used to render markdown.\nIf `null`, value from current theme is used.","$ref":"#/definitions/lineHeight","default":None},"lineWidth":{"title":"Line Width","description":"The text line width expressed in CSS ch units.\nIf `null`, lines fit the viewport width.","$ref":"#/definitions/lineWidth","default":None},"hideFrontMatter":{"title":"Hide Front Matter","description":"Whether to hide YAML front matter.\nThe YAML front matter must be placed at the top of the document,\nstarted by a line of three dashes (---) and ended by a line of\nthree dashes (---) or three points (...).","$ref":"#/definitions/hideFrontMatter","default":True},"renderTimeout":{"title":"Render Timeout","description":"The render timeout in milliseconds.","$ref":"#/definitions/renderTimeout","default":1000}},"additionalProperties":False,"type":"object"},"settings":{},"version":"2.2.0"}
+
+ return self.finish(result)
+
+class ExtensionHandler(FileFindHandler):
+
+ def get(self, path):
+ extname, _, rest = path.partition('/')
+ dirname = 'md_package' if extname == 'example-federated-md' else 'middle_package'
+ path = os.path.join(dirname, 'build', rest)
+ return super().get(path)
+
class ExampleApp(LabServerApp):
base_url = '/foo'
@@ -53,11 +68,9 @@ def init_webapp(self):
# Handle md ext assets
web_app = self.web_app
base_url = web_app.settings['base_url']
- static_path = ujoin(base_url, 'example', 'labextensions', '@jupyterlab', 'example-federated-md', '(.*)')
- static_dir = os.path.join(HERE, 'md_package', 'build')
- web_app.add_handlers('.*$', [(static_path, FileFindHandler, {
- 'path': static_dir,
- })])
+
+ static_path = ujoin(base_url, 'example', 'labextensions', '@jupyterlab', '(.*)')
+ web_app.add_handlers('.*$', [(static_path, ExtensionHandler, { 'path': HERE })])
## Handle the specific setting
static_path = ujoin(base_url, 'example', 'api', 'settings', '@jupyterlab', '(.*)')
diff --git a/md_package/index.js b/md_package/index.js
index e1be0d5..fa2c550 100644
--- a/md_package/index.js
+++ b/md_package/index.js
@@ -31,8 +31,9 @@ const plugin = {
/**
* Activate the markdown viewer plugin.
*/
-function activate(app, restorer, rendermime, settingRegistry) {
+function activate(app, restorer, rendermime, settingRegistry, middleToken) {
const { commands, docRegistry } = app;
+
// Add the markdown renderer factory.
rendermime.addFactory(markdownRendererFactory);
const namespace = 'markdownviewer-widget';
diff --git a/md_package/package.json b/md_package/package.json
index e223ce8..58e351d 100644
--- a/md_package/package.json
+++ b/md_package/package.json
@@ -10,6 +10,7 @@
"@jupyterlab/application": "^3.0.0-alpha.4",
"@jupyterlab/apputils": "^3.0.0-alpha.4",
"@jupyterlab/coreutils": "^5.0.0-alpha.4",
+ "@jupyterlab/example-federated-middle": "~2.1.0",
"@jupyterlab/markdownviewer": "^3.0.0-alpha.4",
"@jupyterlab/rendermime": "^3.0.0-alpha.4",
"@jupyterlab/settingregistry": "^3.0.0-alpha.4"
@@ -24,6 +25,7 @@
},
"jupyterlab": {
"extension": true,
- "schemaDir": "schema"
+ "schemaDir": "schema",
+ "singletonPackages": ["@jupyterlab/example-federated-middle"]
}
}
diff --git a/middle_package/extension.js b/middle_package/extension.js
new file mode 100644
index 0000000..432de3e
--- /dev/null
+++ b/middle_package/extension.js
@@ -0,0 +1,12 @@
+const IMiddleToken = require('./index').IMiddleToken;
+
+module.exports = [{
+ id: '@jupyterlab/example-federated-middle',
+ autoStart: true,
+ provides: IMiddleToken,
+ activate: function (app) {
+ console.log('JupyterLab extension middle is activated!');
+ console.log(app.commands);
+ return 'hello';
+ }
+}];
diff --git a/middle_package/index.js b/middle_package/index.js
new file mode 100644
index 0000000..07312d0
--- /dev/null
+++ b/middle_package/index.js
@@ -0,0 +1,11 @@
+// Need a token here
+
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+import { Token } from '@lumino/coreutils';
+/* tslint:disable */
+/**
+ * The path tracker token.
+ */
+export const IMiddleToken = new Token('@jupyterlab/example-federated-middle2');
+//# sourceMappingURL=tokens.js.map
diff --git a/middle_package/package.json b/middle_package/package.json
new file mode 100644
index 0000000..0557a0c
--- /dev/null
+++ b/middle_package/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@jupyterlab/example-federated-middle",
+ "version": "2.1.0",
+ "private": true,
+ "scripts": {
+ "prepublishOnly": "npm run build",
+ "watch": "npm run clean && webpack --watch"
+ },
+ "dependencies": {
+ "@jupyterlab/coreutils": "^5.0.0-alpha.4"
+ },
+ "devDependencies": {
+ "rimraf": "~3.0.0",
+ "typedoc": "^0.17.7",
+ "typescript": "~3.9.2"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "jupyterlab": {
+ "extension": "./extension.js",
+ "schemaDir": "schema"
+ }
+}
diff --git a/package.json b/package.json
index 82fb0bf..f5c7e0c 100644
--- a/package.json
+++ b/package.json
@@ -3,12 +3,14 @@
"version": "2.1.0",
"private": true,
"scripts": {
- "build": "npm run build:core && npm run build:ext",
+ "build": "npm run build:core && npm run build:middle && npm run build:md",
"build:core": "cd core_package && npm run build",
- "build:ext": "node build-ext.js ./md_package",
+ "build:middle": "node build-ext.js ./middle_package",
+ "build:md": "node build-ext.js ./md_package",
"clean:core": "cd core_package && npm run clean",
- "clean:ext": "rimraf md_package/build",
- "clean": "npm run clean:ext && npm run clean:core"
+ "clean:md": "rimraf md_package/build",
+ "clean:middle": "rimraf middle_package/build",
+ "clean": "npm run clean:md && npm run clean:middle && npm run clean:core"
},
"devDependencies": {
"rimraf": "^3.0.2",
diff --git a/templates/index.html b/templates/index.html
index a1202b9..f8b4494 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -16,7 +16,8 @@
diff --git a/webpack.config.ext.js b/webpack.config.ext.js
index 879abf2..d60e963 100644
--- a/webpack.config.ext.js
+++ b/webpack.config.ext.js
@@ -67,15 +67,17 @@ const extras = Build.ensureAssets({
output: outputPath
});
-let entryPoint = data.jupyterlab.extension ?? data.jupyterlab.mimeExtension;
-
- if (entryPoint === true) {
- // Use require to get the entry point
- entryPoint = require.resolve(packagePath);
- } else {
- // Use the path to get the entry point
- entryPoint = path.join(packagePath, entryPoint);
- }
+// Handle the extension entry point and the lib entry point, if different
+let extPath = data.jupyterlab.extension ?? data.jupyterlab.mimeExtension;
+const index = require.resolve(packagePath);
+const exposes = {
+ './index': index,
+ './extension': index
+}
+
+if (extPath !== true) {
+ exposes['./extension'] = path.join(packagePath, extPath);
+}
const coreData = require('./core_package/package.json');
@@ -97,7 +99,7 @@ Object.keys(data.dependencies).forEach((element) => {
// Remove non-shared.
data.jupyterlab.nonSharedPackages?.forEach((element) => {
delete shared[element];
- });
+});
// Start with core singletons.
coreData.jupyterlab.singletonPackages.forEach((element) => {
@@ -113,7 +115,7 @@ data.jupyterlab.singletonPackages?.forEach((element) => {
if (!shared[element]) {
shared[element] = {};
}
- shared[element].singleton = true;
+ shared[element].import = false;
});
// Remove non-singletons.
@@ -126,6 +128,12 @@ data.jupyterlab.nonSingletonPackages?.forEach((element) => {
// Ensure a clean output directory.
fs.rmdirSync(outputPath, { recursive: true });
+fs.mkdirSync(outputPath);
+
+// Make a bootstrap entrypoint
+const entryPoint = path.join(outputPath, 'bootstrap.js');
+const bootstrap = 'import("' + exposes['./extension'] + '");'
+fs.writeFileSync(entryPoint, bootstrap);
module.exports = [
{
@@ -146,9 +154,7 @@ module.exports = [
name: ['_JUPYTERLAB', data.name]
},
filename: 'remoteEntry.js',
- exposes: {
- './index': entryPoint
- },
+ exposes,
shared,
}),
new webpack.DefinePlugin({
@@ -159,6 +165,5 @@ module.exports = [
}
].concat(extras);
-// TODO: remove debug log
-// console.log(module.exports);
-fs.writeFileSync('log.json', JSON.stringify(module.exports, null, ' '));
+const logPath = path.join(outputPath, 'build_log.json');
+fs.writeFileSync(logPath, JSON.stringify(module.exports, null, ' '));