@gravity-ui/markdown-editor 13.7.0 → 13.9.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.
- package/README.md +8 -1
- package/build/cjs/bundle/Editor.d.ts +14 -0
- package/build/cjs/bundle/Editor.js +9 -6
- package/build/cjs/bundle/index.d.ts +1 -1
- package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/index.js +1 -1
- package/build/cjs/extensions/yfm/FoldingHeading/plugins/Folding.js +10 -7
- package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/const.d.ts +5 -0
- package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/const.js +7 -1
- package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/parser.js +12 -1
- package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +7 -2
- package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/serializer.js +57 -17
- package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/yfmTableCellView.js +9 -0
- package/build/cjs/markup/codemirror/create.d.ts +4 -1
- package/build/cjs/markup/codemirror/create.js +4 -4
- package/build/cjs/version.js +1 -1
- package/build/cjs/view/hooks/useYfmShowElemWithId/useYfmShowElemWithId.d.ts +1 -1
- package/build/cjs/view/hooks/useYfmShowElemWithId/useYfmShowElemWithId.js +15 -1
- package/build/esm/bundle/Editor.d.ts +14 -0
- package/build/esm/bundle/Editor.js +9 -6
- package/build/esm/bundle/index.d.ts +1 -1
- package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/index.js +1 -1
- package/build/esm/extensions/yfm/FoldingHeading/plugins/Folding.js +10 -7
- package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/const.d.ts +5 -0
- package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/const.js +6 -0
- package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/parser.js +13 -2
- package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +8 -3
- package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/serializer.js +57 -18
- package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/yfmTableCellView.js +9 -0
- package/build/esm/markup/codemirror/create.d.ts +4 -1
- package/build/esm/markup/codemirror/create.js +4 -4
- package/build/esm/version.js +1 -1
- package/build/esm/view/hooks/useYfmShowElemWithId/useYfmShowElemWithId.d.ts +1 -1
- package/build/esm/view/hooks/useYfmShowElemWithId/useYfmShowElemWithId.js +15 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -46,9 +46,16 @@ function Editor({onSubmit}) {
|
|
|
46
46
|
};
|
|
47
47
|
}, [onSubmit]);
|
|
48
48
|
|
|
49
|
-
return <MarkdownEditorView autofocus toaster={toaster} editor={editor} />;
|
|
49
|
+
return <MarkdownEditorView stickyToolbar autofocus toaster={toaster} editor={editor} />;
|
|
50
50
|
}
|
|
51
51
|
```
|
|
52
|
+
Read more:
|
|
53
|
+
- [How to connect the editor in the Create React App](docs/how-to-add-editor-with-create-react-app.md)
|
|
54
|
+
- [How to add preview for markup mode](docs/how-to-add-preview.md)
|
|
55
|
+
- [How to add HTML extension](docs/how-to-connect-html-extension.md)
|
|
56
|
+
- [How to add Latex extension](docs/how-to-connect-latex-extension.md)
|
|
57
|
+
- [How to add Mermaid extension](docs/how-to-connect-mermaid-extension.md)
|
|
58
|
+
- [How to write extension](docs/how-to-create-extension.md)
|
|
52
59
|
|
|
53
60
|
### i18n
|
|
54
61
|
|
|
@@ -3,6 +3,8 @@ import type { Extension as CodemirrorExtension } from '@codemirror/state';
|
|
|
3
3
|
import { CommonEditor, MarkupString } from '../common';
|
|
4
4
|
import { WysiwygEditorOptions } from '../core';
|
|
5
5
|
import { ReactRenderStorage } from '../extensions';
|
|
6
|
+
import { type CreateCodemirrorParams } from '../markup/codemirror';
|
|
7
|
+
import type { YfmLangOptions } from '../markup/codemirror/yfm';
|
|
6
8
|
import { Receiver } from '../utils/event-emitter';
|
|
7
9
|
import type { FileUploadHandler } from '../utils/upload';
|
|
8
10
|
export declare type EditorMode = 'wysiwyg' | 'markup';
|
|
@@ -42,6 +44,16 @@ export interface Editor extends Receiver<EventMap>, CommonEditor {
|
|
|
42
44
|
line: number;
|
|
43
45
|
}): void;
|
|
44
46
|
}
|
|
47
|
+
export declare type MarkupConfig = {
|
|
48
|
+
/** Additional extensions for codemirror instance. */
|
|
49
|
+
extensions?: CreateCodemirrorParams['extensions'];
|
|
50
|
+
/**
|
|
51
|
+
* Additional language data for markdown language in codemirror.
|
|
52
|
+
* Can be used to configure additional autocompletions and others.
|
|
53
|
+
* See more https://codemirror.net/docs/ref/#state.EditorState.languageDataAt
|
|
54
|
+
*/
|
|
55
|
+
languageData?: YfmLangOptions['languageData'];
|
|
56
|
+
};
|
|
45
57
|
export declare type EditorOptions = Pick<WysiwygEditorOptions, 'allowHTML' | 'linkify' | 'linkifyTlds' | 'extensions'> & {
|
|
46
58
|
initialMarkup?: MarkupString;
|
|
47
59
|
/** @default 'wysiwyg' */
|
|
@@ -68,5 +80,7 @@ export declare type EditorOptions = Pick<WysiwygEditorOptions, 'allowHTML' | 'li
|
|
|
68
80
|
splitMode?: SplitMode;
|
|
69
81
|
renderPreview?: RenderPreview;
|
|
70
82
|
preset: EditorPreset;
|
|
83
|
+
/** @deprecated Put extra extensions via MarkdownEditorMarkupConfig */
|
|
71
84
|
extraMarkupExtensions?: CodemirrorExtension[];
|
|
85
|
+
markupConfig?: MarkupConfig;
|
|
72
86
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _EditorImpl_markup, _EditorImpl_editorMode, _EditorImpl_toolbarVisible, _EditorImpl_splitModeEnabled, _EditorImpl_splitMode, _EditorImpl_renderPreview, _EditorImpl_wysiwygEditor, _EditorImpl_markupEditor,
|
|
2
|
+
var _EditorImpl_markup, _EditorImpl_editorMode, _EditorImpl_toolbarVisible, _EditorImpl_splitModeEnabled, _EditorImpl_splitMode, _EditorImpl_renderPreview, _EditorImpl_wysiwygEditor, _EditorImpl_markupEditor, _EditorImpl_markupConfig, _EditorImpl_preset, _EditorImpl_allowHTML, _EditorImpl_linkify, _EditorImpl_linkifyTlds, _EditorImpl_extensions, _EditorImpl_renderStorage, _EditorImpl_fileUploadHandler, _EditorImpl_needToSetDimensionsForUploadedImages, _EditorImpl_prepareRawMarkup;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.EditorImpl = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
@@ -13,7 +13,8 @@ const event_emitter_1 = require("../utils/event-emitter");
|
|
|
13
13
|
/** @internal */
|
|
14
14
|
class EditorImpl extends event_emitter_1.SafeEventEmitter {
|
|
15
15
|
constructor(opts) {
|
|
16
|
-
var _a, _b, _c, _d, _e;
|
|
16
|
+
var _a, _b, _c, _d, _e, _f;
|
|
17
|
+
var _g;
|
|
17
18
|
super({ onError: logger_1.logger.error.bind(logger_1.logger) });
|
|
18
19
|
_EditorImpl_markup.set(this, void 0);
|
|
19
20
|
_EditorImpl_editorMode.set(this, void 0);
|
|
@@ -23,7 +24,7 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
|
|
|
23
24
|
_EditorImpl_renderPreview.set(this, void 0);
|
|
24
25
|
_EditorImpl_wysiwygEditor.set(this, void 0);
|
|
25
26
|
_EditorImpl_markupEditor.set(this, void 0);
|
|
26
|
-
|
|
27
|
+
_EditorImpl_markupConfig.set(this, void 0);
|
|
27
28
|
_EditorImpl_preset.set(this, void 0);
|
|
28
29
|
_EditorImpl_allowHTML.set(this, void 0);
|
|
29
30
|
_EditorImpl_linkify.set(this, void 0);
|
|
@@ -45,7 +46,8 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
|
|
|
45
46
|
tslib_1.__classPrivateFieldSet(this, _EditorImpl_linkifyTlds, opts.linkifyTlds, "f");
|
|
46
47
|
tslib_1.__classPrivateFieldSet(this, _EditorImpl_allowHTML, opts.allowHTML, "f");
|
|
47
48
|
tslib_1.__classPrivateFieldSet(this, _EditorImpl_extensions, opts.extensions, "f");
|
|
48
|
-
tslib_1.__classPrivateFieldSet(this,
|
|
49
|
+
tslib_1.__classPrivateFieldSet(this, _EditorImpl_markupConfig, Object.assign({}, opts.markupConfig), "f");
|
|
50
|
+
(_f = (_g = tslib_1.__classPrivateFieldGet(this, _EditorImpl_markupConfig, "f")).extensions) !== null && _f !== void 0 ? _f : (_g.extensions = opts.extraMarkupExtensions);
|
|
49
51
|
tslib_1.__classPrivateFieldSet(this, _EditorImpl_renderStorage, opts.renderStorage, "f");
|
|
50
52
|
tslib_1.__classPrivateFieldSet(this, _EditorImpl_fileUploadHandler, opts.fileUploadHandler, "f");
|
|
51
53
|
tslib_1.__classPrivateFieldSet(this, _EditorImpl_needToSetDimensionsForUploadedImages, Boolean(opts.needToSetDimensionsForUploadedImages), "f");
|
|
@@ -154,7 +156,8 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
|
|
|
154
156
|
reactRenderer: tslib_1.__classPrivateFieldGet(this, _EditorImpl_renderStorage, "f"),
|
|
155
157
|
uploadHandler: this.fileUploadHandler,
|
|
156
158
|
needImgDimms: this.needToSetDimensionsForUploadedImages,
|
|
157
|
-
|
|
159
|
+
extensions: tslib_1.__classPrivateFieldGet(this, _EditorImpl_markupConfig, "f").extensions,
|
|
160
|
+
yfmLangOptions: { languageData: tslib_1.__classPrivateFieldGet(this, _EditorImpl_markupConfig, "f").languageData },
|
|
158
161
|
receiver: this,
|
|
159
162
|
})), "f");
|
|
160
163
|
}
|
|
@@ -275,4 +278,4 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
|
|
|
275
278
|
}
|
|
276
279
|
}
|
|
277
280
|
exports.EditorImpl = EditorImpl;
|
|
278
|
-
_EditorImpl_markup = new WeakMap(), _EditorImpl_editorMode = new WeakMap(), _EditorImpl_toolbarVisible = new WeakMap(), _EditorImpl_splitModeEnabled = new WeakMap(), _EditorImpl_splitMode = new WeakMap(), _EditorImpl_renderPreview = new WeakMap(), _EditorImpl_wysiwygEditor = new WeakMap(), _EditorImpl_markupEditor = new WeakMap(),
|
|
281
|
+
_EditorImpl_markup = new WeakMap(), _EditorImpl_editorMode = new WeakMap(), _EditorImpl_toolbarVisible = new WeakMap(), _EditorImpl_splitModeEnabled = new WeakMap(), _EditorImpl_splitMode = new WeakMap(), _EditorImpl_renderPreview = new WeakMap(), _EditorImpl_wysiwygEditor = new WeakMap(), _EditorImpl_markupEditor = new WeakMap(), _EditorImpl_markupConfig = new WeakMap(), _EditorImpl_preset = new WeakMap(), _EditorImpl_allowHTML = new WeakMap(), _EditorImpl_linkify = new WeakMap(), _EditorImpl_linkifyTlds = new WeakMap(), _EditorImpl_extensions = new WeakMap(), _EditorImpl_renderStorage = new WeakMap(), _EditorImpl_fileUploadHandler = new WeakMap(), _EditorImpl_needToSetDimensionsForUploadedImages = new WeakMap(), _EditorImpl_prepareRawMarkup = new WeakMap();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Editor as MarkdownEditorInstance, EditorMode as MarkdownEditorMode, EditorPreset as MarkdownEditorPreset, RenderPreview, SplitMode, } from './Editor';
|
|
1
|
+
export type { Editor as MarkdownEditorInstance, EditorMode as MarkdownEditorMode, EditorPreset as MarkdownEditorPreset, MarkupConfig as MarkdownEditorMarkupConfig, RenderPreview, SplitMode, } from './Editor';
|
|
2
2
|
export { MarkdownEditorProvider, useMarkdownEditorContext } from './context';
|
|
3
3
|
export { useMarkdownEditor } from './useMarkdownEditor';
|
|
4
4
|
export type { UseMarkdownEditorProps } from './useMarkdownEditor';
|
|
@@ -16,7 +16,7 @@ exports.checkboxInputType = (0, schema_1.nodeTypeFactory)(const_1.CheckboxNode.I
|
|
|
16
16
|
const CheckboxSpecs = (builder, opts) => {
|
|
17
17
|
const schemaSpecs = (0, schema_2.getSchemaSpecs)(opts, builder.context.get('placeholder'));
|
|
18
18
|
builder
|
|
19
|
-
.configureMd((md) => (
|
|
19
|
+
.configureMd((md) => md.use(checkbox_1.default, { idPrefix: const_1.idPrefix, divClass: (0, const_1.b)() }))
|
|
20
20
|
.addNode(const_1.CheckboxNode.Checkbox, () => ({
|
|
21
21
|
spec: schemaSpecs[const_1.CheckboxNode.Checkbox],
|
|
22
22
|
toMd: serializer_1.serializerTokens[const_1.CheckboxNode.Checkbox],
|
|
@@ -106,7 +106,8 @@ function buildDecosSet(doc) {
|
|
|
106
106
|
while ((child = parent.maybeChild(++idx))) {
|
|
107
107
|
const childPos = $pos.posAtIndex(idx, depth);
|
|
108
108
|
if ((0, utils_1.isHeading)(child)) {
|
|
109
|
-
|
|
109
|
+
const hasFolding = (0, utils_1.isFoldingHeading)(child);
|
|
110
|
+
if (hasFolding) {
|
|
110
111
|
nextFoldingHeadingFound = true;
|
|
111
112
|
}
|
|
112
113
|
const level = (0, utils_1.parseLevel)(child);
|
|
@@ -115,12 +116,14 @@ function buildDecosSet(doc) {
|
|
|
115
116
|
if (!hidden) {
|
|
116
117
|
lastNonHiddenChild = { node: child, pos: childPos, level: hLevel };
|
|
117
118
|
}
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
if (hasFolding) {
|
|
120
|
+
if ((0, utils_1.isUnfoldedHeading)(child)) {
|
|
121
|
+
hLevel = level;
|
|
122
|
+
hidden = false;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
hidden = true;
|
|
126
|
+
}
|
|
124
127
|
}
|
|
125
128
|
}
|
|
126
129
|
if (!hidden) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.YfmTableNode = void 0;
|
|
3
|
+
exports.YfmTableAttr = exports.YfmTableNode = void 0;
|
|
4
4
|
var YfmTableNode;
|
|
5
5
|
(function (YfmTableNode) {
|
|
6
6
|
YfmTableNode["Table"] = "yfm_table";
|
|
@@ -8,3 +8,9 @@ var YfmTableNode;
|
|
|
8
8
|
YfmTableNode["Row"] = "yfm_tr";
|
|
9
9
|
YfmTableNode["Cell"] = "yfm_td";
|
|
10
10
|
})(YfmTableNode = exports.YfmTableNode || (exports.YfmTableNode = {}));
|
|
11
|
+
var YfmTableAttr;
|
|
12
|
+
(function (YfmTableAttr) {
|
|
13
|
+
YfmTableAttr["Colspan"] = "colspan";
|
|
14
|
+
YfmTableAttr["Rowspan"] = "rowspan";
|
|
15
|
+
YfmTableAttr["CellAlign"] = "data-cell-align";
|
|
16
|
+
})(YfmTableAttr = exports.YfmTableAttr || (exports.YfmTableAttr = {}));
|
|
@@ -6,5 +6,16 @@ exports.parserTokens = {
|
|
|
6
6
|
[const_1.YfmTableNode.Table]: { name: const_1.YfmTableNode.Table, type: 'block' },
|
|
7
7
|
[const_1.YfmTableNode.Body]: { name: const_1.YfmTableNode.Body, type: 'block' },
|
|
8
8
|
[const_1.YfmTableNode.Row]: { name: const_1.YfmTableNode.Row, type: 'block' },
|
|
9
|
-
[const_1.YfmTableNode.Cell]: {
|
|
9
|
+
[const_1.YfmTableNode.Cell]: {
|
|
10
|
+
name: const_1.YfmTableNode.Cell,
|
|
11
|
+
type: 'block',
|
|
12
|
+
getAttrs: (token) => {
|
|
13
|
+
var _a, _b;
|
|
14
|
+
const attrs = Object.fromEntries(token.attrs || []);
|
|
15
|
+
const align = (_b = (_a = token.attrGet('class')) === null || _a === void 0 ? void 0 : _a.match(/cell-align-[a-z-]*/)) === null || _b === void 0 ? void 0 : _b[0];
|
|
16
|
+
if (align)
|
|
17
|
+
attrs[const_1.YfmTableAttr.CellAlign] = align;
|
|
18
|
+
return attrs;
|
|
19
|
+
},
|
|
20
|
+
},
|
|
10
21
|
};
|
|
@@ -57,12 +57,17 @@ const getSchemaSpecs = (opts, placeholder) => {
|
|
|
57
57
|
content: 'block+',
|
|
58
58
|
isolating: true,
|
|
59
59
|
definingAsContext: true,
|
|
60
|
+
attrs: {
|
|
61
|
+
[const_1.YfmTableAttr.Colspan]: { default: null },
|
|
62
|
+
[const_1.YfmTableAttr.Rowspan]: { default: null },
|
|
63
|
+
[const_1.YfmTableAttr.CellAlign]: { default: null },
|
|
64
|
+
},
|
|
60
65
|
parseDOM: [
|
|
61
66
|
{ tag: 'td', priority: 200 },
|
|
62
67
|
{ tag: 'th', priority: 200 },
|
|
63
68
|
],
|
|
64
|
-
toDOM() {
|
|
65
|
-
return ['td', 0];
|
|
69
|
+
toDOM(node) {
|
|
70
|
+
return ['td', node.attrs, 0];
|
|
66
71
|
},
|
|
67
72
|
placeholder: {
|
|
68
73
|
content: (_b = (_a = placeholder === null || placeholder === void 0 ? void 0 : placeholder[const_1.YfmTableNode.Cell]) !== null && _a !== void 0 ? _a : opts === null || opts === void 0 ? void 0 : opts.yfmTableCellPlaceholder) !== null && _b !== void 0 ? _b : DEFAULT_CELL_PLACEHOLDER,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.serializerTokens = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const is_number_1 = tslib_1.__importDefault(require("is-number"));
|
|
4
6
|
const const_1 = require("./const");
|
|
5
7
|
exports.serializerTokens = {
|
|
6
8
|
[const_1.YfmTableNode.Table]: (state, node) => {
|
|
@@ -13,24 +15,62 @@ exports.serializerTokens = {
|
|
|
13
15
|
state.closeBlock();
|
|
14
16
|
state.write('\n');
|
|
15
17
|
},
|
|
16
|
-
[const_1.YfmTableNode.Body]: (state,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
state.write('||');
|
|
21
|
-
state.ensureNewLine();
|
|
22
|
-
state.write('\n');
|
|
23
|
-
state.renderContent(node);
|
|
24
|
-
state.write('||');
|
|
25
|
-
state.ensureNewLine();
|
|
26
|
-
},
|
|
27
|
-
[const_1.YfmTableNode.Cell]: (state, node, parent) => {
|
|
28
|
-
state.renderContent(node);
|
|
29
|
-
const isLastCell = parent.lastChild === node;
|
|
30
|
-
if (!isLastCell) {
|
|
31
|
-
state.write('|');
|
|
18
|
+
[const_1.YfmTableNode.Body]: (state, tbody) => {
|
|
19
|
+
const rowspanStack = {};
|
|
20
|
+
tbody.forEach((trow) => {
|
|
21
|
+
state.write('||');
|
|
32
22
|
state.ensureNewLine();
|
|
33
23
|
state.write('\n');
|
|
34
|
-
|
|
24
|
+
let colIndex = 0;
|
|
25
|
+
trow.forEach((td) => {
|
|
26
|
+
while (colIndex in rowspanStack && rowspanStack[colIndex] > 0) {
|
|
27
|
+
state.write(colIndex === 0 ? '^' : '|^');
|
|
28
|
+
rowspanStack[colIndex]--;
|
|
29
|
+
colIndex++;
|
|
30
|
+
}
|
|
31
|
+
let rowspan = -1;
|
|
32
|
+
if ((0, is_number_1.default)(td.attrs[const_1.YfmTableAttr.Rowspan])) {
|
|
33
|
+
rowspan = Math.max(0, Number.parseInt(td.attrs[const_1.YfmTableAttr.Rowspan], 10));
|
|
34
|
+
rowspanStack[colIndex] = rowspan - 1;
|
|
35
|
+
}
|
|
36
|
+
if (colIndex > 0) {
|
|
37
|
+
state.write('|');
|
|
38
|
+
state.ensureNewLine();
|
|
39
|
+
state.write('\n');
|
|
40
|
+
}
|
|
41
|
+
state.renderContent(td);
|
|
42
|
+
if (td.attrs[const_1.YfmTableAttr.CellAlign]) {
|
|
43
|
+
state.write(`{.${td.attrs[const_1.YfmTableAttr.CellAlign]}}`);
|
|
44
|
+
state.ensureNewLine();
|
|
45
|
+
}
|
|
46
|
+
colIndex++;
|
|
47
|
+
if ((0, is_number_1.default)(td.attrs[const_1.YfmTableAttr.Colspan])) {
|
|
48
|
+
let colspan = Math.max(0, Number.parseInt(td.attrs[const_1.YfmTableAttr.Colspan], 10));
|
|
49
|
+
while (--colspan > 0) {
|
|
50
|
+
state.write('|>');
|
|
51
|
+
if (rowspan > 0)
|
|
52
|
+
rowspanStack[colIndex] = rowspan - 1;
|
|
53
|
+
colIndex++;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const isLastCell = trow.lastChild === td;
|
|
57
|
+
if (isLastCell) {
|
|
58
|
+
while (colIndex in rowspanStack && rowspanStack[colIndex] > 0) {
|
|
59
|
+
state.write('|^');
|
|
60
|
+
rowspanStack[colIndex]--;
|
|
61
|
+
colIndex++;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
state.ensureNewLine();
|
|
66
|
+
state.write('||');
|
|
67
|
+
state.ensureNewLine();
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
[const_1.YfmTableNode.Row]: (_state, node) => {
|
|
71
|
+
throw new Error(`Should not serialize ${node.type.name} node via serialize-token`);
|
|
72
|
+
},
|
|
73
|
+
[const_1.YfmTableNode.Cell]: (_state, node) => {
|
|
74
|
+
throw new Error(`Should not serialize ${node.type.name} node via serialize-token`);
|
|
35
75
|
},
|
|
36
76
|
};
|
|
@@ -14,6 +14,7 @@ const table_utils_1 = require("../../../../../table-utils");
|
|
|
14
14
|
const node_children_1 = require("../../../../../utils/node-children");
|
|
15
15
|
const nodes_1 = require("../../../../../utils/nodes");
|
|
16
16
|
const ReactRenderer_1 = require("../../../../behavior/ReactRenderer");
|
|
17
|
+
const const_1 = require("../../const");
|
|
17
18
|
const actions_1 = require("./actions");
|
|
18
19
|
exports.yfmTableCellCn = (0, classname_1.cn)('table-cell-view');
|
|
19
20
|
const b = exports.yfmTableCellCn;
|
|
@@ -179,6 +180,14 @@ const yfmTableCellView = (node, view, getPos) => {
|
|
|
179
180
|
return {};
|
|
180
181
|
}
|
|
181
182
|
const dom = document.createElement('td');
|
|
183
|
+
if (node.attrs[const_1.YfmTableAttr.Colspan])
|
|
184
|
+
dom.setAttribute('colspan', node.attrs[const_1.YfmTableAttr.Colspan]);
|
|
185
|
+
if (node.attrs[const_1.YfmTableAttr.Rowspan])
|
|
186
|
+
dom.setAttribute('rowspan', node.attrs[const_1.YfmTableAttr.Rowspan]);
|
|
187
|
+
if (node.attrs[const_1.YfmTableAttr.CellAlign]) {
|
|
188
|
+
dom.classList.add(node.attrs[const_1.YfmTableAttr.CellAlign]);
|
|
189
|
+
dom.setAttribute(const_1.YfmTableAttr.CellAlign, node.attrs[const_1.YfmTableAttr.Rowspan]);
|
|
190
|
+
}
|
|
182
191
|
const contentDOM = document.createElement('div');
|
|
183
192
|
const control = document.createElement('span');
|
|
184
193
|
control.setAttribute('style', 'width: 0; height: 0; float: left;');
|
|
@@ -4,6 +4,8 @@ import { EventMap } from '../../bundle/Editor';
|
|
|
4
4
|
import { ReactRenderStorage } from '../../extensions';
|
|
5
5
|
import { Receiver } from '../../utils';
|
|
6
6
|
import { FileUploadHandler } from './files-upload-facet';
|
|
7
|
+
import { type YfmLangOptions } from './yfm';
|
|
8
|
+
export type { YfmLangOptions };
|
|
7
9
|
export declare type CreateCodemirrorParams = {
|
|
8
10
|
doc: EditorViewConfig['doc'];
|
|
9
11
|
placeholderText: string;
|
|
@@ -15,8 +17,9 @@ export declare type CreateCodemirrorParams = {
|
|
|
15
17
|
reactRenderer: ReactRenderStorage;
|
|
16
18
|
uploadHandler?: FileUploadHandler;
|
|
17
19
|
needImgDimms?: boolean;
|
|
18
|
-
|
|
20
|
+
extensions?: Extension[];
|
|
19
21
|
receiver?: Receiver<EventMap>;
|
|
22
|
+
yfmLangOptions?: YfmLangOptions;
|
|
20
23
|
};
|
|
21
24
|
export declare function createCodemirror(params: CreateCodemirrorParams): EditorView;
|
|
22
25
|
export declare function withLogger(action: string, command: StateCommand): StateCommand;
|
|
@@ -16,7 +16,7 @@ const react_facet_1 = require("./react-facet");
|
|
|
16
16
|
const plugin_1 = require("./search-plugin/plugin");
|
|
17
17
|
const yfm_1 = require("./yfm");
|
|
18
18
|
function createCodemirror(params) {
|
|
19
|
-
const { doc, placeholderText, reactRenderer, onCancel, onScroll, onSubmit, onChange, onDocChange,
|
|
19
|
+
const { doc, placeholderText, reactRenderer, onCancel, onScroll, onSubmit, onChange, onDocChange, extensions: extraExtensions, receiver, yfmLangOptions, } = params;
|
|
20
20
|
const extensions = [
|
|
21
21
|
gravity_1.gravityTheme,
|
|
22
22
|
(0, view_1.placeholder)(placeholderText),
|
|
@@ -60,7 +60,7 @@ function createCodemirror(params) {
|
|
|
60
60
|
...commands_1.historyKeymap,
|
|
61
61
|
]),
|
|
62
62
|
(0, autocomplete_1.autocompletion)(),
|
|
63
|
-
(0, yfm_1.yfmLang)(),
|
|
63
|
+
(0, yfm_1.yfmLang)(yfmLangOptions),
|
|
64
64
|
react_facet_1.ReactRendererFacet.of(reactRenderer),
|
|
65
65
|
pairing_chars_1.PairingCharactersExtension,
|
|
66
66
|
view_1.EditorView.lineWrapping,
|
|
@@ -81,8 +81,8 @@ function createCodemirror(params) {
|
|
|
81
81
|
imgWithDimms: params.needImgDimms,
|
|
82
82
|
}));
|
|
83
83
|
}
|
|
84
|
-
if (
|
|
85
|
-
extensions.push(...
|
|
84
|
+
if (extraExtensions) {
|
|
85
|
+
extensions.push(...extraExtensions);
|
|
86
86
|
}
|
|
87
87
|
return new view_1.EditorView({
|
|
88
88
|
doc,
|
package/build/cjs/version.js
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VERSION = void 0;
|
|
4
4
|
/** During build process, the current version will be injected here */
|
|
5
|
-
exports.VERSION = typeof '13.
|
|
5
|
+
exports.VERSION = typeof '13.9.0' !== 'undefined' ? '13.9.0' : 'unknown';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RefObject } from 'react';
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
2
|
export declare function useYfmShowElemWithId(ref: RefObject<HTMLElement>, id: string): void;
|
|
@@ -13,6 +13,10 @@ const YfmTabsCN = {
|
|
|
13
13
|
Tab: 'yfm-tab',
|
|
14
14
|
TabPanel: 'yfm-tab-panel',
|
|
15
15
|
};
|
|
16
|
+
const FoldingHeadingsCN = {
|
|
17
|
+
Open: 'open',
|
|
18
|
+
Section: 'heading-section',
|
|
19
|
+
};
|
|
16
20
|
function useYfmShowElemWithId(ref, id) {
|
|
17
21
|
(0, react_1.useEffect)(() => {
|
|
18
22
|
const { current: containerDom } = ref;
|
|
@@ -23,7 +27,7 @@ function useYfmShowElemWithId(ref, id) {
|
|
|
23
27
|
return;
|
|
24
28
|
while (elem && elem !== containerDom) {
|
|
25
29
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
26
|
-
openYfmCut(elem) || switchYfmTabs(elem);
|
|
30
|
+
openYfmCut(elem) || openFoldingHeadings(elem, id) || switchYfmTabs(elem);
|
|
27
31
|
elem = elem.parentElement;
|
|
28
32
|
}
|
|
29
33
|
}, [id]);
|
|
@@ -66,3 +70,13 @@ function switchYfmTabs(tabPanelElem) {
|
|
|
66
70
|
}
|
|
67
71
|
return true;
|
|
68
72
|
}
|
|
73
|
+
function openFoldingHeadings(elem, id) {
|
|
74
|
+
var _a;
|
|
75
|
+
if (elem.classList.contains(FoldingHeadingsCN.Section) &&
|
|
76
|
+
!elem.classList.contains(FoldingHeadingsCN.Open) &&
|
|
77
|
+
id !== ((_a = elem.firstElementChild) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
78
|
+
elem.classList.add(FoldingHeadingsCN.Open);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
@@ -3,6 +3,8 @@ import type { Extension as CodemirrorExtension } from '@codemirror/state';
|
|
|
3
3
|
import { CommonEditor, MarkupString } from '../common';
|
|
4
4
|
import { WysiwygEditorOptions } from '../core';
|
|
5
5
|
import { ReactRenderStorage } from '../extensions';
|
|
6
|
+
import { type CreateCodemirrorParams } from '../markup/codemirror';
|
|
7
|
+
import type { YfmLangOptions } from '../markup/codemirror/yfm';
|
|
6
8
|
import { Receiver } from '../utils/event-emitter';
|
|
7
9
|
import type { FileUploadHandler } from '../utils/upload';
|
|
8
10
|
export declare type EditorMode = 'wysiwyg' | 'markup';
|
|
@@ -42,6 +44,16 @@ export interface Editor extends Receiver<EventMap>, CommonEditor {
|
|
|
42
44
|
line: number;
|
|
43
45
|
}): void;
|
|
44
46
|
}
|
|
47
|
+
export declare type MarkupConfig = {
|
|
48
|
+
/** Additional extensions for codemirror instance. */
|
|
49
|
+
extensions?: CreateCodemirrorParams['extensions'];
|
|
50
|
+
/**
|
|
51
|
+
* Additional language data for markdown language in codemirror.
|
|
52
|
+
* Can be used to configure additional autocompletions and others.
|
|
53
|
+
* See more https://codemirror.net/docs/ref/#state.EditorState.languageDataAt
|
|
54
|
+
*/
|
|
55
|
+
languageData?: YfmLangOptions['languageData'];
|
|
56
|
+
};
|
|
45
57
|
export declare type EditorOptions = Pick<WysiwygEditorOptions, 'allowHTML' | 'linkify' | 'linkifyTlds' | 'extensions'> & {
|
|
46
58
|
initialMarkup?: MarkupString;
|
|
47
59
|
/** @default 'wysiwyg' */
|
|
@@ -68,5 +80,7 @@ export declare type EditorOptions = Pick<WysiwygEditorOptions, 'allowHTML' | 'li
|
|
|
68
80
|
splitMode?: SplitMode;
|
|
69
81
|
renderPreview?: RenderPreview;
|
|
70
82
|
preset: EditorPreset;
|
|
83
|
+
/** @deprecated Put extra extensions via MarkdownEditorMarkupConfig */
|
|
71
84
|
extraMarkupExtensions?: CodemirrorExtension[];
|
|
85
|
+
markupConfig?: MarkupConfig;
|
|
72
86
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var _EditorImpl_markup, _EditorImpl_editorMode, _EditorImpl_toolbarVisible, _EditorImpl_splitModeEnabled, _EditorImpl_splitMode, _EditorImpl_renderPreview, _EditorImpl_wysiwygEditor, _EditorImpl_markupEditor,
|
|
1
|
+
var _EditorImpl_markup, _EditorImpl_editorMode, _EditorImpl_toolbarVisible, _EditorImpl_splitModeEnabled, _EditorImpl_splitMode, _EditorImpl_renderPreview, _EditorImpl_wysiwygEditor, _EditorImpl_markupEditor, _EditorImpl_markupConfig, _EditorImpl_preset, _EditorImpl_allowHTML, _EditorImpl_linkify, _EditorImpl_linkifyTlds, _EditorImpl_extensions, _EditorImpl_renderStorage, _EditorImpl_fileUploadHandler, _EditorImpl_needToSetDimensionsForUploadedImages, _EditorImpl_prepareRawMarkup;
|
|
2
2
|
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
3
|
import { TextSelection } from 'prosemirror-state';
|
|
4
4
|
import { WysiwygEditor } from '../core';
|
|
@@ -10,7 +10,8 @@ import { SafeEventEmitter } from '../utils/event-emitter';
|
|
|
10
10
|
/** @internal */
|
|
11
11
|
export class EditorImpl extends SafeEventEmitter {
|
|
12
12
|
constructor(opts) {
|
|
13
|
-
var _a, _b, _c, _d, _e;
|
|
13
|
+
var _a, _b, _c, _d, _e, _f;
|
|
14
|
+
var _g;
|
|
14
15
|
super({ onError: logger.error.bind(logger) });
|
|
15
16
|
_EditorImpl_markup.set(this, void 0);
|
|
16
17
|
_EditorImpl_editorMode.set(this, void 0);
|
|
@@ -20,7 +21,7 @@ export class EditorImpl extends SafeEventEmitter {
|
|
|
20
21
|
_EditorImpl_renderPreview.set(this, void 0);
|
|
21
22
|
_EditorImpl_wysiwygEditor.set(this, void 0);
|
|
22
23
|
_EditorImpl_markupEditor.set(this, void 0);
|
|
23
|
-
|
|
24
|
+
_EditorImpl_markupConfig.set(this, void 0);
|
|
24
25
|
_EditorImpl_preset.set(this, void 0);
|
|
25
26
|
_EditorImpl_allowHTML.set(this, void 0);
|
|
26
27
|
_EditorImpl_linkify.set(this, void 0);
|
|
@@ -42,7 +43,8 @@ export class EditorImpl extends SafeEventEmitter {
|
|
|
42
43
|
__classPrivateFieldSet(this, _EditorImpl_linkifyTlds, opts.linkifyTlds, "f");
|
|
43
44
|
__classPrivateFieldSet(this, _EditorImpl_allowHTML, opts.allowHTML, "f");
|
|
44
45
|
__classPrivateFieldSet(this, _EditorImpl_extensions, opts.extensions, "f");
|
|
45
|
-
__classPrivateFieldSet(this,
|
|
46
|
+
__classPrivateFieldSet(this, _EditorImpl_markupConfig, Object.assign({}, opts.markupConfig), "f");
|
|
47
|
+
(_f = (_g = __classPrivateFieldGet(this, _EditorImpl_markupConfig, "f")).extensions) !== null && _f !== void 0 ? _f : (_g.extensions = opts.extraMarkupExtensions);
|
|
46
48
|
__classPrivateFieldSet(this, _EditorImpl_renderStorage, opts.renderStorage, "f");
|
|
47
49
|
__classPrivateFieldSet(this, _EditorImpl_fileUploadHandler, opts.fileUploadHandler, "f");
|
|
48
50
|
__classPrivateFieldSet(this, _EditorImpl_needToSetDimensionsForUploadedImages, Boolean(opts.needToSetDimensionsForUploadedImages), "f");
|
|
@@ -151,7 +153,8 @@ export class EditorImpl extends SafeEventEmitter {
|
|
|
151
153
|
reactRenderer: __classPrivateFieldGet(this, _EditorImpl_renderStorage, "f"),
|
|
152
154
|
uploadHandler: this.fileUploadHandler,
|
|
153
155
|
needImgDimms: this.needToSetDimensionsForUploadedImages,
|
|
154
|
-
|
|
156
|
+
extensions: __classPrivateFieldGet(this, _EditorImpl_markupConfig, "f").extensions,
|
|
157
|
+
yfmLangOptions: { languageData: __classPrivateFieldGet(this, _EditorImpl_markupConfig, "f").languageData },
|
|
155
158
|
receiver: this,
|
|
156
159
|
})), "f");
|
|
157
160
|
}
|
|
@@ -271,4 +274,4 @@ export class EditorImpl extends SafeEventEmitter {
|
|
|
271
274
|
return (serializedEditorMarkup === null || serializedEditorMarkup === void 0 ? void 0 : serializedEditorMarkup.trim()) !== wysiwygValue.trim();
|
|
272
275
|
}
|
|
273
276
|
}
|
|
274
|
-
_EditorImpl_markup = new WeakMap(), _EditorImpl_editorMode = new WeakMap(), _EditorImpl_toolbarVisible = new WeakMap(), _EditorImpl_splitModeEnabled = new WeakMap(), _EditorImpl_splitMode = new WeakMap(), _EditorImpl_renderPreview = new WeakMap(), _EditorImpl_wysiwygEditor = new WeakMap(), _EditorImpl_markupEditor = new WeakMap(),
|
|
277
|
+
_EditorImpl_markup = new WeakMap(), _EditorImpl_editorMode = new WeakMap(), _EditorImpl_toolbarVisible = new WeakMap(), _EditorImpl_splitModeEnabled = new WeakMap(), _EditorImpl_splitMode = new WeakMap(), _EditorImpl_renderPreview = new WeakMap(), _EditorImpl_wysiwygEditor = new WeakMap(), _EditorImpl_markupEditor = new WeakMap(), _EditorImpl_markupConfig = new WeakMap(), _EditorImpl_preset = new WeakMap(), _EditorImpl_allowHTML = new WeakMap(), _EditorImpl_linkify = new WeakMap(), _EditorImpl_linkifyTlds = new WeakMap(), _EditorImpl_extensions = new WeakMap(), _EditorImpl_renderStorage = new WeakMap(), _EditorImpl_fileUploadHandler = new WeakMap(), _EditorImpl_needToSetDimensionsForUploadedImages = new WeakMap(), _EditorImpl_prepareRawMarkup = new WeakMap();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Editor as MarkdownEditorInstance, EditorMode as MarkdownEditorMode, EditorPreset as MarkdownEditorPreset, RenderPreview, SplitMode, } from './Editor';
|
|
1
|
+
export type { Editor as MarkdownEditorInstance, EditorMode as MarkdownEditorMode, EditorPreset as MarkdownEditorPreset, MarkupConfig as MarkdownEditorMarkupConfig, RenderPreview, SplitMode, } from './Editor';
|
|
2
2
|
export { MarkdownEditorProvider, useMarkdownEditorContext } from './context';
|
|
3
3
|
export { useMarkdownEditor } from './useMarkdownEditor';
|
|
4
4
|
export type { UseMarkdownEditorProps } from './useMarkdownEditor';
|
|
@@ -11,7 +11,7 @@ export const checkboxInputType = nodeTypeFactory(CheckboxNode.Input);
|
|
|
11
11
|
export const CheckboxSpecs = (builder, opts) => {
|
|
12
12
|
const schemaSpecs = getSchemaSpecs(opts, builder.context.get('placeholder'));
|
|
13
13
|
builder
|
|
14
|
-
.configureMd((md) => checkboxPlugin
|
|
14
|
+
.configureMd((md) => md.use(checkboxPlugin, { idPrefix, divClass: b() }))
|
|
15
15
|
.addNode(CheckboxNode.Checkbox, () => ({
|
|
16
16
|
spec: schemaSpecs[CheckboxNode.Checkbox],
|
|
17
17
|
toMd: serializerTokens[CheckboxNode.Checkbox],
|
|
@@ -103,7 +103,8 @@ function buildDecosSet(doc) {
|
|
|
103
103
|
while ((child = parent.maybeChild(++idx))) {
|
|
104
104
|
const childPos = $pos.posAtIndex(idx, depth);
|
|
105
105
|
if (isHeading(child)) {
|
|
106
|
-
|
|
106
|
+
const hasFolding = isFoldingHeading(child);
|
|
107
|
+
if (hasFolding) {
|
|
107
108
|
nextFoldingHeadingFound = true;
|
|
108
109
|
}
|
|
109
110
|
const level = parseLevel(child);
|
|
@@ -112,12 +113,14 @@ function buildDecosSet(doc) {
|
|
|
112
113
|
if (!hidden) {
|
|
113
114
|
lastNonHiddenChild = { node: child, pos: childPos, level: hLevel };
|
|
114
115
|
}
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
if (hasFolding) {
|
|
117
|
+
if (isUnfoldedHeading(child)) {
|
|
118
|
+
hLevel = level;
|
|
119
|
+
hidden = false;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
hidden = true;
|
|
123
|
+
}
|
|
121
124
|
}
|
|
122
125
|
}
|
|
123
126
|
if (!hidden) {
|
|
@@ -5,3 +5,9 @@ export var YfmTableNode;
|
|
|
5
5
|
YfmTableNode["Row"] = "yfm_tr";
|
|
6
6
|
YfmTableNode["Cell"] = "yfm_td";
|
|
7
7
|
})(YfmTableNode || (YfmTableNode = {}));
|
|
8
|
+
export var YfmTableAttr;
|
|
9
|
+
(function (YfmTableAttr) {
|
|
10
|
+
YfmTableAttr["Colspan"] = "colspan";
|
|
11
|
+
YfmTableAttr["Rowspan"] = "rowspan";
|
|
12
|
+
YfmTableAttr["CellAlign"] = "data-cell-align";
|
|
13
|
+
})(YfmTableAttr || (YfmTableAttr = {}));
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import { YfmTableNode } from './const';
|
|
1
|
+
import { YfmTableAttr, YfmTableNode } from './const';
|
|
2
2
|
export const parserTokens = {
|
|
3
3
|
[YfmTableNode.Table]: { name: YfmTableNode.Table, type: 'block' },
|
|
4
4
|
[YfmTableNode.Body]: { name: YfmTableNode.Body, type: 'block' },
|
|
5
5
|
[YfmTableNode.Row]: { name: YfmTableNode.Row, type: 'block' },
|
|
6
|
-
[YfmTableNode.Cell]: {
|
|
6
|
+
[YfmTableNode.Cell]: {
|
|
7
|
+
name: YfmTableNode.Cell,
|
|
8
|
+
type: 'block',
|
|
9
|
+
getAttrs: (token) => {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
const attrs = Object.fromEntries(token.attrs || []);
|
|
12
|
+
const align = (_b = (_a = token.attrGet('class')) === null || _a === void 0 ? void 0 : _a.match(/cell-align-[a-z-]*/)) === null || _b === void 0 ? void 0 : _b[0];
|
|
13
|
+
if (align)
|
|
14
|
+
attrs[YfmTableAttr.CellAlign] = align;
|
|
15
|
+
return attrs;
|
|
16
|
+
},
|
|
17
|
+
},
|
|
7
18
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableRole } from '../../../../table-utils';
|
|
2
|
-
import { YfmTableNode } from './const';
|
|
2
|
+
import { YfmTableAttr, YfmTableNode } from './const';
|
|
3
3
|
const DEFAULT_CELL_PLACEHOLDER = 'Table cell';
|
|
4
4
|
export const getSchemaSpecs = (opts, placeholder) => {
|
|
5
5
|
var _a, _b;
|
|
@@ -54,12 +54,17 @@ export const getSchemaSpecs = (opts, placeholder) => {
|
|
|
54
54
|
content: 'block+',
|
|
55
55
|
isolating: true,
|
|
56
56
|
definingAsContext: true,
|
|
57
|
+
attrs: {
|
|
58
|
+
[YfmTableAttr.Colspan]: { default: null },
|
|
59
|
+
[YfmTableAttr.Rowspan]: { default: null },
|
|
60
|
+
[YfmTableAttr.CellAlign]: { default: null },
|
|
61
|
+
},
|
|
57
62
|
parseDOM: [
|
|
58
63
|
{ tag: 'td', priority: 200 },
|
|
59
64
|
{ tag: 'th', priority: 200 },
|
|
60
65
|
],
|
|
61
|
-
toDOM() {
|
|
62
|
-
return ['td', 0];
|
|
66
|
+
toDOM(node) {
|
|
67
|
+
return ['td', node.attrs, 0];
|
|
63
68
|
},
|
|
64
69
|
placeholder: {
|
|
65
70
|
content: (_b = (_a = placeholder === null || placeholder === void 0 ? void 0 : placeholder[YfmTableNode.Cell]) !== null && _a !== void 0 ? _a : opts === null || opts === void 0 ? void 0 : opts.yfmTableCellPlaceholder) !== null && _b !== void 0 ? _b : DEFAULT_CELL_PLACEHOLDER,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import isNumber from 'is-number';
|
|
2
|
+
import { YfmTableAttr, YfmTableNode } from './const';
|
|
2
3
|
export const serializerTokens = {
|
|
3
4
|
[YfmTableNode.Table]: (state, node) => {
|
|
4
5
|
state.ensureNewLine();
|
|
@@ -10,24 +11,62 @@ export const serializerTokens = {
|
|
|
10
11
|
state.closeBlock();
|
|
11
12
|
state.write('\n');
|
|
12
13
|
},
|
|
13
|
-
[YfmTableNode.Body]: (state,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
state.write('||');
|
|
18
|
-
state.ensureNewLine();
|
|
19
|
-
state.write('\n');
|
|
20
|
-
state.renderContent(node);
|
|
21
|
-
state.write('||');
|
|
22
|
-
state.ensureNewLine();
|
|
23
|
-
},
|
|
24
|
-
[YfmTableNode.Cell]: (state, node, parent) => {
|
|
25
|
-
state.renderContent(node);
|
|
26
|
-
const isLastCell = parent.lastChild === node;
|
|
27
|
-
if (!isLastCell) {
|
|
28
|
-
state.write('|');
|
|
14
|
+
[YfmTableNode.Body]: (state, tbody) => {
|
|
15
|
+
const rowspanStack = {};
|
|
16
|
+
tbody.forEach((trow) => {
|
|
17
|
+
state.write('||');
|
|
29
18
|
state.ensureNewLine();
|
|
30
19
|
state.write('\n');
|
|
31
|
-
|
|
20
|
+
let colIndex = 0;
|
|
21
|
+
trow.forEach((td) => {
|
|
22
|
+
while (colIndex in rowspanStack && rowspanStack[colIndex] > 0) {
|
|
23
|
+
state.write(colIndex === 0 ? '^' : '|^');
|
|
24
|
+
rowspanStack[colIndex]--;
|
|
25
|
+
colIndex++;
|
|
26
|
+
}
|
|
27
|
+
let rowspan = -1;
|
|
28
|
+
if (isNumber(td.attrs[YfmTableAttr.Rowspan])) {
|
|
29
|
+
rowspan = Math.max(0, Number.parseInt(td.attrs[YfmTableAttr.Rowspan], 10));
|
|
30
|
+
rowspanStack[colIndex] = rowspan - 1;
|
|
31
|
+
}
|
|
32
|
+
if (colIndex > 0) {
|
|
33
|
+
state.write('|');
|
|
34
|
+
state.ensureNewLine();
|
|
35
|
+
state.write('\n');
|
|
36
|
+
}
|
|
37
|
+
state.renderContent(td);
|
|
38
|
+
if (td.attrs[YfmTableAttr.CellAlign]) {
|
|
39
|
+
state.write(`{.${td.attrs[YfmTableAttr.CellAlign]}}`);
|
|
40
|
+
state.ensureNewLine();
|
|
41
|
+
}
|
|
42
|
+
colIndex++;
|
|
43
|
+
if (isNumber(td.attrs[YfmTableAttr.Colspan])) {
|
|
44
|
+
let colspan = Math.max(0, Number.parseInt(td.attrs[YfmTableAttr.Colspan], 10));
|
|
45
|
+
while (--colspan > 0) {
|
|
46
|
+
state.write('|>');
|
|
47
|
+
if (rowspan > 0)
|
|
48
|
+
rowspanStack[colIndex] = rowspan - 1;
|
|
49
|
+
colIndex++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const isLastCell = trow.lastChild === td;
|
|
53
|
+
if (isLastCell) {
|
|
54
|
+
while (colIndex in rowspanStack && rowspanStack[colIndex] > 0) {
|
|
55
|
+
state.write('|^');
|
|
56
|
+
rowspanStack[colIndex]--;
|
|
57
|
+
colIndex++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
state.ensureNewLine();
|
|
62
|
+
state.write('||');
|
|
63
|
+
state.ensureNewLine();
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
[YfmTableNode.Row]: (_state, node) => {
|
|
67
|
+
throw new Error(`Should not serialize ${node.type.name} node via serialize-token`);
|
|
68
|
+
},
|
|
69
|
+
[YfmTableNode.Cell]: (_state, node) => {
|
|
70
|
+
throw new Error(`Should not serialize ${node.type.name} node via serialize-token`);
|
|
32
71
|
},
|
|
33
72
|
};
|
|
@@ -10,6 +10,7 @@ import { getTableDimensions, isTableNode } from '../../../../../table-utils';
|
|
|
10
10
|
import { getChildByNode } from '../../../../../utils/node-children';
|
|
11
11
|
import { getChildrenOfNode } from '../../../../../utils/nodes';
|
|
12
12
|
import { getReactRendererFromState } from '../../../../behavior/ReactRenderer';
|
|
13
|
+
import { YfmTableAttr } from '../../const';
|
|
13
14
|
import { controlActions } from './actions';
|
|
14
15
|
import './yfmTableCellView.css';
|
|
15
16
|
export const yfmTableCellCn = cn('table-cell-view');
|
|
@@ -176,6 +177,14 @@ export const yfmTableCellView = (node, view, getPos) => {
|
|
|
176
177
|
return {};
|
|
177
178
|
}
|
|
178
179
|
const dom = document.createElement('td');
|
|
180
|
+
if (node.attrs[YfmTableAttr.Colspan])
|
|
181
|
+
dom.setAttribute('colspan', node.attrs[YfmTableAttr.Colspan]);
|
|
182
|
+
if (node.attrs[YfmTableAttr.Rowspan])
|
|
183
|
+
dom.setAttribute('rowspan', node.attrs[YfmTableAttr.Rowspan]);
|
|
184
|
+
if (node.attrs[YfmTableAttr.CellAlign]) {
|
|
185
|
+
dom.classList.add(node.attrs[YfmTableAttr.CellAlign]);
|
|
186
|
+
dom.setAttribute(YfmTableAttr.CellAlign, node.attrs[YfmTableAttr.Rowspan]);
|
|
187
|
+
}
|
|
179
188
|
const contentDOM = document.createElement('div');
|
|
180
189
|
const control = document.createElement('span');
|
|
181
190
|
control.setAttribute('style', 'width: 0; height: 0; float: left;');
|
|
@@ -4,6 +4,8 @@ import { EventMap } from '../../bundle/Editor';
|
|
|
4
4
|
import { ReactRenderStorage } from '../../extensions';
|
|
5
5
|
import { Receiver } from '../../utils';
|
|
6
6
|
import { FileUploadHandler } from './files-upload-facet';
|
|
7
|
+
import { type YfmLangOptions } from './yfm';
|
|
8
|
+
export type { YfmLangOptions };
|
|
7
9
|
export declare type CreateCodemirrorParams = {
|
|
8
10
|
doc: EditorViewConfig['doc'];
|
|
9
11
|
placeholderText: string;
|
|
@@ -15,8 +17,9 @@ export declare type CreateCodemirrorParams = {
|
|
|
15
17
|
reactRenderer: ReactRenderStorage;
|
|
16
18
|
uploadHandler?: FileUploadHandler;
|
|
17
19
|
needImgDimms?: boolean;
|
|
18
|
-
|
|
20
|
+
extensions?: Extension[];
|
|
19
21
|
receiver?: Receiver<EventMap>;
|
|
22
|
+
yfmLangOptions?: YfmLangOptions;
|
|
20
23
|
};
|
|
21
24
|
export declare function createCodemirror(params: CreateCodemirrorParams): EditorView;
|
|
22
25
|
export declare function withLogger(action: string, command: StateCommand): StateCommand;
|
|
@@ -13,7 +13,7 @@ import { ReactRendererFacet } from './react-facet';
|
|
|
13
13
|
import { SearchPanelPlugin } from './search-plugin/plugin';
|
|
14
14
|
import { yfmLang } from './yfm';
|
|
15
15
|
export function createCodemirror(params) {
|
|
16
|
-
const { doc, placeholderText, reactRenderer, onCancel, onScroll, onSubmit, onChange, onDocChange,
|
|
16
|
+
const { doc, placeholderText, reactRenderer, onCancel, onScroll, onSubmit, onChange, onDocChange, extensions: extraExtensions, receiver, yfmLangOptions, } = params;
|
|
17
17
|
const extensions = [
|
|
18
18
|
gravityTheme,
|
|
19
19
|
placeholder(placeholderText),
|
|
@@ -57,7 +57,7 @@ export function createCodemirror(params) {
|
|
|
57
57
|
...historyKeymap,
|
|
58
58
|
]),
|
|
59
59
|
autocompletion(),
|
|
60
|
-
yfmLang(),
|
|
60
|
+
yfmLang(yfmLangOptions),
|
|
61
61
|
ReactRendererFacet.of(reactRenderer),
|
|
62
62
|
PairingCharactersExtension,
|
|
63
63
|
EditorView.lineWrapping,
|
|
@@ -78,8 +78,8 @@ export function createCodemirror(params) {
|
|
|
78
78
|
imgWithDimms: params.needImgDimms,
|
|
79
79
|
}));
|
|
80
80
|
}
|
|
81
|
-
if (
|
|
82
|
-
extensions.push(...
|
|
81
|
+
if (extraExtensions) {
|
|
82
|
+
extensions.push(...extraExtensions);
|
|
83
83
|
}
|
|
84
84
|
return new EditorView({
|
|
85
85
|
doc,
|
package/build/esm/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** During build process, the current version will be injected here */
|
|
2
|
-
export const VERSION = typeof '13.
|
|
2
|
+
export const VERSION = typeof '13.9.0' !== 'undefined' ? '13.9.0' : 'unknown';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RefObject } from 'react';
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
2
|
export declare function useYfmShowElemWithId(ref: RefObject<HTMLElement>, id: string): void;
|
|
@@ -10,6 +10,10 @@ const YfmTabsCN = {
|
|
|
10
10
|
Tab: 'yfm-tab',
|
|
11
11
|
TabPanel: 'yfm-tab-panel',
|
|
12
12
|
};
|
|
13
|
+
const FoldingHeadingsCN = {
|
|
14
|
+
Open: 'open',
|
|
15
|
+
Section: 'heading-section',
|
|
16
|
+
};
|
|
13
17
|
export function useYfmShowElemWithId(ref, id) {
|
|
14
18
|
useEffect(() => {
|
|
15
19
|
const { current: containerDom } = ref;
|
|
@@ -20,7 +24,7 @@ export function useYfmShowElemWithId(ref, id) {
|
|
|
20
24
|
return;
|
|
21
25
|
while (elem && elem !== containerDom) {
|
|
22
26
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
23
|
-
openYfmCut(elem) || switchYfmTabs(elem);
|
|
27
|
+
openYfmCut(elem) || openFoldingHeadings(elem, id) || switchYfmTabs(elem);
|
|
24
28
|
elem = elem.parentElement;
|
|
25
29
|
}
|
|
26
30
|
}, [id]);
|
|
@@ -62,3 +66,13 @@ function switchYfmTabs(tabPanelElem) {
|
|
|
62
66
|
}
|
|
63
67
|
return true;
|
|
64
68
|
}
|
|
69
|
+
function openFoldingHeadings(elem, id) {
|
|
70
|
+
var _a;
|
|
71
|
+
if (elem.classList.contains(FoldingHeadingsCN.Section) &&
|
|
72
|
+
!elem.classList.contains(FoldingHeadingsCN.Open) &&
|
|
73
|
+
id !== ((_a = elem.firstElementChild) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
74
|
+
elem.classList.add(FoldingHeadingsCN.Open);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/markdown-editor",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.9.0",
|
|
4
4
|
"description": "Markdown wysiwyg and markup editor",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
"@diplodoc/html-extension": "1.2.7",
|
|
204
204
|
"@diplodoc/latex-extension": "1.0.3",
|
|
205
205
|
"@diplodoc/mermaid-extension": "1.2.1",
|
|
206
|
-
"@diplodoc/transform": "4.
|
|
206
|
+
"@diplodoc/transform": "4.22.0",
|
|
207
207
|
"@gravity-ui/components": "3.0.0",
|
|
208
208
|
"@gravity-ui/eslint-config": "3.1.1",
|
|
209
209
|
"@gravity-ui/prettier-config": "1.1.0",
|