@jupyterlab/markdownviewer 4.0.0-alpha.9 → 4.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/toc.d.ts +67 -0
- package/lib/toc.js +126 -0
- package/lib/toc.js.map +1 -0
- package/lib/widget.d.ts +6 -0
- package/lib/widget.js +16 -2
- package/lib/widget.js.map +1 -1
- package/package.json +15 -12
- package/src/index.ts +10 -0
- package/src/toc.ts +195 -0
- package/src/tokens.ts +19 -0
- package/src/widget.ts +392 -0
- package/style/index.css +1 -0
- package/style/index.js +1 -0
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,2DAA2D;AAC3D;;;GAGG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,2DAA2D;AAC3D;;;GAGG;AAEH,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
|
package/lib/toc.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { IWidgetTracker } from '@jupyterlab/apputils';
|
|
2
|
+
import { IMarkdownParser } from '@jupyterlab/rendermime';
|
|
3
|
+
import { TableOfContents, TableOfContentsFactory, TableOfContentsModel, TableOfContentsUtils } from '@jupyterlab/toc';
|
|
4
|
+
import { MarkdownDocument } from './widget';
|
|
5
|
+
/**
|
|
6
|
+
* Interface describing a Markdown viewer heading.
|
|
7
|
+
*/
|
|
8
|
+
export interface IMarkdownViewerHeading extends TableOfContentsUtils.Markdown.IMarkdownHeading {
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Table of content model for Markdown viewer files.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MarkdownViewerTableOfContentsModel extends TableOfContentsModel<IMarkdownViewerHeading, MarkdownDocument> {
|
|
14
|
+
protected parser: IMarkdownParser | null;
|
|
15
|
+
/**
|
|
16
|
+
* Constructor
|
|
17
|
+
*
|
|
18
|
+
* @param widget The widget to search in
|
|
19
|
+
* @param parser Markdown parser
|
|
20
|
+
* @param configuration Default model configuration
|
|
21
|
+
*/
|
|
22
|
+
constructor(widget: MarkdownDocument, parser: IMarkdownParser | null, configuration?: TableOfContents.IConfig);
|
|
23
|
+
/**
|
|
24
|
+
* Type of document supported by the model.
|
|
25
|
+
*
|
|
26
|
+
* #### Notes
|
|
27
|
+
* A `data-document-type` attribute with this value will be set
|
|
28
|
+
* on the tree view `.jp-TableOfContents-content[data-document-type="..."]`
|
|
29
|
+
*/
|
|
30
|
+
get documentType(): string;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the model gets updated even if the table of contents panel
|
|
33
|
+
* is hidden or not.
|
|
34
|
+
*/
|
|
35
|
+
protected get isAlwaysActive(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* List of configuration options supported by the model.
|
|
38
|
+
*/
|
|
39
|
+
get supportedOptions(): (keyof TableOfContents.IConfig)[];
|
|
40
|
+
/**
|
|
41
|
+
* Produce the headings for a document.
|
|
42
|
+
*
|
|
43
|
+
* @returns The list of new headings or `null` if nothing needs to be updated.
|
|
44
|
+
*/
|
|
45
|
+
protected getHeadings(): Promise<IMarkdownViewerHeading[] | null>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Table of content model factory for Markdown viewer files.
|
|
49
|
+
*/
|
|
50
|
+
export declare class MarkdownViewerTableOfContentsFactory extends TableOfContentsFactory<MarkdownDocument> {
|
|
51
|
+
protected parser: IMarkdownParser | null;
|
|
52
|
+
/**
|
|
53
|
+
* Constructor
|
|
54
|
+
*
|
|
55
|
+
* @param tracker Widget tracker
|
|
56
|
+
* @param parser Markdown parser
|
|
57
|
+
*/
|
|
58
|
+
constructor(tracker: IWidgetTracker<MarkdownDocument>, parser: IMarkdownParser | null);
|
|
59
|
+
/**
|
|
60
|
+
* Create a new table of contents model for the widget
|
|
61
|
+
*
|
|
62
|
+
* @param widget - widget
|
|
63
|
+
* @param configuration - Table of contents configuration
|
|
64
|
+
* @returns The table of contents model
|
|
65
|
+
*/
|
|
66
|
+
protected _createNew(widget: MarkdownDocument, configuration?: TableOfContents.IConfig): TableOfContentsModel<TableOfContents.IHeading, MarkdownDocument>;
|
|
67
|
+
}
|
package/lib/toc.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
import { TableOfContentsFactory, TableOfContentsModel, TableOfContentsUtils } from '@jupyterlab/toc';
|
|
4
|
+
/**
|
|
5
|
+
* Table of content model for Markdown viewer files.
|
|
6
|
+
*/
|
|
7
|
+
export class MarkdownViewerTableOfContentsModel extends TableOfContentsModel {
|
|
8
|
+
/**
|
|
9
|
+
* Constructor
|
|
10
|
+
*
|
|
11
|
+
* @param widget The widget to search in
|
|
12
|
+
* @param parser Markdown parser
|
|
13
|
+
* @param configuration Default model configuration
|
|
14
|
+
*/
|
|
15
|
+
constructor(widget, parser, configuration) {
|
|
16
|
+
super(widget, configuration);
|
|
17
|
+
this.parser = parser;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Type of document supported by the model.
|
|
21
|
+
*
|
|
22
|
+
* #### Notes
|
|
23
|
+
* A `data-document-type` attribute with this value will be set
|
|
24
|
+
* on the tree view `.jp-TableOfContents-content[data-document-type="..."]`
|
|
25
|
+
*/
|
|
26
|
+
get documentType() {
|
|
27
|
+
return 'markdown-viewer';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Whether the model gets updated even if the table of contents panel
|
|
31
|
+
* is hidden or not.
|
|
32
|
+
*/
|
|
33
|
+
get isAlwaysActive() {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* List of configuration options supported by the model.
|
|
38
|
+
*/
|
|
39
|
+
get supportedOptions() {
|
|
40
|
+
return ['maximalDepth', 'numberingH1', 'numberHeaders'];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Produce the headings for a document.
|
|
44
|
+
*
|
|
45
|
+
* @returns The list of new headings or `null` if nothing needs to be updated.
|
|
46
|
+
*/
|
|
47
|
+
getHeadings() {
|
|
48
|
+
const content = this.widget.context.model.toString();
|
|
49
|
+
const headings = TableOfContentsUtils.filterHeadings(TableOfContentsUtils.Markdown.getHeadings(content), {
|
|
50
|
+
...this.configuration,
|
|
51
|
+
// Force base number to be equal to 1
|
|
52
|
+
baseNumbering: 1
|
|
53
|
+
});
|
|
54
|
+
return Promise.resolve(headings);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Table of content model factory for Markdown viewer files.
|
|
59
|
+
*/
|
|
60
|
+
export class MarkdownViewerTableOfContentsFactory extends TableOfContentsFactory {
|
|
61
|
+
/**
|
|
62
|
+
* Constructor
|
|
63
|
+
*
|
|
64
|
+
* @param tracker Widget tracker
|
|
65
|
+
* @param parser Markdown parser
|
|
66
|
+
*/
|
|
67
|
+
constructor(tracker, parser) {
|
|
68
|
+
super(tracker);
|
|
69
|
+
this.parser = parser;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a new table of contents model for the widget
|
|
73
|
+
*
|
|
74
|
+
* @param widget - widget
|
|
75
|
+
* @param configuration - Table of contents configuration
|
|
76
|
+
* @returns The table of contents model
|
|
77
|
+
*/
|
|
78
|
+
_createNew(widget, configuration) {
|
|
79
|
+
const model = new MarkdownViewerTableOfContentsModel(widget, this.parser, configuration);
|
|
80
|
+
let headingToElement = new WeakMap();
|
|
81
|
+
const onActiveHeadingChanged = (model, heading) => {
|
|
82
|
+
if (heading) {
|
|
83
|
+
const el = headingToElement.get(heading);
|
|
84
|
+
if (el) {
|
|
85
|
+
const widgetBox = widget.content.node.getBoundingClientRect();
|
|
86
|
+
const elementBox = el.getBoundingClientRect();
|
|
87
|
+
if (elementBox.top > widgetBox.bottom ||
|
|
88
|
+
elementBox.bottom < widgetBox.top) {
|
|
89
|
+
el.scrollIntoView({ block: 'center' });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const onHeadingsChanged = () => {
|
|
95
|
+
if (!this.parser) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Clear all numbering items
|
|
99
|
+
TableOfContentsUtils.clearNumbering(widget.content.node);
|
|
100
|
+
// Create a new mapping
|
|
101
|
+
headingToElement = new WeakMap();
|
|
102
|
+
model.headings.forEach(async (heading) => {
|
|
103
|
+
var _a;
|
|
104
|
+
const elementId = await TableOfContentsUtils.Markdown.getHeadingId(this.parser, heading.raw, heading.level);
|
|
105
|
+
if (!elementId) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const selector = `h${heading.level}[id="${elementId}"]`;
|
|
109
|
+
headingToElement.set(heading, TableOfContentsUtils.addPrefix(widget.content.node, selector, (_a = heading.prefix) !== null && _a !== void 0 ? _a : ''));
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
void widget.content.ready.then(() => {
|
|
113
|
+
onHeadingsChanged();
|
|
114
|
+
widget.content.rendered.connect(onHeadingsChanged);
|
|
115
|
+
model.activeHeadingChanged.connect(onActiveHeadingChanged);
|
|
116
|
+
model.headingsChanged.connect(onHeadingsChanged);
|
|
117
|
+
widget.disposed.connect(() => {
|
|
118
|
+
widget.content.rendered.disconnect(onHeadingsChanged);
|
|
119
|
+
model.activeHeadingChanged.disconnect(onActiveHeadingChanged);
|
|
120
|
+
model.headingsChanged.disconnect(onHeadingsChanged);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
return model;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=toc.js.map
|
package/lib/toc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toc.js","sourceRoot":"","sources":["../src/toc.ts"],"names":[],"mappings":"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"}
|
package/lib/widget.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ABCWidgetFactory, DocumentRegistry, DocumentWidget } from '@jupyterlab/
|
|
|
2
2
|
import { IRenderMime, IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
3
3
|
import { ITranslator } from '@jupyterlab/translation';
|
|
4
4
|
import { Message } from '@lumino/messaging';
|
|
5
|
+
import { ISignal } from '@lumino/signaling';
|
|
5
6
|
import { Widget } from '@lumino/widgets';
|
|
6
7
|
/**
|
|
7
8
|
* A widget for markdown documents.
|
|
@@ -15,6 +16,10 @@ export declare class MarkdownViewer extends Widget {
|
|
|
15
16
|
* A promise that resolves when the markdown viewer is ready.
|
|
16
17
|
*/
|
|
17
18
|
get ready(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Signal emitted when the content has been rendered.
|
|
21
|
+
*/
|
|
22
|
+
get rendered(): ISignal<MarkdownViewer, void>;
|
|
18
23
|
/**
|
|
19
24
|
* Set URI fragment identifier.
|
|
20
25
|
*/
|
|
@@ -49,6 +54,7 @@ export declare class MarkdownViewer extends Widget {
|
|
|
49
54
|
private _ready;
|
|
50
55
|
private _isRendering;
|
|
51
56
|
private _renderRequested;
|
|
57
|
+
private _rendered;
|
|
52
58
|
}
|
|
53
59
|
/**
|
|
54
60
|
* The namespace for MarkdownViewer class statics.
|
package/lib/widget.js
CHANGED
|
@@ -6,6 +6,7 @@ import { ABCWidgetFactory, DocumentWidget } from '@jupyterlab/docregistry';
|
|
|
6
6
|
import { MimeModel } from '@jupyterlab/rendermime';
|
|
7
7
|
import { nullTranslator } from '@jupyterlab/translation';
|
|
8
8
|
import { PromiseDelegate } from '@lumino/coreutils';
|
|
9
|
+
import { Signal } from '@lumino/signaling';
|
|
9
10
|
import { StackedLayout, Widget } from '@lumino/widgets';
|
|
10
11
|
/**
|
|
11
12
|
* The class name added to a markdown viewer.
|
|
@@ -24,11 +25,12 @@ export class MarkdownViewer extends Widget {
|
|
|
24
25
|
*/
|
|
25
26
|
constructor(options) {
|
|
26
27
|
super();
|
|
27
|
-
this._config =
|
|
28
|
+
this._config = { ...MarkdownViewer.defaultConfig };
|
|
28
29
|
this._fragment = '';
|
|
29
30
|
this._ready = new PromiseDelegate();
|
|
30
31
|
this._isRendering = false;
|
|
31
32
|
this._renderRequested = false;
|
|
33
|
+
this._rendered = new Signal(this);
|
|
32
34
|
this.context = options.context;
|
|
33
35
|
this.translator = options.translator || nullTranslator;
|
|
34
36
|
this._trans = this.translator.load('jupyterlab');
|
|
@@ -54,6 +56,12 @@ export class MarkdownViewer extends Widget {
|
|
|
54
56
|
get ready() {
|
|
55
57
|
return this._ready.promise;
|
|
56
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Signal emitted when the content has been rendered.
|
|
61
|
+
*/
|
|
62
|
+
get rendered() {
|
|
63
|
+
return this._rendered;
|
|
64
|
+
}
|
|
57
65
|
/**
|
|
58
66
|
* Set URI fragment identifier.
|
|
59
67
|
*/
|
|
@@ -162,6 +170,9 @@ export class MarkdownViewer extends Widget {
|
|
|
162
170
|
if (this._renderRequested) {
|
|
163
171
|
return this._render();
|
|
164
172
|
}
|
|
173
|
+
else {
|
|
174
|
+
this._rendered.emit();
|
|
175
|
+
}
|
|
165
176
|
}
|
|
166
177
|
catch (reason) {
|
|
167
178
|
// Dispose the document if rendering fails.
|
|
@@ -234,7 +245,10 @@ var Private;
|
|
|
234
245
|
* Create the document registry options.
|
|
235
246
|
*/
|
|
236
247
|
function createRegistryOptions(options) {
|
|
237
|
-
return
|
|
248
|
+
return {
|
|
249
|
+
...options,
|
|
250
|
+
readOnly: true
|
|
251
|
+
};
|
|
238
252
|
}
|
|
239
253
|
Private.createRegistryOptions = createRegistryOptions;
|
|
240
254
|
/**
|
package/lib/widget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,2DAA2D;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,gBAAgB,EAEhB,cAAc,EACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,SAAS,EACV,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,cAAc,EAEf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAc,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEhE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAExD;;GAEG;AACH,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AAEjD;;GAEG;AACH,MAAM,QAAQ,GAAG,eAAe,CAAC;AAEjC;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,MAAM;IACxC;;OAEG;IACH,YAAY,OAAgC;QAC1C,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlab/markdownviewer",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-beta.1",
|
|
4
4
|
"description": "JupyterLab - Markdown viewer Widget",
|
|
5
5
|
"homepage": "https://github.com/jupyterlab/jupyterlab",
|
|
6
6
|
"bugs": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"lib/*.js.map",
|
|
28
28
|
"lib/*.js",
|
|
29
29
|
"style/*.css",
|
|
30
|
-
"style/index.js"
|
|
30
|
+
"style/index.js",
|
|
31
|
+
"src/**/*.{ts,tsx}"
|
|
31
32
|
],
|
|
32
33
|
"scripts": {
|
|
33
34
|
"build": "tsc -b",
|
|
@@ -36,19 +37,21 @@
|
|
|
36
37
|
"watch": "tsc -b --watch"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
|
-
"@jupyterlab/apputils": "^4.0.0-
|
|
40
|
-
"@jupyterlab/coreutils": "^6.0.0-
|
|
41
|
-
"@jupyterlab/docregistry": "^4.0.0-
|
|
42
|
-
"@jupyterlab/rendermime": "^4.0.0-
|
|
43
|
-
"@jupyterlab/
|
|
44
|
-
"@
|
|
45
|
-
"@lumino/
|
|
46
|
-
"@lumino/
|
|
40
|
+
"@jupyterlab/apputils": "^4.0.0-beta.1",
|
|
41
|
+
"@jupyterlab/coreutils": "^6.0.0-beta.1",
|
|
42
|
+
"@jupyterlab/docregistry": "^4.0.0-beta.1",
|
|
43
|
+
"@jupyterlab/rendermime": "^4.0.0-beta.1",
|
|
44
|
+
"@jupyterlab/toc": "^6.0.0-beta.1",
|
|
45
|
+
"@jupyterlab/translation": "^4.0.0-beta.1",
|
|
46
|
+
"@lumino/coreutils": "^2.0.0",
|
|
47
|
+
"@lumino/messaging": "^2.0.0",
|
|
48
|
+
"@lumino/signaling": "^2.0.0",
|
|
49
|
+
"@lumino/widgets": "^2.0.1"
|
|
47
50
|
},
|
|
48
51
|
"devDependencies": {
|
|
49
52
|
"rimraf": "~3.0.0",
|
|
50
|
-
"typedoc": "~0.
|
|
51
|
-
"typescript": "~
|
|
53
|
+
"typedoc": "~0.23.25",
|
|
54
|
+
"typescript": "~5.0.2"
|
|
52
55
|
},
|
|
53
56
|
"publishConfig": {
|
|
54
57
|
"access": "public"
|
package/src/index.ts
ADDED
package/src/toc.ts
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
|
|
4
|
+
import { IWidgetTracker } from '@jupyterlab/apputils';
|
|
5
|
+
import { IMarkdownParser } from '@jupyterlab/rendermime';
|
|
6
|
+
import {
|
|
7
|
+
TableOfContents,
|
|
8
|
+
TableOfContentsFactory,
|
|
9
|
+
TableOfContentsModel,
|
|
10
|
+
TableOfContentsUtils
|
|
11
|
+
} from '@jupyterlab/toc';
|
|
12
|
+
import { MarkdownDocument } from './widget';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Interface describing a Markdown viewer heading.
|
|
16
|
+
*/
|
|
17
|
+
export interface IMarkdownViewerHeading
|
|
18
|
+
extends TableOfContentsUtils.Markdown.IMarkdownHeading {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Table of content model for Markdown viewer files.
|
|
22
|
+
*/
|
|
23
|
+
export class MarkdownViewerTableOfContentsModel extends TableOfContentsModel<
|
|
24
|
+
IMarkdownViewerHeading,
|
|
25
|
+
MarkdownDocument
|
|
26
|
+
> {
|
|
27
|
+
/**
|
|
28
|
+
* Constructor
|
|
29
|
+
*
|
|
30
|
+
* @param widget The widget to search in
|
|
31
|
+
* @param parser Markdown parser
|
|
32
|
+
* @param configuration Default model configuration
|
|
33
|
+
*/
|
|
34
|
+
constructor(
|
|
35
|
+
widget: MarkdownDocument,
|
|
36
|
+
protected parser: IMarkdownParser | null,
|
|
37
|
+
configuration?: TableOfContents.IConfig
|
|
38
|
+
) {
|
|
39
|
+
super(widget, configuration);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Type of document supported by the model.
|
|
44
|
+
*
|
|
45
|
+
* #### Notes
|
|
46
|
+
* A `data-document-type` attribute with this value will be set
|
|
47
|
+
* on the tree view `.jp-TableOfContents-content[data-document-type="..."]`
|
|
48
|
+
*/
|
|
49
|
+
get documentType(): string {
|
|
50
|
+
return 'markdown-viewer';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Whether the model gets updated even if the table of contents panel
|
|
55
|
+
* is hidden or not.
|
|
56
|
+
*/
|
|
57
|
+
protected get isAlwaysActive(): boolean {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* List of configuration options supported by the model.
|
|
63
|
+
*/
|
|
64
|
+
get supportedOptions(): (keyof TableOfContents.IConfig)[] {
|
|
65
|
+
return ['maximalDepth', 'numberingH1', 'numberHeaders'];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Produce the headings for a document.
|
|
70
|
+
*
|
|
71
|
+
* @returns The list of new headings or `null` if nothing needs to be updated.
|
|
72
|
+
*/
|
|
73
|
+
protected getHeadings(): Promise<IMarkdownViewerHeading[] | null> {
|
|
74
|
+
const content = this.widget.context.model.toString();
|
|
75
|
+
const headings = TableOfContentsUtils.filterHeadings(
|
|
76
|
+
TableOfContentsUtils.Markdown.getHeadings(content),
|
|
77
|
+
{
|
|
78
|
+
...this.configuration,
|
|
79
|
+
// Force base number to be equal to 1
|
|
80
|
+
baseNumbering: 1
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
return Promise.resolve(headings);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Table of content model factory for Markdown viewer files.
|
|
89
|
+
*/
|
|
90
|
+
export class MarkdownViewerTableOfContentsFactory extends TableOfContentsFactory<MarkdownDocument> {
|
|
91
|
+
/**
|
|
92
|
+
* Constructor
|
|
93
|
+
*
|
|
94
|
+
* @param tracker Widget tracker
|
|
95
|
+
* @param parser Markdown parser
|
|
96
|
+
*/
|
|
97
|
+
constructor(
|
|
98
|
+
tracker: IWidgetTracker<MarkdownDocument>,
|
|
99
|
+
protected parser: IMarkdownParser | null
|
|
100
|
+
) {
|
|
101
|
+
super(tracker);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Create a new table of contents model for the widget
|
|
106
|
+
*
|
|
107
|
+
* @param widget - widget
|
|
108
|
+
* @param configuration - Table of contents configuration
|
|
109
|
+
* @returns The table of contents model
|
|
110
|
+
*/
|
|
111
|
+
protected _createNew(
|
|
112
|
+
widget: MarkdownDocument,
|
|
113
|
+
configuration?: TableOfContents.IConfig
|
|
114
|
+
): TableOfContentsModel<TableOfContents.IHeading, MarkdownDocument> {
|
|
115
|
+
const model = new MarkdownViewerTableOfContentsModel(
|
|
116
|
+
widget,
|
|
117
|
+
this.parser,
|
|
118
|
+
configuration
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
let headingToElement = new WeakMap<
|
|
122
|
+
IMarkdownViewerHeading,
|
|
123
|
+
Element | null
|
|
124
|
+
>();
|
|
125
|
+
|
|
126
|
+
const onActiveHeadingChanged = (
|
|
127
|
+
model: TableOfContentsModel<IMarkdownViewerHeading, MarkdownDocument>,
|
|
128
|
+
heading: IMarkdownViewerHeading | null
|
|
129
|
+
) => {
|
|
130
|
+
if (heading) {
|
|
131
|
+
const el = headingToElement.get(heading);
|
|
132
|
+
|
|
133
|
+
if (el) {
|
|
134
|
+
const widgetBox = widget.content.node.getBoundingClientRect();
|
|
135
|
+
const elementBox = el.getBoundingClientRect();
|
|
136
|
+
|
|
137
|
+
if (
|
|
138
|
+
elementBox.top > widgetBox.bottom ||
|
|
139
|
+
elementBox.bottom < widgetBox.top
|
|
140
|
+
) {
|
|
141
|
+
el.scrollIntoView({ block: 'center' });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const onHeadingsChanged = () => {
|
|
148
|
+
if (!this.parser) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Clear all numbering items
|
|
153
|
+
TableOfContentsUtils.clearNumbering(widget.content.node);
|
|
154
|
+
|
|
155
|
+
// Create a new mapping
|
|
156
|
+
headingToElement = new WeakMap<IMarkdownViewerHeading, Element | null>();
|
|
157
|
+
model.headings.forEach(async heading => {
|
|
158
|
+
const elementId = await TableOfContentsUtils.Markdown.getHeadingId(
|
|
159
|
+
this.parser!,
|
|
160
|
+
heading.raw,
|
|
161
|
+
heading.level
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
if (!elementId) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const selector = `h${heading.level}[id="${elementId}"]`;
|
|
168
|
+
|
|
169
|
+
headingToElement.set(
|
|
170
|
+
heading,
|
|
171
|
+
TableOfContentsUtils.addPrefix(
|
|
172
|
+
widget.content.node,
|
|
173
|
+
selector,
|
|
174
|
+
heading.prefix ?? ''
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
void widget.content.ready.then(() => {
|
|
181
|
+
onHeadingsChanged();
|
|
182
|
+
|
|
183
|
+
widget.content.rendered.connect(onHeadingsChanged);
|
|
184
|
+
model.activeHeadingChanged.connect(onActiveHeadingChanged);
|
|
185
|
+
model.headingsChanged.connect(onHeadingsChanged);
|
|
186
|
+
widget.disposed.connect(() => {
|
|
187
|
+
widget.content.rendered.disconnect(onHeadingsChanged);
|
|
188
|
+
model.activeHeadingChanged.disconnect(onActiveHeadingChanged);
|
|
189
|
+
model.headingsChanged.disconnect(onHeadingsChanged);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return model;
|
|
194
|
+
}
|
|
195
|
+
}
|
package/src/tokens.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
|
|
4
|
+
import { IWidgetTracker } from '@jupyterlab/apputils';
|
|
5
|
+
import { Token } from '@lumino/coreutils';
|
|
6
|
+
import { MarkdownDocument } from './widget';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The markdownviewer tracker token.
|
|
10
|
+
*/
|
|
11
|
+
export const IMarkdownViewerTracker = new Token<IMarkdownViewerTracker>(
|
|
12
|
+
'@jupyterlab/markdownviewer:IMarkdownViewerTracker'
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A class that tracks markdown viewer widgets.
|
|
17
|
+
*/
|
|
18
|
+
export interface IMarkdownViewerTracker
|
|
19
|
+
extends IWidgetTracker<MarkdownDocument> {}
|
package/src/widget.ts
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
|
|
4
|
+
import { showErrorMessage } from '@jupyterlab/apputils';
|
|
5
|
+
import { ActivityMonitor } from '@jupyterlab/coreutils';
|
|
6
|
+
import {
|
|
7
|
+
ABCWidgetFactory,
|
|
8
|
+
DocumentRegistry,
|
|
9
|
+
DocumentWidget
|
|
10
|
+
} from '@jupyterlab/docregistry';
|
|
11
|
+
import {
|
|
12
|
+
IRenderMime,
|
|
13
|
+
IRenderMimeRegistry,
|
|
14
|
+
MimeModel
|
|
15
|
+
} from '@jupyterlab/rendermime';
|
|
16
|
+
import {
|
|
17
|
+
ITranslator,
|
|
18
|
+
nullTranslator,
|
|
19
|
+
TranslationBundle
|
|
20
|
+
} from '@jupyterlab/translation';
|
|
21
|
+
import { JSONObject, PromiseDelegate } from '@lumino/coreutils';
|
|
22
|
+
import { Message } from '@lumino/messaging';
|
|
23
|
+
import { ISignal, Signal } from '@lumino/signaling';
|
|
24
|
+
import { StackedLayout, Widget } from '@lumino/widgets';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The class name added to a markdown viewer.
|
|
28
|
+
*/
|
|
29
|
+
const MARKDOWNVIEWER_CLASS = 'jp-MarkdownViewer';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The markdown MIME type.
|
|
33
|
+
*/
|
|
34
|
+
const MIMETYPE = 'text/markdown';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A widget for markdown documents.
|
|
38
|
+
*/
|
|
39
|
+
export class MarkdownViewer extends Widget {
|
|
40
|
+
/**
|
|
41
|
+
* Construct a new markdown viewer widget.
|
|
42
|
+
*/
|
|
43
|
+
constructor(options: MarkdownViewer.IOptions) {
|
|
44
|
+
super();
|
|
45
|
+
this.context = options.context;
|
|
46
|
+
this.translator = options.translator || nullTranslator;
|
|
47
|
+
this._trans = this.translator.load('jupyterlab');
|
|
48
|
+
this.renderer = options.renderer;
|
|
49
|
+
this.node.tabIndex = 0;
|
|
50
|
+
this.addClass(MARKDOWNVIEWER_CLASS);
|
|
51
|
+
|
|
52
|
+
const layout = (this.layout = new StackedLayout());
|
|
53
|
+
layout.addWidget(this.renderer);
|
|
54
|
+
|
|
55
|
+
void this.context.ready.then(async () => {
|
|
56
|
+
await this._render();
|
|
57
|
+
|
|
58
|
+
// Throttle the rendering rate of the widget.
|
|
59
|
+
this._monitor = new ActivityMonitor({
|
|
60
|
+
signal: this.context.model.contentChanged,
|
|
61
|
+
timeout: this._config.renderTimeout
|
|
62
|
+
});
|
|
63
|
+
this._monitor.activityStopped.connect(this.update, this);
|
|
64
|
+
|
|
65
|
+
this._ready.resolve(undefined);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A promise that resolves when the markdown viewer is ready.
|
|
71
|
+
*/
|
|
72
|
+
get ready(): Promise<void> {
|
|
73
|
+
return this._ready.promise;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Signal emitted when the content has been rendered.
|
|
78
|
+
*/
|
|
79
|
+
get rendered(): ISignal<MarkdownViewer, void> {
|
|
80
|
+
return this._rendered;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Set URI fragment identifier.
|
|
85
|
+
*/
|
|
86
|
+
setFragment(fragment: string): void {
|
|
87
|
+
this._fragment = fragment;
|
|
88
|
+
this.update();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Set a config option for the markdown viewer.
|
|
93
|
+
*/
|
|
94
|
+
setOption<K extends keyof MarkdownViewer.IConfig>(
|
|
95
|
+
option: K,
|
|
96
|
+
value: MarkdownViewer.IConfig[K]
|
|
97
|
+
): void {
|
|
98
|
+
if (this._config[option] === value) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this._config[option] = value;
|
|
102
|
+
const { style } = this.renderer.node;
|
|
103
|
+
switch (option) {
|
|
104
|
+
case 'fontFamily':
|
|
105
|
+
style.setProperty('font-family', value as string | null);
|
|
106
|
+
break;
|
|
107
|
+
case 'fontSize':
|
|
108
|
+
style.setProperty('font-size', value ? value + 'px' : null);
|
|
109
|
+
break;
|
|
110
|
+
case 'hideFrontMatter':
|
|
111
|
+
this.update();
|
|
112
|
+
break;
|
|
113
|
+
case 'lineHeight':
|
|
114
|
+
style.setProperty('line-height', value ? value.toString() : null);
|
|
115
|
+
break;
|
|
116
|
+
case 'lineWidth': {
|
|
117
|
+
const padding = value ? `calc(50% - ${(value as number) / 2}ch)` : null;
|
|
118
|
+
style.setProperty('padding-left', padding);
|
|
119
|
+
style.setProperty('padding-right', padding);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
case 'renderTimeout':
|
|
123
|
+
if (this._monitor) {
|
|
124
|
+
this._monitor.timeout = value as number;
|
|
125
|
+
}
|
|
126
|
+
break;
|
|
127
|
+
default:
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Dispose of the resources held by the widget.
|
|
134
|
+
*/
|
|
135
|
+
dispose(): void {
|
|
136
|
+
if (this.isDisposed) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (this._monitor) {
|
|
140
|
+
this._monitor.dispose();
|
|
141
|
+
}
|
|
142
|
+
this._monitor = null;
|
|
143
|
+
super.dispose();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Handle an `update-request` message to the widget.
|
|
148
|
+
*/
|
|
149
|
+
protected onUpdateRequest(msg: Message): void {
|
|
150
|
+
if (this.context.isReady && !this.isDisposed) {
|
|
151
|
+
void this._render();
|
|
152
|
+
this._fragment = '';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Handle `'activate-request'` messages.
|
|
158
|
+
*/
|
|
159
|
+
protected onActivateRequest(msg: Message): void {
|
|
160
|
+
this.node.focus();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Render the mime content.
|
|
165
|
+
*/
|
|
166
|
+
private async _render(): Promise<void> {
|
|
167
|
+
if (this.isDisposed) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Since rendering is async, we note render requests that happen while we
|
|
172
|
+
// actually are rendering for a future rendering.
|
|
173
|
+
if (this._isRendering) {
|
|
174
|
+
this._renderRequested = true;
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Set up for this rendering pass.
|
|
179
|
+
this._renderRequested = false;
|
|
180
|
+
const { context } = this;
|
|
181
|
+
const { model } = context;
|
|
182
|
+
const source = model.toString();
|
|
183
|
+
const data: JSONObject = {};
|
|
184
|
+
// If `hideFrontMatter`is true remove front matter.
|
|
185
|
+
data[MIMETYPE] = this._config.hideFrontMatter
|
|
186
|
+
? Private.removeFrontMatter(source)
|
|
187
|
+
: source;
|
|
188
|
+
const mimeModel = new MimeModel({
|
|
189
|
+
data,
|
|
190
|
+
metadata: { fragment: this._fragment }
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
// Do the rendering asynchronously.
|
|
195
|
+
this._isRendering = true;
|
|
196
|
+
await this.renderer.renderModel(mimeModel);
|
|
197
|
+
this._isRendering = false;
|
|
198
|
+
|
|
199
|
+
// If there is an outstanding request to render, go ahead and render
|
|
200
|
+
if (this._renderRequested) {
|
|
201
|
+
return this._render();
|
|
202
|
+
} else {
|
|
203
|
+
this._rendered.emit();
|
|
204
|
+
}
|
|
205
|
+
} catch (reason) {
|
|
206
|
+
// Dispose the document if rendering fails.
|
|
207
|
+
requestAnimationFrame(() => {
|
|
208
|
+
this.dispose();
|
|
209
|
+
});
|
|
210
|
+
void showErrorMessage(
|
|
211
|
+
this._trans.__('Renderer Failure: %1', context.path),
|
|
212
|
+
reason
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
readonly context: DocumentRegistry.Context;
|
|
218
|
+
readonly renderer: IRenderMime.IRenderer;
|
|
219
|
+
protected translator: ITranslator;
|
|
220
|
+
private _trans: TranslationBundle;
|
|
221
|
+
private _config = { ...MarkdownViewer.defaultConfig };
|
|
222
|
+
private _fragment = '';
|
|
223
|
+
private _monitor: ActivityMonitor<DocumentRegistry.IModel, void> | null;
|
|
224
|
+
private _ready = new PromiseDelegate<void>();
|
|
225
|
+
private _isRendering = false;
|
|
226
|
+
private _renderRequested = false;
|
|
227
|
+
private _rendered = new Signal<MarkdownViewer, void>(this);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* The namespace for MarkdownViewer class statics.
|
|
232
|
+
*/
|
|
233
|
+
export namespace MarkdownViewer {
|
|
234
|
+
/**
|
|
235
|
+
* The options used to initialize a MarkdownViewer.
|
|
236
|
+
*/
|
|
237
|
+
export interface IOptions {
|
|
238
|
+
/**
|
|
239
|
+
* Context
|
|
240
|
+
*/
|
|
241
|
+
context: DocumentRegistry.IContext<DocumentRegistry.IModel>;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The renderer instance.
|
|
245
|
+
*/
|
|
246
|
+
renderer: IRenderMime.IRenderer;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The application language translator.
|
|
250
|
+
*/
|
|
251
|
+
translator?: ITranslator;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export interface IConfig {
|
|
255
|
+
/**
|
|
256
|
+
* User preferred font family for markdown viewer.
|
|
257
|
+
*/
|
|
258
|
+
fontFamily: string | null;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* User preferred size in pixel of the font used in markdown viewer.
|
|
262
|
+
*/
|
|
263
|
+
fontSize: number | null;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* User preferred text line height, as a multiplier of font size.
|
|
267
|
+
*/
|
|
268
|
+
lineHeight: number | null;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* User preferred text line width expressed in CSS ch units.
|
|
272
|
+
*/
|
|
273
|
+
lineWidth: number | null;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Whether to hide the YAML front matter.
|
|
277
|
+
*/
|
|
278
|
+
hideFrontMatter: boolean;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* The render timeout.
|
|
282
|
+
*/
|
|
283
|
+
renderTimeout: number;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* The default configuration options for an editor.
|
|
288
|
+
*/
|
|
289
|
+
export const defaultConfig: MarkdownViewer.IConfig = {
|
|
290
|
+
fontFamily: null,
|
|
291
|
+
fontSize: null,
|
|
292
|
+
lineHeight: null,
|
|
293
|
+
lineWidth: null,
|
|
294
|
+
hideFrontMatter: true,
|
|
295
|
+
renderTimeout: 1000
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* A document widget for markdown content.
|
|
301
|
+
*/
|
|
302
|
+
export class MarkdownDocument extends DocumentWidget<MarkdownViewer> {
|
|
303
|
+
setFragment(fragment: string): void {
|
|
304
|
+
this.content.setFragment(fragment);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* A widget factory for markdown viewers.
|
|
310
|
+
*/
|
|
311
|
+
export class MarkdownViewerFactory extends ABCWidgetFactory<MarkdownDocument> {
|
|
312
|
+
/**
|
|
313
|
+
* Construct a new markdown viewer widget factory.
|
|
314
|
+
*/
|
|
315
|
+
constructor(options: MarkdownViewerFactory.IOptions) {
|
|
316
|
+
super(Private.createRegistryOptions(options));
|
|
317
|
+
this._fileType = options.primaryFileType;
|
|
318
|
+
this._rendermime = options.rendermime;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Create a new widget given a context.
|
|
323
|
+
*/
|
|
324
|
+
protected createNewWidget(
|
|
325
|
+
context: DocumentRegistry.Context
|
|
326
|
+
): MarkdownDocument {
|
|
327
|
+
const rendermime = this._rendermime.clone({
|
|
328
|
+
resolver: context.urlResolver
|
|
329
|
+
});
|
|
330
|
+
const renderer = rendermime.createRenderer(MIMETYPE);
|
|
331
|
+
const content = new MarkdownViewer({ context, renderer });
|
|
332
|
+
content.title.icon = this._fileType?.icon;
|
|
333
|
+
content.title.iconClass = this._fileType?.iconClass ?? '';
|
|
334
|
+
content.title.iconLabel = this._fileType?.iconLabel ?? '';
|
|
335
|
+
const widget = new MarkdownDocument({ content, context });
|
|
336
|
+
|
|
337
|
+
return widget;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private _fileType: DocumentRegistry.IFileType | undefined;
|
|
341
|
+
private _rendermime: IRenderMimeRegistry;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* The namespace for MarkdownViewerFactory class statics.
|
|
346
|
+
*/
|
|
347
|
+
export namespace MarkdownViewerFactory {
|
|
348
|
+
/**
|
|
349
|
+
* The options used to initialize a MarkdownViewerFactory.
|
|
350
|
+
*/
|
|
351
|
+
export interface IOptions extends DocumentRegistry.IWidgetFactoryOptions {
|
|
352
|
+
/**
|
|
353
|
+
* The primary file type associated with the document.
|
|
354
|
+
*/
|
|
355
|
+
primaryFileType: DocumentRegistry.IFileType | undefined;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* The rendermime instance.
|
|
359
|
+
*/
|
|
360
|
+
rendermime: IRenderMimeRegistry;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* A namespace for markdown viewer widget private data.
|
|
366
|
+
*/
|
|
367
|
+
namespace Private {
|
|
368
|
+
/**
|
|
369
|
+
* Create the document registry options.
|
|
370
|
+
*/
|
|
371
|
+
export function createRegistryOptions(
|
|
372
|
+
options: MarkdownViewerFactory.IOptions
|
|
373
|
+
): DocumentRegistry.IWidgetFactoryOptions {
|
|
374
|
+
return {
|
|
375
|
+
...options,
|
|
376
|
+
readOnly: true
|
|
377
|
+
} as DocumentRegistry.IWidgetFactoryOptions;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Remove YAML front matter from source.
|
|
382
|
+
*/
|
|
383
|
+
export function removeFrontMatter(source: string): string {
|
|
384
|
+
const re = /^---\n[^]*?\n(---|...)\n/;
|
|
385
|
+
const match = source.match(re);
|
|
386
|
+
if (!match) {
|
|
387
|
+
return source;
|
|
388
|
+
}
|
|
389
|
+
const { length } = match[0];
|
|
390
|
+
return source.slice(length);
|
|
391
|
+
}
|
|
392
|
+
}
|
package/style/index.css
CHANGED
package/style/index.js
CHANGED