@gravity-ui/markdown-editor 13.1.0 → 13.1.2

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 (31) hide show
  1. package/build/cjs/core/markdown/MarkdownSerializer.js +1 -1
  2. package/build/cjs/extensions/markdown/Lists/ListsSpecs/const.d.ts +9 -0
  3. package/build/cjs/extensions/markdown/Lists/ListsSpecs/const.js +11 -1
  4. package/build/cjs/extensions/markdown/Lists/ListsSpecs/index.d.ts +1 -1
  5. package/build/cjs/extensions/markdown/Lists/ListsSpecs/index.js +2 -1
  6. package/build/cjs/extensions/markdown/Lists/ListsSpecs/parser.js +12 -5
  7. package/build/cjs/extensions/markdown/Lists/ListsSpecs/schema.js +11 -9
  8. package/build/cjs/extensions/markdown/Lists/ListsSpecs/serializer.js +2 -2
  9. package/build/cjs/extensions/markdown/Lists/index.d.ts +1 -1
  10. package/build/cjs/extensions/markdown/Lists/index.js +2 -1
  11. package/build/cjs/extensions/markdown/Lists/inputrules.js +3 -2
  12. package/build/cjs/extensions/markdown/Lists/plugins/MergeListsPlugin.js +4 -5
  13. package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/yfmTableCellView.d.ts +1 -1
  14. package/build/cjs/extensions/yfm/YfmTable/plugins/YfmTableControls/yfmTableCellView.js +34 -22
  15. package/build/cjs/version.js +1 -1
  16. package/build/esm/core/markdown/MarkdownSerializer.js +1 -1
  17. package/build/esm/extensions/markdown/Lists/ListsSpecs/const.d.ts +9 -0
  18. package/build/esm/extensions/markdown/Lists/ListsSpecs/const.js +10 -0
  19. package/build/esm/extensions/markdown/Lists/ListsSpecs/index.d.ts +1 -1
  20. package/build/esm/extensions/markdown/Lists/ListsSpecs/index.js +1 -1
  21. package/build/esm/extensions/markdown/Lists/ListsSpecs/parser.js +13 -6
  22. package/build/esm/extensions/markdown/Lists/ListsSpecs/schema.js +12 -10
  23. package/build/esm/extensions/markdown/Lists/ListsSpecs/serializer.js +3 -3
  24. package/build/esm/extensions/markdown/Lists/index.d.ts +1 -1
  25. package/build/esm/extensions/markdown/Lists/index.js +1 -1
  26. package/build/esm/extensions/markdown/Lists/inputrules.js +3 -2
  27. package/build/esm/extensions/markdown/Lists/plugins/MergeListsPlugin.js +4 -5
  28. package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/yfmTableCellView.d.ts +1 -1
  29. package/build/esm/extensions/yfm/YfmTable/plugins/YfmTableControls/yfmTableCellView.js +37 -25
  30. package/build/esm/version.js +1 -1
  31. package/package.json +1 -1
@@ -299,7 +299,7 @@ class MarkdownSerializerState {
299
299
  node.forEach((child, _, i) => {
300
300
  if (i && isTight)
301
301
  this.flushClose(1);
302
- this.wrapBlock(delim, firstDelim(i), node, () => this.render(child, node, i));
302
+ this.wrapBlock(delim, firstDelim(i, child), node, () => this.render(child, node, i));
303
303
  });
304
304
  this.inTightList = prevTight;
305
305
  }
@@ -3,3 +3,12 @@ export declare enum ListNode {
3
3
  BulletList = "bullet_list",
4
4
  OrderedList = "ordered_list"
5
5
  }
6
+ export declare enum ListsAttr {
7
+ Tight = "tight",
8
+ /** used in bullet list only */
9
+ Bullet = "bullet",
10
+ /** used in ordered list only */
11
+ Order = "order",
12
+ /** used in list item only */
13
+ Markup = "markup"
14
+ }
@@ -1,9 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ListNode = void 0;
3
+ exports.ListsAttr = exports.ListNode = void 0;
4
4
  var ListNode;
5
5
  (function (ListNode) {
6
6
  ListNode["ListItem"] = "list_item";
7
7
  ListNode["BulletList"] = "bullet_list";
8
8
  ListNode["OrderedList"] = "ordered_list";
9
9
  })(ListNode = exports.ListNode || (exports.ListNode = {}));
10
+ var ListsAttr;
11
+ (function (ListsAttr) {
12
+ ListsAttr["Tight"] = "tight";
13
+ /** used in bullet list only */
14
+ ListsAttr["Bullet"] = "bullet";
15
+ /** used in ordered list only */
16
+ ListsAttr["Order"] = "order";
17
+ /** used in list item only */
18
+ ListsAttr["Markup"] = "markup";
19
+ })(ListsAttr = exports.ListsAttr || (exports.ListsAttr = {}));
@@ -1,5 +1,5 @@
1
1
  import type { ExtensionAuto } from '../../../../core';
2
- export { ListNode } from './const';
2
+ export { ListsAttr, ListNode } from './const';
3
3
  export declare const liType: (schema: import("prosemirror-model").Schema<any, any>) => import("prosemirror-model").NodeType;
4
4
  export declare const blType: (schema: import("prosemirror-model").Schema<any, any>) => import("prosemirror-model").NodeType;
