@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.
Files changed (34) hide show
  1. package/README.md +8 -1
  2. package/build/cjs/bundle/Editor.d.ts +14 -0
  3. package/build/cjs/bundle/Editor.js +9 -6
  4. package/build/cjs/bundle/index.d.ts +1 -1
  5. package/build/cjs/extensions/yfm/Checkbox/CheckboxSpecs/index.js +1 -1
  6. package/build/cjs/extensions/yfm/FoldingHeading/plugins/Folding.js +10 -7
  7. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/const.d.ts +5 -0
  8. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/const.js +7 -1
  9. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/parser.js +12 -1
  10. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +7 -2
  11. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/serializer.js +57 -17
  12. package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/yfmTableCellView.js +9 -0
  13. package/build/cjs/markup/codemirror/create.d.ts +4 -1
  14. package/build/cjs/markup/codemirror/create.js +4 -4
  15. package/build/cjs/version.js +1 -1
  16. package/build/cjs/view/hooks/useYfmShowElemWithId/useYfmShowElemWithId.d.ts +1 -1
  17. package/build/cjs/view/hooks/useYfmShowElemWithId/useYfmShowElemWithId.js +15 -1
  18. package/build/esm/bundle/Editor.d.ts +14 -0
  19. package/build/esm/bundle/Editor.js +9 -6
  20. package/build/esm/bundle/index.d.ts +1 -1
  21. package/build/esm/extensions/yfm/Checkbox/CheckboxSpecs/index.js +1 -1
  22. package/build/esm/extensions/yfm/FoldingHeading/plugins/Folding.js +10 -7
  23. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/const.d.ts +5 -0
  24. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/const.js +6 -0
  25. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/parser.js +13 -2
  26. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +8 -3
  27. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/serializer.js +57 -18
  28. package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/yfmTableCellView.js +9 -0
  29. package/build/esm/markup/codemirror/create.d.ts +4 -1
  30. package/build/esm/markup/codemirror/create.js +4 -4
  31. package/build/esm/version.js +1 -1
  32. package/build/esm/view/hooks/useYfmShowElemWithId/useYfmShowElemWithId.d.ts +1 -1
  33. package/build/esm/view/hooks/useYfmShowElemWithId/useYfmShowElemWithId.js +15 -1
  34. 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, _EditorImpl_extraMarkupExtensions, _EditorImpl_preset, _EditorImpl_allowHTML, _EditorImpl_linkify, _EditorImpl_linkifyTlds, _EditorImpl_extensions, _EditorImpl_renderStorage, _EditorImpl_fileUploadHandler, _EditorImpl_needToSetDimensionsForUploadedImages, _EditorImpl_prepareRawMarkup;
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
- _EditorImpl_extraMarkupExtensions.set(this, void 0);
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, _EditorImpl_extraMarkupExtensions, opts.extraMarkupExtensions, "f");
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
- extraMarkupExtensions: tslib_1.__classPrivateFieldGet(this, _EditorImpl_extraMarkupExtensions, "f"),
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(), _EditorImpl_extraMarkupExtensions = 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();
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) => (0, checkbox_1.default)(md, { idPrefix: const_1.idPrefix, divClass: (0, const_1.b)() }))
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
- if ((0, utils_1.isFoldingHeading)(child)) {
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 ((0, utils_1.isUnfoldedHeading)(child)) {
119
- hLevel = level;
120
- hidden = false;
121
- }
122
- else {
123
- hidden = true;
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) {
@@ -4,3 +4,8 @@ export declare enum YfmTableNode {
4
4
  Row = "yfm_tr",
5
5
  Cell = "yfm_td"
6
6
  }
7
+ export declare enum YfmTableAttr {
8
+ Colspan = "colspan",
9
+ Rowspan = "rowspan",
10
+ CellAlign = "data-cell-align"
11
+ }
@@ -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]: { name: const_1.YfmTableNode.Cell, type: 'block' },
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, node) => {
17
- state.renderContent(node);
18
- },
19
- [const_1.YfmTableNode.Row]: (state, node) => {
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
- extraMarkupExtensions?: Extension[];
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, extraMarkupExtensions, receiver, } = params;
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 (extraMarkupExtensions) {
85
- extensions.push(...extraMarkupExtensions);
84
+ if (extraExtensions) {
85
+ extensions.push(...extraExtensions);
86
86
  }
87
87
  return new view_1.EditorView({
88
88
  doc,
@@ -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.7.0' !== 'undefined' ? '13.7.0' : 'unknown';
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, _EditorImpl_extraMarkupExtensions, _EditorImpl_preset, _EditorImpl_allowHTML, _EditorImpl_linkify, _EditorImpl_linkifyTlds, _EditorImpl_extensions, _EditorImpl_renderStorage, _EditorImpl_fileUploadHandler, _EditorImpl_needToSetDimensionsForUploadedImages, _EditorImpl_prepareRawMarkup;
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
- _EditorImpl_extraMarkupExtensions.set(this, void 0);
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, _EditorImpl_extraMarkupExtensions, opts.extraMarkupExtensions, "f");
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
- extraMarkupExtensions: __classPrivateFieldGet(this, _EditorImpl_extraMarkupExtensions, "f"),
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(), _EditorImpl_extraMarkupExtensions = 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();
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(md, { idPrefix, divClass: b() }))
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
- if (isFoldingHeading(child)) {
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 (isUnfoldedHeading(child)) {
116
- hLevel = level;
117
- hidden = false;
118
- }
119
- else {
120
- hidden = true;
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) {
@@ -4,3 +4,8 @@ export declare enum YfmTableNode {
4
4
  Row = "yfm_tr",
5
5
  Cell = "yfm_td"
6
6
  }
7
+ export declare enum YfmTableAttr {
8
+ Colspan = "colspan",
9
+ Rowspan = "rowspan",
10
+ CellAlign = "data-cell-align"
11
+ }
@@ -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]: { name: YfmTableNode.Cell, type: 'block' },
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 { YfmTableNode } from './const';
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, node) => {
14
- state.renderContent(node);
15
- },
16
- [YfmTableNode.Row]: (state, node) => {
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
- extraMarkupExtensions?: Extension[];
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, extraMarkupExtensions, receiver, } = params;
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 (extraMarkupExtensions) {
82
- extensions.push(...extraMarkupExtensions);
81
+ if (extraExtensions) {
82
+ extensions.push(...extraExtensions);
83
83
  }
84
84
  return new EditorView({
85
85
  doc,
@@ -1,2 +1,2 @@
1
1
  /** During build process, the current version will be injected here */
2
- export const VERSION = typeof '13.7.0' !== 'undefined' ? '13.7.0' : 'unknown';
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.7.0",
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.5.0",
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",