@jupyterlab/fileeditor 4.0.0-alpha.9 → 4.0.0-beta.0

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.
Files changed (49) hide show
  1. package/lib/fileeditorlspadapter.d.ts +96 -0
  2. package/lib/fileeditorlspadapter.js +175 -0
  3. package/lib/fileeditorlspadapter.js.map +1 -0
  4. package/lib/index.d.ts +4 -0
  5. package/lib/index.js +4 -0
  6. package/lib/index.js.map +1 -1
  7. package/lib/searchprovider.d.ts +60 -0
  8. package/lib/searchprovider.js +80 -0
  9. package/lib/searchprovider.js.map +1 -0
  10. package/lib/syntaxstatus.d.ts +74 -0
  11. package/lib/syntaxstatus.js +151 -0
  12. package/lib/syntaxstatus.js.map +1 -0
  13. package/lib/tabspacestatus.d.ts +8 -12
  14. package/lib/tabspacestatus.js +23 -27
  15. package/lib/tabspacestatus.js.map +1 -1
  16. package/lib/toc/factory.d.ts +25 -0
  17. package/lib/toc/factory.js +32 -0
  18. package/lib/toc/factory.js.map +1 -0
  19. package/lib/toc/index.d.ts +4 -0
  20. package/lib/toc/index.js +7 -0
  21. package/lib/toc/index.js.map +1 -0
  22. package/lib/toc/latex.d.ts +48 -0
  23. package/lib/toc/latex.js +117 -0
  24. package/lib/toc/latex.js.map +1 -0
  25. package/lib/toc/markdown.d.ts +44 -0
  26. package/lib/toc/markdown.js +68 -0
  27. package/lib/toc/markdown.js.map +1 -0
  28. package/lib/toc/python.d.ts +44 -0
  29. package/lib/toc/python.js +116 -0
  30. package/lib/toc/python.js.map +1 -0
  31. package/lib/widget.d.ts +4 -0
  32. package/lib/widget.js +21 -4
  33. package/lib/widget.js.map +1 -1
  34. package/package.json +26 -21
  35. package/src/fileeditorlspadapter.ts +225 -0
  36. package/src/index.ts +14 -0
  37. package/src/searchprovider.ts +115 -0
  38. package/src/syntaxstatus.tsx +217 -0
  39. package/src/tabspacestatus.tsx +166 -0
  40. package/src/toc/factory.ts +72 -0
  41. package/src/toc/index.ts +7 -0
  42. package/src/toc/latex.ts +145 -0
  43. package/src/toc/markdown.ts +90 -0
  44. package/src/toc/python.ts +143 -0
  45. package/src/tokens.ts +20 -0
  46. package/src/widget.ts +267 -0
  47. package/style/base.css +8 -0
  48. package/style/index.css +4 -0
  49. package/style/index.js +4 -0
