@gravity-ui/markdown-editor 15.37.0 → 15.38.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 (129) hide show
  1. package/build/cjs/core/ExtensionBuilder.d.ts +21 -0
  2. package/build/cjs/core/ExtensionBuilder.js +306 -4
  3. package/build/cjs/core/ExtensionBuilder.js.map +1 -1
  4. package/build/cjs/core/markdown/MarkdownSerializer.d.ts +4 -1
  5. package/build/cjs/core/markdown/MarkdownSerializer.js +86 -23
  6. package/build/cjs/core/markdown/MarkdownSerializer.js.map +1 -1
  7. package/build/cjs/extensions/behavior/SelectionContext/TextSelectionTooltip.d.ts +13 -0
  8. package/build/cjs/extensions/behavior/SelectionContext/TextSelectionTooltip.js +42 -0
  9. package/build/cjs/extensions/behavior/SelectionContext/TextSelectionTooltip.js.map +1 -0
  10. package/build/cjs/extensions/behavior/SelectionContext/index.js +10 -7
  11. package/build/cjs/extensions/behavior/SelectionContext/index.js.map +1 -1
  12. package/build/cjs/extensions/behavior/SelectionContext/tooltip.d.ts +11 -15
  13. package/build/cjs/extensions/behavior/SelectionContext/tooltip.js +24 -56
  14. package/build/cjs/extensions/behavior/SelectionContext/tooltip.js.map +1 -1
  15. package/build/cjs/extensions/behavior/SelectionContext/types.d.ts +10 -0
  16. package/build/cjs/extensions/behavior/SelectionContext/types.js +3 -0
  17. package/build/cjs/extensions/behavior/SelectionContext/types.js.map +1 -0
  18. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js +24 -34
  19. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js.map +1 -1
  20. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/const.d.ts +4 -0
  21. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/const.js +9 -0
  22. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/const.js.map +1 -0
  23. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/index.d.ts +3 -5
  24. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/index.js +22 -25
  25. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/index.js.map +1 -1
  26. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/utils.d.ts +7 -0
  27. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/utils.js +15 -0
  28. package/build/cjs/extensions/markdown/Heading/HeadingSpecs/utils.js.map +1 -0
  29. package/build/cjs/extensions/markdown/Heading/actions.d.ts +2 -2
  30. package/build/cjs/extensions/markdown/Heading/actions.js +3 -4
  31. package/build/cjs/extensions/markdown/Heading/actions.js.map +1 -1
  32. package/build/cjs/extensions/markdown/Heading/commands.d.ts +3 -1
  33. package/build/cjs/extensions/markdown/Heading/commands.js +16 -1
  34. package/build/cjs/extensions/markdown/Heading/commands.js.map +1 -1
  35. package/build/cjs/extensions/markdown/Heading/index.js +7 -9
  36. package/build/cjs/extensions/markdown/Heading/index.js.map +1 -1
  37. package/build/cjs/extensions/markdown/Lists/index.js +1 -0
  38. package/build/cjs/extensions/markdown/Lists/index.js.map +1 -1
  39. package/build/cjs/extensions/markdown/Lists/plugins/CollapseListsPlugin.d.ts +14 -2
  40. package/build/cjs/extensions/markdown/Lists/plugins/CollapseListsPlugin.js +97 -51
  41. package/build/cjs/extensions/markdown/Lists/plugins/CollapseListsPlugin.js.map +1 -1
  42. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.d.ts +1 -1
  43. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js +2 -2
  44. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js.map +1 -1
  45. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.d.ts +3 -7
  46. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js +72 -90
  47. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js.map +1 -1
  48. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.d.ts +3 -0
  49. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js +14 -1
  50. package/build/cjs/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js.map +1 -1
  51. package/build/cjs/extensions/yfm/YfmHeading/actions.js +2 -10
  52. package/build/cjs/extensions/yfm/YfmHeading/actions.js.map +1 -1
  53. package/build/cjs/extensions/yfm/YfmHeading/commands.d.ts +1 -4
  54. package/build/cjs/extensions/yfm/YfmHeading/commands.js +3 -21
  55. package/build/cjs/extensions/yfm/YfmHeading/commands.js.map +1 -1
  56. package/build/cjs/extensions/yfm/YfmHeading/index.d.ts +3 -22
  57. package/build/cjs/extensions/yfm/YfmHeading/index.js +2 -33
  58. package/build/cjs/extensions/yfm/YfmHeading/index.js.map +1 -1
  59. package/build/cjs/presets/yfm-specs.js +5 -1
  60. package/build/cjs/presets/yfm-specs.js.map +1 -1
  61. package/build/cjs/presets/yfm.js +5 -1
  62. package/build/cjs/presets/yfm.js.map +1 -1
  63. package/build/cjs/version.js +1 -1
  64. package/build/cjs/version.js.map +1 -1
  65. package/build/esm/core/ExtensionBuilder.d.ts +21 -0
  66. package/build/esm/core/ExtensionBuilder.js +306 -4
  67. package/build/esm/core/ExtensionBuilder.js.map +1 -1
  68. package/build/esm/core/markdown/MarkdownSerializer.d.ts +4 -1
  69. package/build/esm/core/markdown/MarkdownSerializer.js +86 -23
  70. package/build/esm/core/markdown/MarkdownSerializer.js.map +1 -1
  71. package/build/esm/extensions/behavior/SelectionContext/TextSelectionTooltip.d.ts +13 -0
  72. package/build/esm/extensions/behavior/SelectionContext/TextSelectionTooltip.js +38 -0
  73. package/build/esm/extensions/behavior/SelectionContext/TextSelectionTooltip.js.map +1 -0
  74. package/build/esm/extensions/behavior/SelectionContext/index.js +10 -7
  75. package/build/esm/extensions/behavior/SelectionContext/index.js.map +1 -1
  76. package/build/esm/extensions/behavior/SelectionContext/tooltip.d.ts +11 -15
  77. package/build/esm/extensions/behavior/SelectionContext/tooltip.js +24 -56
  78. package/build/esm/extensions/behavior/SelectionContext/tooltip.js.map +1 -1
  79. package/build/esm/extensions/behavior/SelectionContext/types.d.ts +10 -0
  80. package/build/esm/extensions/behavior/SelectionContext/types.js +2 -0
  81. package/build/esm/extensions/behavior/SelectionContext/types.js.map +1 -0
  82. package/build/esm/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js +24 -34
  83. package/build/esm/extensions/markdown/CodeBlock/CodeBlockSpecs/index.js.map +1 -1
  84. package/build/esm/extensions/markdown/Heading/HeadingSpecs/const.d.ts +4 -0
  85. package/build/esm/extensions/markdown/Heading/HeadingSpecs/const.js +6 -0
  86. package/build/esm/extensions/markdown/Heading/HeadingSpecs/const.js.map +1 -0
  87. package/build/esm/extensions/markdown/Heading/HeadingSpecs/index.d.ts +3 -5
  88. package/build/esm/extensions/markdown/Heading/HeadingSpecs/index.js +5 -10
  89. package/build/esm/extensions/markdown/Heading/HeadingSpecs/index.js.map +1 -1
  90. package/build/esm/extensions/markdown/Heading/HeadingSpecs/utils.d.ts +7 -0
  91. package/build/esm/extensions/markdown/Heading/HeadingSpecs/utils.js +12 -0
  92. package/build/esm/extensions/markdown/Heading/HeadingSpecs/utils.js.map +1 -0
  93. package/build/esm/extensions/markdown/Heading/actions.d.ts +2 -2
  94. package/build/esm/extensions/markdown/Heading/actions.js +3 -4
  95. package/build/esm/extensions/markdown/Heading/actions.js.map +1 -1
  96. package/build/esm/extensions/markdown/Heading/commands.d.ts +3 -1
  97. package/build/esm/extensions/markdown/Heading/commands.js +15 -1
  98. package/build/esm/extensions/markdown/Heading/commands.js.map +1 -1
  99. package/build/esm/extensions/markdown/Heading/index.js +9 -11
  100. package/build/esm/extensions/markdown/Heading/index.js.map +1 -1
  101. package/build/esm/extensions/markdown/Lists/index.js +1 -0
  102. package/build/esm/extensions/markdown/Lists/index.js.map +1 -1
  103. package/build/esm/extensions/markdown/Lists/plugins/CollapseListsPlugin.d.ts +14 -2
  104. package/build/esm/extensions/markdown/Lists/plugins/CollapseListsPlugin.js +95 -49
  105. package/build/esm/extensions/markdown/Lists/plugins/CollapseListsPlugin.js.map +1 -1
  106. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.d.ts +1 -1
  107. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js +3 -3
  108. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/const.js.map +1 -1
  109. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.d.ts +3 -7
  110. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js +70 -90
  111. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/index.js.map +1 -1
  112. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.d.ts +3 -0
  113. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js +11 -0
  114. package/build/esm/extensions/yfm/YfmHeading/YfmHeadingSpecs/utils.js.map +1 -1
  115. package/build/esm/extensions/yfm/YfmHeading/actions.js +2 -10
  116. package/build/esm/extensions/yfm/YfmHeading/actions.js.map +1 -1
  117. package/build/esm/extensions/yfm/YfmHeading/commands.d.ts +1 -4
  118. package/build/esm/extensions/yfm/YfmHeading/commands.js +3 -21
  119. package/build/esm/extensions/yfm/YfmHeading/commands.js.map +1 -1
  120. package/build/esm/extensions/yfm/YfmHeading/index.d.ts +3 -22
  121. package/build/esm/extensions/yfm/YfmHeading/index.js +0 -31
  122. package/build/esm/extensions/yfm/YfmHeading/index.js.map +1 -1
  123. package/build/esm/presets/yfm-specs.js +5 -1
  124. package/build/esm/presets/yfm-specs.js.map +1 -1
  125. package/build/esm/presets/yfm.js +5 -1
  126. package/build/esm/presets/yfm.js.map +1 -1
  127. package/build/esm/version.js +1 -1
  128. package/build/esm/version.js.map +1 -1
  129. package/package.json +2 -2
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Heading = exports.HeadingAction = exports.headingType = exports.headingNodeName = void 0;
4
- const prosemirror_commands_1 = require("prosemirror-commands");
5
4
  const keymap_1 = require("../../../utils/keymap.js");
