Skip to content

Commit 73512c1

Browse files
Lite deployment in doc (#162)
* Add a very simple extension in docs * First try to build lite in docs * Add the jupyterlite_sphinx extension * use pyodide kernel instead of xeus * Replace embedded lite with a button * Improve the example extension, add a readme and rename the build script * Move the example .ipynb in a sub-directory of the lite build directory * Avoid building/installing the extension from docs in regular build/installation * try removing the README from built lite * Move the README at the root of the build directory * Mimic the button from Jupytergis doc * Automatic application of license header * Add settings * Fix link --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent be22aa3 commit 73512c1

File tree

20 files changed

+604
-14
lines changed

20 files changed

+604
-14
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ labextension
1212

1313
# Version file is handled by hatchling
1414
python/**/_version.py
15+
docs/**/_version.py
1516

1617
# jest test reports
1718
packages/jupyter-chat/junit.xml

.readthedocs.yaml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44
version: 2
55

66
build:
7-
os: ubuntu-22.04
7+
os: ubuntu-24.04
88
tools:
9-
python: "3.11"
10-
nodejs: "18"
9+
python: "3.12"
10+
nodejs: "20"
11+
12+
jobs:
13+
pre_build:
14+
- /bin/bash -c "jlpm install && jlpm build:lite-docs"
15+
- /bin/bash -c "pip install docs/jupyter-chat-example"
1116

1217
# Build documentation in the docs/ directory with Sphinx
1318
sphinx:

docs/jupyter-chat-example/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# jupyter-chat-example
2+
3+
A simple extension providing a chat side bar.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"packageManager": "python",
3+
"packageName": "jupyter_chat_example",
4+
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlab_chat"
5+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright (c) Jupyter Development Team.
2+
# Distributed under the terms of the Modified BSD License.
3+
4+
try:
5+
from ._version import __version__
6+
except ImportError:
7+
# Fallback when using the package in dev mode without installing
8+
# in editable mode with pip. It is highly recommended to install
9+
# the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs
10+
import warnings
11+
warnings.warn("Importing 'jupyter-chat-example' outside a proper installation.")
12+
__version__ = "dev"
13+
14+
15+
def _jupyter_labextension_paths():
16+
return [{
17+
"src": "labextension",
18+
"dest": "jupyter-chat-example"
19+
}]
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
"name": "jupyter-chat-example",
3+
"version": "1.0.0",
4+
"description": "A chat extension providing a chat as example",
5+
"keywords": [
6+
"jupyter",
7+
"jupyterlab",
8+
"jupyterlab-extension"
9+
],
10+
"homepage": "https://github.com/jupyterlab/jupyter-chat",
11+
"bugs": {
12+
"url": "https://github.com/jupyterlab/jupyter-chat/issues"
13+
},
14+
"license": "BSD-3-Clause",
15+
"author": {
16+
"name": "Jupyter Development Team",
17+
"email": "[email protected]"
18+
},
19+
"files": [
20+
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
21+
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
22+
"src/**/*.{ts,tsx}",
23+
"schema/*.json"
24+
],
25+
"main": "lib/index.js",
26+
"types": "lib/index.d.ts",
27+
"style": "style/index.css",
28+
"repository": {
29+
"type": "git",
30+
"url": "https://github.com/jupyterlab/jupyter-chat.git"
31+
},
32+
"scripts": {
33+
"build": "jlpm build:lib && jlpm build:labextension:dev",
34+
"build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
35+
"build:labextension": "jupyter labextension build .",
36+
"build:labextension:dev": "jupyter labextension build --development True .",
37+
"build:lib": "tsc --sourceMap",
38+
"build:lib:prod": "tsc",
39+
"clean": "jlpm clean:lib",
40+
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
41+
"clean:lintcache": "rimraf .eslintcache .stylelintcache",
42+
"clean:labextension": "rimraf jupyterlab_chat/labextension jupyterlab_chat/_version.py",
43+
"clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache",
44+
"install:extension": "jlpm build"
45+
},
46+
"dependencies": {
47+
"@jupyter/chat": "^0.7.1",
48+
"@jupyterlab/application": "^4.2.0",
49+
"@jupyterlab/apputils": "^4.3.0",
50+
"@jupyterlab/notebook": "^4.2.0",
51+
"@jupyterlab/rendermime": "^4.2.0",
52+
"@jupyterlab/settingregistry": "^4.2.0",
53+
"@lumino/coreutils": "^2.0.0"
54+
},
55+
"devDependencies": {
56+
"@jupyterlab/builder": "^4.2.0",
57+
"@types/json-schema": "^7.0.11",
58+
"@types/react": "^18.2.0",
59+
"@types/react-addons-linked-state-mixin": "^0.14.22",
60+
"css-loader": "^6.7.1",
61+
"mkdirp": "^1.0.3",
62+
"npm-run-all": "^4.1.5",
63+
"rimraf": "^5.0.1",
64+
"source-map-loader": "^1.0.2",
65+
"style-loader": "^3.3.1",
66+
"typescript": "~5.0.2"
67+
},
68+
"sideEffects": [
69+
"style/*.css",
70+
"style/index.js"
71+
],
72+
"styleModule": "style/index.js",
73+
"publishConfig": {
74+
"access": "public"
75+
},
76+
"jupyterlab": {
77+
"discovery": {
78+
"server": {
79+
"managers": [
80+
"pip"
81+
],
82+
"base": {
83+
"name": "jupyter_chat_example"
84+
}
85+
}
86+
},
87+
"extension": true,
88+
"outputDir": "jupyter_chat_example/labextension",
89+
"schemaDir": "schema",
90+
"sharedPackages": {
91+
"@jupyter/chat": {
92+
"bundled": true,
93+
"singleton": true
94+
}
95+
}
96+
}
97+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Copyright (c) Jupyter Development Team.
2+
# Distributed under the terms of the Modified BSD License.
3+
4+
[build-system]
5+
requires = ["hatchling>=1.5.0", "jupyterlab>=4.0.0,<5", "hatch-nodejs-version>=0.3.2"]
6+
build-backend = "hatchling.build"
7+
8+
[project]
9+
name = "jupyter-chat-example"
10+
readme = "README.md"
11+
license = { file = "../../LICENSE" }
12+
requires-python = ">=3.8"
13+
classifiers = [
14+
"Framework :: Jupyter",
15+
"Framework :: Jupyter :: JupyterLab",
16+
"Framework :: Jupyter :: JupyterLab :: 4",
17+
"Framework :: Jupyter :: JupyterLab :: Extensions",
18+
"Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt",
19+
"License :: OSI Approved :: BSD License",
20+
"Programming Language :: Python",
21+
"Programming Language :: Python :: 3",
22+
"Programming Language :: Python :: 3.8",
23+
"Programming Language :: Python :: 3.9",
24+
"Programming Language :: Python :: 3.10",
25+
"Programming Language :: Python :: 3.11",
26+
"Programming Language :: Python :: 3.12",
27+
]
28+
dependencies = []
29+
dynamic = ["version", "description", "authors", "urls", "keywords"]
30+
31+
[tool.hatch.version]
32+
source = "nodejs"
33+
34+
[tool.hatch.metadata.hooks.nodejs]
35+
fields = ["description", "authors", "urls"]
36+
37+
[tool.hatch.build.targets.wheel.shared-data]
38+
"jupyter_chat_example/labextension" = "share/jupyter/labextensions/jupyter-chat-example"
39+
"install.json" = "share/jupyter/labextensions/jupyter-chat-example/install.json"
40+
41+
[tool.hatch.build.hooks.version]
42+
path = "jupyter_chat_example/_version.py"
43+
44+
[tool.hatch.build.hooks.jupyter-builder]
45+
dependencies = ["hatch-jupyter-builder>=0.5"]
46+
build-function = "hatch_jupyter_builder.npm_builder"
47+
ensured-targets = [
48+
"jupyter_chat_example/labextension/static/style.js",
49+
"jupyter_chat_example/labextension/package.json",
50+
]
51+
skip-if-exists = ["jupyter_chat_example/labextension/static/style.js"]
52+
53+
[tool.hatch.build.hooks.jupyter-builder.build-kwargs]
54+
build_cmd = "build:prod"
55+
npm = ["jlpm"]
56+
57+
[tool.hatch.build.hooks.jupyter-builder.editable-build-kwargs]
58+
build_cmd = "install:extension"
59+
npm = ["jlpm"]
60+
source_dir = "src"
61+
build_dir = "jupyter_chat_example/labextension"
62+
63+
[tool.jupyter-releaser.hooks]
64+
before-build-npm = [
65+
"python -m pip install 'jupyterlab>=4.0.0,<5'",
66+
"jlpm",
67+
"jlpm build:prod"
68+
]
69+
before-build-python = ["jlpm clean:lib"]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"title": "Chat",
3+
"description": "Configuration for the chat widgets",
4+
"type": "object",
5+
"properties": {
6+
"sendWithShiftEnter": {
7+
"description": "Whether to send a message via Shift-Enter instead of Enter.",
8+
"type": "boolean",
9+
"default": false,
10+
"readOnly": false
11+
},
12+
"stackMessages": {
13+
"description": "Whether to stack consecutive messages from same user.",
14+
"type": "boolean",
15+
"default": true,
16+
"readOnly": false
17+
},
18+
"unreadNotifications": {
19+
"description": "Whether to enable or not the notifications on unread messages.",
20+
"type": "boolean",
21+
"default": true,
22+
"readOnly": false
23+
},
24+
"enableCodeToolbar": {
25+
"description": "Whether to enable or not the code toolbar.",
26+
"type": "boolean",
27+
"default": true,
28+
"readOnly": false
29+
}
30+
},
31+
"additionalProperties": false
32+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright (c) Jupyter Development Team.
3+
* Distributed under the terms of the Modified BSD License.
4+
*/
5+
6+
import {
7+
ActiveCellManager,
8+
buildChatSidebar,
9+
ChatModel,
10+
IChatMessage,
11+
INewMessage,
12+
SelectionWatcher
13+
} from '@jupyter/chat';
14+
import {
15+
JupyterFrontEnd,
16+
JupyterFrontEndPlugin
17+
} from '@jupyterlab/application';
18+
import { IThemeManager } from '@jupyterlab/apputils';
19+
import { INotebookTracker } from '@jupyterlab/notebook';
20+
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
21+
import { ISettingRegistry } from '@jupyterlab/settingregistry';
22+
import { UUID } from '@lumino/coreutils';
23+
24+
class MyChatModel extends ChatModel {
25+
sendMessage(
26+
newMessage: INewMessage
27+
): Promise<boolean | void> | boolean | void {
28+
console.log(`New Message:\n${newMessage.body}`);
29+
const message: IChatMessage = {
30+
body: newMessage.body,
31+
id: newMessage.id ?? UUID.uuid4(),
32+
type: 'msg',
33+
time: Date.now() / 1000,
34+
sender: { username: 'me' }
35+
};
36+
this.messageAdded(message);
37+
}
38+
}
39+
40+
/*
41+
* Extension providing a chat panel.
42+
*/
43+
const plugin: JupyterFrontEndPlugin<void> = {
44+
id: 'jupyter-chat-example:plugin',
45+
description: 'The chat panel widget.',
46+
autoStart: true,
47+
requires: [IRenderMimeRegistry],
48+
optional: [INotebookTracker, ISettingRegistry, IThemeManager],
49+
activate: (
50+
app: JupyterFrontEnd,
51+
rmRegistry: IRenderMimeRegistry,
52+
notebookTracker: INotebookTracker | null,
53+
settingRegistry: ISettingRegistry | null,
54+
themeManager: IThemeManager | null
55+
): void => {
56+
// Track the current active cell.
57+
let activeCellManager: ActiveCellManager | null = null;
58+
if (notebookTracker) {
59+
activeCellManager = new ActiveCellManager({
60+
tracker: notebookTracker,
61+
shell: app.shell
62+
});
63+
}
64+
65+
// Track the current selection.
66+
const selectionWatcher = new SelectionWatcher({
67+
shell: app.shell
68+
});
69+
70+
const model = new MyChatModel({ activeCellManager, selectionWatcher });
71+
72+
// Update the settings when they change.
73+
function loadSetting(setting: ISettingRegistry.ISettings): void {
74+
model.config = {
75+
sendWithShiftEnter: setting.get('sendWithShiftEnter')
76+
.composite as boolean,
77+
stackMessages: setting.get('stackMessages').composite as boolean,
78+
unreadNotifications: setting.get('unreadNotifications')
79+
.composite as boolean,
80+
enableCodeToolbar: setting.get('enableCodeToolbar').composite as boolean
81+
};
82+
}
83+
84+
// Init the settings.
85+
if (settingRegistry) {
86+
// Wait for the application to be restored and for the settings to be loaded.
87+
Promise.all([
88+
app.restored,
89+
settingRegistry.load('jupyter-chat-example:plugin')
90+
])
91+
.then(([, setting]) => {
92+
// Read the settings
93+
loadSetting(setting);
94+
95+
// Listen for the plugin setting changes
96+
setting.changed.connect(loadSetting);
97+
})
98+
.catch(reason => {
99+
console.error(
100+
`Something went wrong when reading the settings.\n${reason}`
101+
);
102+
});
103+
}
104+
105+
const panel = buildChatSidebar({ model, rmRegistry, themeManager });
106+
app.shell.add(panel, 'left');
107+
}
108+
};
109+
110+
export default [plugin];
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright (c) Jupyter Development Team.
3+
* Distributed under the terms of the Modified BSD License.
4+
*/
5+
6+
/*
7+
See the JupyterLab Developer Guide for useful CSS Patterns:
8+
9+
https://jupyterlab.readthedocs.io/en/stable/developer/css.html
10+
*/
11+
12+
@import url('~jupyterlab-chat/style/index.css');

0 commit comments

Comments
 (0)