Theme initialisation according to JupyterLab or Voilà (lab)
Theme.dark is initialised as False in Themes.py and this value sets the vuetify theme in Themes.js.
When JupyterLab or Voilà is set to a dark theme, the ipyvuetify widgets are rendered by default in light theme, and one has to manually execute ipyvuetify.model.dark = True to change the ipyvuetify theme.
Could this be changed in Themes.js line 22 by adding
if (document.body.classList.contains('theme-dark') ||
document.body.attributes.getNamedItem("data-jp-theme-light") &&
document.body.attributes.getNamedItem('data-jp-theme-light').value=='false') {
this.dark = true;
}
The first condition checks the use of a dark theme in a Voilà display (with the default lab template) and the second in JupyterLab display.
I tested it in a VuetifyTemplate and it worked.
I love this idea ❤️
This feature was implemented in v1.7.0 (9be42b9)
Thanks for the implementation with respect to JupyterLab. What about adding the check for Voilà on line 39 of Theme.js?
It should work when using Voila with e.g. --theme=dark (https://voila.readthedocs.io/en/stable/customize.html)
I have tried with --theme=dark as well as with the URL query string ?voila-theme=dark, it didn't work. Does it work on your side? What source code is supposed to catch Voilà dark setting?
You are right, I misremembered, I was using the VoilaVuetify template in which this is handled.
Would you want to make a PR for this? If not, I can make the change.
Although it might work without that change in a future version of Voila: https://github.com/voila-dashboards/voila/pull/846
I'll try to make a PR. I have an issue with building the extension. After modifying Themes.js, I run jlpm run prepare in the js folder, but webpack complains as follows:
ERROR in ./lib/Themes.js
Module not found: Error: Can't resolve './plugins/vuetify' in '[...]/src/ipyvuetify/js/lib'
@ ./lib/Themes.js 4:0-40 21:9-16 28:10-17 34:6-13 36:6-13 38:6-13 42:6-13 73:9-16 79:6-13 81:8-15
@ ./lib/nodepsEmbed.js
If I add .js to ./plugins/vuetify, the error disappears.
How do you usually rebuild ipyvuetify under development?
I had a look at Jupyterlab documentation and the cookiecutter-ts extension README, but ipyvuetify seems not to follow the same structure (package.json is in js folder and has no general build script).
It's based on an older js cookiecutter and is also supporting the classic notebook. I'll have to take a look why it's not building.
Running npm run prepare in the js directory works for me.
After running jupyter labextension develop . --overwrite in the top directory, then running npm run watch in the js directory also works for me.
I still get an error with npm run prepare for two children of webpack, when it processes ./lib/nodeps.js and ./lib/nodepsEmbed.js:
Child
Hash: da66faa312a62ab78080
Time: 2942ms
Built at: 14/09/2021 08:58:30
Entrypoint main =
[0] external "jupyter-vue" 42 bytes {0} [built]
[1] external "@jupyter-widgets/base" 42 bytes {0} [built]
[2] ./lib/public-path.js 390 bytes {0} [built]
[3] ./lib/styles.css 1.06 KiB {0} [built]
[4] ./node_modules/css-loader/dist/cjs.js!./lib/styles.css 858 bytes {0} [built]
[8] ./package.json 2.36 KiB {0} [built]
[9] ./lib/nodeps.js + 167 modules 150 KiB {0} [built]
| ./lib/nodeps.js 54 bytes [built]
| ./lib/nodepsEmbed.js 342 bytes [built]
| ./src/nodepsVuetifyView.js 444 bytes [built]
| ./lib/generated/index.js 7.76 KiB [built]
| ./lib/Html.js 501 bytes [built]
| ./lib/VuetifyTemplate.js 531 bytes [built]
| ./lib/Themes.js 2.59 KiB [built]
| ./lib/generated/VuetifyWidget.js 530 bytes [built]
| ./lib/generated/Text.js 394 bytes [built]
| ./lib/generated/App.js 430 bytes [built]
| ./lib/generated/AppBar.js 1.33 KiB [built]
| ./lib/generated/AppBarNavIcon.js 414 bytes [built]
| ./lib/generated/Alert.js 1020 bytes [built]
| ./lib/generated/Autocomplete.js 2.17 KiB [built]
| ./lib/generated/Avatar.js 665 bytes [built]
| + 153 hidden modules
+ 3 hidden modules
ERROR in ./lib/Themes.js
Module not found: Error: Can't resolve './plugins/vuetify' in '/home/guillaume/src/ipyvuetify/js/lib'
@ ./lib/Themes.js 4:0-40 21:9-16 28:10-17 34:6-13 36:6-13 38:6-13 42:6-13 73:9-16 79:6-13 81:8-15
@ ./lib/nodepsEmbed.js
@ ./lib/nodeps.js
ERROR in chunk main [entry]
nodeps.js
/home/guillaume/src/ipyvuetify/js/lib/nodeps.js cfbd2241da5a323bdbb1837bc399228b
Assigning to rvalue (29:10)
| ThemeModel.themeManager.themeChanged.connect(() => {
| if (this.get('dark') === null) {
| !(function webpackMissingModule() { var e = new Error("Cannot find module './plugins/vuetify'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()).framework.theme.dark = document.body.dataset.jpThemeLight === 'false';
| }
| }, this);
Child
Hash: a46f58f9ab21d5221240
Time: 1825ms
Built at: 14/09/2021 08:58:29
Entrypoint main =
[0] external "jupyter-vue" 42 bytes {0} [built]
[1] external "@jupyter-widgets/base" 42 bytes {0} [built]
[2] ./lib/styles.css 1.06 KiB {0} [built]
[3] ./node_modules/css-loader/dist/cjs.js!./lib/styles.css 858 bytes {0} [built]
[7] ./package.json 2.36 KiB {0} [built]
[8] ./lib/nodepsEmbed.js + 166 modules 150 KiB {0} [built]
| ./lib/nodepsEmbed.js 342 bytes [built]
| ./src/nodepsVuetifyView.js 444 bytes [built]
| ./lib/generated/index.js 7.76 KiB [built]
| ./lib/Html.js 501 bytes [built]
| ./lib/VuetifyTemplate.js 531 bytes [built]
| ./lib/Themes.js 2.59 KiB [built]
| ./lib/generated/VuetifyWidget.js 530 bytes [built]
| ./lib/generated/Text.js 394 bytes [built]
| ./lib/generated/App.js 430 bytes [built]
| ./lib/generated/AppBar.js 1.33 KiB [built]
| ./lib/generated/AppBarNavIcon.js 414 bytes [built]
| ./lib/generated/Alert.js 1020 bytes [built]
| ./lib/generated/Autocomplete.js 2.17 KiB [built]
| ./lib/generated/Avatar.js 665 bytes [built]
| ./lib/generated/Badge.js 824 bytes [built]
| + 152 hidden modules
+ 3 hidden modules
ERROR in ./lib/Themes.js
Module not found: Error: Can't resolve './plugins/vuetify' in '/home/guillaume/src/ipyvuetify/js/lib'
@ ./lib/Themes.js 4:0-40 21:9-16 28:10-17 34:6-13 36:6-13 38:6-13 42:6-13 73:9-16 79:6-13 81:8-15
@ ./lib/nodepsEmbed.js
ERROR in chunk main [entry]
nodeps.js
/home/guillaume/src/ipyvuetify/js/lib/nodepsEmbed.js 216d9b2e91b735de5c7349321e4700f4
Assigning to rvalue (29:10)
| ThemeModel.themeManager.themeChanged.connect(() => {
| if (this.get('dark') === null) {
| !(function webpackMissingModule() { var e = new Error("Cannot find module './plugins/vuetify'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()).framework.theme.dark = document.body.dataset.jpThemeLight === 'false';
| }
| }, this);
No issue with ./lib/notebook.js and ./lib/embed.js.
The log file from npm for build:webpack reads:
0 verbose cli [
0 verbose cli '/usr/bin/node',
0 verbose cli '/usr/share/nodejs/npm/bin/npm-cli.js',
0 verbose cli 'run',
0 verbose cli 'build:webpack'
0 verbose cli ]
1 info using [email protected]
2 info using [email protected]
3 timing config:load:defaults Completed in 2ms
4 timing config:load:file:/usr/share/nodejs/npm/npmrc Completed in 2ms
5 timing config:load:builtin Completed in 2ms
6 timing config:load:cli Completed in 1ms
7 timing config:load:env Completed in 1ms
8 timing config:load:file:/home/guillaume/src/ipyvuetify/js/.npmrc Completed in 1ms
9 timing config:load:project Completed in 1ms
10 timing config:load:file:/home/guillaume/.npmrc Completed in 0ms
11 timing config:load:user Completed in 0ms
12 timing config:load:file:/etc/npmrc Completed in 0ms
13 timing config:load:global Completed in 0ms
14 timing config:load:cafile Completed in 0ms
15 timing config:load:validate Completed in 1ms
16 timing config:load:setUserAgent Completed in 0ms
17 timing config:load:setEnvs Completed in 1ms
18 timing config:load Completed in 9ms
19 verbose npm-session f2e98852e7934577
20 timing npm:load Completed in 17ms
21 timing command:run-script Completed in 7166ms
22 verbose stack Error: command failed
22 verbose stack at ChildProcess.<anonymous> (/usr/share/nodejs/@npmcli/promise-spawn/index.js:64:27)
22 verbose stack at ChildProcess.emit (events.js:314:20)
22 verbose stack at maybeClose (internal/child_process.js:1022:16)
22 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:287:5)
23 verbose pkgid [email protected]
24 verbose cwd /home/guillaume/src/ipyvuetify/js
25 verbose Linux 5.10.0-8-amd64
26 verbose argv "/usr/bin/node" "/usr/share/nodejs/npm/bin/npm-cli.js" "run" "build:webpack"
27 verbose node v12.21.0
28 verbose npm v7.5.2
29 error code 2
30 error path /home/guillaume/src/ipyvuetify/js
31 error command failed
32 error command sh -c webpack
33 verbose exit 2
Could it come from an incompatible version of one of the compilers? npm list answers:
[email protected] /home/guillaume/src/ipyvuetify/js
├── @babel/[email protected]
├── @babel/[email protected]
├── @babel/[email protected]
├── @jupyter-widgets/[email protected]
├── @jupyterlab/[email protected]
├── @jupyterlab/[email protected]
├── @mariobuikhuizen/[email protected]
├── @mdi/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
Can you confirm that after running npm run build:babel lib/plugins/vuetify.js is present?
My dependencies are indeed different, you should have the same after resetting package-lock.json (if it has changed) and running npm install
├── @babel/[email protected]
├── @babel/[email protected]
├── @babel/[email protected]
├── @jupyter-widgets/[email protected]
├── @jupyterlab/[email protected]
├── @jupyterlab/[email protected]
├── @mariobuikhuizen/[email protected]
├── @mdi/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
Yes, lib/plugins/vuetify.js is present. Resetting package-lock.json (changed by pip install I guess?) didn't help.
I gave a try with a fresh clone of ipvuetify, as follows:
git clone https://github.com/mariobuikhuizen/ipyvuetify.git mario_ipyvuetify
cd mario_ipyvuetify/
pip install -e .
jupyter labextension develop . --overwrite
cd js
npm run prepare
npm ends with the same error as before.
Finally, I found the cause: the file https://github.com/mariobuikhuizen/ipyvuetify/blob/master/js/src/plugins/noDepsVuetify.js has the letter D in capital whereas the webpack config file defines the alias 'src/plugins/nodepsVuetify.js'. Renaming js/src/plugins/noDepsVuetify.js to js/src/plugins/nodepsVuetify.js solved the issue.
Running
npm run preparein thejsdirectory works for me.
@mariobuikhuizen Did you run it on macOS?
I am using Linux. Apparently, webpack behaves differently between macOS and Linux with respect to case sensitivity: https://stackoverflow.com/questions/28789050/webpack-fine-on-macos-loader-errors-on-linux It may be good to use a Webpack plugin like case-sensitive-paths-webpack-plugin to notive such issues in the future.
Currently, after displaying a widget in Jupyterlab, v.theme.dark remains None, and if v.theme.dark is set, then the widget theme remains that of v.theme.dark whatever the Jupyterlab or Voila lab/vuetify dark/light theme, so the None value corresponds to an 'inherit' behavior. I thought it would be useful to add a dark_jlab trait to Themes to know the inherited theme on the python side, but eventually I don't see any clear need for that. Do you think it would be useful? If so, I can add it to the PR.
Great find! I indeed run it on macOS, which has a case-insensitive file system.
It might be useful to have dark_jlab trait, but I can't think of a scenario in which one would need it yet.