6
5
  const HeadingSpecs_1 = require("./HeadingSpecs/index.js");
7
6
  const actions_1 = require("./actions.js");
@@ -16,22 +15,21 @@ Object.defineProperty(exports, "HeadingAction", { enumerable: true, get: functio
16
15
  const Heading = (builder, opts) => {
17
16
  builder.use(HeadingSpecs_1.HeadingSpecs, opts);
18
17
  builder
19
- .addKeymap(({ schema }) => {
18
+ .addKeymap(() => {
20
19
  const { h1Key, h2Key, h3Key, h4Key, h5Key, h6Key } = opts ?? {};
21
- const cmd4lvl = (level) => (0, prosemirror_commands_1.setBlockType)((0, HeadingSpecs_1.headingType)(schema), { [const_1.headingLevelAttr]: level });
22
20
  const bindings = { Backspace: commands_1.resetHeading };
23
21
  if (h1Key)
24
- bindings[h1Key] = (0, keymap_1.withLogAction)('heading1', cmd4lvl(1));
22
+ bindings[h1Key] = (0, keymap_1.withLogAction)('heading1', (0, commands_1.toHeading)(1));
25
23
  if (h2Key)
26
- bindings[h2Key] = (0, keymap_1.withLogAction)('heading2', cmd4lvl(2));
24
+ bindings[h2Key] = (0, keymap_1.withLogAction)('heading2', (0, commands_1.toHeading)(2));
27
25
  if (h3Key)
28
- bindings[h3Key] = (0, keymap_1.withLogAction)('heading3', cmd4lvl(3));
26
+ bindings[h3Key] = (0, keymap_1.withLogAction)('heading3', (0, commands_1.toHeading)(3));
29
27
  if (h4Key)
30
- bindings[h4Key] = (0, keymap_1.withLogAction)('heading4', cmd4lvl(4));
28
+ bindings[h4Key] = (0, keymap_1.withLogAction)('heading4', (0, commands_1.toHeading)(4));
31
29
  if (h5Key)
32
- bindings[h5Key] = (0, keymap_1.withLogAction)('heading5', cmd4lvl(5));
30
+ bindings[h5Key] = (0, keymap_1.withLogAction)('heading5', (0, commands_1.toHeading)(5));
33
31
  if (h6Key)
34
- bindings[h6Key] = (0, keymap_1.withLogAction)('heading6', cmd4lvl(6));
32
+ bindings[h6Key] = (0, keymap_1.withLogAction)('heading6', (0, commands_1.toHeading)(6));
35
33
  return bindings;
36
34
  })
37
35
  .addInputRules(({ schema }) => ({ rules: [(0, utils_1.headingRule)((0, HeadingSpecs_1.headingType)(schema), 6)] }));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Heading/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {setBlockType} from 'prosemirror-commands';\n\nimport type {Action, ExtensionAuto, Keymap} from '../../../core';\nimport {withLogAction} from '../../../utils/keymap';\n\nimport {HeadingSpecs, type HeadingSpecsOptions, headingType} from './HeadingSpecs';\nimport {headingAction} from './actions';\nimport {resetHeading} from './commands';\nimport {HeadingAction, type HeadingLevel, headingLevelAttr} from './const';\nimport {headingRule} from './utils';\n\nexport {headingNodeName, headingType} from './HeadingSpecs';\nexport {HeadingAction} from './const';\n\nexport type HeadingOptions = HeadingSpecsOptions & {\n h1Key?: string | null;\n h2Key?: string | null;\n h3Key?: string | null;\n h4Key?: string | null;\n h5Key?: string | null;\n h6Key?: string | null;\n};\n\nexport const Heading: ExtensionAuto<HeadingOptions> = (builder, opts) => {\n builder.use(HeadingSpecs, opts);\n\n builder\n .addKeymap(({schema}) => {\n const {h1Key, h2Key, h3Key, h4Key, h5Key, h6Key} = opts ?? {};\n const cmd4lvl = (level: HeadingLevel) =>\n setBlockType(headingType(schema), {[headingLevelAttr]: level});\n\n const bindings: Keymap = {Backspace: resetHeading};\n if (h1Key) bindings[h1Key] = withLogAction('heading1', cmd4lvl(1));\n if (h2Key) bindings[h2Key] = withLogAction('heading2', cmd4lvl(2));\n if (h3Key) bindings[h3Key] = withLogAction('heading3', cmd4lvl(3));\n if (h4Key) bindings[h4Key] = withLogAction('heading4', cmd4lvl(4));\n if (h5Key) bindings[h5Key] = withLogAction('heading5', cmd4lvl(5));\n if (h6Key) bindings[h6Key] = withLogAction('heading6', cmd4lvl(6));\n return bindings;\n })\n .addInputRules(({schema}) => ({rules: [headingRule(headingType(schema), 6)]}));\n\n builder\n .addAction(HeadingAction.ToH1, ({schema}) => headingAction(headingType(schema), 1))\n .addAction(HeadingAction.ToH2, ({schema}) => headingAction(headingType(schema), 2))\n .addAction(HeadingAction.ToH3, ({schema}) => headingAction(headingType(schema), 3))\n .addAction(HeadingAction.ToH4, ({schema}) => headingAction(headingType(schema), 4))\n .addAction(HeadingAction.ToH5, ({schema}) => headingAction(headingType(schema), 5))\n .addAction(HeadingAction.ToH6, ({schema}) => headingAction(headingType(schema), 6));\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [HeadingAction.ToH1]: Action;\n [HeadingAction.ToH2]: Action;\n [HeadingAction.ToH3]: Action;\n [HeadingAction.ToH4]: Action;\n [HeadingAction.ToH5]: Action;\n [HeadingAction.ToH6]: Action;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Heading/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Action, ExtensionAuto, Keymap} from '../../../core';\nimport {withLogAction} from '../../../utils/keymap';\n\nimport {HeadingSpecs, type HeadingSpecsOptions, headingType} from './HeadingSpecs';\nimport {headingAction} from './actions';\nimport {resetHeading, toHeading} from './commands';\nimport {HeadingAction} from './const';\nimport {headingRule} from './utils';\n\nexport {headingNodeName, headingType} from './HeadingSpecs';\nexport {HeadingAction} from './const';\n\nexport type HeadingOptions = HeadingSpecsOptions & {\n h1Key?: string | null;\n h2Key?: string | null;\n h3Key?: string | null;\n h4Key?: string | null;\n h5Key?: string | null;\n h6Key?: string | null;\n};\n\nexport const Heading: ExtensionAuto<HeadingOptions> = (builder, opts) => {\n builder.use(HeadingSpecs, opts);\n\n builder\n .addKeymap(() => {\n const {h1Key, h2Key, h3Key, h4Key, h5Key, h6Key} = opts ?? {};\n\n const bindings: Keymap = {Backspace: resetHeading};\n if (h1Key) bindings[h1Key] = withLogAction('heading1', toHeading(1));\n if (h2Key) bindings[h2Key] = withLogAction('heading2', toHeading(2));\n if (h3Key) bindings[h3Key] = withLogAction('heading3', toHeading(3));\n if (h4Key) bindings[h4Key] = withLogAction('heading4', toHeading(4));\n if (h5Key) bindings[h5Key] = withLogAction('heading5', toHeading(5));\n if (h6Key) bindings[h6Key] = withLogAction('heading6', toHeading(6));\n return bindings;\n })\n .addInputRules(({schema}) => ({rules: [headingRule(headingType(schema), 6)]}));\n\n builder\n .addAction(HeadingAction.ToH1, ({schema}) => headingAction(headingType(schema), 1))\n .addAction(HeadingAction.ToH2, ({schema}) => headingAction(headingType(schema), 2))\n .addAction(HeadingAction.ToH3, ({schema}) => headingAction(headingType(schema), 3))\n .addAction(HeadingAction.ToH4, ({schema}) => headingAction(headingType(schema), 4))\n .addAction(HeadingAction.ToH5, ({schema}) => headingAction(headingType(schema), 5))\n .addAction(HeadingAction.ToH6, ({schema}) => headingAction(headingType(schema), 6));\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [HeadingAction.ToH1]: Action;\n [HeadingAction.ToH2]: Action;\n [HeadingAction.ToH3]: Action;\n [HeadingAction.ToH4]: Action;\n [HeadingAction.ToH5]: Action;\n [HeadingAction.ToH6]: Action;\n }\n }\n}\n"]}
@@ -39,6 +39,7 @@ const Lists = (builder, opts) => {
39
39
  Backspace: commands_1.joinPrevList,
40
40
  }), builder.Priority.Low);
41
41
  builder.use(inputrules_1.ListsInputRulesExtension, { bulletListInputRule: opts?.ulInputRules });
42
+ // Order matters: merge must run before collapse (see CollapseListsPlugin.ts)
42
43
  builder.addPlugin(MergeListsPlugin_1.mergeListsPlugin);
43
44
  builder.addPlugin(CollapseListsPlugin_1.collapseListsPlugin);
44
45
  builder
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Lists/index.ts"],"names":[],"mappings":";;;AAAA,qEAAoE;AAGpE,qDAAoD;AAEpD,sDAAgE;AAChE,0CAAkC;AAClC,4CAA6F;AAC7F,sCAAmC;AACnC,gDAAmF;AACnF,0EAAkE;AAClE,oEAA4D;AAE5D,oDAAyE;AAAjE,sGAAA,QAAQ,OAAA;AAAE,uGAAA,SAAS,OAAA;AAAE,oGAAA,MAAM,OAAA;AAAE,oGAAA,MAAM,OAAA;AAAE,oGAAA,MAAM,OAAA;AAQ5C,MAAM,KAAK,GAAgC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IAChE,OAAO,CAAC,GAAG,CAAC,uBAAU,CAAC,CAAC;IAExB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE;QAC3B,MAAM,EAAC,KAAK,EAAE,KAAK,EAAC,GAAG,IAAI,IAAI,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAW,EAAE,CAAC;QAC5B,IAAI,KAAK;YAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAA,sBAAa,EAAC,YAAY,EAAE,IAAA,iBAAM,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjF,IAAI,KAAK;YAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAA,sBAAa,EAAC,aAAa,EAAE,IAAA,iBAAM,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAElF,OAAO;YACH,GAAG,EAAE,IAAA,mCAAwB,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YAC7C,WAAW,EAAE,IAAA,sCAAY,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YACzC,SAAS,EAAE,IAAA,4BAAiB,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YAE5C,OAAO,EAAE,IAAA,sCAAY,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YACrC,OAAO,EAAE,IAAA,mCAAwB,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YAEjD,GAAG,QAAQ;SACd,CAAC;IACN,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE1B,OAAO,CAAC,SAAS,CACb,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;QACX,KAAK,EAAE,IAAA,uCAAa,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;QACpC,SAAS,EAAE,uBAAY;KAC1B,CAAC,EACF,OAAO,CAAC,QAAQ,CAAC,GAAG,CACvB,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,qCAAwB,EAAE,EAAC,mBAAmB,EAAE,IAAI,EAAE,YAAY,EAAC,CAAC,CAAC;IAEjF,OAAO,CAAC,SAAS,CAAC,mCAAgB,CAAC,CAAC;IAEpC,OAAO,CAAC,SAAS,CAAC,yCAAmB,CAAC,CAAC;IAEvC,OAAO;SACF,SAAS,CAAC,kBAAU,CAAC,YAAY,EAAE,iBAAO,CAAC,YAAY,CAAC;SACxD,SAAS,CAAC,kBAAU,CAAC,aAAa,EAAE,iBAAO,CAAC,aAAa,CAAC;SAC1D,SAAS,CAAC,kBAAU,CAAC,YAAY,EAAE,iBAAO,CAAC,YAAY,CAAC;SACxD,SAAS,CAAC,kBAAU,CAAC,YAAY,EAAE,iBAAO,CAAC,YAAY,CAAC,CAAC;AAClE,CAAC,CAAC;AAxCW,QAAA,KAAK,SAwChB","sourcesContent":["import {liftListItem, splitListItem} from 'prosemirror-schema-list';\n\nimport type {Action, ExtensionAuto, Keymap} from '../../../core';\nimport {withLogAction} from '../../../utils/keymap';\n\nimport {ListsSpecs, blType, liType, olType} from './ListsSpecs';\nimport {actions} from './actions';\nimport {joinPrevList, liftEmptyListItem, sinkOnlySelectedListItem, toList} from './commands';\nimport {ListAction} from './const';\nimport {ListsInputRulesExtension, type ListsInputRulesOptions} from './inputrules';\nimport {collapseListsPlugin} from './plugins/CollapseListsPlugin';\nimport {mergeListsPlugin} from './plugins/MergeListsPlugin';\n\nexport {ListNode, ListsAttr, blType, liType, olType} from './ListsSpecs';\n\nexport type ListsOptions = {\n ulKey?: string | null;\n olKey?: string | null;\n ulInputRules?: ListsInputRulesOptions['bulletListInputRule'];\n};\n\nexport const Lists: ExtensionAuto<ListsOptions> = (builder, opts) => {\n builder.use(ListsSpecs);\n\n builder.addKeymap(({schema}) => {\n const {ulKey, olKey} = opts ?? {};\n const bindings: Keymap = {};\n if (ulKey) bindings[ulKey] = withLogAction('bulletList', toList(blType(schema)));\n if (olKey) bindings[olKey] = withLogAction('orderedList', toList(olType(schema)));\n\n return {\n Tab: sinkOnlySelectedListItem(liType(schema)),\n 'Shift-Tab': liftListItem(liType(schema)),\n Backspace: liftEmptyListItem(liType(schema)),\n\n 'Mod-[': liftListItem(liType(schema)),\n 'Mod-]': sinkOnlySelectedListItem(liType(schema)),\n\n ...bindings,\n };\n }, builder.Priority.High);\n\n builder.addKeymap(\n ({schema}) => ({\n Enter: splitListItem(liType(schema)),\n Backspace: joinPrevList,\n }),\n builder.Priority.Low,\n );\n\n builder.use(ListsInputRulesExtension, {bulletListInputRule: opts?.ulInputRules});\n\n builder.addPlugin(mergeListsPlugin);\n\n builder.addPlugin(collapseListsPlugin);\n\n builder\n .addAction(ListAction.ToBulletList, actions.toBulletList)\n .addAction(ListAction.ToOrderedList, actions.toOrderedList)\n .addAction(ListAction.SinkListItem, actions.sinkListItem)\n .addAction(ListAction.LiftListItem, actions.liftListItem);\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [ListAction.ToBulletList]: Action;\n [ListAction.ToOrderedList]: Action;\n [ListAction.SinkListItem]: Action;\n [ListAction.LiftListItem]: Action;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Lists/index.ts"],"names":[],"mappings":";;;AAAA,qEAAoE;AAGpE,qDAAoD;AAEpD,sDAAgE;AAChE,0CAAkC;AAClC,4CAA6F;AAC7F,sCAAmC;AACnC,gDAAmF;AACnF,0EAAkE;AAClE,oEAA4D;AAE5D,oDAAyE;AAAjE,sGAAA,QAAQ,OAAA;AAAE,uGAAA,SAAS,OAAA;AAAE,oGAAA,MAAM,OAAA;AAAE,oGAAA,MAAM,OAAA;AAAE,oGAAA,MAAM,OAAA;AAQ5C,MAAM,KAAK,GAAgC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IAChE,OAAO,CAAC,GAAG,CAAC,uBAAU,CAAC,CAAC;IAExB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE;QAC3B,MAAM,EAAC,KAAK,EAAE,KAAK,EAAC,GAAG,IAAI,IAAI,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAW,EAAE,CAAC;QAC5B,IAAI,KAAK;YAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAA,sBAAa,EAAC,YAAY,EAAE,IAAA,iBAAM,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjF,IAAI,KAAK;YAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAA,sBAAa,EAAC,aAAa,EAAE,IAAA,iBAAM,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAElF,OAAO;YACH,GAAG,EAAE,IAAA,mCAAwB,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YAC7C,WAAW,EAAE,IAAA,sCAAY,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YACzC,SAAS,EAAE,IAAA,4BAAiB,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YAE5C,OAAO,EAAE,IAAA,sCAAY,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YACrC,OAAO,EAAE,IAAA,mCAAwB,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;YAEjD,GAAG,QAAQ;SACd,CAAC;IACN,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE1B,OAAO,CAAC,SAAS,CACb,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;QACX,KAAK,EAAE,IAAA,uCAAa,EAAC,IAAA,mBAAM,EAAC,MAAM,CAAC,CAAC;QACpC,SAAS,EAAE,uBAAY;KAC1B,CAAC,EACF,OAAO,CAAC,QAAQ,CAAC,GAAG,CACvB,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,qCAAwB,EAAE,EAAC,mBAAmB,EAAE,IAAI,EAAE,YAAY,EAAC,CAAC,CAAC;IAEjF,6EAA6E;IAC7E,OAAO,CAAC,SAAS,CAAC,mCAAgB,CAAC,CAAC;IACpC,OAAO,CAAC,SAAS,CAAC,yCAAmB,CAAC,CAAC;IAEvC,OAAO;SACF,SAAS,CAAC,kBAAU,CAAC,YAAY,EAAE,iBAAO,CAAC,YAAY,CAAC;SACxD,SAAS,CAAC,kBAAU,CAAC,aAAa,EAAE,iBAAO,CAAC,aAAa,CAAC;SAC1D,SAAS,CAAC,kBAAU,CAAC,YAAY,EAAE,iBAAO,CAAC,YAAY,CAAC;SACxD,SAAS,CAAC,kBAAU,CAAC,YAAY,EAAE,iBAAO,CAAC,YAAY,CAAC,CAAC;AAClE,CAAC,CAAC;AAxCW,QAAA,KAAK,SAwChB","sourcesContent":["import {liftListItem, splitListItem} from 'prosemirror-schema-list';\n\nimport type {Action, ExtensionAuto, Keymap} from '../../../core';\nimport {withLogAction} from '../../../utils/keymap';\n\nimport {ListsSpecs, blType, liType, olType} from './ListsSpecs';\nimport {actions} from './actions';\nimport {joinPrevList, liftEmptyListItem, sinkOnlySelectedListItem, toList} from './commands';\nimport {ListAction} from './const';\nimport {ListsInputRulesExtension, type ListsInputRulesOptions} from './inputrules';\nimport {collapseListsPlugin} from './plugins/CollapseListsPlugin';\nimport {mergeListsPlugin} from './plugins/MergeListsPlugin';\n\nexport {ListNode, ListsAttr, blType, liType, olType} from './ListsSpecs';\n\nexport type ListsOptions = {\n ulKey?: string | null;\n olKey?: string | null;\n ulInputRules?: ListsInputRulesOptions['bulletListInputRule'];\n};\n\nexport const Lists: ExtensionAuto<ListsOptions> = (builder, opts) => {\n builder.use(ListsSpecs);\n\n builder.addKeymap(({schema}) => {\n const {ulKey, olKey} = opts ?? {};\n const bindings: Keymap = {};\n if (ulKey) bindings[ulKey] = withLogAction('bulletList', toList(blType(schema)));\n if (olKey) bindings[olKey] = withLogAction('orderedList', toList(olType(schema)));\n\n return {\n Tab: sinkOnlySelectedListItem(liType(schema)),\n 'Shift-Tab': liftListItem(liType(schema)),\n Backspace: liftEmptyListItem(liType(schema)),\n\n 'Mod-[': liftListItem(liType(schema)),\n 'Mod-]': sinkOnlySelectedListItem(liType(schema)),\n\n ...bindings,\n };\n }, builder.Priority.High);\n\n builder.addKeymap(\n ({schema}) => ({\n Enter: splitListItem(liType(schema)),\n Backspace: joinPrevList,\n }),\n builder.Priority.Low,\n );\n\n builder.use(ListsInputRulesExtension, {bulletListInputRule: opts?.ulInputRules});\n\n // Order matters: merge must run before collapse (see CollapseListsPlugin.ts)\n builder.addPlugin(mergeListsPlugin);\n builder.addPlugin(collapseListsPlugin);\n\n builder\n .addAction(ListAction.ToBulletList, actions.toBulletList)\n .addAction(ListAction.ToOrderedList, actions.toOrderedList)\n .addAction(ListAction.SinkListItem, actions.sinkListItem)\n .addAction(ListAction.LiftListItem, actions.liftListItem);\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [ListAction.ToBulletList]: Action;\n [ListAction.ToOrderedList]: Action;\n [ListAction.SinkListItem]: Action;\n [ListAction.LiftListItem]: Action;\n }\n }\n}\n"]}
@@ -1,4 +1,16 @@
1
1
  import { Plugin, type Transaction } from 'prosemirror-state';
2
- import { findChildren } from 'prosemirror-utils';
2
+ /**
3
+ * Collapses redundant nested lists inside list items
4
+ *
5
+ * Converts structures where a list item starts with
6
+ * a nested list into a flat list structure
7
+ *
8
+ * IMPORTANT: must be registered AFTER MergeListsPlugin.
9
+ * Collapsing may create adjacent lists that require merging
10
+ */
3
11
  export declare const collapseListsPlugin: () => Plugin<any>;
4
- export declare function collapseEmptyListItems(tr: Transaction, nodes: ReturnType<typeof findChildren>): number;
12
+ /**
13
+ * Finds list items with redundant nesting, collapses them recursively,
14
+ * and applies replacements in reverse document order
15
+ */
16
+ export declare function collapseAllNestedListItems(tr: Transaction): number | null;
@@ -1,76 +1,122 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.collapseListsPlugin = void 0;
4
- exports.collapseEmptyListItems = collapseEmptyListItems;
4
+ exports.collapseAllNestedListItems = collapseAllNestedListItems;
5
5
  const prosemirror_model_1 = require("prosemirror-model");
6
6
  const prosemirror_state_1 = require("prosemirror-state");
7
7
  // @ts-ignore // TODO: fix cjs build
8
8
  const prosemirror_utils_1 = require("prosemirror-utils");
9
- const utils_1 = require("../../../../utils/index.js");
10
- const utils_2 = require("../utils.js");
9
+ const utils_1 = require("../utils.js");
10
+ const MAX_COLLAPSE_DEPTH = 100;
11
+ /**
12
+ * Collapses redundant nested lists inside list items
13
+ *
14
+ * Converts structures where a list item starts with
15
+ * a nested list into a flat list structure
16
+ *
17
+ * IMPORTANT: must be registered AFTER MergeListsPlugin.
18
+ * Collapsing may create adjacent lists that require merging
19
+ */
11
20
  const collapseListsPlugin = () => new prosemirror_state_1.Plugin({
12
21
  appendTransaction(trs, oldState, newState) {
22
+ // early exit if document unchanged
13
23
  const docChanged = trs.some((tr) => tr.docChanged);
14
- if (!docChanged)
24
+ if (!docChanged) {
15
25
  return null;
16
- const hasParentList = (0, prosemirror_utils_1.hasParentNode)(utils_2.isListNode)(newState.selection) ||
17
- (0, prosemirror_utils_1.hasParentNode)(utils_2.isListNode)(oldState.selection);
18
- if (!hasParentList)
26
+ }
27
+ // early exit if not inside a list
28
+ const hasParentList = (0, prosemirror_utils_1.hasParentNode)(utils_1.isListNode)(newState.selection) ||
29
+ (0, prosemirror_utils_1.hasParentNode)(utils_1.isListNode)(oldState.selection);
30
+ if (!hasParentList) {
19
31
  return null;
32
+ }
20
33
  const { tr } = newState;
21
- let prevStepsCount = -1;
22
- let currentStepsCount = 0;
23
- // execute until there are no nested lists.
24
- while (prevStepsCount !== currentStepsCount) {
25
- const listNodes = (0, prosemirror_utils_1.findChildren)(tr.doc, utils_2.isListNode, true);
26
- prevStepsCount = currentStepsCount;
27
- currentStepsCount = collapseEmptyListItems(tr, listNodes);
34
+ // collapse of redundant nested lists
35
+ const lastCollapsePos = collapseAllNestedListItems(tr);
36
+ // restore cursor position
37
+ if (lastCollapsePos !== null) {
38
+ const clampedPos = Math.min(lastCollapsePos, tr.doc.content.size);
39
+ tr.setSelection(prosemirror_state_1.Selection.near(tr.doc.resolve(clampedPos)));
28
40
  }
29
41
  return tr.docChanged ? tr : null;
30
42
  },
31
43
  });
32
44
  exports.collapseListsPlugin = collapseListsPlugin;
33
- function collapseEmptyListItems(tr, nodes) {
34
- const stepsCountBefore = tr.steps.length;
35
- // TODO: fix cjs build
36
- nodes.reverse().forEach((list) => {
37
- const listNode = list.node;
38
- const listPos = list.pos;
39
- const childrenOfList = (0, utils_1.getChildrenOfNode)(listNode).reverse();
40
- childrenOfList.forEach(({ node: itemNode, offset }) => {
41
- if ((0, utils_2.isListItemNode)(itemNode)) {
42
- const { firstChild } = itemNode;
43
- const listItemNodePos = listPos + 1 + offset;
44
- // if the first child of a list element is a list,
45
- // then collapse is required
46
- if (firstChild && (0, utils_2.isListNode)(firstChild)) {
47
- const nestedList = firstChild.content;
48
- // nodes at the same level as the list
49
- const remainingNodes = itemNode.content.content.slice(1);
50
- const listItems = remainingNodes.length
51
- ? nestedList.append(prosemirror_model_1.Fragment.from((0, utils_2.liType)(tr.doc.type.schema).create(null, remainingNodes)))
52
- : nestedList;
53
- const mappedStart = tr.mapping.map(listItemNodePos);
54
- const mappedEnd = tr.mapping.map(listItemNodePos + itemNode.nodeSize);
55
- tr.replaceWith(mappedStart, mappedEnd, listItems);
56
- const closestTextNodePos = findClosestTextNodePos(tr.doc, mappedStart + nestedList.size);
57
- if (closestTextNodePos) {
58
- tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, closestTextNodePos));
59
- }
60
- }
61
- }
45
+ /**
46
+ * Finds list items with redundant nesting, collapses them recursively,
47
+ * and applies replacements in reverse document order
48
+ */
49
+ function collapseAllNestedListItems(tr) {
50
+ const replacements = [];
51
+ const schema = tr.doc.type.schema;
52
+ // skipUntil prevents re-processing children that were already collapsed
53
+ // by the recursive call in collapseListItemContent
54
+ let skipUntil = -1;
55
+ tr.doc.descendants((node, pos) => {
56
+ if (pos < skipUntil || node.isTextblock) {
57
+ return false;
58
+ }
59
+ if (!(0, utils_1.isListItemNode)(node)) {
60
+ return true;
61
+ }
62
+ const { firstChild } = node;
63
+ if (!firstChild || !(0, utils_1.isListNode)(firstChild)) {
64
+ return true;
65
+ }
66
+ const collapsedContent = collapseListItemContent(node, schema, 0);
67
+ if (collapsedContent === null) {
68
+ return true;
69
+ }
70
+ replacements.push({
71
+ from: pos,
72
+ to: pos + node.nodeSize,
73
+ content: collapsedContent,
62
74
  });
75
+ skipUntil = pos + node.nodeSize;
76
+ return false;
63
77
  });
64
- return tr.steps.length - stepsCountBefore;
78
+ if (replacements.length === 0) {
79
+ return null;
80
+ }
81
+ // apply from end to start so earlier positions stay valid
82
+ for (let i = replacements.length - 1; i >= 0; i--) {
83
+ const { from, to, content } = replacements[i];
84
+ tr.replaceWith(from, to, content);
85
+ }
86
+ // map the original end of the last replacement to its post-edit position
87
+ const last = replacements[replacements.length - 1];
88
+ return tr.mapping.map(last.to);
65
89
  }
66
- function findClosestTextNodePos(doc, pos) {
67
- while (pos < doc.content.size) {
68
- const node = doc.nodeAt(pos);
69
- if (node && node.isText) {
70
- return pos;
90
+ /**
91
+ * Recursively collapses a list item with redundant nesting
92
+ * into a Fragment of flat list items
93
+ *
94
+ * A redundantly nested list item has a list as its first child
95
+ * (instead of a paragraph)
96
+ */
97
+ function collapseListItemContent(itemNode, schema, depth) {
98
+ const { firstChild } = itemNode;
99
+ if (!firstChild || !(0, utils_1.isListNode)(firstChild)) {
100
+ return null;
101
+ }
102
+ if (depth >= MAX_COLLAPSE_DEPTH) {
103
+ return null;
104
+ }
105
+ // .slice(1) = all children except firstChild
106
+ const remaining = itemNode.content.content.slice(1);
107
+ let result = prosemirror_model_1.Fragment.empty;
108
+ firstChild.forEach((child) => {
109
+ if ((0, utils_1.isListItemNode)(child)) {
110
+ const collapsed = collapseListItemContent(child, schema, depth + 1);
111
+ result = result.append(collapsed ?? prosemirror_model_1.Fragment.from(child));
112
+ }
113
+ else {
114
+ result = result.append(prosemirror_model_1.Fragment.from(child));
71
115
  }
72
- pos++;
116
+ });
117
+ if (remaining.length) {
118
+ result = result.append(prosemirror_model_1.Fragment.from((0, utils_1.liType)(schema).create(null, remaining)));
73
119
  }
74
- return null;
120
+ return result;
75
121
  }
76
122
  //# sourceMappingURL=CollapseListsPlugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CollapseListsPlugin.js","sourceRoot":"../../../../../../src","sources":["extensions/markdown/Lists/plugins/CollapseListsPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import {Fragment, type Node} from 'prosemirror-model';\nimport {Plugin, TextSelection, type Transaction} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {findChildren, hasParentNode} from 'prosemirror-utils';\n\nimport {getChildrenOfNode} from '../../../../utils';\nimport {isListItemNode, isListNode, liType} from '../utils';\n\nexport const collapseListsPlugin = () =>\n new Plugin({\n appendTransaction(trs, oldState, newState) {\n const docChanged = trs.some((tr) => tr.docChanged);\n if (!docChanged) return null;\n\n const hasParentList =\n hasParentNode(isListNode)(newState.selection) ||\n hasParentNode(isListNode)(oldState.selection);\n if (!hasParentList) return null;\n\n const {tr} = newState;\n let prevStepsCount = -1;\n let currentStepsCount = 0;\n\n // execute until there are no nested lists.\n while (prevStepsCount !== currentStepsCount) {\n const listNodes = findChildren(tr.doc, isListNode, true);\n prevStepsCount = currentStepsCount;\n currentStepsCount = collapseEmptyListItems(tr, listNodes);\n }\n\n return tr.docChanged ? tr : null;\n },\n });\n\nexport function collapseEmptyListItems(\n tr: Transaction,\n nodes: ReturnType<typeof findChildren>,\n): number {\n const stepsCountBefore = tr.steps.length;\n // TODO: fix cjs build\n nodes.reverse().forEach((list: {node: Node; pos: number}) => {\n const listNode = list.node;\n const listPos = list.pos;\n const childrenOfList = getChildrenOfNode(listNode).reverse();\n\n childrenOfList.forEach(({node: itemNode, offset}) => {\n if (isListItemNode(itemNode)) {\n const {firstChild} = itemNode;\n const listItemNodePos = listPos + 1 + offset;\n\n // if the first child of a list element is a list,\n // then collapse is required\n if (firstChild && isListNode(firstChild)) {\n const nestedList = firstChild.content;\n\n // nodes at the same level as the list\n const remainingNodes = itemNode.content.content.slice(1);\n\n const listItems = remainingNodes.length\n ? nestedList.append(\n Fragment.from(\n liType(tr.doc.type.schema).create(null, remainingNodes),\n ),\n )\n : nestedList;\n\n const mappedStart = tr.mapping.map(listItemNodePos);\n const mappedEnd = tr.mapping.map(listItemNodePos + itemNode.nodeSize);\n\n tr.replaceWith(mappedStart, mappedEnd, listItems);\n\n const closestTextNodePos = findClosestTextNodePos(\n tr.doc,\n mappedStart + nestedList.size,\n );\n if (closestTextNodePos) {\n tr.setSelection(TextSelection.create(tr.doc, closestTextNodePos));\n }\n }\n }\n });\n });\n\n return tr.steps.length - stepsCountBefore;\n}\n\nfunction findClosestTextNodePos(doc: Node, pos: number): number | null {\n while (pos < doc.content.size) {\n const node = doc.nodeAt(pos);\n if (node && node.isText) {\n return pos;\n }\n pos++;\n }\n return null;\n}\n"]}
1
+ {"version":3,"file":"CollapseListsPlugin.js","sourceRoot":"../../../../../../src","sources":["extensions/markdown/Lists/plugins/CollapseListsPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import {Fragment, type Node, type Schema} from 'prosemirror-model';\nimport {Plugin, Selection, type Transaction} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {hasParentNode} from 'prosemirror-utils';\n\nimport {isListItemNode, isListNode, liType} from '../utils';\n\nconst MAX_COLLAPSE_DEPTH = 100;\n\n/**\n * Collapses redundant nested lists inside list items\n *\n * Converts structures where a list item starts with\n * a nested list into a flat list structure\n *\n * IMPORTANT: must be registered AFTER MergeListsPlugin.\n * Collapsing may create adjacent lists that require merging\n */\nexport const collapseListsPlugin = () =>\n new Plugin({\n appendTransaction(trs, oldState, newState) {\n // early exit if document unchanged\n const docChanged = trs.some((tr) => tr.docChanged);\n if (!docChanged) {\n return null;\n }\n\n // early exit if not inside a list\n const hasParentList =\n hasParentNode(isListNode)(newState.selection) ||\n hasParentNode(isListNode)(oldState.selection);\n if (!hasParentList) {\n return null;\n }\n\n const {tr} = newState;\n\n // collapse of redundant nested lists\n const lastCollapsePos = collapseAllNestedListItems(tr);\n\n // restore cursor position\n if (lastCollapsePos !== null) {\n const clampedPos = Math.min(lastCollapsePos, tr.doc.content.size);\n tr.setSelection(Selection.near(tr.doc.resolve(clampedPos)));\n }\n\n return tr.docChanged ? tr : null;\n },\n });\n\ninterface Replacement {\n from: number;\n to: number;\n content: Fragment;\n}\n\n/**\n * Finds list items with redundant nesting, collapses them recursively,\n * and applies replacements in reverse document order\n */\nexport function collapseAllNestedListItems(tr: Transaction): number | null {\n const replacements: Replacement[] = [];\n const schema = tr.doc.type.schema;\n\n // skipUntil prevents re-processing children that were already collapsed\n // by the recursive call in collapseListItemContent\n let skipUntil = -1;\n\n tr.doc.descendants((node, pos) => {\n if (pos < skipUntil || node.isTextblock) {\n return false;\n }\n\n if (!isListItemNode(node)) {\n return true;\n }\n\n const {firstChild} = node;\n if (!firstChild || !isListNode(firstChild)) {\n return true;\n }\n\n const collapsedContent = collapseListItemContent(node, schema, 0);\n if (collapsedContent === null) {\n return true;\n }\n\n replacements.push({\n from: pos,\n to: pos + node.nodeSize,\n content: collapsedContent,\n });\n skipUntil = pos + node.nodeSize;\n\n return false;\n });\n\n if (replacements.length === 0) {\n return null;\n }\n\n // apply from end to start so earlier positions stay valid\n for (let i = replacements.length - 1; i >= 0; i--) {\n const {from, to, content} = replacements[i];\n tr.replaceWith(from, to, content);\n }\n\n // map the original end of the last replacement to its post-edit position\n const last = replacements[replacements.length - 1];\n return tr.mapping.map(last.to);\n}\n\n/**\n * Recursively collapses a list item with redundant nesting\n * into a Fragment of flat list items\n *\n * A redundantly nested list item has a list as its first child\n * (instead of a paragraph)\n */\nfunction collapseListItemContent(itemNode: Node, schema: Schema, depth: number): Fragment | null {\n const {firstChild} = itemNode;\n if (!firstChild || !isListNode(firstChild)) {\n return null;\n }\n if (depth >= MAX_COLLAPSE_DEPTH) {\n return null;\n }\n\n // .slice(1) = all children except firstChild\n const remaining = itemNode.content.content.slice(1);\n\n let result = Fragment.empty;\n firstChild.forEach((child) => {\n if (isListItemNode(child)) {\n const collapsed = collapseListItemContent(child, schema, depth + 1);\n result = result.append(collapsed ?? Fragment.from(child));\n } else {\n result = result.append(Fragment.from(child));\n }\n });\n\n if (remaining.length) {\n result = result.append(Fragment.from(liType(schema).create(null, remaining)));\n }\n\n return result;\n}\n"]}
@@ -2,7 +2,7 @@ export type { HeadingLevel } from "../../../markdown/Heading/const.js";
2
2
  export { headingLevelAttr, headingNodeName } from "../../../markdown/Heading/HeadingSpecs/index.js";
3
3
  export declare const YfmHeadingAttr: {
4
4
  readonly Level: "level";
5
- readonly Id: "id";
6
5
  readonly DataLine: "data-line";
6
+ readonly Id: "id";
7
7
  readonly Folding: "folded";
8
8
  };
@@ -7,8 +7,8 @@ Object.defineProperty(exports, "headingLevelAttr", { enumerable: true, get: func
7
7
  Object.defineProperty(exports, "headingNodeName", { enumerable: true, get: function () { return HeadingSpecs_2.headingNodeName; } });
8
8
  exports.YfmHeadingAttr = {
9
9
  Level: HeadingSpecs_1.headingLevelAttr,
10
+ DataLine: HeadingSpecs_1.headingLineNumberAttr,
10
11
  Id: 'id',
11
- DataLine: 'data-line',
12
- Folding: 'folded',
12
+ Folding: 'folded', // TODO: move to FoldingHeadingExtension
13
13
  };
14
14
  //# sourceMappingURL=const.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"const.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/YfmHeading/YfmHeadingSpecs/const.ts"],"names":[],"mappings":";;;AAAA,kFAAwE;AAGxE,gFAAyF;AAAjF,gHAAA,gBAAgB,OAAA;AAAE,+GAAA,eAAe,OAAA;AAE5B,QAAA,cAAc,GAAG;IAC1B,KAAK,EAAE,+BAAgB;IACvB,EAAE,EAAE,IAAI;IACR,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,QAAQ;CACX,CAAC","sourcesContent":["import {headingLevelAttr} from '../../../markdown/Heading/HeadingSpecs';\nexport type {HeadingLevel} from '../../../markdown/Heading/const';\n\nexport {headingLevelAttr, headingNodeName} from '../../../markdown/Heading/HeadingSpecs';\n\nexport const YfmHeadingAttr = {\n Level: headingLevelAttr,\n Id: 'id',\n DataLine: 'data-line',\n Folding: 'folded',\n} as const;\n"]}
1
+ {"version":3,"file":"const.js","sourceRoot":"../../../../../../src","sources":["extensions/yfm/YfmHeading/YfmHeadingSpecs/const.ts"],"names":[],"mappings":";;;AAAA,kFAA+F;AAG/F,gFAAyF;AAAjF,gHAAA,gBAAgB,OAAA;AAAE,+GAAA,eAAe,OAAA;AAE5B,QAAA,cAAc,GAAG;IAC1B,KAAK,EAAE,+BAAgB;IACvB,QAAQ,EAAE,oCAAqB;IAC/B,EAAE,EAAE,IAAI;IACR,OAAO,EAAE,QAAQ,EAAE,wCAAwC;CACrD,CAAC","sourcesContent":["import {headingLevelAttr, headingLineNumberAttr} from '../../../markdown/Heading/HeadingSpecs';\nexport type {HeadingLevel} from '../../../markdown/Heading/const';\n\nexport {headingLevelAttr, headingNodeName} from '../../../markdown/Heading/HeadingSpecs';\n\nexport const YfmHeadingAttr = {\n Level: headingLevelAttr,\n DataLine: headingLineNumberAttr,\n Id: 'id',\n Folding: 'folded', // TODO: move to FoldingHeadingExtension\n} as const;\n"]}
@@ -1,11 +1,7 @@
1
1
  import type { ExtensionAuto } from "../../../../core/index.js";
2
- import type { NodeSpec } from "../../../../pm/model.js";
2
+ import { type HeadingSpecsOptions } from "../../../markdown/Heading/HeadingSpecs/index.js";
3
3
  export { YfmHeadingAttr } from "./const.js";
4
- export type YfmHeadingSpecsOptions = {
5
- /**
6
- * @deprecated: use placeholder option in BehaviorPreset instead.
7
- */
8
- headingPlaceholder?: NonNullable<NodeSpec['placeholder']>['content'];
9
- };
4
+ export { renderYfmHeadingAttributes, renderYfmHeadingMarkup } from "./utils.js";
5
+ export type YfmHeadingSpecsOptions = HeadingSpecsOptions & {};
10
6
  /** YfmHeading extension needs markdown-it-attrs plugin */
11
7
  export declare const YfmHeadingSpecs: ExtensionAuto<YfmHeadingSpecsOptions>;
@@ -1,108 +1,90 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.YfmHeadingSpecs = exports.YfmHeadingAttr = void 0;
3
+ exports.YfmHeadingSpecs = exports.renderYfmHeadingMarkup = exports.renderYfmHeadingAttributes = exports.YfmHeadingAttr = void 0;
4
+ const HeadingSpecs_1 = require("../../../markdown/Heading/HeadingSpecs/index.js");
4
5
  const const_1 = require("./const.js");
5
6
  const heading_ids_1 = require("./markdown/heading-ids.js");
6
7
  const utils_1 = require("./utils.js");
7
- const DEFAULT_PLACEHOLDER = (node) => 'Heading ' + node.attrs[const_1.YfmHeadingAttr.Level];
8
8
  var const_2 = require("./const.js");
9
9
  Object.defineProperty(exports, "YfmHeadingAttr", { enumerable: true, get: function () { return const_2.YfmHeadingAttr; } });
10
+ var utils_2 = require("./utils.js");
11
+ Object.defineProperty(exports, "renderYfmHeadingAttributes", { enumerable: true, get: function () { return utils_2.renderYfmHeadingAttributes; } });
12
+ Object.defineProperty(exports, "renderYfmHeadingMarkup", { enumerable: true, get: function () { return utils_2.renderYfmHeadingMarkup; } });
10
13
  /** YfmHeading extension needs markdown-it-attrs plugin */
11
- const YfmHeadingSpecs = (builder, opts) => {
14
+ const YfmHeadingSpecs = (builder, _opts) => {
12
15
  builder.configureMd((md) => md.use(heading_ids_1.headingIdsPlugin));
13
- builder.addNode(const_1.headingNodeName, () => ({
14
- spec: {
15
- attrs: {
16
- [const_1.YfmHeadingAttr.Id]: { default: '' },
17
- [const_1.YfmHeadingAttr.Level]: { default: 1 },
18
- [const_1.YfmHeadingAttr.DataLine]: { default: null },
19
- [const_1.YfmHeadingAttr.Folding]: { default: null },
16
+ builder.overrideNodeSpec(const_1.headingNodeName, (prev) => ({
17
+ ...prev,
18
+ attrs: {
19
+ ...prev.attrs,
20
+ [const_1.YfmHeadingAttr.Id]: { default: '' },
21
+ [const_1.YfmHeadingAttr.Folding]: { default: null },
22
+ },
23
+ selectable: true,
24
+ parseDOM: [
25
+ { tag: 'h1', getAttrs: (0, utils_1.getNodeAttrs)(1), priority: 100, consuming: true },
26
+ { tag: 'h2', getAttrs: (0, utils_1.getNodeAttrs)(2), priority: 100, consuming: true },
27
+ { tag: 'h3', getAttrs: (0, utils_1.getNodeAttrs)(3), priority: 100, consuming: true },
28
+ { tag: 'h4', getAttrs: (0, utils_1.getNodeAttrs)(4), priority: 100, consuming: true },
29
+ { tag: 'h5', getAttrs: (0, utils_1.getNodeAttrs)(5), priority: 100, consuming: true },
30
+ { tag: 'h6', getAttrs: (0, utils_1.getNodeAttrs)(6), priority: 100, consuming: true },
31
+ {
32
+ // ignore anchor link inside headings
33
+ tag: 'a.yfm-anchor',
34
+ context: `${const_1.headingNodeName}/`,
35
+ skip: true,
36
+ ignore: true,
37
+ priority: 1000,
20
38
  },
21
- content: '(text | inline)*',
22
- group: 'block',
23
- defining: true,
24
- selectable: true,
25
- parseDOM: [
26
- { tag: 'h1', getAttrs: (0, utils_1.getNodeAttrs)(1), priority: 100, consuming: true },
27
- { tag: 'h2', getAttrs: (0, utils_1.getNodeAttrs)(2), priority: 100, consuming: true },
28
- { tag: 'h3', getAttrs: (0, utils_1.getNodeAttrs)(3), priority: 100, consuming: true },
29
- { tag: 'h4', getAttrs: (0, utils_1.getNodeAttrs)(4), priority: 100, consuming: true },
30
- { tag: 'h5', getAttrs: (0, utils_1.getNodeAttrs)(5), priority: 100, consuming: true },
31
- { tag: 'h6', getAttrs: (0, utils_1.getNodeAttrs)(6), priority: 100, consuming: true },
39
+ ],
40
+ toDOM(node) {
41
+ const id = node.attrs[const_1.YfmHeadingAttr.Id];
42
+ const lineNumber = node.attrs[const_1.YfmHeadingAttr.DataLine];
43
+ const folding = node.attrs[const_1.YfmHeadingAttr.Folding];
44
+ return [
45
+ 'h' + node.attrs[const_1.YfmHeadingAttr.Level],
32
46
  {
33
- // ignore anchor link inside headings
34
- tag: 'a.yfm-anchor',
35
- context: `${const_1.headingNodeName}/`,
36
- skip: true,
37
- ignore: true,
38
- priority: 1000,
39
- },
40
- ],
41
- toDOM(node) {
42
- const id = node.attrs[const_1.YfmHeadingAttr.Id];
43
- const lineNumber = node.attrs[const_1.YfmHeadingAttr.DataLine];
44
- const folding = node.attrs[const_1.YfmHeadingAttr.Folding];
45
- return [
46
- 'h' + node.attrs[const_1.YfmHeadingAttr.Level],
47
- {
48
- id: id || null,
49
- [const_1.YfmHeadingAttr.DataLine]: lineNumber,
50
- [`data-${const_1.YfmHeadingAttr.Folding}`]: folding,
51
- },
52
- 0,
53
- // [
54
- // 'a',
55
- // {
56
- // href: `#${node.attrs[YfmHeadingAttr.Id]}`,
57
- // class: 'yfm-anchor',
58
- // 'aria-hidden': 'true',
59
- // contenteditable: 'false',
60
- // },
61
- // ],
62
- // ['span', 0],
63
- ];
64
- },
65
- placeholder: {
66
- content: builder.context.get('placeholder')?.heading ??
67
- opts.headingPlaceholder ??
68
- DEFAULT_PLACEHOLDER,
69
- alwaysVisible: true,
70
- },
71
- },
72
- fromMd: {
73
- tokenSpec: {
74
- name: const_1.headingNodeName,
75
- type: 'block',
76
- getAttrs: (token) => {
77
- if (token.type.endsWith('_close'))
78
- return {};
79
- const attrs = Object.fromEntries(token.attrs || []);
80
- // if (!attrs[YfmHeadingAttr.Id]) {
81
- // // calculate id if it was not specified
82
- // // tokens[index + 1] is child inline token
83
- // attrs[YfmHeadingAttr.Id] = slugify(tokens[index + 1].content);
84
- // }
85
- // attrs have id only if it explicitly specified manually
86
- return {
87
- [const_1.YfmHeadingAttr.Level]: Number(token.tag.slice(1)),
88
- [const_1.YfmHeadingAttr.Folding]: token.meta?.folding === true ? true : null,
89
- ...attrs,
90
- };
47
+ id: id || null,
48
+ [const_1.YfmHeadingAttr.DataLine]: lineNumber,
49
+ [`data-${const_1.YfmHeadingAttr.Folding}`]: folding,
91
50
  },
92
- },
51
+ 0,
52
+ // [
53
+ // 'a',
54
+ // {
55
+ // href: `#${node.attrs[YfmHeadingAttr.Id]}`,
56
+ // class: 'yfm-anchor',
57
+ // 'aria-hidden': 'true',
58
+ // contenteditable: 'false',
59
+ // },
60
+ // ],
61
+ // ['span', 0],
62
+ ];
93
63
  },
94
- toMd: (state, node) => {
95
- const folding = node.attrs[const_1.YfmHeadingAttr.Folding];
96
- const level = node.attrs[const_1.YfmHeadingAttr.Level];
97
- state.write(state.repeat('#', level) + (typeof folding === 'boolean' ? '+' : '') + ' ');
98
- state.renderInline(node);
99
- const anchor = node.attrs[const_1.YfmHeadingAttr.Id];
100
- if (anchor /*&& anchor !== node.firstChild?.textContent*/) {
101
- state.write(` {#${anchor}}`);
102
- }
103
- state.closeBlock(node);
64
+ }));
65
+ builder.overrideMarkdownTokenParserSpec(const_1.headingNodeName, (prev) => ({
66
+ ...prev,
67
+ getAttrs: (token) => {
68
+ if (token.type.endsWith('_close'))
69
+ return {};
70
+ const attrs = Object.fromEntries(token.attrs || []);
71
+ // if (!attrs[YfmHeadingAttr.Id]) {
72
+ // // calculate id if it was not specified
73
+ // // tokens[index + 1] is child inline token
74
+ // attrs[YfmHeadingAttr.Id] = slugify(tokens[index + 1].content);
75
+ // }
76
+ // attrs have id only if it explicitly specified manually
77
+ return {
78
+ [const_1.YfmHeadingAttr.Level]: Number(token.tag.slice(1)),
79
+ [const_1.YfmHeadingAttr.Folding]: token.meta?.folding === true ? true : null,
80
+ ...attrs,
81
+ };
104
82
  },
105
83
  }));
84
+ builder.overrideNodeSerializerSpec(const_1.headingNodeName, () => (0, HeadingSpecs_1.headingToMarkdown)({
85
+ renderMarkup: utils_1.renderYfmHeadingMarkup,
86
+ renderAttributes: utils_1.renderYfmHeadingAttributes,
87
+ }));
106
88
  };
107
89
  exports.YfmHeadingSpecs = YfmHeadingSpecs;
108
90
  //# sourceMappingURL=index.js.map