@quarto/jupyterlab-quarto 0.1.45 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +1 -1
- package/README.md +48 -15
- package/lib/__tests__/jupyterlab_quarto.spec.d.ts +3 -0
- package/lib/__tests__/jupyterlab_quarto.spec.js +9 -0
- package/lib/ast/ast.d.ts +1 -2
- package/lib/ast/ast.js +4 -3
- package/lib/const.d.ts +1 -2
- package/lib/const.js +5 -6
- package/lib/hooks/codemirror.d.ts +5 -4
- package/lib/hooks/codemirror.js +37 -12
- package/lib/index.d.ts +2 -3
- package/lib/index.js +6 -5
- package/lib/manager.d.ts +2 -2
- package/lib/manager.js +14 -16
- package/lib/plugins/callouts.d.ts +1 -2
- package/lib/plugins/callouts.js +59 -58
- package/lib/plugins/cites.d.ts +1 -2
- package/lib/plugins/cites.js +41 -23
- package/lib/plugins/decorator.d.ts +1 -2
- package/lib/plugins/decorator.js +11 -12
- package/lib/plugins/divs.d.ts +1 -2
- package/lib/plugins/divs.js +20 -9
- package/lib/plugins/figure-divs.d.ts +1 -2
- package/lib/plugins/figure-divs.js +18 -17
- package/lib/plugins/figures.d.ts +3 -4
- package/lib/plugins/figures.js +30 -31
- package/lib/plugins/gridtables/common/gridtables/GetCells.d.ts +5 -6
- package/lib/plugins/gridtables/common/gridtables/GetCells.js +6 -8
- package/lib/plugins/gridtables/common/gridtables/GetColumnWidths.d.ts +5 -6
- package/lib/plugins/gridtables/common/gridtables/GetColumnWidths.js +9 -14
- package/lib/plugins/gridtables/common/markdown-it/ColumnAlignments.d.ts +0 -1
- package/lib/plugins/gridtables/common/markdown-it/ColumnAlignments.js +0 -1
- package/lib/plugins/gridtables/common/markdown-it/EmitTable.d.ts +3 -4
- package/lib/plugins/gridtables/common/markdown-it/EmitTable.js +12 -15
- package/lib/plugins/gridtables/common/markdown-it/GetCharCodeAtStartOfLine.d.ts +1 -2
- package/lib/plugins/gridtables/common/markdown-it/GetCharCodeAtStartOfLine.js +1 -3
- package/lib/plugins/gridtables/common/markdown-it/GetLine.d.ts +1 -2
- package/lib/plugins/gridtables/common/markdown-it/GetLine.js +0 -1
- package/lib/plugins/gridtables/common/markdown-it/ParseTable.d.ts +2 -3
- package/lib/plugins/gridtables/common/markdown-it/ParseTable.js +18 -28
- package/lib/plugins/gridtables/common/markdown-it/ParseTableResult.d.ts +1 -2
- package/lib/plugins/gridtables/common/markdown-it/ParseTableResult.js +0 -1
- package/lib/plugins/gridtables/index.d.ts +0 -1
- package/lib/plugins/gridtables/index.js +2 -3
- package/lib/plugins/gridtables/interfaces/markdown-it/IState.d.ts +1 -2
- package/lib/plugins/gridtables/interfaces/markdown-it/IState.js +0 -1
- package/lib/plugins/gridtables/interfaces/markdown-it/IToken.d.ts +0 -1
- package/lib/plugins/gridtables/interfaces/markdown-it/IToken.js +0 -1
- package/lib/plugins/gridtables/interfaces/markdown-it/TRuleFunction.d.ts +1 -2
- package/lib/plugins/gridtables/interfaces/markdown-it/TRuleFunction.js +0 -1
- package/lib/plugins/gridtables/rules/gridtable.d.ts +2 -3
- package/lib/plugins/gridtables/rules/gridtable.js +5 -6
- package/lib/plugins/index.d.ts +15 -0
- package/lib/plugins/index.js +21 -0
- package/lib/plugins/math.d.ts +4 -3
- package/lib/plugins/math.js +33 -31
- package/lib/plugins/mermaid/index.d.ts +1 -2
- package/lib/plugins/mermaid/index.js +19 -14
- package/lib/plugins/shortcodes.d.ts +1 -2
- package/lib/plugins/shortcodes.js +6 -7
- package/lib/plugins/spans.d.ts +1 -2
- package/lib/plugins/spans.js +2 -4
- package/lib/plugins/table-captions.d.ts +1 -2
- package/lib/plugins/table-captions.js +19 -16
- package/lib/plugins/utils/html.d.ts +1 -2
- package/lib/plugins/utils/html.js +19 -15
- package/lib/plugins/utils/markdownit.d.ts +0 -1
- package/lib/plugins/utils/markdownit.js +14 -13
- package/lib/plugins/utils/tok.d.ts +0 -1
- package/lib/plugins/utils/tok.js +12 -13
- package/lib/plugins/yaml.d.ts +1 -2
- package/lib/plugins/yaml.js +59 -49
- package/lib/providers/attrs.d.ts +1 -2
- package/lib/providers/attrs.js +5 -6
- package/lib/providers/callouts.d.ts +1 -2
- package/lib/providers/callouts.js +7 -8
- package/lib/providers/cites.d.ts +1 -2
- package/lib/providers/cites.js +7 -8
- package/lib/providers/decorator.d.ts +1 -2
- package/lib/providers/decorator.js +7 -8
- package/lib/providers/deflist.d.ts +1 -2
- package/lib/providers/deflist.js +5 -6
- package/lib/providers/divs.d.ts +1 -2
- package/lib/providers/divs.js +9 -10
- package/lib/providers/figure-divs.d.ts +1 -2
- package/lib/providers/figure-divs.js +5 -6
- package/lib/providers/figures.d.ts +1 -2
- package/lib/providers/figures.js +5 -6
- package/lib/providers/footnotes.d.ts +1 -2
- package/lib/providers/footnotes.js +5 -6
- package/lib/providers/gridtables.d.ts +1 -2
- package/lib/providers/gridtables.js +5 -6
- package/lib/providers/math.d.ts +1 -2
- package/lib/providers/math.js +12 -13
- package/lib/providers/mermaid.d.ts +1 -2
- package/lib/providers/mermaid.js +10 -9
- package/lib/providers/provider.d.ts +1 -2
- package/lib/providers/provider.js +0 -1
- package/lib/providers/shortcodes.d.ts +1 -2
- package/lib/providers/shortcodes.js +5 -6
- package/lib/providers/spans.d.ts +1 -2
- package/lib/providers/spans.js +8 -9
- package/lib/providers/sub.d.ts +1 -2
- package/lib/providers/sub.js +5 -6
- package/lib/providers/sup.d.ts +1 -2
- package/lib/providers/sup.js +5 -6
- package/lib/providers/table-captions.d.ts +1 -2
- package/lib/providers/table-captions.js +5 -6
- package/lib/providers/tasklists.d.ts +1 -2
- package/lib/providers/tasklists.js +5 -6
- package/lib/providers/yaml.d.ts +1 -2
- package/lib/providers/yaml.js +7 -8
- package/lib/types.d.ts +0 -1
- package/lib/types.js +0 -1
- package/lib/widgets.d.ts +0 -1
- package/lib/widgets.js +5 -6
- package/package.json +105 -39
- package/style/base.css +34 -33
- package/style/index.css +1 -1
- package/lib/__tests__/index.spec.d.ts +0 -6
- package/lib/__tests__/index.spec.js +0 -61
- package/lib/__tests__/index.spec.js.map +0 -1
- package/lib/__tests__/myextension.spec.d.ts +0 -6
- package/lib/__tests__/myextension.spec.js +0 -11
- package/lib/__tests__/myextension.spec.js.map +0 -1
- package/lib/ast/ast.js.map +0 -1
- package/lib/const.js.map +0 -1
- package/lib/hooks/codemirror.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/manager.js.map +0 -1
- package/lib/plugins/callouts.js.map +0 -1
- package/lib/plugins/cites.js.map +0 -1
- package/lib/plugins/decorator.js.map +0 -1
- package/lib/plugins/divs.js.map +0 -1
- package/lib/plugins/figure-divs.js.map +0 -1
- package/lib/plugins/figures.js.map +0 -1
- package/lib/plugins/gridtables/common/gridtables/GetCells.js.map +0 -1
- package/lib/plugins/gridtables/common/gridtables/GetColumnWidths.js.map +0 -1
- package/lib/plugins/gridtables/common/markdown-it/ColumnAlignments.js.map +0 -1
- package/lib/plugins/gridtables/common/markdown-it/EmitTable.js.map +0 -1
- package/lib/plugins/gridtables/common/markdown-it/GetCharCodeAtStartOfLine.js.map +0 -1
- package/lib/plugins/gridtables/common/markdown-it/GetLine.js.map +0 -1
- package/lib/plugins/gridtables/common/markdown-it/ParseTable.js.map +0 -1
- package/lib/plugins/gridtables/common/markdown-it/ParseTableResult.js.map +0 -1
- package/lib/plugins/gridtables/index.js.map +0 -1
- package/lib/plugins/gridtables/interfaces/markdown-it/IState.js.map +0 -1
- package/lib/plugins/gridtables/interfaces/markdown-it/IToken.js.map +0 -1
- package/lib/plugins/gridtables/interfaces/markdown-it/TRuleFunction.js.map +0 -1
- package/lib/plugins/gridtables/rules/gridtable.js.map +0 -1
- package/lib/plugins/math.js.map +0 -1
- package/lib/plugins/mermaid/index.js.map +0 -1
- package/lib/plugins/shortcodes.js.map +0 -1
- package/lib/plugins/spans.js.map +0 -1
- package/lib/plugins/table-captions.js.map +0 -1
- package/lib/plugins/utils/html.js.map +0 -1
- package/lib/plugins/utils/markdownit.js.map +0 -1
- package/lib/plugins/utils/tok.js.map +0 -1
- package/lib/plugins/yaml.js.map +0 -1
- package/lib/providers/attrs.js.map +0 -1
- package/lib/providers/callouts.js.map +0 -1
- package/lib/providers/cites.js.map +0 -1
- package/lib/providers/decorator.js.map +0 -1
- package/lib/providers/deflist.js.map +0 -1
- package/lib/providers/divs.js.map +0 -1
- package/lib/providers/figure-divs.js.map +0 -1
- package/lib/providers/figures.js.map +0 -1
- package/lib/providers/footnotes.js.map +0 -1
- package/lib/providers/gridtables.js.map +0 -1
- package/lib/providers/math.js.map +0 -1
- package/lib/providers/mermaid.js.map +0 -1
- package/lib/providers/provider.js.map +0 -1
- package/lib/providers/shortcodes.js.map +0 -1
- package/lib/providers/spans.js.map +0 -1
- package/lib/providers/sub.js.map +0 -1
- package/lib/providers/sup.js.map +0 -1
- package/lib/providers/table-captions.js.map +0 -1
- package/lib/providers/tasklists.js.map +0 -1
- package/lib/providers/yaml.js.map +0 -1
- package/lib/types.js.map +0 -1
- package/lib/widgets.js.map +0 -1
- package/schema/plugin.json +0 -8
- package/src/@types/markdown-it-deflist.d.ts +0 -10
- package/src/@types/markdown-it-footnote.d.ts +0 -10
- package/src/@types/markdown-it-gridtables.d.ts +0 -10
- package/src/@types/markdown-it-implicit-figures.d.ts +0 -10
- package/src/@types/markdown-it-sub.d.ts +0 -10
- package/src/@types/markdown-it-sup.d.ts +0 -10
- package/src/@types/markdown-it-task-lists.d.ts +0 -10
package/LICENSE
CHANGED
package/README.md
CHANGED
@@ -1,23 +1,34 @@
|
|
1
1
|
# JupyterLab Quarto Extension
|
2
2
|
|
3
|
-
[Quarto](https://www.quarto.org) is an open source project that combines Jupyter notebooks with flexible options to use a single source document to produce high-quality articles, reports, presentations, websites, and books in HTML, PDF, MS Word, ePub, and more. Quarto supports a wide variety of useful new features useful in technical documents, including support for LaTeX equations, citations, cross-references, figure panels, callouts, advanced page layout, and more.
|
3
|
+
[Quarto](https://www.quarto.org) is an open source project that combines Jupyter notebooks with flexible options to use a single source document to produce high-quality articles, reports, presentations, websites, and books in HTML, PDF, MS Word, ePub, and more. Quarto supports a wide variety of useful new features useful in technical documents, including support for LaTeX equations, citations, cross-references, figure panels, callouts, advanced page layout, and more.
|
4
4
|
|
5
5
|
The JupyterLab Quarto extension allows JupyterLab to render notebooks which include Quarto markdown content.
|
6
6
|
<br/><br/>
|
7
|
+
|
7
8
|
<p align="center">
|
8
9
|
<img src="https://user-images.githubusercontent.com/261654/230087634-d5027ebc-8508-43b4-81c9-c4b7d6cfa738.png" width="60%">
|
9
10
|
</p>
|
10
11
|
|
12
|
+
### Binder
|
13
|
+
|
14
|
+
You can try an example of the extension in a notebook (though you can't actually render the notebook using Quarto) on Binder.
|
15
|
+
|
16
|
+
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/quarto-dev/jupyterlab-quarto/main?urlpath=lab)
|
17
|
+
|
18
|
+
## Status
|
19
|
+
|
20
|
+
[![Github Actions Status](https://github.com/quarto-dev/jupyterlab-quarto/workflows/Build/badge.svg)](https://github.com/quarto-dev/jupyterlab-quarto/actions/workflows/build.yml)
|
21
|
+
|
11
22
|
## Requirements
|
12
23
|
|
13
|
-
- JupyterLab >=
|
24
|
+
- JupyterLab >= 4.0.0
|
14
25
|
|
15
26
|
## Install
|
16
27
|
|
17
28
|
To install the extension, execute:
|
18
29
|
|
19
30
|
```bash
|
20
|
-
pip install
|
31
|
+
pip install jupyterlab_quarto
|
21
32
|
```
|
22
33
|
|
23
34
|
## Uninstall
|
@@ -25,40 +36,42 @@ pip install jupyterlab-quarto
|
|
25
36
|
To remove the extension, execute:
|
26
37
|
|
27
38
|
```bash
|
28
|
-
pip uninstall
|
39
|
+
pip uninstall jupyterlab_quarto
|
29
40
|
```
|
30
41
|
|
31
42
|
## Contributing
|
32
43
|
|
33
44
|
### Development install
|
34
45
|
|
46
|
+
Note: You will need NodeJS to build the extension package.
|
47
|
+
|
48
|
+
The `jlpm` command is JupyterLab's pinned version of
|
49
|
+
[yarn](https://yarnpkg.com/) that is installed with JupyterLab. You may use
|
50
|
+
`yarn` or `npm` in lieu of `jlpm` below.
|
51
|
+
|
35
52
|
```bash
|
36
|
-
#
|
53
|
+
# Clone the repo to your local environment
|
54
|
+
# Change directory to the jupyterlab_quarto directory
|
37
55
|
# Install package in development mode
|
38
56
|
pip install -e "."
|
39
57
|
# Link your development version of the extension with JupyterLab
|
40
58
|
jupyter labextension develop . --overwrite
|
41
59
|
# Rebuild extension Typescript source after making changes
|
42
|
-
|
60
|
+
jlpm build
|
43
61
|
```
|
44
|
-
Note: You will need NodeJS to build the extension package.
|
45
|
-
|
46
|
-
Note: The `jlpm` command is JupyterLab's pinned version of
|
47
|
-
[yarn](https://yarnpkg.com/) that is installed with JupyterLab. You may use
|
48
|
-
`yarn` or `npm` in lieu of `jlpm` below.
|
49
62
|
|
50
63
|
You can watch the source directory and run JupyterLab at the same time in different terminals to watch for changes in the extension's source and automatically rebuild the extension.
|
51
64
|
|
52
65
|
```bash
|
53
66
|
# Watch the source directory in one terminal, automatically rebuilding when needed
|
54
|
-
|
67
|
+
jlpm watch
|
55
68
|
# Run JupyterLab in another terminal
|
56
69
|
jupyter lab
|
57
70
|
```
|
58
71
|
|
59
72
|
With the watch command running, every saved change will immediately be built locally and available in your running JupyterLab. Refresh JupyterLab to load the change in your browser (you may need to wait several seconds for the extension to be rebuilt).
|
60
73
|
|
61
|
-
By default, the `build` command generates the source maps for this extension to make it easier to debug using the browser dev tools. To also generate source maps for the JupyterLab core extensions, you can run the following command:
|
74
|
+
By default, the `jlpm build` command generates the source maps for this extension to make it easier to debug using the browser dev tools. To also generate source maps for the JupyterLab core extensions, you can run the following command:
|
62
75
|
|
63
76
|
```bash
|
64
77
|
jupyter lab build --minimize=False
|
@@ -67,12 +80,32 @@ jupyter lab build --minimize=False
|
|
67
80
|
### Development uninstall
|
68
81
|
|
69
82
|
```bash
|
70
|
-
pip uninstall
|
83
|
+
pip uninstall jupyterlab_quarto
|
71
84
|
```
|
72
85
|
|
73
86
|
In development mode, you will also need to remove the symlink created by `jupyter labextension develop`
|
74
87
|
command. To find its location, you can run `jupyter labextension list` to figure out where the `labextensions`
|
75
|
-
folder is located. Then you can remove the symlink named
|
88
|
+
folder is located. Then you can remove the symlink named `@quarto/jupyterlab-quarto` within that folder.
|
89
|
+
|
90
|
+
### Testing the extension
|
91
|
+
|
92
|
+
#### Frontend tests
|
93
|
+
|
94
|
+
This extension is using [Jest](https://jestjs.io/) for JavaScript code testing.
|
95
|
+
|
96
|
+
To execute them, execute:
|
97
|
+
|
98
|
+
```sh
|
99
|
+
jlpm
|
100
|
+
jlpm test
|
101
|
+
```
|
102
|
+
|
103
|
+
#### Integration tests
|
104
|
+
|
105
|
+
This extension uses [Playwright](https://playwright.dev/) for the integration tests (aka user level tests).
|
106
|
+
More precisely, the JupyterLab helper [Galata](https://github.com/jupyterlab/jupyterlab/tree/master/galata) is used to handle testing the extension in JupyterLab.
|
107
|
+
|
108
|
+
More information are provided within the [ui-tests](./ui-tests/README.md) README.
|
76
109
|
|
77
110
|
### Packaging the extension
|
78
111
|
|
package/lib/ast/ast.d.ts
CHANGED
package/lib/ast/ast.js
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
export const toAst = (toks) => {
|
2
2
|
let pos = 0;
|
3
3
|
const inner = () => {
|
4
|
-
if (pos >= toks.length)
|
4
|
+
if (pos >= toks.length) {
|
5
5
|
return;
|
6
|
+
}
|
6
7
|
const tok = toks[pos];
|
7
8
|
if (tok.type.endsWith('_open')) {
|
8
9
|
++pos;
|
@@ -31,9 +32,9 @@ export const toAst = (toks) => {
|
|
31
32
|
const result = [];
|
32
33
|
while (pos < toks.length) {
|
33
34
|
const node = inner();
|
34
|
-
if (node)
|
35
|
+
if (node) {
|
35
36
|
result.push(node);
|
37
|
+
}
|
36
38
|
}
|
37
39
|
return result;
|
38
40
|
};
|
39
|
-
//# sourceMappingURL=ast.js.map
|
package/lib/const.d.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import { Token } from '@lumino/coreutils';
|
2
|
-
import { MarkdownItManager } from
|
2
|
+
import { MarkdownItManager } from './types';
|
3
3
|
export declare const kPackageNamespace = "jupyterlab-quarto";
|
4
4
|
export declare const kMarkdownItMgr: Token<MarkdownItManager>;
|
5
|
-
//# sourceMappingURL=const.d.ts.map
|
package/lib/const.js
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
/*
|
2
|
-
* const.ts
|
3
|
-
*
|
4
|
-
* Copyright (C) 2020-2023 Posit Software, PBC
|
5
|
-
*
|
6
|
-
*/
|
2
|
+
* const.ts
|
3
|
+
*
|
4
|
+
* Copyright (C) 2020-2023 Posit Software, PBC
|
5
|
+
*
|
6
|
+
*/
|
7
7
|
import { Token } from '@lumino/coreutils';
|
8
8
|
// The namespace for this project
|
9
9
|
export const kPackageNamespace = 'jupyterlab-quarto';
|
10
10
|
// The MarkdownIt manager token.
|
11
11
|
export const kMarkdownItMgr = new Token(kPackageNamespace);
|
12
|
-
//# sourceMappingURL=const.js.map
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import { Hook } from
|
2
|
-
|
3
|
-
export declare
|
4
|
-
|
1
|
+
import { Hook } from '../types';
|
2
|
+
import { IEditorLanguageRegistry } from '@jupyterlab/codemirror';
|
3
|
+
export declare function codeMirrorPreloadHook(registry: IEditorLanguageRegistry): Hook<string, string>;
|
4
|
+
export declare const codeMirrorHighlighter: (languageRegistry: IEditorLanguageRegistry) => (str: string, lang: string, _attr: any) => string;
|
5
|
+
export declare const codeMirrorHighlight: (str: string, lang: string, registry: IEditorLanguageRegistry) => string;
|
package/lib/hooks/codemirror.js
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
/*
|
2
|
-
* hooks.ts
|
3
|
-
*
|
4
|
-
* Copyright (C) 2020-2023 Posit Software, PBC
|
5
|
-
*
|
6
|
-
*/
|
7
|
-
|
8
|
-
export function codeMirrorPreloadHook() {
|
2
|
+
* hooks.ts
|
3
|
+
*
|
4
|
+
* Copyright (C) 2020-2023 Posit Software, PBC
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
export function codeMirrorPreloadHook(registry) {
|
9
8
|
// TODO: Properly deal with {r}, {{r}} style expressions
|
10
9
|
const fenced = new RegExp(/^`{3}([^\s]+)/g);
|
11
10
|
return {
|
@@ -14,7 +13,7 @@ export function codeMirrorPreloadHook() {
|
|
14
13
|
let match;
|
15
14
|
while ((match = fenced.exec(source))) {
|
16
15
|
if (!newModes.has(match[1])) {
|
17
|
-
newModes.set(match[1],
|
16
|
+
newModes.set(match[1], registry.getLanguage(match[1]));
|
18
17
|
}
|
19
18
|
}
|
20
19
|
if (newModes.size) {
|
@@ -24,19 +23,46 @@ export function codeMirrorPreloadHook() {
|
|
24
23
|
}
|
25
24
|
};
|
26
25
|
}
|
27
|
-
export const
|
26
|
+
export const codeMirrorHighlighter = (languageRegistry) => {
|
27
|
+
return (str, lang, _attr) => {
|
28
|
+
if (!lang) {
|
29
|
+
return ''; // use external default escaping
|
30
|
+
}
|
31
|
+
try {
|
32
|
+
const spec = languageRegistry.findBest(lang);
|
33
|
+
if (!spec) {
|
34
|
+
console.warn(`No CodeMirror mode: ${lang}`);
|
35
|
+
return '';
|
36
|
+
}
|
37
|
+
const el = document.createElement('div');
|
38
|
+
try {
|
39
|
+
languageRegistry.highlight(str, spec, el);
|
40
|
+
return el.innerHTML;
|
41
|
+
}
|
42
|
+
catch (err) {
|
43
|
+
console.warn(`Failed to highlight ${lang} code`, err);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
catch (err) {
|
47
|
+
console.warn(`No CodeMirror mode: ${lang}`);
|
48
|
+
console.warn(`Require CodeMirror mode error: ${err}`);
|
49
|
+
}
|
50
|
+
return '';
|
51
|
+
};
|
52
|
+
};
|
53
|
+
export const codeMirrorHighlight = (str, lang, registry) => {
|
28
54
|
if (!lang) {
|
29
55
|
return ''; // use external default escaping
|
30
56
|
}
|
31
57
|
try {
|
32
|
-
const spec =
|
58
|
+
const spec = registry.findBest(lang);
|
33
59
|
if (!spec) {
|
34
60
|
console.warn(`No CodeMirror mode: ${lang}`);
|
35
61
|
return '';
|
36
62
|
}
|
37
63
|
const el = document.createElement('div');
|
38
64
|
try {
|
39
|
-
|
65
|
+
registry.highlight(str, spec, el);
|
40
66
|
return el.innerHTML;
|
41
67
|
}
|
42
68
|
catch (err) {
|
@@ -49,4 +75,3 @@ export const codeMirrorHighlight = (str, lang) => {
|
|
49
75
|
}
|
50
76
|
return '';
|
51
77
|
};
|
52
|
-
//# sourceMappingURL=codemirror.js.map
|
package/lib/index.d.ts
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
import {
|
1
|
+
import { JupyterFrontEndPlugin } from '@jupyterlab/application';
|
2
2
|
import { MarkdownItManager } from './types';
|
3
3
|
import '../style/index.css';
|
4
|
-
declare const _default: (JupyterFrontEndPlugin<void
|
4
|
+
declare const _default: (JupyterFrontEndPlugin<void> | JupyterFrontEndPlugin<MarkdownItManager>)[];
|
5
5
|
export default _default;
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import { IEditorLanguageRegistry, IEditorThemeRegistry } from '@jupyterlab/codemirror';
|
1
2
|
import { mermaid } from './providers/mermaid';
|
2
3
|
import { kMarkdownItMgr, kPackageNamespace } from './const';
|
3
4
|
import { footnotes } from './providers/footnotes';
|
@@ -24,10 +25,11 @@ const plugin = {
|
|
24
25
|
id: `${kPackageNamespace}:plugin`,
|
25
26
|
autoStart: true,
|
26
27
|
provides: kMarkdownItMgr,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
requires: [IEditorThemeRegistry, IEditorLanguageRegistry],
|
29
|
+
activate: (_app, themeRegistry, languageRegistry) => {
|
30
|
+
console.log('JupyterLab extension @quarto/jupyterlab-quarto is activated!');
|
31
|
+
// Create a markdown rendering manager
|
32
|
+
return markdownItManager(themeRegistry, languageRegistry);
|
31
33
|
}
|
32
34
|
};
|
33
35
|
// Markdown It Extensions which provide base Pandoc behavior
|
@@ -57,4 +59,3 @@ const kQuartoExtensions = [
|
|
57
59
|
];
|
58
60
|
// The extensions that should be enabled for Jupyter
|
59
61
|
export default [plugin, ...kPandocExtensions, ...kQuartoExtensions];
|
60
|
-
//# sourceMappingURL=index.js.map
|
package/lib/manager.d.ts
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
+
import { IEditorLanguageRegistry, IEditorThemeRegistry } from '@jupyterlab/codemirror';
|
1
2
|
import { Options } from 'markdown-it';
|
2
3
|
import { RenderedMarkdown } from './widgets';
|
3
4
|
import { MarkdownItPluginProvider, Renderer } from './types';
|
4
|
-
export declare function markdownItManager(): {
|
5
|
+
export declare function markdownItManager(themeRegistry: IEditorThemeRegistry, languageRegistry: IEditorLanguageRegistry): {
|
5
6
|
registerPlugin(provider: MarkdownItPluginProvider): void;
|
6
7
|
getRenderer(widget: RenderedMarkdown, options?: Options): Promise<Renderer>;
|
7
8
|
};
|
8
|
-
//# sourceMappingURL=manager.d.ts.map
|
package/lib/manager.js
CHANGED
@@ -1,24 +1,23 @@
|
|
1
1
|
/*
|
2
|
-
* manager.ts
|
3
|
-
*
|
4
|
-
* Copyright (C) 2020-2023 Posit Software, PBC
|
5
|
-
*
|
6
|
-
*/
|
2
|
+
* manager.ts
|
3
|
+
*
|
4
|
+
* Copyright (C) 2020-2023 Posit Software, PBC
|
5
|
+
*
|
6
|
+
*/
|
7
7
|
import { markdownRendererFactory } from '@jupyterlab/rendermime';
|
8
|
-
import { CodeMirrorEditor } from '@jupyterlab/codemirror';
|
9
8
|
import MarkdownIt from 'markdown-it';
|
10
9
|
import { RenderedMarkdown } from './widgets';
|
11
|
-
import {
|
10
|
+
import { codeMirrorHighlighter, codeMirrorPreloadHook } from './hooks/codemirror';
|
12
11
|
// Provides resolved MarkdownIt options using the passed in options, the plugin
|
13
12
|
// options, and default options.
|
14
|
-
const resolveOptions = (widget, options, providers) => {
|
13
|
+
const resolveOptions = (widget, options, providers, themeRegistry, languageRegistry) => {
|
15
14
|
// Build options table
|
16
15
|
let allOptions = {
|
17
16
|
html: true,
|
18
17
|
linkify: true,
|
19
18
|
typographer: true,
|
20
|
-
langPrefix: `cm-s-${
|
21
|
-
highlight:
|
19
|
+
langPrefix: `cm-s-${themeRegistry.defaultTheme} language-`,
|
20
|
+
highlight: codeMirrorHighlighter(languageRegistry)
|
22
21
|
};
|
23
22
|
for (const plugin of providers) {
|
24
23
|
if (plugin.options) {
|
@@ -36,7 +35,7 @@ const resolveOptions = (widget, options, providers) => {
|
|
36
35
|
...options
|
37
36
|
};
|
38
37
|
};
|
39
|
-
export function markdownItManager() {
|
38
|
+
export function markdownItManager(themeRegistry, languageRegistry) {
|
40
39
|
// The plugin providers
|
41
40
|
const pluginProviders = new Map();
|
42
41
|
// The IMarkdownItManager
|
@@ -50,14 +49,14 @@ export function markdownItManager() {
|
|
50
49
|
const providers = [...pluginProviders.values()];
|
51
50
|
providers.sort(sortRanked);
|
52
51
|
// Create MarkdownIt instance
|
53
|
-
const allOptions = resolveOptions(widget, options, providers);
|
52
|
+
const allOptions = resolveOptions(widget, options, providers, themeRegistry, languageRegistry);
|
54
53
|
let md = new MarkdownIt('default', allOptions);
|
55
54
|
// Lifecycle hooks
|
56
55
|
const preParseHooks = [];
|
57
56
|
const postRenderHooks = [];
|
58
57
|
// add mode pre-loading hook if using default highlighter
|
59
|
-
if (
|
60
|
-
preParseHooks.push(codeMirrorPreloadHook());
|
58
|
+
if (codeMirrorHighlighter(languageRegistry) === allOptions.highlight) {
|
59
|
+
preParseHooks.push(codeMirrorPreloadHook(languageRegistry));
|
61
60
|
}
|
62
61
|
// Build MarkdownIt and load lifecycle hooks
|
63
62
|
for (const provider of providers) {
|
@@ -83,7 +82,7 @@ export function markdownItManager() {
|
|
83
82
|
postRenderHooks.sort(sortRanked);
|
84
83
|
return {
|
85
84
|
// Parse and render Markdown
|
86
|
-
render:
|
85
|
+
render: content => {
|
87
86
|
return md.render(content);
|
88
87
|
},
|
89
88
|
// Run hooks serially
|
@@ -114,4 +113,3 @@ const sortRanked = (left, right) => {
|
|
114
113
|
var _a, _b;
|
115
114
|
return ((_a = left.rank) !== null && _a !== void 0 ? _a : kDefaultRank) - ((_b = right.rank) !== null && _b !== void 0 ? _b : kDefaultRank);
|
116
115
|
};
|
117
|
-
//# sourceMappingURL=manager.js.map
|
package/lib/plugins/callouts.js
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
import Token from
|
2
|
-
import { addClass, readAttrValue } from
|
3
|
-
import { kTokDivClose, kTokDivOpen } from
|
4
|
-
const kTokCalloutOpen =
|
5
|
-
const kTokCalloutClose =
|
6
|
-
const kTokCalloutTitleOpen =
|
7
|
-
const kTokCalloutTitleClose =
|
8
|
-
const kTokCalloutContentOpen =
|
9
|
-
const kTokCalloutContentClose =
|
10
|
-
const kCalloutPrefix =
|
11
|
-
const kCalloutRuleName =
|
1
|
+
import Token from 'markdown-it/lib/token';
|
2
|
+
import { addClass, readAttrValue } from './utils/markdownit';
|
3
|
+
import { kTokDivClose, kTokDivOpen } from './divs';
|
4
|
+
const kTokCalloutOpen = 'quarto_callout_open';
|
5
|
+
const kTokCalloutClose = 'quarto_callout_close';
|
6
|
+
const kTokCalloutTitleOpen = 'quarto_callout_title_open';
|
7
|
+
const kTokCalloutTitleClose = 'quarto_callout_title_close';
|
8
|
+
const kTokCalloutContentOpen = 'quarto_callout_content_open';
|
9
|
+
const kTokCalloutContentClose = 'quarto_callout_content_close';
|
10
|
+
const kCalloutPrefix = 'callout-';
|
11
|
+
const kCalloutRuleName = 'quarto-callouts';
|
12
12
|
export const calloutPlugin = (md) => {
|
13
13
|
// Handle pandoc-style divs
|
14
|
-
md.core.ruler.push(kCalloutRuleName,
|
14
|
+
md.core.ruler.push(kCalloutRuleName, state => {
|
15
15
|
const noteStartCallout = (callout, depth) => {
|
16
|
-
if (calloutDepth
|
16
|
+
if (calloutDepth === -1) {
|
17
17
|
calloutDepth = depth;
|
18
18
|
}
|
19
19
|
state.env['quarto-active-callout'] = callout;
|
@@ -29,28 +29,28 @@ export const calloutPlugin = (md) => {
|
|
29
29
|
return calloutDepth === depth;
|
30
30
|
};
|
31
31
|
const titleOpenTok = (title) => {
|
32
|
-
const token = new Token(kTokCalloutTitleOpen,
|
33
|
-
token.tag =
|
34
|
-
token.attrs = [[
|
32
|
+
const token = new Token(kTokCalloutTitleOpen, '', 1);
|
33
|
+
token.tag = 'div';
|
34
|
+
token.attrs = [['class', 'callout-header']];
|
35
35
|
if (title) {
|
36
|
-
token.attrs.push([
|
36
|
+
token.attrs.push(['title', title]);
|
37
37
|
}
|
38
38
|
return token;
|
39
39
|
};
|
40
40
|
const titleCloseTok = () => {
|
41
|
-
const token = new Token(kTokCalloutTitleClose,
|
42
|
-
token.tag =
|
41
|
+
const token = new Token(kTokCalloutTitleClose, '', -1);
|
42
|
+
token.tag = 'div';
|
43
43
|
return token;
|
44
44
|
};
|
45
45
|
const contentOpenTok = () => {
|
46
|
-
const token = new Token(kTokCalloutContentOpen,
|
47
|
-
token.tag =
|
48
|
-
token.attrs = [[
|
46
|
+
const token = new Token(kTokCalloutContentOpen, '', 1);
|
47
|
+
token.tag = 'div';
|
48
|
+
token.attrs = [['class', 'callout-body-container callout-body']];
|
49
49
|
return token;
|
50
50
|
};
|
51
51
|
const contentCloseTok = () => {
|
52
|
-
const token = new Token(kTokCalloutContentClose,
|
53
|
-
token.tag =
|
52
|
+
const token = new Token(kTokCalloutContentClose, '', -1);
|
53
|
+
token.tag = 'div';
|
54
54
|
return token;
|
55
55
|
};
|
56
56
|
const outTokens = [];
|
@@ -58,44 +58,44 @@ export const calloutPlugin = (md) => {
|
|
58
58
|
let divDepth = 0;
|
59
59
|
// just started callout - process title
|
60
60
|
// finished processing title - process content
|
61
|
-
let calloutState =
|
61
|
+
let calloutState = 'scanning';
|
62
62
|
for (const token of state.tokens) {
|
63
63
|
switch (calloutState) {
|
64
|
-
case
|
65
|
-
if (token.type ===
|
64
|
+
case 'add-title':
|
65
|
+
if (token.type === 'heading_open') {
|
66
66
|
outTokens.push(titleOpenTok());
|
67
|
-
calloutState =
|
67
|
+
calloutState = 'capturing-title';
|
68
68
|
}
|
69
69
|
else {
|
70
70
|
const callout = activeCallout();
|
71
71
|
outTokens.push(titleOpenTok(callout.title));
|
72
72
|
outTokens.push(titleCloseTok());
|
73
|
-
calloutState =
|
73
|
+
calloutState = 'add-body';
|
74
74
|
}
|
75
75
|
break;
|
76
|
-
case
|
77
|
-
if (token.type ===
|
76
|
+
case 'capturing-title':
|
77
|
+
if (token.type === 'heading_close') {
|
78
78
|
outTokens.push(titleCloseTok());
|
79
|
-
calloutState =
|
79
|
+
calloutState = 'add-body';
|
80
80
|
}
|
81
81
|
else {
|
82
82
|
outTokens.push(token);
|
83
83
|
}
|
84
84
|
break;
|
85
|
-
case
|
85
|
+
case 'add-body':
|
86
86
|
outTokens.push(contentOpenTok());
|
87
87
|
outTokens.push(token);
|
88
|
-
calloutState =
|
88
|
+
calloutState = 'capturing-body';
|
89
89
|
break;
|
90
|
-
case
|
90
|
+
case 'scanning':
|
91
91
|
default:
|
92
92
|
if (token.type === kTokDivOpen) {
|
93
93
|
divDepth++;
|
94
94
|
const callout = parseCallout(token.attrs);
|
95
95
|
if (callout) {
|
96
96
|
noteStartCallout(callout, divDepth);
|
97
|
-
calloutState =
|
98
|
-
const openCallout = new Token(kTokCalloutOpen,
|
97
|
+
calloutState = 'add-title';
|
98
|
+
const openCallout = new Token(kTokCalloutOpen, '', 1);
|
99
99
|
openCallout.attrs = openCallout.attrs || [];
|
100
100
|
openCallout.meta = callout;
|
101
101
|
outTokens.push(openCallout);
|
@@ -107,7 +107,7 @@ export const calloutPlugin = (md) => {
|
|
107
107
|
else if (token.type === kTokDivClose) {
|
108
108
|
if (isCloseCallout(divDepth)) {
|
109
109
|
outTokens.push(contentCloseTok());
|
110
|
-
outTokens.push(new Token(kTokCalloutClose,
|
110
|
+
outTokens.push(new Token(kTokCalloutClose, '', -1));
|
111
111
|
noteCloseCallout();
|
112
112
|
}
|
113
113
|
else {
|
@@ -141,11 +141,11 @@ function renderStartCallout(tokens, idx, _options, _env, self) {
|
|
141
141
|
}
|
142
142
|
// Render pandoc-style divs
|
143
143
|
function renderEndCallout() {
|
144
|
-
return
|
144
|
+
return '</div>';
|
145
145
|
}
|
146
146
|
function renderStartCalloutTitle(tokens, idx) {
|
147
147
|
const token = tokens[idx];
|
148
|
-
const title = readAttrValue(
|
148
|
+
const title = readAttrValue('title', token.attrs) || '';
|
149
149
|
const startContent = `
|
150
150
|
<div class="callout-header">
|
151
151
|
<div class="callout-icon-container">
|
@@ -156,43 +156,45 @@ function renderStartCalloutTitle(tokens, idx) {
|
|
156
156
|
return startContent;
|
157
157
|
}
|
158
158
|
function renderEndCalloutTitle() {
|
159
|
-
return
|
159
|
+
return '</div>\n</div>';
|
160
160
|
}
|
161
161
|
const calloutAppearance = (val) => {
|
162
162
|
if (val) {
|
163
163
|
switch (val) {
|
164
|
-
case
|
165
|
-
return
|
166
|
-
case
|
167
|
-
return
|
168
|
-
case
|
164
|
+
case 'minimal':
|
165
|
+
return 'minimal';
|
166
|
+
case 'simple':
|
167
|
+
return 'simple';
|
168
|
+
case 'default':
|
169
169
|
default:
|
170
|
-
return
|
170
|
+
return 'default';
|
171
171
|
}
|
172
172
|
}
|
173
173
|
else {
|
174
|
-
return
|
174
|
+
return 'default';
|
175
175
|
}
|
176
176
|
};
|
177
177
|
const parseCallout = (attrs) => {
|
178
178
|
if (attrs === null) {
|
179
179
|
return undefined;
|
180
180
|
}
|
181
|
-
const classAttr = attrs.find(
|
181
|
+
const classAttr = attrs.find(attr => {
|
182
|
+
return attr[0] === 'class';
|
183
|
+
});
|
182
184
|
if (!classAttr) {
|
183
185
|
return undefined;
|
184
186
|
}
|
185
|
-
const classes = classAttr[1].split(
|
186
|
-
const calloutClass = classes.find(
|
187
|
+
const classes = classAttr[1].split(' ');
|
188
|
+
const calloutClass = classes.find(clz => {
|
187
189
|
return clz.startsWith('callout-');
|
188
190
|
});
|
189
191
|
if (calloutClass) {
|
190
|
-
const type = calloutClass.replace(kCalloutPrefix,
|
191
|
-
const title = readAttrValue(
|
192
|
-
|
193
|
-
const appearance = calloutAppearance(readAttrValue(
|
192
|
+
const type = calloutClass.replace(kCalloutPrefix, '');
|
193
|
+
const title = readAttrValue('title', attrs) ||
|
194
|
+
type.slice(0, 1).toUpperCase() + type.slice(1);
|
195
|
+
const appearance = calloutAppearance(readAttrValue('appearance', attrs));
|
194
196
|
return {
|
195
|
-
type: type ||
|
197
|
+
type: type || 'note',
|
196
198
|
clz: calloutClass,
|
197
199
|
title,
|
198
200
|
appearance
|
@@ -203,7 +205,6 @@ const parseCallout = (attrs) => {
|
|
203
205
|
}
|
204
206
|
};
|
205
207
|
const appearanceClass = (appearance) => {
|
206
|
-
const style = appearance ||
|
208
|
+
const style = appearance || 'default';
|
207
209
|
return `callout-style-${style}`;
|
208
210
|
};
|
209
|
-
//# sourceMappingURL=callouts.js.map
|