Skip to content

Commit

Permalink
Use mathjax-extension to render latex in markdown cells (#1410)
Browse files Browse the repository at this point in the history
* use mathjax-extension

* Support both mathjax 2 and 3

* Fix eslint

* Test only Mathjax2

* Load mathjax manually
  • Loading branch information
trungleduc authored Oct 31, 2023
1 parent 9a8147a commit 560dbc1
Show file tree
Hide file tree
Showing 20 changed files with 8,300 additions and 7,363 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:

- name: Create the conda environment
shell: bash -l {0}
run: mamba install -q python=${{ matrix.python_version }} pip jupyterlab_pygments==0.1.0 pytest-cov pytest-rerunfailures nodejs=18 yarn ipywidgets matplotlib xeus-cling "traitlets>=5.0.3,<6" ipykernel
run: mamba install -q python=${{ matrix.python_version }} pip jupyterlab_pygments==0.1.0 pytest-cov pytest-rerunfailures nodejs=18 yarn=3 ipywidgets matplotlib xeus-cling "traitlets>=5.0.3,<6" ipykernel

- name: Install dependencies
shell: bash -l {0}
Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:
- name: Create the conda environment
shell: bash -l {0}
# TODO unpin pyzmq
run: mamba install -q python=${{ matrix.python_version }} pip jupyterlab_pygments==0.1.0 pytest-cov pytest-rerunfailures nodejs=18 yarn ipywidgets matplotlib xeus-cling "traitlets>=5.0.3,<6" ipykernel pyzmq==25.1.0
run: mamba install -q python=${{ matrix.python_version }} pip jupyterlab_pygments==0.1.0 pytest-cov pytest-rerunfailures nodejs=18 yarn=3 ipywidgets matplotlib xeus-cling "traitlets>=5.0.3,<6" ipykernel pyzmq==25.1.0

- name: Install dependencies
shell: bash -l {0}
Expand Down
2 changes: 1 addition & 1 deletion docs/contribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ First, you need to fork the project. Then setup your environment:

```bash
# create a new conda environment
conda create -n voila -c conda-forge notebook jupyterlab nodejs "yarn<3" pip
conda create -n voila -c conda-forge notebook jupyterlab nodejs "yarn<4" pip
conda activate voila

# download voila from your GitHub fork
Expand Down
3 changes: 1 addition & 2 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"npmClient": "yarn",
"version": "independent",
"useWorkspaces": true
"version": "independent"
}
21 changes: 10 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,21 @@
"test": "lerna run test"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.2.0",
"@typescript-eslint/parser": "^4.2.0",
"eslint": "^7.10.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.21.5",
"@typescript-eslint/eslint-plugin": "^5.56.0",
"@typescript-eslint/parser": "^5.56.0",
"eslint": "^8.36.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.32.2",
"jest": "^26.4.2",
"jest-junit": "^11.1.0",
"jest-raw-loader": "^1.0.1",
"jest-summary-reporter": "^0.0.2",
"lerna": "^4.0.0",
"lerna": "^7.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.0",
"prettier": "^2.8.6",
"rimraf": "^3.0.2",
"shell-quote": "^1.7.2",
"typescript": "~4.1.3"
"shell-quote": "^1.7.2"
}
}
16 changes: 10 additions & 6 deletions packages/jupyterlab-preview/src/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,26 @@ export class VoilaPreview extends DocumentWidget<IFrame, INotebookModel> {

window.onmessage = (event: any) => {
//console.log("EVENT: ", event);

switch (event.data?.level) {
const level = event?.data?.level;
const msg = event?.data?.msg;
if (!level || !msg) {
return;
}
switch (level) {
case 'debug':
console.debug(...event.data?.msg);
console.debug(msg);
break;

case 'info':
console.info(...event.data?.msg);
console.info(msg);
break;

case 'warn':
console.warn(...event.data?.msg);
console.warn(msg);
break;

case 'error':
console.error(...event.data?.msg);
console.error(msg);
break;

default:
Expand Down
2 changes: 1 addition & 1 deletion packages/voila/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"@jupyterlab/json-extension": "^4.0.0",
"@jupyterlab/logconsole": "^4.0.0",
"@jupyterlab/mainmenu": "^4.0.0",
"@jupyterlab/markdownviewer-extension": "^4.0.0",
"@jupyterlab/markedparser-extension": "^4.0.0",
"@jupyterlab/mathjax-extension": "^4.0.0",
"@jupyterlab/mathjax2-extension": "^4.0.0",
"@jupyterlab/nbformat": "^4.0.0",
"@jupyterlab/notebook": "^4.0.0",
Expand Down
1 change: 1 addition & 0 deletions packages/voila/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export * from './tools';
export * from './plugins/tree/browser';
export * from './plugins/tree/listing';
export * from './plugins/themes/thememanager';
export * from './plugins/widget/renderedcells';
11 changes: 8 additions & 3 deletions packages/voila/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
IFederatedExtensionData,
activePlugins,
createModule,
loadComponent
loadComponent,
shouldUseMathJax2
} from './tools';

//Inspired by: https://github.com/jupyterlab/jupyterlab/blob/master/dev_mode/index.js
Expand All @@ -35,7 +36,6 @@ async function main() {
(p: any) => p.id === '@jupyterlab/codemirror-extension:languages'
),
require('@jupyterlab/markedparser-extension'),
require('@jupyterlab/mathjax2-extension'),
require('@jupyterlab/rendermime-extension'),
require('@jupyterlab/theme-light-extension'),
require('@jupyterlab/theme-dark-extension'),
Expand All @@ -45,12 +45,17 @@ async function main() {
plugins
];

if (shouldUseMathJax2()) {
mods.push(require('@jupyterlab/mathjax2-extension'));
} else {
mods.push(require('@jupyterlab/mathjax-extension'));
}

const mimeExtensions = [
require('@jupyterlab/javascript-extension'),
require('@jupyterlab/json-extension'),
require('@jupyterlab/vega5-extension')
];

const extensionData: IFederatedExtensionData[] = JSON.parse(
PageConfig.getOption('federated_extensions')
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ import {
IWidgetRegistryData
} from '@jupyter-widgets/base';

import { VoilaApp } from '../app';
import { VoilaApp } from '../../app';

import { Widget } from '@lumino/widgets';
import { RenderedCells } from './renderedcells';

const WIDGET_MIMETYPE = 'application/vnd.jupyter.widget-view+json';

Expand Down Expand Up @@ -78,7 +79,6 @@ export const widgetManager: JupyterFrontEndPlugin<IJupyterWidgetRegistry> = {
},
-10
);

window.addEventListener('beforeunload', (e) => {
const data = new FormData();
// it seems if we attach this to early, it will not be called
Expand Down Expand Up @@ -113,7 +113,16 @@ export const renderOutputsPlugin: JupyterFrontEndPlugin<void> = {
app: JupyterFrontEnd,
rendermime: IRenderMimeRegistry
): Promise<void> => {
// Render outputs
// TODO: Typeset a fake element to get MathJax loaded, remove this hack once
// MathJax 2 is removed.
await rendermime.latexTypesetter?.typeset(document.createElement('div'));

// Render latex in markdown cells
const mdOutput = document.body.querySelectorAll('div.jp-MarkdownOutput');
mdOutput.forEach((md) => {
rendermime.latexTypesetter?.typeset(md as HTMLElement);
});
// Render code cell
const cellOutputs = document.body.querySelectorAll(
'script[type="application/vnd.voila.cell-output+json"]'
);
Expand Down Expand Up @@ -150,7 +159,7 @@ export const renderOutputsPlugin: JupyterFrontEndPlugin<void> = {
});
const node = document.getElementById('rendered_cells');
if (node) {
const cells = new Widget({ node });
const cells = new RenderedCells({ node });
app.shell.add(cells, 'main');
}
}
Expand Down
22 changes: 22 additions & 0 deletions packages/voila/src/plugins/widget/renderedcells.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Message } from '@lumino/messaging';
import { Widget } from '@lumino/widgets';

/**
* Wrapper widget of rendered cells, this class converts the Lumino resize
* message to a window event. It helps fix the zero-heigh issue of some
* widgets
*
*/
export class RenderedCells extends Widget {
processMessage(msg: Message): void {
super.processMessage(msg);
switch (msg.type) {
case 'resize':
window.dispatchEvent(new Event('resize'));
break;

default:
break;
}
}
}
24 changes: 24 additions & 0 deletions packages/voila/src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,27 @@ export interface IFederatedExtensionData {
style?: string;
mimeExtension?: string;
}

/**
* Check if Voila app should use MathJax 2 or MathJax 3
* @TODO remove in 1.0.0
*/
export function shouldUseMathJax2() {
const [urlParam, configParam] = ['fullMathjaxUrl', 'mathjaxConfig'];
const url = PageConfig.getOption(urlParam);
const config = PageConfig.getOption(configParam);
if (url !== 'null' || config !== 'null') {
PageConfig.setOption(
urlParam,
url === 'null'
? 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js'
: url
);
PageConfig.setOption(
configParam,
config === 'null' ? 'TeX-AMS_CHTML-full,Safe' : config
);
return true;
}
return false;
}
1 change: 1 addition & 0 deletions packages/voila/style/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import '@jupyterlab/rendermime/style/index.js';
import '@jupyterlab/docregistry/style/index.js';
import '@jupyterlab/markedparser-extension/style/index.js';
import '@jupyterlab/filebrowser/style/index.js';
import '@jupyterlab/mathjax-extension/style/index.js';
import './base.css';
4 changes: 4 additions & 0 deletions share/jupyter/voila/templates/classic/index.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
{{ super() }}
{%- endblock notebook_css -%}

{%- block html_head_js_mathjax -%}
{# remove mathjax CDN #}
{%- endblock html_head_js_mathjax -%}

{% block body_header %}
<body data-base-url="{{resources.base_url}}voila/">
{{ spinner.html() }}
Expand Down
4 changes: 4 additions & 0 deletions share/jupyter/voila/templates/lab/index.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
{{ super() }}
{%- endblock notebook_css -%}

{%- block html_head_js_mathjax -%}
{# remove mathjax CDN #}
{%- endblock html_head_js_mathjax -%}

{# this overrides the default behaviour of rendering static widgets #}
{% block jupyter_widgets %}
{% endblock jupyter_widgets %}
Expand Down
4 changes: 4 additions & 0 deletions share/jupyter/voila/templates/reveal/index.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
{{ super() }}
{%- endblock notebook_css -%}

{%- block html_head_js_mathjax -%}
{# remove mathjax CDN #}
{%- endblock html_head_js_mathjax -%}

{% block body_header %}
{% if resources.theme == 'dark' %}
<body class="jp-Notebook" data-base-url="{{resources.base_url}}voila/" data-jp-theme-light="false" data-jp-theme-name="JupyterLab Dark">
Expand Down
4 changes: 3 additions & 1 deletion tsconfig.eslint.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"extends": "./tsconfigbase",
"include": ["packages/**/*", "ui-tests"],
"types": ["jest"]
"compilerOptions": {
"types": ["jest"]
}
}
2 changes: 1 addition & 1 deletion ui-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Voila UI Tests",
"private": true,
"scripts": {
"start": "voila ../notebooks --no-browser --show_tracebacks True",
"start": "voila ../notebooks --no-browser --show_tracebacks True --Voila.mathjax_url=https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js",
"start:detached": "yarn run start&",
"test": "npx playwright test",
"test:debug": "PWDEBUG=1 playwright test",
Expand Down
Loading

0 comments on commit 560dbc1

Please sign in to comment.