5
5
  export declare const olType: (schema: import("prosemirror-model").Schema<any, any>) => import("prosemirror-model").NodeType;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ListsSpecs = exports.olType = exports.blType = exports.liType = exports.ListNode = void 0;
3
+ exports.ListsSpecs = exports.olType = exports.blType = exports.liType = exports.ListNode = exports.ListsAttr = void 0;
4
4
  const schema_1 = require("../../../../utils/schema");
5
5
  const const_1 = require("./const");
6
6
  const parser_1 = require("./parser");
7
7
  const schema_2 = require("./schema");
8
8
  const serializer_1 = require("./serializer");
9
9
  var const_2 = require("./const");
10
+ Object.defineProperty(exports, "ListsAttr", { enumerable: true, get: function () { return const_2.ListsAttr; } });
10
11
  Object.defineProperty(exports, "ListNode", { enumerable: true, get: function () { return const_2.ListNode; } });
11
12
  exports.liType = (0, schema_1.nodeTypeFactory)(const_1.ListNode.ListItem);
12
13
  exports.blType = (0, schema_1.nodeTypeFactory)(const_1.ListNode.BulletList);
@@ -3,18 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parserTokens = void 0;
4
4
  const const_1 = require("./const");
5
5
  exports.parserTokens = {
6
- [const_1.ListNode.ListItem]: { name: const_1.ListNode.ListItem, type: 'block' },
6
+ [const_1.ListNode.ListItem]: {
7
+ name: const_1.ListNode.ListItem,
8
+ type: 'block',
9
+ getAttrs: (token) => ({ [const_1.ListsAttr.Markup]: token.markup }),
10
+ },
7
11
  [const_1.ListNode.BulletList]: {
8
12
  name: const_1.ListNode.BulletList,
9
13
  type: 'block',
10
- getAttrs: (_, tokens, i) => ({ tight: listIsTight(tokens, i) }),
14
+ getAttrs: (token, tokens, i) => ({
15
+ [const_1.ListsAttr.Tight]: listIsTight(tokens, i),
16
+ [const_1.ListsAttr.Bullet]: token.markup,
17
+ }),
11
18
  },
12
19
  [const_1.ListNode.OrderedList]: {
13
20
  name: const_1.ListNode.OrderedList,
14
21
  type: 'block',
15
- getAttrs: (tok, tokens, i) => ({
16
- order: Number(tok.attrGet('start')) || 1,
17
- tight: listIsTight(tokens, i),
22
+ getAttrs: (token, tokens, i) => ({
23
+ [const_1.ListsAttr.Order]: Number(token.attrGet('start')) || 1,
24
+ [const_1.ListsAttr.Tight]: listIsTight(tokens, i),
18
25
  }),
19
26
  },
20
27
  };
@@ -4,7 +4,7 @@ exports.schemaSpecs = void 0;
4
4
  const const_1 = require("./const");
5
5
  exports.schemaSpecs = {
6
6
  [const_1.ListNode.ListItem]: {
7
- attrs: { tight: { default: false } },
7
+ attrs: { [const_1.ListsAttr.Tight]: { default: false }, [const_1.ListsAttr.Markup]: { default: null } },
8
8
  content: '(paragraph|block)+',
9
9
  defining: true,
10
10
  parseDOM: [{ tag: 'li' }],
@@ -19,22 +19,24 @@ exports.schemaSpecs = {
19
19
  [const_1.ListNode.BulletList]: {
20
20
  content: `${const_1.ListNode.ListItem}+`,
21
21
  group: 'block',
22
- attrs: { tight: { default: false } },
22
+ attrs: { [const_1.ListsAttr.Tight]: { default: false }, [const_1.ListsAttr.Bullet]: { default: '*' } },
23
23
  parseDOM: [
24
24
  {
25
25
  tag: 'ul',
26
- getAttrs: (dom) => ({ tight: dom.hasAttribute('data-tight') }),
26
+ getAttrs: (dom) => ({
27
+ [const_1.ListsAttr.Tight]: dom.hasAttribute('data-tight'),
28
+ }),
27
29
  },
28
30
  ],
29
31
  toDOM(node) {
30
- return ['ul', { 'data-tight': node.attrs.tight ? 'true' : null }, 0];
32
+ return ['ul', { 'data-tight': node.attrs[const_1.ListsAttr.Tight] ? 'true' : null }, 0];
31
33
  },
32
34
  selectable: false,
33
35
  allowSelection: false,
34
36
  complex: 'root',
35
37
  },
36
38
  [const_1.ListNode.OrderedList]: {
37
- attrs: { order: { default: 1 }, tight: { default: false } },
39
+ attrs: { [const_1.ListsAttr.Order]: { default: 1 }, [const_1.ListsAttr.Tight]: { default: false } },
38
40
  content: `${const_1.ListNode.ListItem}+`,
39
41
  group: 'block',
40
42
  parseDOM: [
@@ -42,10 +44,10 @@ exports.schemaSpecs = {
42
44
  tag: 'ol',
43
45
  getAttrs(dom) {
44
46
  return {
45
- order: dom.hasAttribute('start')
47
+ [const_1.ListsAttr.Order]: dom.hasAttribute('start')
46
48
  ? Number(dom.getAttribute('start'))
47
49
  : 1,
48
- tight: dom.hasAttribute('data-tight'),
50
+ [const_1.ListsAttr.Tight]: dom.hasAttribute('data-tight'),
49
51
  };
50
52
  },
51
53
  },
@@ -54,8 +56,8 @@ exports.schemaSpecs = {
54
56
  return [
55
57
  'ol',
56
58
  {
57
- start: node.attrs.order === 1 ? null : node.attrs.order,
58
- 'data-tight': node.attrs.tight ? 'true' : null,
59
+ start: node.attrs[const_1.ListsAttr.Order] === 1 ? null : node.attrs[const_1.ListsAttr.Order],
60
+ 'data-tight': node.attrs[const_1.ListsAttr.Tight] ? 'true' : null,
59
61
  },
60
62
  0,
61
63
  ];
@@ -7,10 +7,10 @@ exports.serializerTokens = {
7
7
  state.renderContent(node);
8
8
  },
9
9
  [const_1.ListNode.BulletList]: (state, node) => {
10
- state.renderList(node, ' ', () => (node.attrs.bullet || '*') + ' ');
10
+ state.renderList(node, ' ', (_i, li) => (li.attrs[const_1.ListsAttr.Markup] || node.attrs[const_1.ListsAttr.Bullet] || '*') + ' ');
11
11
  },
12
12
  [const_1.ListNode.OrderedList]: (state, node) => {
13
- const start = node.attrs.order || 1;
13
+ const start = node.attrs[const_1.ListsAttr.Order] || 1;
14
14
  const maxW = String(start + node.childCount - 1).length;
15
15
  const space = state.repeat(' ', maxW + 2);
16
16
  state.renderList(node, space, (i) => {
@@ -1,7 +1,7 @@
1
1
  import type { Action, ExtensionAuto } from '../../../core';
2
2
  import { ListAction } from './const';
3
3
  import { ListsInputRulesOptions } from './inputrules';
4
- export { ListNode, blType, liType, olType } from './ListsSpecs';
4
+ export { ListNode, ListsAttr, blType, liType, olType } from './ListsSpecs';
5
5
  export declare type ListsOptions = {
6
6
  ulKey?: string | null;
7
7
  olKey?: string | null;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Lists = exports.olType = exports.liType = exports.blType = exports.ListNode = void 0;
3
+ exports.Lists = exports.olType = exports.liType = exports.blType = exports.ListsAttr = exports.ListNode = void 0;
4
4
  const prosemirror_commands_1 = require("prosemirror-commands");
5
5
  const prosemirror_schema_list_1 = require("prosemirror-schema-list");
6
6
  const keymap_1 = require("../../../utils/keymap");
@@ -12,6 +12,7 @@ const inputrules_1 = require("./inputrules");
12
12
  const MergeListsPlugin_1 = require("./plugins/MergeListsPlugin");
13
13
  var ListsSpecs_2 = require("./ListsSpecs");
14
14
  Object.defineProperty(exports, "ListNode", { enumerable: true, get: function () { return ListsSpecs_2.ListNode; } });
15
+ Object.defineProperty(exports, "ListsAttr", { enumerable: true, get: function () { return ListsSpecs_2.ListsAttr; } });
15
16
  Object.defineProperty(exports, "blType", { enumerable: true, get: function () { return ListsSpecs_2.blType; } });
16
17
  Object.defineProperty(exports, "liType", { enumerable: true, get: function () { return ListsSpecs_2.liType; } });
17
18
  Object.defineProperty(exports, "olType", { enumerable: true, get: function () { return ListsSpecs_2.olType; } });
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.bulletListRule = exports.orderedListRule = exports.ListsInputRulesExtension = void 0;
4
4
  const inputrules_1 = require("../../../utils/inputrules");
5
+ const ListsSpecs_1 = require("./ListsSpecs");
5
6
  const utils_1 = require("./utils");
6
7
  const ListsInputRulesExtension = (builder, options) => {
7
8
  builder.addInputRules(({ schema }) => {
@@ -20,7 +21,7 @@ exports.ListsInputRulesExtension = ListsInputRulesExtension;
20
21
  * followed by a dot at the start of a textblock into an ordered list.
21
22
  */
22
23
  function orderedListRule(nodeType) {
23
- return (0, inputrules_1.wrappingInputRule)(/^(\d+)\.\s$/, nodeType, (match) => ({ order: Number(match[1]) }), (match, node) => node.childCount + node.attrs.order === Number(match[1]));
24
+ return (0, inputrules_1.wrappingInputRule)(/^(\d+)\.\s$/, nodeType, (match) => ({ [ListsSpecs_1.ListsAttr.Order]: Number(match[1]) }), (match, node) => node.childCount + node.attrs[ListsSpecs_1.ListsAttr.Order] === Number(match[1]));
24
25
  }
25
26
  exports.orderedListRule = orderedListRule;
26
27
  /**
@@ -39,6 +40,6 @@ function bulletListRule(nodeType, config) {
39
40
  if (bullets.length === 0)
40
41
  return null;
41
42
  const regexp = new RegExp(`^\\s*([${bullets.join('')}])\\s$`); // same as /^\s*([-+*])\s$/
42
- return (0, inputrules_1.wrappingInputRule)(regexp, nodeType);
43
+ return (0, inputrules_1.wrappingInputRule)(regexp, nodeType, (match) => ({ [ListsSpecs_1.ListsAttr.Bullet]: match[1] }));
43
44
  }
44
45
  exports.bulletListRule = bulletListRule;
@@ -21,11 +21,10 @@ const mergeListsPlugin = () => new prosemirror_state_1.Plugin({
21
21
  });
22
22
  exports.mergeListsPlugin = mergeListsPlugin;
23
23
  function mergeAdjacentNodesWithSameType(tr, nodes) {
24
- for (let i = 0; i < nodes.length - 1; i++) {
25
- const current = nodes[i];
26
- const next = nodes[i + 1];
27
- if (current.node.type === next.node.type &&
28
- current.pos + current.node.nodeSize === next.pos) {
24
+ for (let i = nodes.length - 1; i > 0; i--) {
25
+ const prev = nodes[i - 1];
26
+ const next = nodes[i];
27
+ if (prev.node.type === next.node.type && prev.pos + prev.node.nodeSize === next.pos) {
29
28
  tr.join(next.pos);
30
29
  }
31
30
  }
@@ -1,3 +1,3 @@
1
- import { NodeViewConstructor } from 'prosemirror-view';
1
+ import type { NodeViewConstructor } from 'prosemirror-view';
2
2
  export declare const yfmTableCellCn: import("@bem-react/classname").ClassNameFormatter;
3
3
  export declare const yfmTableCellView: NodeViewConstructor;
@@ -6,12 +6,13 @@ const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const icons_1 = require("@gravity-ui/icons");
7
7
  const uikit_1 = require("@gravity-ui/uikit");
8
8
  const prosemirror_utils_1 = require("prosemirror-utils");
9
- const react_dom_1 = require("react-dom");
10
9
  const classname_1 = require("../../../../../classname");
11
10
  const core_1 = require("../../../../../core");
12
11
  const yfm_table_1 = require("../../../../../i18n/yfm-table");
13
12
  const ErrorBoundary_1 = require("../../../../../react-utils/ErrorBoundary");
14
13
  const table_utils_1 = require("../../../../../table-utils");
14
+ const node_children_1 = require("../../../../../utils/node-children");
15
+ const nodes_1 = require("../../../../../utils/nodes");
15
16
  const ReactRenderer_1 = require("../../../../behavior/ReactRenderer");
16
17
  const actions_1 = require("./actions");
17
18
  exports.yfmTableCellCn = (0, classname_1.cn)('table-cell-view');
@@ -163,34 +164,30 @@ const Controls = function Controls({ columnNumber, rowNumber, view, getParentTab
163
164
  return controls.length ? react_1.default.createElement(react_1.default.Fragment, null, controls) : null;
164
165
  };
165
166
  const yfmTableCellView = (node, view, getPos) => {
167
+ const getParentTable = () => (0, prosemirror_utils_1.findParentNodeClosestToPos)(view.state.doc.resolve(getPos()), table_utils_1.isTableNode);
168
+ const parentTable = getParentTable();
169
+ const cellCoords = parentTable ? findCellCoords(parentTable.node, node) : null;
170
+ // @ts-expect-error
171
+ if (!cellCoords)
172
+ return {};
173
+ const { cellIndex, rowIndex } = cellCoords;
174
+ const isFirstRow = rowIndex === 0;
175
+ const isFirstColumn = cellIndex === 0;
176
+ if (!isFirstRow && !isFirstColumn) {
177
+ // in this case, we don't need custom nodeView.
178
+ // @ts-expect-error
179
+ return {};
180
+ }
166
181
  const dom = document.createElement('td');
167
182
  const contentDOM = document.createElement('div');
168
183
  const control = document.createElement('span');
169
184
  control.setAttribute('style', 'width: 0; height: 0; float: left;');
170
185
  dom.setAttribute('style', 'position: relative; overflow: visible;');
171
- const getParentTable = () => (0, prosemirror_utils_1.findParentNodeClosestToPos)(view.state.doc.resolve(getPos()), table_utils_1.isTableNode);
172
- const parentTable = getParentTable();
173
- // @ts-expect-error
174
- if (!parentTable)
175
- return {};
176
- const rowNodes = (0, prosemirror_utils_1.findChildren)(parentTable === null || parentTable === void 0 ? void 0 : parentTable.node, table_utils_1.isTableRowNode);
177
- const relativeCelPos = getPos() - (parentTable === null || parentTable === void 0 ? void 0 : parentTable.pos);
178
- const rowNumber = rowNodes.findIndex((_v, i) => {
179
- var _a;
180
- return relativeCelPos > rowNodes[i].pos &&
181
- relativeCelPos < (((_a = rowNodes[i + 1]) === null || _a === void 0 ? void 0 : _a.pos) || Number.MAX_SAFE_INTEGER);
182
- });
183
- const parentRow = rowNodes[rowNumber];
184
- const columnNumber = (0, prosemirror_utils_1.findChildren)(parentRow.node, table_utils_1.isTableCellNode).findIndex((c) => {
185
- return c.pos === relativeCelPos - parentRow.pos - 2;
186
- });
187
- const isFirstInRow = rowNodes.findIndex((r) => r.pos === relativeCelPos - 2) >= 0;
188
186
  dom.appendChild(contentDOM);
189
187
  dom.appendChild(control);
190
- const renderItem = (0, ReactRenderer_1.getReactRendererFromState)(view.state).createItem('yfm-table-cell-view', () => (0, react_dom_1.createPortal)(react_1.default.createElement(ErrorBoundary_1.ErrorLoggerBoundary, null,
191
- react_1.default.createElement(Controls, { columnNumber: columnNumber, rowNumber: rowNumber, isFirstInRow: isFirstInRow, isInFirstRow: rowNumber === 0, getParentTable: getParentTable, view: view })), control));
192
- contentDOM.setAttribute('data-row-number', String(rowNumber));
193
- contentDOM.setAttribute('data-col-number', String(columnNumber));
188
+ const renderItem = (0, ReactRenderer_1.getReactRendererFromState)(view.state).createItem('yfm-table-cell-view', () => (react_1.default.createElement(uikit_1.Portal, { container: control },
189
+ react_1.default.createElement(ErrorBoundary_1.ErrorLoggerBoundary, null,
190
+ react_1.default.createElement(Controls, { columnNumber: cellIndex, rowNumber: rowIndex, isFirstInRow: isFirstColumn, isInFirstRow: isFirstRow, getParentTable: getParentTable, view: view })))));
194
191
  return {
195
192
  dom,
196
193
  contentDOM,
@@ -208,3 +205,18 @@ const yfmTableCellView = (node, view, getPos) => {
208
205
  };
209
206
  };
210
207
  exports.yfmTableCellView = yfmTableCellView;
208
+ function findCellCoords(table, cell) {
209
+ if (!table.lastChild)
210
+ return null;
211
+ const rows = (0, nodes_1.getChildrenOfNode)(table.lastChild); // children of tBody
212
+ for (const row of rows) {
213
+ const node = (0, node_children_1.getChildByNode)(row.node, cell);
214
+ if (node) {
215
+ return {
216
+ rowIndex: row.index,
217
+ cellIndex: node.index,
218
+ };
219
+ }
220
+ }
221
+ return null;
222
+ }
@@ -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.1.0' !== 'undefined' ? '13.1.0' : 'unknown';
5
+ exports.VERSION = typeof '13.1.2' !== 'undefined' ? '13.1.2' : 'unknown';
@@ -295,7 +295,7 @@ export class MarkdownSerializerState {
295
295
  node.forEach((child, _, i) => {
296
296
  if (i && isTight)
297
297
  this.flushClose(1);
298
- this.wrapBlock(delim, firstDelim(i), node, () => this.render(child, node, i));
298
+ this.wrapBlock(delim, firstDelim(i, child), node, () => this.render(child, node, i));
299
299
  });
300
300
  this.inTightList = prevTight;
301
301
  }
@@ -3,3 +3,12 @@ export declare enum ListNode {
3
3
  BulletList = "bullet_list",
4
4
  OrderedList = "ordered_list"
5
5
  }
6
+ export declare enum ListsAttr {
7
+ Tight = "tight",
8
+ /** used in bullet list only */
9
+ Bullet = "bullet",
10
+ /** used in ordered list only */
11
+ Order = "order",
12
+ /** used in list item only */
13
+ Markup = "markup"
14
+ }
@@ -4,3 +4,13 @@ export var ListNode;
4
4
  ListNode["BulletList"] = "bullet_list";
5
5
  ListNode["OrderedList"] = "ordered_list";
6
6
  })(ListNode || (ListNode = {}));
7
+ export var ListsAttr;
8
+ (function (ListsAttr) {
9
+ ListsAttr["Tight"] = "tight";
10
+ /** used in bullet list only */
11
+ ListsAttr["Bullet"] = "bullet";
12
+ /** used in ordered list only */
13
+ ListsAttr["Order"] = "order";
14
+ /** used in list item only */
15
+ ListsAttr["Markup"] = "markup";
16
+ })(ListsAttr || (ListsAttr = {}));
@@ -1,5 +1,5 @@
1
1
  import type { ExtensionAuto } from '../../../../core';
2
- export { ListNode } from './const';
2
+ export { ListsAttr, ListNode } from './const';
3
3
  export declare const liType: (schema: import("prosemirror-model").Schema<any, any>) => import("prosemirror-model").NodeType;
4
4
  export declare const blType: (schema: import("prosemirror-model").Schema<any, any>) => import("prosemirror-model").NodeType;
5
5
  export declare const olType: (schema: import("prosemirror-model").Schema<any, any>) => import("prosemirror-model").NodeType;
@@ -3,7 +3,7 @@ import { ListNode } from './const';
3
3
  import { parserTokens } from './parser';
4
4
  import { schemaSpecs } from './schema';
5
5
  import { serializerTokens } from './serializer';
6
- export { ListNode } from './const';
6
+ export { ListsAttr, ListNode } from './const';
7
7
  export const liType = nodeTypeFactory(ListNode.ListItem);
8
8
  export const blType = nodeTypeFactory(ListNode.BulletList);
9
9
  export const olType = nodeTypeFactory(ListNode.OrderedList);
@@ -1,17 +1,24 @@
1
- import { ListNode } from './const';
1
+ import { ListNode, ListsAttr } from './const';
2
2
  export const parserTokens = {
3
- [ListNode.ListItem]: { name: ListNode.ListItem, type: 'block' },
3
+ [ListNode.ListItem]: {
4
+ name: ListNode.ListItem,
5
+ type: 'block',
6
+ getAttrs: (token) => ({ [ListsAttr.Markup]: token.markup }),
7
+ },
4
8
  [ListNode.BulletList]: {
5
9
  name: ListNode.BulletList,
6
10
  type: 'block',
7
- getAttrs: (_, tokens, i) => ({ tight: listIsTight(tokens, i) }),
11
+ getAttrs: (token, tokens, i) => ({
12
+ [ListsAttr.Tight]: listIsTight(tokens, i),
13
+ [ListsAttr.Bullet]: token.markup,
14
+ }),
8
15
  },
9
16
  [ListNode.OrderedList]: {
10
17
  name: ListNode.OrderedList,
11
18
  type: 'block',
12
- getAttrs: (tok, tokens, i) => ({
13
- order: Number(tok.attrGet('start')) || 1,
14
- tight: listIsTight(tokens, i),
19
+ getAttrs: (token, tokens, i) => ({
20
+ [ListsAttr.Order]: Number(token.attrGet('start')) || 1,
21
+ [ListsAttr.Tight]: listIsTight(tokens, i),
15
22
  }),
16
23
  },
17
24
  };
@@ -1,7 +1,7 @@
1
- import { ListNode } from './const';
1
+ import { ListNode, ListsAttr } from './const';
2
2
  export const schemaSpecs = {
3
3
  [ListNode.ListItem]: {
4
- attrs: { tight: { default: false } },
4
+ attrs: { [ListsAttr.Tight]: { default: false }, [ListsAttr.Markup]: { default: null } },
5
5
  content: '(paragraph|block)+',
6
6
  defining: true,
7
7
  parseDOM: [{ tag: 'li' }],
@@ -16,22 +16,24 @@ export const schemaSpecs = {
16
16
  [ListNode.BulletList]: {
17
17
  content: `${ListNode.ListItem}+`,
18
18
  group: 'block',
19
- attrs: { tight: { default: false } },
19
+ attrs: { [ListsAttr.Tight]: { default: false }, [ListsAttr.Bullet]: { default: '*' } },
20
20
  parseDOM: [
21
21
  {
22
22
  tag: 'ul',
23
- getAttrs: (dom) => ({ tight: dom.hasAttribute('data-tight') }),
23
+ getAttrs: (dom) => ({
24
+ [ListsAttr.Tight]: dom.hasAttribute('data-tight'),
25
+ }),
24
26
  },
25
27
  ],
26
28
  toDOM(node) {
27
- return ['ul', { 'data-tight': node.attrs.tight ? 'true' : null }, 0];
29
+ return ['ul', { 'data-tight': node.attrs[ListsAttr.Tight] ? 'true' : null }, 0];
28
30
  },
29
31
  selectable: false,
30
32
  allowSelection: false,
31
33
  complex: 'root',
32
34
  },
33
35
  [ListNode.OrderedList]: {
34
- attrs: { order: { default: 1 }, tight: { default: false } },
36
+ attrs: { [ListsAttr.Order]: { default: 1 }, [ListsAttr.Tight]: { default: false } },
35
37
  content: `${ListNode.ListItem}+`,
36
38
  group: 'block',
37
39
  parseDOM: [
@@ -39,10 +41,10 @@ export const schemaSpecs = {
39
41
  tag: 'ol',
40
42
  getAttrs(dom) {
41
43
  return {
42
- order: dom.hasAttribute('start')
44
+ [ListsAttr.Order]: dom.hasAttribute('start')
43
45
  ? Number(dom.getAttribute('start'))
44
46
  : 1,
45
- tight: dom.hasAttribute('data-tight'),
47
+ [ListsAttr.Tight]: dom.hasAttribute('data-tight'),
46
48
  };
47
49
  },
48
50
  },
@@ -51,8 +53,8 @@ export const schemaSpecs = {
51
53
  return [
52
54
  'ol',
53
55
  {
54
- start: node.attrs.order === 1 ? null : node.attrs.order,
55
- 'data-tight': node.attrs.tight ? 'true' : null,
56
+ start: node.attrs[ListsAttr.Order] === 1 ? null : node.attrs[ListsAttr.Order],
57
+ 'data-tight': node.attrs[ListsAttr.Tight] ? 'true' : null,
56
58
  },
57
59
  0,
58
60
  ];
@@ -1,13 +1,13 @@
1
- import { ListNode } from './const';
1
+ import { ListNode, ListsAttr } from './const';
2
2
  export const serializerTokens = {
3
3
  [ListNode.ListItem]: (state, node) => {
4
4
  state.renderContent(node);
5
5
  },
6
6
  [ListNode.BulletList]: (state, node) => {
7
- state.renderList(node, ' ', () => (node.attrs.bullet || '*') + ' ');
7
+ state.renderList(node, ' ', (_i, li) => (li.attrs[ListsAttr.Markup] || node.attrs[ListsAttr.Bullet] || '*') + ' ');
8
8
  },
9
9
  [ListNode.OrderedList]: (state, node) => {
10
- const start = node.attrs.order || 1;
10
+ const start = node.attrs[ListsAttr.Order] || 1;
11
11
  const maxW = String(start + node.childCount - 1).length;
12
12
  const space = state.repeat(' ', maxW + 2);
13
13
  state.renderList(node, space, (i) => {
@@ -1,7 +1,7 @@
1
1
  import type { Action, ExtensionAuto } from '../../../core';
2
2
  import { ListAction } from './const';
3
3
  import { ListsInputRulesOptions } from './inputrules';
4
- export { ListNode, blType, liType, olType } from './ListsSpecs';
4
+ export { ListNode, ListsAttr, blType, liType, olType } from './ListsSpecs';
5
5
  export declare type ListsOptions = {
6
6
  ulKey?: string | null;
7
7
  olKey?: string | null;
@@ -7,7 +7,7 @@ import { joinPrevList, liftIfCursorIsAtBeginningOfItem, toList } from './command
7
7
  import { ListAction } from './const';
8
8
  import { ListsInputRulesExtension } from './inputrules';
9
9
  import { mergeListsPlugin } from './plugins/MergeListsPlugin';
10
- export { ListNode, blType, liType, olType } from './ListsSpecs';
10
+ export { ListNode, ListsAttr, blType, liType, olType } from './ListsSpecs';
11
11
  export const Lists = (builder, opts) => {
12
12
  builder.use(ListsSpecs);
13
13
  builder.addKeymap(({ schema }) => {
@@ -1,4 +1,5 @@
1
1
  import { wrappingInputRule } from '../../../utils/inputrules';
2
+ import { ListsAttr } from './ListsSpecs';
2
3
  import { blType, olType } from './utils';
3
4
  export const ListsInputRulesExtension = (builder, options) => {
4
5
  builder.addInputRules(({ schema }) => {
@@ -16,7 +17,7 @@ export const ListsInputRulesExtension = (builder, options) => {
16
17
  * followed by a dot at the start of a textblock into an ordered list.
17
18
  */
18
19
  export function orderedListRule(nodeType) {
19
- return wrappingInputRule(/^(\d+)\.\s$/, nodeType, (match) => ({ order: Number(match[1]) }), (match, node) => node.childCount + node.attrs.order === Number(match[1]));
20
+ return wrappingInputRule(/^(\d+)\.\s$/, nodeType, (match) => ({ [ListsAttr.Order]: Number(match[1]) }), (match, node) => node.childCount + node.attrs[ListsAttr.Order] === Number(match[1]));
20
21
  }
21
22
  /**
22
23
  * Given a list node type, returns an input rule that turns a bullet
@@ -34,5 +35,5 @@ export function bulletListRule(nodeType, config) {
34
35
  if (bullets.length === 0)
35
36
  return null;
36
37
  const regexp = new RegExp(`^\\s*([${bullets.join('')}])\\s$`); // same as /^\s*([-+*])\s$/
37
- return wrappingInputRule(regexp, nodeType);
38
+ return wrappingInputRule(regexp, nodeType, (match) => ({ [ListsAttr.Bullet]: match[1] }));
38
39
  }
@@ -17,11 +17,10 @@ export const mergeListsPlugin = () => new Plugin({
17
17
  },
18
18
  });
19
19
  function mergeAdjacentNodesWithSameType(tr, nodes) {
20
- for (let i = 0; i < nodes.length - 1; i++) {
21
- const current = nodes[i];
22
- const next = nodes[i + 1];
23
- if (current.node.type === next.node.type &&
24
- current.pos + current.node.nodeSize === next.pos) {
20
+ for (let i = nodes.length - 1; i > 0; i--) {
21
+ const prev = nodes[i - 1];
22
+ const next = nodes[i];
23
+ if (prev.node.type === next.node.type && prev.pos + prev.node.nodeSize === next.pos) {
25
24
  tr.join(next.pos);
26
25
  }
27
26
  }
@@ -1,4 +1,4 @@
1
- import { NodeViewConstructor } from 'prosemirror-view';
1
+ import type { NodeViewConstructor } from 'prosemirror-view';
2
2
  import './yfmTableCellView.css';
3
3
  export declare const yfmTableCellCn: import("@bem-react/classname").ClassNameFormatter;
4
4
  export declare const yfmTableCellView: NodeViewConstructor;
@@ -1,13 +1,14 @@
1
1
  import React from 'react';
2
2
  import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, EllipsisVertical, TrashBin, Xmark, } from '@gravity-ui/icons';
3
- import { Button, DropdownMenu, Icon } from '@gravity-ui/uikit';
4
- import { findChildren, findParentNodeClosestToPos } from 'prosemirror-utils';
5
- import { createPortal } from 'react-dom';
3
+ import { Button, DropdownMenu, Icon, Portal } from '@gravity-ui/uikit';
4
+ import { findParentNodeClosestToPos } from 'prosemirror-utils';
6
5
  import { cn } from '../../../../../classname';
7
6
  import { bindActions } from '../../../../../core';
8
7
  import { i18n } from '../../../../../i18n/yfm-table';
9
8
  import { ErrorLoggerBoundary } from '../../../../../react-utils/ErrorBoundary';
10
- import { getTableDimensions, isTableCellNode, isTableNode, isTableRowNode, } from '../../../../../table-utils';
9
+ import { getTableDimensions, isTableNode } from '../../../../../table-utils';
10
+ import { getChildByNode } from '../../../../../utils/node-children';
11
+ import { getChildrenOfNode } from '../../../../../utils/nodes';
11
12
  import { getReactRendererFromState } from '../../../../behavior/ReactRenderer';
12
13
  import { controlActions } from './actions';
13
14
  import './yfmTableCellView.css';
@@ -160,34 +161,30 @@ const Controls = function Controls({ columnNumber, rowNumber, view, getParentTab
160
161
  return controls.length ? React.createElement(React.Fragment, null, controls) : null;
161
162
  };
162
163
  export const yfmTableCellView = (node, view, getPos) => {
164
+ const getParentTable = () => findParentNodeClosestToPos(view.state.doc.resolve(getPos()), isTableNode);
165
+ const parentTable = getParentTable();
166
+ const cellCoords = parentTable ? findCellCoords(parentTable.node, node) : null;
167
+ // @ts-expect-error
168
+ if (!cellCoords)
169
+ return {};
170
+ const { cellIndex, rowIndex } = cellCoords;
171
+ const isFirstRow = rowIndex === 0;
172
+ const isFirstColumn = cellIndex === 0;
173
+ if (!isFirstRow && !isFirstColumn) {
174
+ // in this case, we don't need custom nodeView.
175
+ // @ts-expect-error
176
+ return {};
177
+ }
163
178
  const dom = document.createElement('td');
164
179
  const contentDOM = document.createElement('div');
165
180
  const control = document.createElement('span');
166
181
  control.setAttribute('style', 'width: 0; height: 0; float: left;');
167
182
  dom.setAttribute('style', 'position: relative; overflow: visible;');
168
- const getParentTable = () => findParentNodeClosestToPos(view.state.doc.resolve(getPos()), isTableNode);
169
- const parentTable = getParentTable();
170
- // @ts-expect-error
171
- if (!parentTable)
172
- return {};
173
- const rowNodes = findChildren(parentTable === null || parentTable === void 0 ? void 0 : parentTable.node, isTableRowNode);
174
- const relativeCelPos = getPos() - (parentTable === null || parentTable === void 0 ? void 0 : parentTable.pos);
175
- const rowNumber = rowNodes.findIndex((_v, i) => {
176
- var _a;
177
- return relativeCelPos > rowNodes[i].pos &&
178
- relativeCelPos < (((_a = rowNodes[i + 1]) === null || _a === void 0 ? void 0 : _a.pos) || Number.MAX_SAFE_INTEGER);
179
- });
180
- const parentRow = rowNodes[rowNumber];
181
- const columnNumber = findChildren(parentRow.node, isTableCellNode).findIndex((c) => {
182
- return c.pos === relativeCelPos - parentRow.pos - 2;
183
- });
184
- const isFirstInRow = rowNodes.findIndex((r) => r.pos === relativeCelPos - 2) >= 0;
185
183
  dom.appendChild(contentDOM);
186
184
  dom.appendChild(control);
187
- const renderItem = getReactRendererFromState(view.state).createItem('yfm-table-cell-view', () => createPortal(React.createElement(ErrorLoggerBoundary, null,
188
- React.createElement(Controls, { columnNumber: columnNumber, rowNumber: rowNumber, isFirstInRow: isFirstInRow, isInFirstRow: rowNumber === 0, getParentTable: getParentTable, view: view })), control));
189
- contentDOM.setAttribute('data-row-number', String(rowNumber));
190
- contentDOM.setAttribute('data-col-number', String(columnNumber));
185
+ const renderItem = getReactRendererFromState(view.state).createItem('yfm-table-cell-view', () => (React.createElement(Portal, { container: control },
186
+ React.createElement(ErrorLoggerBoundary, null,
187
+ React.createElement(Controls, { columnNumber: cellIndex, rowNumber: rowIndex, isFirstInRow: isFirstColumn, isInFirstRow: isFirstRow, getParentTable: getParentTable, view: view })))));
191
188
  return {
192
189
  dom,
193
190
  contentDOM,
@@ -204,3 +201,18 @@ export const yfmTableCellView = (node, view, getPos) => {
204
201
  },
205
202
  };
206
203
  };
204
+ function findCellCoords(table, cell) {
205
+ if (!table.lastChild)
206
+ return null;
207
+ const rows = getChildrenOfNode(table.lastChild); // children of tBody
208
+ for (const row of rows) {
209
+ const node = getChildByNode(row.node, cell);
210
+ if (node) {
211
+ return {
212
+ rowIndex: row.index,
213
+ cellIndex: node.index,
214
+ };
215
+ }
216
+ }
217
+ return null;
218
+ }
@@ -1,2 +1,2 @@
1
1
  /** During build process, the current version will be injected here */
2
- export const VERSION = typeof '13.1.0' !== 'undefined' ? '13.1.0' : 'unknown';
2
+ export const VERSION = typeof '13.1.2' !== 'undefined' ? '13.1.2' : 'unknown';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/markdown-editor",
3
- "version": "13.1.0",
3
+ "version": "13.1.2",
4
4
  "description": "Markdown wysiwyg and markup editor",
5
5
  "license": "MIT",
6
6
  "repository": {