@@ -0,0 +1,217 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+
6
+ import { CodeEditor, IEditorMimeTypeService } from '@jupyterlab/codeeditor';
7
+ import { IEditorLanguageRegistry } from '@jupyterlab/codemirror';
8
+ import { IChangedArgs } from '@jupyterlab/coreutils';
9
+ import { Popup, showPopup, TextItem } from '@jupyterlab/statusbar';
10
+ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
11
+ import { VDomModel, VDomRenderer } from '@jupyterlab/ui-components';
12
+ import { CommandRegistry } from '@lumino/commands';
13
+ import { JSONObject } from '@lumino/coreutils';
14
+ import { Menu } from '@lumino/widgets';
15
+ import React from 'react';
16
+
17
+ /**
18
+ * A namespace for `EditorSyntaxComponentStatics`.
19
+ */
20
+ namespace EditorSyntaxComponent {
21
+ /**
22
+ * The props for the `EditorSyntaxComponent`.
23
+ */
24
+ export interface IProps {
25
+ /**
26
+ * The current CodeMirror language for an editor.
27
+ */
28
+ language: string;
29
+
30
+ /**
31
+ * A function to execute on clicking the component.
32
+ * By default we provide a function that opens a menu
33
+ * for CodeMirror language selection.
34
+ */
35
+ handleClick: () => void;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * A pure function that returns a tsx component for an editor syntax item.
41
+ *
42
+ * @param props: the props for the component.
43
+ *
44
+ * @returns an editor syntax component.
45
+ */
46
+ function EditorSyntaxComponent(
47
+ props: EditorSyntaxComponent.IProps
48
+ ): React.ReactElement<EditorSyntaxComponent.IProps> {
49
+ return <TextItem source={props.language} onClick={props.handleClick} />;
50
+ }
51
+
52
+ /**
53
+ * StatusBar item to change the language syntax highlighting of the file editor.
54
+ */
55
+ export class EditorSyntaxStatus extends VDomRenderer<EditorSyntaxStatus.Model> {
56
+ /**
57
+ * Construct a new VDomRenderer for the status item.
58
+ */
59
+ constructor(options: EditorSyntaxStatus.IOptions) {
60
+ super(new EditorSyntaxStatus.Model(options.languages));
61
+ this._commands = options.commands;
62
+ this.translator = options.translator ?? nullTranslator;
63
+ const trans = this.translator.load('jupyterlab');
64
+
65
+ this.addClass('jp-mod-highlighted');
66
+ this.title.caption = trans.__('Change text editor syntax highlighting');
67
+ }
68
+
69
+ /**
70
+ * Render the status item.
71
+ */
72
+ render(): JSX.Element | null {
73
+ if (!this.model) {
74
+ return null;
75
+ }
76
+ return (
77
+ <EditorSyntaxComponent
78
+ language={this.model.language}
79
+ handleClick={this._handleClick}
80
+ />
81
+ );
82
+ }
83
+
84
+ /**
85
+ * Create a menu for selecting the language of the editor.
86
+ */
87
+ private _handleClick = () => {
88
+ const languageMenu = new Menu({ commands: this._commands });
89
+ const command = 'fileeditor:change-language';
90
+ if (this._popup) {
91
+ this._popup.dispose();
92
+ }
93
+ this.model.languages
94
+ .getLanguages()
95
+ .sort((a, b) => {
96
+ const aName = a.displayName ?? a.name;
97
+ const bName = b.displayName ?? b.name;
98
+ return aName.localeCompare(bName);
99
+ })
100
+ .forEach(spec => {
101
+ if (spec.name.toLowerCase().indexOf('brainf') === 0) {
102
+ return;
103
+ }
104
+
105
+ const args: JSONObject = {
106
+ name: spec.name,
107
+ displayName: spec.displayName ?? spec.name
108
+ };
109
+
110
+ languageMenu.addItem({
111
+ command,
112
+ args
113
+ });
114
+ });
115
+ this._popup = showPopup({
116
+ body: languageMenu,
117
+ anchor: this,
118
+ align: 'left'
119
+ });
120
+ };
121
+
122
+ protected translator: ITranslator;
123
+ private _commands: CommandRegistry;
124
+ private _popup: Popup | null = null;
125
+ }
126
+
127
+ /**
128
+ * A namespace for EditorSyntax statics.
129
+ */
130
+ export namespace EditorSyntaxStatus {
131
+ /**
132
+ * A VDomModel for the current editor/mode combination.
133
+ */
134
+ export class Model extends VDomModel {
135
+ constructor(public languages: IEditorLanguageRegistry) {
136
+ super();
137
+ }
138
+ /**
139
+ * The current editor language. If no editor is present,
140
+ * returns the empty string.
141
+ */
142
+ get language(): string {
143
+ return this._language;
144
+ }
145
+
146
+ /**
147
+ * The current editor for the application editor tracker.
148
+ */
149
+ get editor(): CodeEditor.IEditor | null {
150
+ return this._editor;
151
+ }
152
+ set editor(editor: CodeEditor.IEditor | null) {
153
+ const oldEditor = this._editor;
154
+ if (oldEditor !== null) {
155
+ oldEditor.model.mimeTypeChanged.disconnect(this._onMIMETypeChange);
156
+ }
157
+ const oldLanguage = this._language;
158
+ this._editor = editor;
159
+ if (this._editor === null) {
160
+ this._language = '';
161
+ } else {
162
+ const spec = this.languages.findByMIME(this._editor.model.mimeType);
163
+ this._language = spec?.name ?? IEditorMimeTypeService.defaultMimeType;
164
+
165
+ this._editor.model.mimeTypeChanged.connect(this._onMIMETypeChange);
166
+ }
167
+
168
+ this._triggerChange(oldLanguage, this._language);
169
+ }
170
+
171
+ /**
172
+ * If the editor mode changes, update the model.
173
+ */
174
+ private _onMIMETypeChange = (
175
+ mode: CodeEditor.IModel,
176
+ change: IChangedArgs<string>
177
+ ) => {
178
+ const oldLanguage = this._language;
179
+ const spec = this.languages.findByMIME(change.newValue);
180
+ this._language = spec?.name ?? IEditorMimeTypeService.defaultMimeType;
181
+
182
+ this._triggerChange(oldLanguage, this._language);
183
+ };
184
+
185
+ /**
186
+ * Trigger a rerender of the model.
187
+ */
188
+ private _triggerChange(oldState: string, newState: string) {
189
+ if (oldState !== newState) {
190
+ this.stateChanged.emit(void 0);
191
+ }
192
+ }
193
+
194
+ private _language: string = '';
195
+ private _editor: CodeEditor.IEditor | null = null;
196
+ }
197
+
198
+ /**
199
+ * Options for the EditorSyntax status item.
200
+ */
201
+ export interface IOptions {
202
+ /**
203
+ * The application command registry.
204
+ */
205
+ commands: CommandRegistry;
206
+
207
+ /**
208
+ * Editor languages.
209
+ */
210
+ languages: IEditorLanguageRegistry;
211
+
212
+ /**
213
+ * The language translator.
214
+ */
215
+ translator?: ITranslator;
216
+ }
217
+ }
@@ -0,0 +1,166 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import { Popup, showPopup, TextItem } from '@jupyterlab/statusbar';
5
+ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
6
+ import { VDomModel, VDomRenderer } from '@jupyterlab/ui-components';
7
+ import { Menu } from '@lumino/widgets';
8
+ import React from 'react';
9
+
10
+ /**
11
+ * A namespace for TabSpaceComponent statics.
12
+ */
13
+ namespace TabSpaceComponent {
14
+ /**
15
+ * The props for TabSpaceComponent.
16
+ */
17
+ export interface IProps {
18
+ /**
19
+ * The number of spaces for indentation.
20
+ *
21
+ * `null` means use tab character for indentation.
22
+ */
23
+ tabSpace: number | null;
24
+
25
+ /**
26
+ * The application language translator.
27
+ */
28
+ translator?: ITranslator;
29
+
30
+ /**
31
+ * A click handler for the TabSpace component. By default
32
+ * opens a menu allowing the user to select tabs vs spaces.
33
+ */
34
+ handleClick: () => void;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * A pure functional component for rendering the TabSpace status.
40
+ */
41
+ function TabSpaceComponent(
42
+ props: TabSpaceComponent.IProps
43
+ ): React.ReactElement<TabSpaceComponent.IProps> {
44
+ const translator = props.translator || nullTranslator;
45
+ const trans = translator.load('jupyterlab');
46
+ const description =
47
+ typeof props.tabSpace === 'number'
48
+ ? trans.__('Spaces')
49
+ : trans.__('Tab Indent');
50
+ return (
51
+ <TextItem
52
+ onClick={props.handleClick}
53
+ source={
54
+ typeof props.tabSpace === 'number'
55
+ ? `${description}: ${props.tabSpace}`
56
+ : description
57
+ }
58
+ title={trans.__('Change the indentation…')}
59
+ />
60
+ );
61
+ }
62
+
63
+ /**
64
+ * A VDomRenderer for a tabs vs. spaces status item.
65
+ */
66
+ export class TabSpaceStatus extends VDomRenderer<TabSpaceStatus.Model> {
67
+ /**
68
+ * Create a new tab/space status item.
69
+ */
70
+ constructor(options: TabSpaceStatus.IOptions) {
71
+ super(new TabSpaceStatus.Model());
72
+ this._menu = options.menu;
73
+ this.translator = options.translator || nullTranslator;
74
+ this.addClass('jp-mod-highlighted');
75
+ }
76
+
77
+ /**
78
+ * Render the TabSpace status item.
79
+ */
80
+ render(): React.ReactElement<TabSpaceComponent.IProps> | null {
81
+ if (!this.model?.indentUnit) {
82
+ return null;
83
+ } else {
84
+ const tabSpace =
85
+ this.model.indentUnit === 'Tab'
86
+ ? null
87
+ : parseInt(this.model.indentUnit, 10);
88
+ return (
89
+ <TabSpaceComponent
90
+ tabSpace={tabSpace}
91
+ handleClick={() => this._handleClick()}
92
+ translator={this.translator}
93
+ />
94
+ );
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Handle a click on the status item.
100
+ */
101
+ private _handleClick(): void {
102
+ const menu = this._menu;
103
+ if (this._popup) {
104
+ this._popup.dispose();
105
+ }
106
+
107
+ menu.aboutToClose.connect(this._menuClosed, this);
108
+
109
+ this._popup = showPopup({
110
+ body: menu,
111
+ anchor: this,
112
+ align: 'right'
113
+ });
114
+ // Update the menu items
115
+ menu.update();
116
+ }
117
+
118
+ private _menuClosed(): void {
119
+ this.removeClass('jp-mod-clicked');
120
+ }
121
+
122
+ protected translator: ITranslator;
123
+ private _menu: Menu;
124
+ private _popup: Popup | null = null;
125
+ }
126
+
127
+ /**
128
+ * A namespace for TabSpace statics.
129
+ */
130
+ export namespace TabSpaceStatus {
131
+ /**
132
+ * A VDomModel for the TabSpace status item.
133
+ */
134
+ export class Model extends VDomModel {
135
+ /**
136
+ * Code editor indentation unit
137
+ */
138
+ get indentUnit(): string | null {
139
+ return this._indentUnit;
140
+ }
141
+ set indentUnit(v: string | null) {
142
+ if (v !== this._indentUnit) {
143
+ this._indentUnit = v;
144
+ this.stateChanged.emit();
145
+ }
146
+ }
147
+
148
+ private _indentUnit: string | null;
149
+ }
150
+
151
+ /**
152
+ * Options for creating a TabSpace status item.
153
+ */
154
+ export interface IOptions {
155
+ /**
156
+ * A menu to open when clicking on the status item. This should allow
157
+ * the user to make a different selection about tabs/spaces.
158
+ */
159
+ menu: Menu;
160
+
161
+ /**
162
+ * Language translator.
163
+ */
164
+ translator?: ITranslator;
165
+ }
166
+ }
@@ -0,0 +1,72 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import { DocumentRegistry, IDocumentWidget } from '@jupyterlab/docregistry';
5
+ import {
6
+ TableOfContents,
7
+ TableOfContentsFactory,
8
+ TableOfContentsModel
9
+ } from '@jupyterlab/toc';
10
+ import { FileEditor } from '../widget';
11
+
12
+ /**
13
+ * Interface describing a file editor heading.
14
+ */
15
+ export interface IEditorHeading extends TableOfContents.IHeading {
16
+ /**
17
+ * Heading line number.
18
+ */
19
+ line: number;
20
+ }
21
+
22
+ /**
23
+ * Base table of contents model factory for file editor
24
+ */
25
+ export abstract class EditorTableOfContentsFactory extends TableOfContentsFactory<
26
+ IDocumentWidget<FileEditor>
27
+ > {
28
+ /**
29
+ * Create a new table of contents model for the widget
30
+ *
31
+ * @param widget - widget
32
+ * @param configuration - Table of contents configuration
33
+ * @returns The table of contents model
34
+ */
35
+ createNew(
36
+ widget: IDocumentWidget<FileEditor, DocumentRegistry.IModel>,
37
+ configuration?: TableOfContents.IConfig
38
+ ): TableOfContentsModel<
39
+ IEditorHeading,
40
+ IDocumentWidget<FileEditor, DocumentRegistry.IModel>
41
+ > {
42
+ const model = super.createNew(
43
+ widget,
44
+ configuration
45
+ ) as TableOfContentsModel<
46
+ IEditorHeading,
47
+ IDocumentWidget<FileEditor, DocumentRegistry.IModel>
48
+ >;
49
+
50
+ const onActiveHeadingChanged = (
51
+ model: TableOfContentsModel<
52
+ IEditorHeading,
53
+ IDocumentWidget<FileEditor, DocumentRegistry.IModel>
54
+ >,
55
+ heading: IEditorHeading | null
56
+ ) => {
57
+ if (heading) {
58
+ widget.content.editor.setCursorPosition({
59
+ line: heading.line,
60
+ column: 0
61
+ });
62
+ }
63
+ };
64
+
65
+ model.activeHeadingChanged.connect(onActiveHeadingChanged);
66
+ widget.disposed.connect(() => {
67
+ model.activeHeadingChanged.disconnect(onActiveHeadingChanged);
68
+ });
69
+
70
+ return model;
71
+ }
72
+ }
@@ -0,0 +1,7 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ export * from './factory';
5
+ export * from './latex';
6
+ export * from './markdown';
7
+ export * from './python';
@@ -0,0 +1,145 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import { DocumentRegistry, IDocumentWidget } from '@jupyterlab/docregistry';
5
+ import {
6
+ TableOfContents,
7
+ TableOfContentsModel,
8
+ TableOfContentsUtils
9
+ } from '@jupyterlab/toc';
10
+ import { Widget } from '@lumino/widgets';
11
+ import { FileEditor } from '../widget';
12
+ import { EditorTableOfContentsFactory, IEditorHeading } from './factory';
13
+
14
+ /**
15
+ * Maps LaTeX section headings to HTML header levels.
16
+ *
17
+ * ## Notes
18
+ *
19
+ * - As `part` and `chapter` section headings appear to be less common, assign them to heading level 1.
20
+ *
21
+ * @private
22
+ */
23
+ const LATEX_LEVELS: { [label: string]: number } = {
24
+ part: 1, // Only available for report and book classes
25
+ chapter: 1, // Only available for report and book classes
26
+ section: 1,
27
+ subsection: 2,
28
+ subsubsection: 3,
29
+ paragraph: 4,
30
+ subparagraph: 5
31
+ };
32
+
33
+ /**
34
+ * Regular expression to create the outline
35
+ */
36
+ const SECTIONS = /^\s*\\(section|subsection|subsubsection){(.+)}/;
37
+
38
+ /**
39
+ * Table of content model for LaTeX files.
40
+ */
41
+ export class LaTeXTableOfContentsModel extends TableOfContentsModel<
42
+ IEditorHeading,
43
+ IDocumentWidget<FileEditor, DocumentRegistry.IModel>
44
+ > {
45
+ /**
46
+ * Type of document supported by the model.
47
+ *
48
+ * #### Notes
49
+ * A `data-document-type` attribute with this value will be set
50
+ * on the tree view `.jp-TableOfContents-content[data-document-type="..."]`
51
+ */
52
+ get documentType(): string {
53
+ return 'latex';
54
+ }
55
+
56
+ /**
57
+ * List of configuration options supported by the model.
58
+ */
59
+ get supportedOptions(): (keyof TableOfContents.IConfig)[] {
60
+ return ['maximalDepth', 'numberHeaders'];
61
+ }
62
+
63
+ /**
64
+ * Produce the headings for a document.
65
+ *
66
+ * @returns The list of new headings or `null` if nothing needs to be updated.
67
+ */
68
+ protected getHeadings(): Promise<IEditorHeading[] | null> {
69
+ if (!this.isActive) {
70
+ return Promise.resolve(null);
71
+ }
72
+
73
+ // Split the text into lines:
74
+ const lines = this.widget.content.model.sharedModel
75
+ .getSource()
76
+ .split('\n') as Array<string>;
77
+
78
+ const levels = new Array<number>();
79
+ let previousLevel = levels.length;
80
+ const headings = new Array<IEditorHeading>();
81
+ for (let i = 0; i < lines.length; i++) {
82
+ const match = lines[i].match(SECTIONS);
83
+ if (match) {
84
+ const level = LATEX_LEVELS[match[1]];
85
+ if (level <= this.configuration.maximalDepth) {
86
+ const prefix = TableOfContentsUtils.getPrefix(
87
+ level,
88
+ previousLevel,
89
+ levels,
90
+ {
91
+ ...this.configuration,
92
+ // Force base numbering and numbering first level
93
+ baseNumbering: 1,
94
+ numberingH1: true
95
+ }
96
+ );
97
+ previousLevel = level;
98
+
99
+ headings.push({
100
+ text: match[2],
101
+ prefix: prefix,
102
+ level,
103
+ line: i
104
+ });
105
+ }
106
+ }
107
+ }
108
+ return Promise.resolve(headings);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Table of content model factory for LaTeX files.
114
+ */
115
+ export class LaTeXTableOfContentsFactory extends EditorTableOfContentsFactory {
116
+ /**
117
+ * Whether the factory can handle the widget or not.
118
+ *
119
+ * @param widget - widget
120
+ * @returns boolean indicating a ToC can be generated
121
+ */
122
+ isApplicable(widget: Widget): boolean {
123
+ const isApplicable = super.isApplicable(widget);
124
+
125
+ if (isApplicable) {
126
+ let mime = (widget as any).content?.model?.mimeType;
127
+ return mime && (mime === 'text/x-latex' || mime === 'text/x-stex');
128
+ }
129
+ return false;
130
+ }
131
+
132
+ /**
133
+ * Create a new table of contents model for the widget
134
+ *
135
+ * @param widget - widget
136
+ * @param configuration - Table of contents configuration
137
+ * @returns The table of contents model
138
+ */
139
+ protected _createNew(
140
+ widget: IDocumentWidget<FileEditor, DocumentRegistry.IModel>,
141
+ configuration?: TableOfContents.IConfig
142
+ ): LaTeXTableOfContentsModel {
143
+ return new LaTeXTableOfContentsModel(widget, configuration);
144
+ }
145
+ }
@@ -0,0 +1,90 @@
1
+ // Copyright (c) Jupyter Development Team.
2
+ // Distributed under the terms of the Modified BSD License.
3
+
4
+ import { DocumentRegistry, IDocumentWidget } from '@jupyterlab/docregistry';
5
+ import {
6
+ TableOfContents,
7
+ TableOfContentsModel,
8
+ TableOfContentsUtils
9
+ } from '@jupyterlab/toc';
10
+ import { Widget } from '@lumino/widgets';
11
+ import { FileEditor } from '../widget';
12
+ import { EditorTableOfContentsFactory, IEditorHeading } from './factory';
13
+
14
+ /**
15
+ * Table of content model for Markdown files.
16
+ */
17
+ export class MarkdownTableOfContentsModel extends TableOfContentsModel<
18
+ IEditorHeading,
19
+ IDocumentWidget<FileEditor, DocumentRegistry.IModel>
20
+ > {
21
+ /**
22
+ * Type of document supported by the model.
23
+ *
24
+ * #### Notes
25
+ * A `data-document-type` attribute with this value will be set
26
+ * on the tree view `.jp-TableOfContents-content[data-document-type="..."]`
27
+ */
28
+ get documentType(): string {
29
+ return 'markdown';
30
+ }
31
+
32
+ /**
33
+ * Produce the headings for a document.
34
+ *
35
+ * @returns The list of new headings or `null` if nothing needs to be updated.
36
+ */
37
+ protected getHeadings(): Promise<IEditorHeading[] | null> {
38
+ if (!this.isActive) {
39
+ return Promise.resolve(null);
40
+ }
41
+
42
+ const content = this.widget.content.model.sharedModel.getSource();
43
+
44
+ const headings = TableOfContentsUtils.filterHeadings(
45
+ TableOfContentsUtils.Markdown.getHeadings(content),
46
+ {
47
+ ...this.configuration,
48
+ // Force removing numbering as they cannot be displayed
49
+ // in the document
50
+ numberHeaders: false
51
+ }
52
+ );
53
+ return Promise.resolve(headings);
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Table of content model factory for Markdown files.
59
+ */
60
+ export class MarkdownTableOfContentsFactory extends EditorTableOfContentsFactory {
61
+ /**
62
+ * Whether the factory can handle the widget or not.
63
+ *
64
+ * @param widget - widget
65
+ * @returns boolean indicating a ToC can be generated
66
+ */
67
+ isApplicable(widget: Widget): boolean {
68
+ const isApplicable = super.isApplicable(widget);
69
+
70
+ if (isApplicable) {
71
+ let mime = (widget as any).content?.model?.mimeType;
72
+ return mime && TableOfContentsUtils.Markdown.isMarkdown(mime);
73
+ }
74
+ return false;
75
+ }
76
+
77
+ /**
78
+ * Create a new table of contents model for the widget
79
+ *
80
+ * @param widget - widget
81
+ * @param configuration - Table of contents configuration
82
+ * @returns The table of contents model
83
+ */
84
+ protected _createNew(
85
+ widget: IDocumentWidget<FileEditor, DocumentRegistry.IModel>,
86
+ configuration?: TableOfContents.IConfig
87
+ ): MarkdownTableOfContentsModel {
88
+ return new MarkdownTableOfContentsModel(widget, configuration);
89
+ }
90
+ }