@gravity-ui/markdown-editor 15.35.1 → 15.37.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 (205) hide show
  1. package/README.md +87 -0
  2. package/build/cjs/core/Editor.js +2 -0
  3. package/build/cjs/core/Editor.js.map +1 -1
  4. package/build/cjs/core/index.d.ts +1 -0
  5. package/build/cjs/core/index.js +3 -1
  6. package/build/cjs/core/index.js.map +1 -1
  7. package/build/cjs/core/markdown/MarkdownParser.d.ts +1 -0
  8. package/build/cjs/core/markdown/MarkdownParser.js +3 -0
  9. package/build/cjs/core/markdown/MarkdownParser.js.map +1 -1
  10. package/build/cjs/core/types/parser.d.ts +1 -0
  11. package/build/cjs/core/types/parser.js.map +1 -1
  12. package/build/cjs/core/utils/parser.d.ts +3 -0
  13. package/build/cjs/core/utils/parser.js +12 -0
  14. package/build/cjs/core/utils/parser.js.map +1 -0
  15. package/build/cjs/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js +1 -0
  16. package/build/cjs/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js.map +1 -1
  17. package/build/cjs/extensions/behavior/Clipboard/clipboard.js +2 -13
  18. package/build/cjs/extensions/behavior/Clipboard/clipboard.js.map +1 -1
  19. package/build/cjs/extensions/behavior/Clipboard/selection-content.d.ts +1 -0
  20. package/build/cjs/extensions/behavior/Clipboard/selection-content.js +35 -0
  21. package/build/cjs/extensions/behavior/Clipboard/selection-content.js.map +1 -0
  22. package/build/cjs/extensions/behavior/Selection/commands.d.ts +2 -1
  23. package/build/cjs/extensions/behavior/Selection/commands.js +47 -1
  24. package/build/cjs/extensions/behavior/Selection/commands.js.map +1 -1
  25. package/build/cjs/extensions/behavior/Selection/selection.d.ts +15 -0
  26. package/build/cjs/extensions/behavior/Selection/selection.js +1 -0
  27. package/build/cjs/extensions/behavior/Selection/selection.js.map +1 -1
  28. package/build/cjs/extensions/behavior/SelectionContext/tooltip.js +3 -0
  29. package/build/cjs/extensions/behavior/SelectionContext/tooltip.js.map +1 -1
  30. package/build/cjs/extensions/markdown/Blockquote/BlockquoteSpecs/index.js +1 -0
  31. package/build/cjs/extensions/markdown/Blockquote/BlockquoteSpecs/index.js.map +1 -1
  32. package/build/cjs/extensions/markdown/Bold/index.js +1 -1
  33. package/build/cjs/extensions/markdown/Bold/index.js.map +1 -1
  34. package/build/cjs/extensions/markdown/Code/index.js +1 -1
  35. package/build/cjs/extensions/markdown/Code/index.js.map +1 -1
  36. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.d.ts +2 -2
  37. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js +79 -128
  38. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js.map +1 -1
  39. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.d.ts +14 -0
  40. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js +117 -0
  41. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js.map +1 -0
  42. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.d.ts +9 -0
  43. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js +22 -0
  44. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js.map +1 -0
  45. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.d.ts +2 -3
  46. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js +5 -93
  47. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js.map +1 -1
  48. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.d.ts +23 -0
  49. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js +88 -0
  50. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js.map +1 -0
  51. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLineNumbersPlugin.js +42 -22
  52. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLineNumbersPlugin.js.map +1 -1
  53. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/utils.js +20 -0
  54. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/utils.js.map +1 -1
  55. package/build/cjs/extensions/markdown/Deflist/DeflistSpecs/schema.js +2 -0
  56. package/build/cjs/extensions/markdown/Deflist/DeflistSpecs/schema.js.map +1 -1
  57. package/build/cjs/extensions/markdown/Italic/index.js +1 -1
  58. package/build/cjs/extensions/markdown/Italic/index.js.map +1 -1
  59. package/build/cjs/extensions/markdown/Mark/index.js +1 -1
  60. package/build/cjs/extensions/markdown/Mark/index.js.map +1 -1
  61. package/build/cjs/extensions/markdown/Strike/index.js +1 -1
  62. package/build/cjs/extensions/markdown/Strike/index.js.map +1 -1
  63. package/build/cjs/extensions/markdown/Table/TableSpecs/schema.js +1 -0
  64. package/build/cjs/extensions/markdown/Table/TableSpecs/schema.js.map +1 -1
  65. package/build/cjs/extensions/markdown/Underline/index.js +1 -1
  66. package/build/cjs/extensions/markdown/Underline/index.js.map +1 -1
  67. package/build/cjs/extensions/yfm/Monospace/index.js +1 -1
  68. package/build/cjs/extensions/yfm/Monospace/index.js.map +1 -1
  69. package/build/cjs/extensions/yfm/YfmCut/YfmCutSpecs/schema.js +2 -0
  70. package/build/cjs/extensions/yfm/YfmCut/YfmCutSpecs/schema.js.map +1 -1
  71. package/build/cjs/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js +2 -0
  72. package/build/cjs/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js.map +1 -1
  73. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.css +20 -0
  74. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.d.ts +9 -0
  75. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js +77 -0
  76. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js.map +1 -0
  77. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.d.ts +1 -2
  78. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js +5 -65
  79. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js.map +1 -1
  80. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +2 -0
  81. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/schema.js.map +1 -1
  82. package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js +3 -0
  83. package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js.map +1 -1
  84. package/build/cjs/plugins/BaseTooltip/index.d.ts +1 -0
  85. package/build/cjs/plugins/BaseTooltip/index.js +4 -3
  86. package/build/cjs/plugins/BaseTooltip/index.js.map +1 -1
  87. package/build/cjs/toolbar/ToolbarGroup.js +4 -3
  88. package/build/cjs/toolbar/ToolbarGroup.js.map +1 -1
  89. package/build/cjs/toolbar/types.d.ts +2 -0
  90. package/build/cjs/toolbar/types.js.map +1 -1
  91. package/build/cjs/utils/actions.d.ts +6 -0
  92. package/build/cjs/utils/actions.js +24 -0
  93. package/build/cjs/utils/actions.js.map +1 -1
  94. package/build/cjs/utils/marks.d.ts +6 -0
  95. package/build/cjs/utils/marks.js +31 -0
  96. package/build/cjs/utils/marks.js.map +1 -1
  97. package/build/cjs/utils/transaction.d.ts +1 -0
  98. package/build/cjs/utils/transaction.js +40 -0
  99. package/build/cjs/utils/transaction.js.map +1 -0
  100. package/build/cjs/version.js +1 -1
  101. package/build/cjs/version.js.map +1 -1
  102. package/build/esm/core/Editor.js +2 -0
  103. package/build/esm/core/Editor.js.map +1 -1
  104. package/build/esm/core/index.d.ts +1 -0
  105. package/build/esm/core/index.js +1 -0
  106. package/build/esm/core/index.js.map +1 -1
  107. package/build/esm/core/markdown/MarkdownParser.d.ts +1 -0
  108. package/build/esm/core/markdown/MarkdownParser.js +3 -0
  109. package/build/esm/core/markdown/MarkdownParser.js.map +1 -1
  110. package/build/esm/core/types/parser.d.ts +1 -0
  111. package/build/esm/core/types/parser.js.map +1 -1
  112. package/build/esm/core/utils/parser.d.ts +3 -0
  113. package/build/esm/core/utils/parser.js +8 -0
  114. package/build/esm/core/utils/parser.js.map +1 -0
  115. package/build/esm/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js +1 -0
  116. package/build/esm/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js.map +1 -1
  117. package/build/esm/extensions/behavior/Clipboard/clipboard.js +1 -12
  118. package/build/esm/extensions/behavior/Clipboard/clipboard.js.map +1 -1
  119. package/build/esm/extensions/behavior/Clipboard/selection-content.d.ts +1 -0
  120. package/build/esm/extensions/behavior/Clipboard/selection-content.js +32 -0
  121. package/build/esm/extensions/behavior/Clipboard/selection-content.js.map +1 -0
  122. package/build/esm/extensions/behavior/Selection/commands.d.ts +2 -1
  123. package/build/esm/extensions/behavior/Selection/commands.js +47 -2
  124. package/build/esm/extensions/behavior/Selection/commands.js.map +1 -1
  125. package/build/esm/extensions/behavior/Selection/selection.d.ts +15 -0
  126. package/build/esm/extensions/behavior/Selection/selection.js +2 -1
  127. package/build/esm/extensions/behavior/Selection/selection.js.map +1 -1
  128. package/build/esm/extensions/behavior/SelectionContext/tooltip.js +3 -0
  129. package/build/esm/extensions/behavior/SelectionContext/tooltip.js.map +1 -1
  130. package/build/esm/extensions/markdown/Blockquote/BlockquoteSpecs/index.js +1 -0
  131. package/build/esm/extensions/markdown/Blockquote/BlockquoteSpecs/index.js.map +1 -1
  132. package/build/esm/extensions/markdown/Bold/index.js +2 -2
  133. package/build/esm/extensions/markdown/Bold/index.js.map +1 -1
  134. package/build/esm/extensions/markdown/Code/index.js +2 -2
  135. package/build/esm/extensions/markdown/Code/index.js.map +1 -1
  136. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.d.ts +2 -2
  137. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js +79 -128
  138. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js.map +1 -1
  139. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.d.ts +14 -0
  140. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js +114 -0
  141. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js.map +1 -0
  142. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.d.ts +9 -0
  143. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js +19 -0
  144. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js.map +1 -0
  145. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.d.ts +2 -3
  146. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js +6 -94
  147. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js.map +1 -1
  148. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.d.ts +23 -0
  149. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js +83 -0
  150. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js.map +1 -0
  151. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLineNumbersPlugin.js +43 -23
  152. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLineNumbersPlugin.js.map +1 -1
  153. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/utils.js +20 -1
  154. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/utils.js.map +1 -1
  155. package/build/esm/extensions/markdown/Deflist/DeflistSpecs/schema.js +2 -0
  156. package/build/esm/extensions/markdown/Deflist/DeflistSpecs/schema.js.map +1 -1
  157. package/build/esm/extensions/markdown/Italic/index.js +2 -2
  158. package/build/esm/extensions/markdown/Italic/index.js.map +1 -1
  159. package/build/esm/extensions/markdown/Mark/index.js +2 -2
  160. package/build/esm/extensions/markdown/Mark/index.js.map +1 -1
  161. package/build/esm/extensions/markdown/Strike/index.js +2 -2
  162. package/build/esm/extensions/markdown/Strike/index.js.map +1 -1
  163. package/build/esm/extensions/markdown/Table/TableSpecs/schema.js +1 -0
  164. package/build/esm/extensions/markdown/Table/TableSpecs/schema.js.map +1 -1
  165. package/build/esm/extensions/markdown/Underline/index.js +2 -2
  166. package/build/esm/extensions/markdown/Underline/index.js.map +1 -1
  167. package/build/esm/extensions/yfm/Monospace/index.js +2 -2
  168. package/build/esm/extensions/yfm/Monospace/index.js.map +1 -1
  169. package/build/esm/extensions/yfm/YfmCut/YfmCutSpecs/schema.js +2 -0
  170. package/build/esm/extensions/yfm/YfmCut/YfmCutSpecs/schema.js.map +1 -1
  171. package/build/esm/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js +2 -0
  172. package/build/esm/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js.map +1 -1
  173. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.css +20 -0
  174. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.d.ts +9 -0
  175. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js +74 -0
  176. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js.map +1 -0
  177. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.d.ts +1 -2
  178. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js +4 -64
  179. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js.map +1 -1
  180. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +2 -0
  181. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/schema.js.map +1 -1
  182. package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js +3 -0
  183. package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js.map +1 -1
  184. package/build/esm/plugins/BaseTooltip/index.d.ts +1 -0
  185. package/build/esm/plugins/BaseTooltip/index.js +4 -3
  186. package/build/esm/plugins/BaseTooltip/index.js.map +1 -1
  187. package/build/esm/toolbar/ToolbarGroup.js +4 -3
  188. package/build/esm/toolbar/ToolbarGroup.js.map +1 -1
  189. package/build/esm/toolbar/types.d.ts +2 -0
  190. package/build/esm/toolbar/types.js.map +1 -1
  191. package/build/esm/utils/actions.d.ts +6 -0
  192. package/build/esm/utils/actions.js +24 -1
  193. package/build/esm/utils/actions.js.map +1 -1
  194. package/build/esm/utils/marks.d.ts +6 -0
  195. package/build/esm/utils/marks.js +30 -0
  196. package/build/esm/utils/marks.js.map +1 -1
  197. package/build/esm/utils/transaction.d.ts +1 -0
  198. package/build/esm/utils/transaction.js +36 -0
  199. package/build/esm/utils/transaction.js.map +1 -0
  200. package/build/esm/version.js +1 -1
  201. package/build/esm/version.js.map +1 -1
  202. package/build/styles.css +9 -5
  203. package/package.json +4 -3
  204. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.css +0 -16
  205. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.css +0 -16
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Code/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAC,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAGzC,OAAO,EAAC,sBAAsB,EAAC,kCAA+B;AAC9D,OAAO,EAAC,aAAa,EAAC,iCAA8B;AAEpD,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAC,6BAAoB;AAEhD,oBAAqB;AAErB,OAAO,EAAC,YAAY,EAAE,QAAQ,EAAC,6BAAoB;AACnD,MAAM,UAAU,GAAG,MAAM,CAAC;AAM1B,MAAM,CAAC,MAAM,IAAI,GAA+B,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IAC9D,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvB,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,sBAAsB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAEtF,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;QAChB,MAAM,EAAC,OAAO,EAAC,GAAG,IAAI,CAAC;QACvB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,aAAa,EAAE,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;SACxE,CAAC,CAAC,CAAC;IACR,CAAC;IAED,OAAO;QACH,sCAAsC;QACtC,mEAAmE;QACnE,kEAAkE;QAClE,8DAA8D;SAC7D,SAAS,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC,CAAC;IAErE,OAAO,CAAC,SAAS,CACb,GAAG,EAAE;IACD,6CAA6C;IAC7C,IAAI,MAAM,CAAC;QACP,KAAK,EAAE;YACH,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;gBACtC,MAAM,EACF,SAAS,EAAE,EAAC,OAAO,EAAC,EACpB,EAAE,EACF,MAAM,GACT,GAAG,IAAI,CAAC,KAAK,CAAC;gBACf,IACI,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC;oBACvC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,EAC1C,CAAC;oBACC,IAAI,CAAC,QAAQ,CACT,EAAE,CAAC,gBAAgB,CACf,IAAI,GAAG,CAAC,EACR,EAAE,GAAG,CAAC,EACN,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAC5D,CACJ,CAAC;oBAEF,OAAO,IAAI,CAAC;gBAChB,CAAC;gBACD,OAAO,KAAK,CAAC;YACjB,CAAC;SACJ;KACJ,CAAC,CACT,CAAC;AACN,CAAC,CAAC","sourcesContent":["import codemark from 'prosemirror-codemark';\nimport {toggleMark} from 'prosemirror-commands';\nimport {Plugin} from 'prosemirror-state';\n\nimport type {Action, ExtensionAuto} from '../../../core';\nimport {createToggleMarkAction} from '../../../utils/actions';\nimport {withLogAction} from '../../../utils/keymap';\n\nimport {CodeSpecs, codeType} from './CodeSpecs';\n\nimport './code.scss';\n\nexport {codeMarkName, codeType} from './CodeSpecs';\nconst codeAction = 'code';\n\nexport type CodeOptions = {\n codeKey?: string | null;\n};\n\nexport const Code: ExtensionAuto<CodeOptions> = (builder, opts) => {\n builder.use(CodeSpecs);\n builder.addAction(codeAction, ({schema}) => createToggleMarkAction(codeType(schema)));\n\n if (opts?.codeKey) {\n const {codeKey} = opts;\n builder.addKeymap(({schema}) => ({\n [codeKey]: withLogAction('code_inline', toggleMark(codeType(schema))),\n }));\n }\n\n builder\n // codemark adds inputRule for `code`,\n // adds fake cursor behaviour when crossing inline_code boundaries,\n // wrap current selected text to inline_code when '`' was pressed.\n // See demo: https://curvenote.github.io/prosemirror-codemark/\n .addPlugin(({schema}) => codemark({markType: codeType(schema)}));\n\n builder.addPlugin(\n () =>\n // apply codemark when typing text between ``\n new Plugin({\n props: {\n handleTextInput: (view, from, to, text) => {\n const {\n selection: {$anchor},\n tr,\n schema,\n } = view.state;\n if (\n $anchor.nodeBefore?.text?.endsWith('`') &&\n $anchor.nodeAfter?.text?.startsWith('`')\n ) {\n view.dispatch(\n tr.replaceRangeWith(\n from - 1,\n to + 1,\n view.state.schema.text(text, [codeType(schema).create()]),\n ),\n );\n\n return true;\n }\n return false;\n },\n },\n }),\n );\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [codeAction]: Action;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["extensions/markdown/Code/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAC,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAGzC,OAAO,EAAC,8BAA8B,EAAC,kCAA+B;AACtE,OAAO,EAAC,aAAa,EAAC,iCAA8B;AAEpD,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAC,6BAAoB;AAEhD,oBAAqB;AAErB,OAAO,EAAC,YAAY,EAAE,QAAQ,EAAC,6BAAoB;AACnD,MAAM,UAAU,GAAG,MAAM,CAAC;AAM1B,MAAM,CAAC,MAAM,IAAI,GAA+B,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;IAC9D,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvB,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,8BAA8B,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAE9F,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;QAChB,MAAM,EAAC,OAAO,EAAC,GAAG,IAAI,CAAC;QACvB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,aAAa,EAAE,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;SACxE,CAAC,CAAC,CAAC;IACR,CAAC;IAED,OAAO;QACH,sCAAsC;QACtC,mEAAmE;QACnE,kEAAkE;QAClE,8DAA8D;SAC7D,SAAS,CAAC,CAAC,EAAC,MAAM,EAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC,CAAC;IAErE,OAAO,CAAC,SAAS,CACb,GAAG,EAAE;IACD,6CAA6C;IAC7C,IAAI,MAAM,CAAC;QACP,KAAK,EAAE;YACH,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;gBACtC,MAAM,EACF,SAAS,EAAE,EAAC,OAAO,EAAC,EACpB,EAAE,EACF,MAAM,GACT,GAAG,IAAI,CAAC,KAAK,CAAC;gBACf,IACI,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC;oBACvC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,EAC1C,CAAC;oBACC,IAAI,CAAC,QAAQ,CACT,EAAE,CAAC,gBAAgB,CACf,IAAI,GAAG,CAAC,EACR,EAAE,GAAG,CAAC,EACN,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAC5D,CACJ,CAAC;oBAEF,OAAO,IAAI,CAAC;gBAChB,CAAC;gBACD,OAAO,KAAK,CAAC;YACjB,CAAC;SACJ;KACJ,CAAC,CACT,CAAC;AACN,CAAC,CAAC","sourcesContent":["import codemark from 'prosemirror-codemark';\nimport {toggleMark} from 'prosemirror-commands';\nimport {Plugin} from 'prosemirror-state';\n\nimport type {Action, ExtensionAuto} from '../../../core';\nimport {createMarkdownInlineMarkAction} from '../../../utils/actions';\nimport {withLogAction} from '../../../utils/keymap';\n\nimport {CodeSpecs, codeType} from './CodeSpecs';\n\nimport './code.scss';\n\nexport {codeMarkName, codeType} from './CodeSpecs';\nconst codeAction = 'code';\n\nexport type CodeOptions = {\n codeKey?: string | null;\n};\n\nexport const Code: ExtensionAuto<CodeOptions> = (builder, opts) => {\n builder.use(CodeSpecs);\n builder.addAction(codeAction, ({schema}) => createMarkdownInlineMarkAction(codeType(schema)));\n\n if (opts?.codeKey) {\n const {codeKey} = opts;\n builder.addKeymap(({schema}) => ({\n [codeKey]: withLogAction('code_inline', toggleMark(codeType(schema))),\n }));\n }\n\n builder\n // codemark adds inputRule for `code`,\n // adds fake cursor behaviour when crossing inline_code boundaries,\n // wrap current selected text to inline_code when '`' was pressed.\n // See demo: https://curvenote.github.io/prosemirror-codemark/\n .addPlugin(({schema}) => codemark({markType: codeType(schema)}));\n\n builder.addPlugin(\n () =>\n // apply codemark when typing text between ``\n new Plugin({\n props: {\n handleTextInput: (view, from, to, text) => {\n const {\n selection: {$anchor},\n tr,\n schema,\n } = view.state;\n if (\n $anchor.nodeBefore?.text?.endsWith('`') &&\n $anchor.nodeAfter?.text?.startsWith('`')\n ) {\n view.dispatch(\n tr.replaceRangeWith(\n from - 1,\n to + 1,\n view.state.schema.text(text, [codeType(schema).create()]),\n ),\n );\n\n return true;\n }\n return false;\n },\n },\n }),\n );\n};\n\ndeclare global {\n namespace WysiwygEditor {\n interface Actions {\n [codeAction]: Action;\n }\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
- import type { Options } from '@diplodoc/transform';
2
1
  import type { ExtensionAuto } from "../../../../core/index.js";
3
2
  import { type LineNumbersOptions } from "../CodeBlockSpecs/index.js";
3
+ import { type HighlightLangMap } from "./plugins/codeBlockLangsPlugin.js";
4
4
  import "./CodeBlockHighlight.css";
5
- export type HighlightLangMap = Options['highlightLangs'];
5
+ export type { HighlightLangMap };
6
6
  export type CodeBlockHighlightOptions = {
7
7
  lineWrapping?: {
8
8
  enabled?: boolean;
@@ -2,122 +2,76 @@ import { Plugin, PluginKey } from 'prosemirror-state';
2
2
  // @ts-ignore // TODO: fix cjs build
3
3
  import { findChildrenByType } from 'prosemirror-utils';
4
4
  import { Decoration, DecorationSet } from 'prosemirror-view';
5
- import { capitalize } from "../../../../lodash.js";
6
- import { globalLogger } from "../../../../logger.js";
7
5
  import { CodeBlockNodeAttr, codeBlockNodeName, codeBlockType, } from "../CodeBlockSpecs/index.js";
8
6
  import { CodeBlockNodeView } from "./CodeBlockNodeView.js";
9
7
  import { codeLangSelectTooltipViewCreator } from "./TooltipPlugin/index.js";
10
- import { PlainTextLang } from "./const.js";
8
+ import { codeBlockLangsPlugin, codeBlockLangsPluginKey, getCodeBlockLangsState, } from "./plugins/codeBlockLangsPlugin.js";
11
9
  import { codeBlockLineNumbersPlugin } from "./plugins/codeBlockLineNumbersPlugin.js";
12
10
  import { codeBlockLineWrappingPlugin } from "./plugins/codeBlockLineWrappingPlugin.js";
11
+ import { processChangedCodeBlocks } from "./utils.js";
13
12
  import "./CodeBlockHighlight.css";
14
- const key = new PluginKey('code_block_highlight');
13
+ const pluginKey = new PluginKey('code_block_highlight');
15
14
  export const CodeBlockHighlight = (builder, opts) => {
16
- let langs;
17
- let lowlight;
18
- let hljs;
19
- const loadModules = async () => {
20
- try {
21
- hljs = (await import('highlight.js/lib/core')).default;
22
- const low = await import('lowlight');
23
- const all = low.all;
24
- const create = low.createLowlight;
25
- langs = { ...all, ...opts.langs };
26
- lowlight = create(langs);
27
- return true;
28
- }
29
- catch (e) {
30
- globalLogger.info('Skip code_block highlighting');
31
- builder.logger.log('Skip code_block highlighting');
32
- return false;
33
- }
34
- };
35
15
  if (opts.lineWrapping?.enabled)
36
16
  builder.addPlugin(codeBlockLineWrappingPlugin);
37
17
  if (opts.lineNumbers?.enabled)
38
18
  builder.addPlugin(codeBlockLineNumbersPlugin);
19
+ builder.addPlugin(() => codeBlockLangsPlugin(opts.langs, builder.logger));
39
20
  builder.addPlugin(() => {
40
- let modulesLoaded = false;
41
- let view = null;
42
- // empty array by default, but is filled after loading modules
43
- const selectItems = [];
44
- const mapping = {};
45
21
  // TODO: add TAB key handler
46
22
  // TODO: Remove constant selection of block
47
23
  return new Plugin({
48
- key,
24
+ key: pluginKey,
49
25
  state: {
50
- init: (_, state) => {
51
- loadModules().then((loaded) => {
52
- modulesLoaded = loaded;
53
- if (modulesLoaded) {
54
- for (const lang of Object.keys(langs)) {
55
- const defs = langs[lang](hljs);
56
- selectItems.push({
57
- value: lang,
58
- content: defs.name || capitalize(lang),
59
- });
60
- if (defs.aliases) {
61
- for (const alias of defs.aliases) {
62
- mapping[alias] = lang;
63
- }
64
- }
65
- }
66
- selectItems.sort(sortLangs);
67
- if (view && !view.isDestroyed) {
68
- view.dispatch(view.state.tr.setMeta(key, { modulesLoaded }));
69
- }
70
- }
71
- });
72
- return getDecorations(state.doc);
26
+ init: (_config, _state) => {
27
+ const cache = new WeakMap();
28
+ return { cache, decoSet: DecorationSet.empty };
73
29
  },
74
- apply: (tr, decos, oldState, newState) => {
75
- if (!modulesLoaded) {
76
- return DecorationSet.empty;
30
+ apply: (tr, { cache, decoSet }, _oldState, newState) => {
31
+ const langsUpdate = tr.getMeta(codeBlockLangsPluginKey);
32
+ if (langsUpdate?.loaded && langsUpdate.lowlight) {
33
+ return {
34
+ cache,
35
+ decoSet: getDecorations(tr.doc, cache, langsUpdate.lowlight),
36
+ };
77
37
  }
78
- if (tr.getMeta(key)?.modulesLoaded) {
79
- return getDecorations(tr.doc);
38
+ const { lowlight } = getCodeBlockLangsState(newState);
39
+ if (!lowlight) {
40
+ return { cache, decoSet: DecorationSet.empty };
80
41
  }
81
- if (tr.docChanged) {
82
- const oldNodeName = oldState.selection.$head.parent.type.name;
83
- const newNodeName = newState.selection.$head.parent.type.name;
84
- // Apply decorations if:
85
- if (oldNodeName === codeBlockNodeName ||
86
- newNodeName === codeBlockNodeName) {
87
- // selection includes codeblock node,
88
- return getDecorations(tr.doc);
42
+ if (!tr.docChanged)
43
+ return { cache, decoSet };
44
+ decoSet = processChangedCodeBlocks(tr, decoSet, (node, pos, decoSet) => {
45
+ const lang = node.attrs[CodeBlockNodeAttr.Lang];
46
+ if (!lang || !lowlight.registered(lang)) {
47
+ return decoSet.remove(decoSet.find(pos, pos + node.nodeSize));
89
48
  }
90
- else {
91
- const oldNodes = findChildrenByType(oldState.doc, codeBlockType(oldState.schema));
92
- const newNodes = findChildrenByType(newState.doc, codeBlockType(newState.schema));
93
- if (
94
- // OR transaction adds/removes codeblock nodes,
95
- newNodes.length !== oldNodes.length ||
96
- // OR transaction has changes that completely encapsulate a node
97
- // (for example, a transaction that affects the entire document).
98
- // Such transactions can happen during collab syncing via y-prosemirror, for example.
99
- tr.steps.some((step) => {
100
- return (stepHasFromTo(step) &&
101
- oldNodes.some((node) => node.pos >= step.from &&
102
- node.pos + node.node.nodeSize <= step.to));
103
- })) {
104
- return getDecorations(tr.doc);
49
+ const cached = cache.get(node);
50
+ if (cached) {
51
+ // node is in cache, but decorations may be missing (for example, after undo)
52
+ if (!decoSet.find(pos, pos + node.nodeSize).length) {
53
+ return decoSet.add(tr.doc, renderTree(cached, pos + 1));
105
54
  }
55
+ return decoSet;
106
56
  }
107
- }
108
- return decos.map(tr.mapping, tr.doc);
57
+ decoSet = decoSet.remove(decoSet.find(pos, pos + node.nodeSize));
58
+ const ast = lowlight.highlight(lang, node.textContent);
59
+ const parsed = parseNodes(ast.children);
60
+ cache.set(node, parsed);
61
+ return decoSet.add(tr.doc, renderTree(parsed, pos + 1));
62
+ });
63
+ return { cache, decoSet };
109
64
  },
110
65
  },
111
- view: (v) => {
112
- view = v;
113
- return codeLangSelectTooltipViewCreator(view, selectItems, mapping, {
66
+ view: (view) => {
67
+ return codeLangSelectTooltipViewCreator(view, {
114
68
  showCodeWrapping: Boolean(opts.lineWrapping?.enabled),
115
69
  showLineNumbers: Boolean(opts.lineNumbers?.enabled),
116
70
  });
117
71
  },
118
72
  props: {
119
- decorations: (state) => {
120
- return key.getState(state);
73
+ decorations(state) {
74
+ return pluginKey.getState(state)?.decoSet;
121
75
  },
122
76
  nodeViews: {
123
77
  [codeBlockNodeName]: CodeBlockNodeView.withOpts(opts),
@@ -125,59 +79,56 @@ export const CodeBlockHighlight = (builder, opts) => {
125
79
  },
126
80
  });
127
81
  });
128
- function getDecorations(doc) {
82
+ function getDecorations(doc, cache, lowlight) {
129
83
  const decos = [];
130
- if (!lowlight) {
131
- return DecorationSet.empty;
132
- }
133
84
  for (const { node, pos } of findChildrenByType(doc, codeBlockType(doc.type.schema), true)) {
134
- let from = pos + 1;
135
- let nodes;
136
85
  const lang = node.attrs[CodeBlockNodeAttr.Lang];
137
- if (lang && lowlight.registered(lang)) {
138
- nodes = lowlight.highlight(lang, node.textContent).children;
139
- }
140
- else {
86
+ if (!lang || !lowlight.registered(lang)) {
141
87
  continue;
142
88
  }
143
- for (const { text, classes } of parseNodes(nodes)) {
144
- const to = from + text.length;
145
- if (classes.length) {
146
- decos.push(Decoration.inline(from, to, {
147
- class: classes.join(' '),
148
- }));
149
- }
150
- from = to;
89
+ // Try to get parsed result from cache using node as key
90
+ let parsedNodes = cache.get(node);
91
+ if (!parsedNodes) {
92
+ // Compute, parse and cache using the node itself as key
93
+ const nodes = lowlight.highlight(lang, node.textContent).children;
94
+ parsedNodes = parseNodes(nodes);
95
+ cache.set(node, parsedNodes);
151
96
  }
97
+ decos.push(...renderTree(parsedNodes, pos + 1));
152
98
  }
153
99
  return DecorationSet.create(doc, decos);
154
100
  }
155
101
  };
156
- function parseNodes(nodes, className = []) {
157
- return nodes
158
- .map((node) => {
159
- let classes = className;
160
- if (node.type === 'element') {
161
- classes = classes.concat(node.properties.className ?? []);
162
- return parseNodes(node.children, classes);
102
+ function renderTree(parsedNodes, from) {
103
+ const decos = [];
104
+ for (const { text, classes } of parsedNodes) {
105
+ const to = from + text.length;
106
+ if (classes.length) {
107
+ decos.push(Decoration.inline(from, to, {
108
+ class: classes.join(' '),
109
+ }));
163
110
  }
164
- return {
165
- text: node.type === 'comment' || node.type === 'text' ? node.value : '',
166
- classes,
167
- };
168
- })
169
- .flat();
111
+ from = to;
112
+ }
113
+ return decos;
170
114
  }
171
- function stepHasFromTo(step) {
172
- // @ts-expect-error
173
- return typeof step.from === 'number' && typeof step.to === 'number';
115
+ function parseNodes(nodes, className = []) {
116
+ const result = [];
117
+ collectNodes(nodes, className, result);
118
+ return result;
174
119
  }
175
- function sortLangs(a, b) {
176
- // plaintext always goes first
177
- if (a.value === PlainTextLang)
178
- return -1;
179
- if (b.value === PlainTextLang)
180
- return 1;
181
- return 0;
120
+ function collectNodes(nodes, className, result) {
121
+ for (const node of nodes) {
122
+ if (node.type === 'element') {
123
+ const classes = className.concat(node.properties.className ?? []);
124
+ collectNodes(node.children, classes, result);
125
+ }
126
+ else {
127
+ result.push({
128
+ text: node.type === 'comment' || node.type === 'text' ? node.value : '',
129
+ classes: className,
130
+ });
131
+ }
132
+ }
182
133
  }
183
134
  //# sourceMappingURL=CodeBlockHighlight.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlockHighlight.js","sourceRoot":"../../../../../../src","sources":["extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Options} from '@diplodoc/transform';\n// importing only type, because lowlight and highlight.js is optional deps\nimport type HLJS from 'highlight.js/lib/core';\nimport type {createLowlight} from 'lowlight' with {'resolution-mode': 'import'};\nimport type {Node} from 'prosemirror-model';\nimport {Plugin, PluginKey} from 'prosemirror-state';\nimport type {Step} from 'prosemirror-transform';\n// @ts-ignore // TODO: fix cjs build\nimport {findChildrenByType} from 'prosemirror-utils';\nimport {Decoration, DecorationSet, type EditorView} from 'prosemirror-view';\n\nimport type {ExtensionAuto} from '../../../../core';\nimport {capitalize} from '../../../../lodash';\nimport {globalLogger} from '../../../../logger';\nimport {\n CodeBlockNodeAttr,\n type LineNumbersOptions,\n codeBlockNodeName,\n codeBlockType,\n} from '../CodeBlockSpecs';\n\nimport {CodeBlockNodeView} from './CodeBlockNodeView';\nimport {codeLangSelectTooltipViewCreator} from './TooltipPlugin';\nimport {PlainTextLang} from './const';\nimport {codeBlockLineNumbersPlugin} from './plugins/codeBlockLineNumbersPlugin';\nimport {codeBlockLineWrappingPlugin} from './plugins/codeBlockLineWrappingPlugin';\n\nimport './CodeBlockHighlight.scss';\n\nexport type HighlightLangMap = Options['highlightLangs'];\n\ntype Lowlight = ReturnType<typeof createLowlight>;\ntype Root = ReturnType<Lowlight['highlight']>;\n\ntype LangSelectItem = {\n value: string;\n content: string;\n};\n\nconst key = new PluginKey<DecorationSet>('code_block_highlight');\n\nexport type CodeBlockHighlightOptions = {\n lineWrapping?: {\n enabled?: boolean;\n };\n lineNumbers?: LineNumbersOptions;\n langs?: HighlightLangMap;\n};\n\nexport const CodeBlockHighlight: ExtensionAuto<CodeBlockHighlightOptions> = (builder, opts) => {\n let langs: NonNullable<HighlightLangMap>;\n let lowlight: Lowlight;\n let hljs: typeof HLJS;\n\n const loadModules = async () => {\n try {\n hljs = (await import('highlight.js/lib/core')).default;\n const low = await import('lowlight');\n\n const all: HighlightLangMap = low.all;\n const create: typeof createLowlight = low.createLowlight;\n langs = {...all, ...opts.langs};\n lowlight = create(langs);\n return true;\n } catch (e) {\n globalLogger.info('Skip code_block highlighting');\n builder.logger.log('Skip code_block highlighting');\n return false;\n }\n };\n\n if (opts.lineWrapping?.enabled) builder.addPlugin(codeBlockLineWrappingPlugin);\n if (opts.lineNumbers?.enabled) builder.addPlugin(codeBlockLineNumbersPlugin);\n\n builder.addPlugin(() => {\n let modulesLoaded = false;\n let view: EditorView | null = null;\n\n // empty array by default, but is filled after loading modules\n const selectItems: LangSelectItem[] = [];\n const mapping: Record<string, string> = {};\n\n // TODO: add TAB key handler\n // TODO: Remove constant selection of block\n return new Plugin<DecorationSet>({\n key,\n state: {\n init: (_, state) => {\n loadModules().then((loaded) => {\n modulesLoaded = loaded;\n\n if (modulesLoaded) {\n for (const lang of Object.keys(langs)) {\n const defs = langs[lang](hljs);\n selectItems.push({\n value: lang,\n content: defs.name || capitalize(lang),\n });\n if (defs.aliases) {\n for (const alias of defs.aliases) {\n mapping[alias] = lang;\n }\n }\n }\n\n selectItems.sort(sortLangs);\n\n if (view && !view.isDestroyed) {\n view.dispatch(view.state.tr.setMeta(key, {modulesLoaded}));\n }\n }\n });\n return getDecorations(state.doc);\n },\n apply: (tr, decos, oldState, newState) => {\n if (!modulesLoaded) {\n return DecorationSet.empty;\n }\n\n if (tr.getMeta(key)?.modulesLoaded) {\n return getDecorations(tr.doc);\n }\n\n if (tr.docChanged) {\n const oldNodeName = oldState.selection.$head.parent.type.name;\n const newNodeName = newState.selection.$head.parent.type.name;\n\n // Apply decorations if:\n if (\n oldNodeName === codeBlockNodeName ||\n newNodeName === codeBlockNodeName\n ) {\n // selection includes codeblock node,\n return getDecorations(tr.doc);\n } else {\n const oldNodes = findChildrenByType(\n oldState.doc,\n codeBlockType(oldState.schema),\n );\n const newNodes = findChildrenByType(\n newState.doc,\n codeBlockType(newState.schema),\n );\n if (\n // OR transaction adds/removes codeblock nodes,\n newNodes.length !== oldNodes.length ||\n // OR transaction has changes that completely encapsulate a node\n // (for example, a transaction that affects the entire document).\n // Such transactions can happen during collab syncing via y-prosemirror, for example.\n tr.steps.some((step) => {\n return (\n stepHasFromTo(step) &&\n oldNodes.some(\n (node: {node: Node; pos: number}) =>\n node.pos >= step.from &&\n node.pos + node.node.nodeSize <= step.to,\n )\n );\n })\n ) {\n return getDecorations(tr.doc);\n }\n }\n }\n return decos.map(tr.mapping, tr.doc);\n },\n },\n view: (v) => {\n view = v;\n return codeLangSelectTooltipViewCreator(view, selectItems, mapping, {\n showCodeWrapping: Boolean(opts.lineWrapping?.enabled),\n showLineNumbers: Boolean(opts.lineNumbers?.enabled),\n });\n },\n props: {\n decorations: (state) => {\n return key.getState(state);\n },\n nodeViews: {\n [codeBlockNodeName]: CodeBlockNodeView.withOpts(opts),\n },\n },\n });\n });\n\n function getDecorations(doc: Node) {\n const decos: Decoration[] = [];\n\n if (!lowlight) {\n return DecorationSet.empty;\n }\n\n for (const {node, pos} of findChildrenByType(doc, codeBlockType(doc.type.schema), true)) {\n let from = pos + 1;\n let nodes: Root['children'];\n\n const lang: string | undefined = node.attrs[CodeBlockNodeAttr.Lang];\n if (lang && lowlight.registered(lang)) {\n nodes = lowlight.highlight(lang, node.textContent).children;\n } else {\n continue;\n }\n\n for (const {text, classes} of parseNodes(nodes)) {\n const to = from + text.length;\n if (classes.length) {\n decos.push(\n Decoration.inline(from, to, {\n class: classes.join(' '),\n }),\n );\n }\n from = to;\n }\n }\n\n return DecorationSet.create(doc, decos);\n }\n};\n\nfunction parseNodes(\n nodes: Root['children'],\n className: readonly string[] = [],\n): {text: string; classes: readonly string[]}[] {\n return nodes\n .map((node) => {\n let classes = className;\n if (node.type === 'element') {\n classes = classes.concat((node.properties.className as string[]) ?? []);\n return parseNodes(node.children, classes);\n }\n\n return {\n text: node.type === 'comment' || node.type === 'text' ? node.value : '',\n classes,\n };\n })\n .flat();\n}\n\nfunction stepHasFromTo(step: Step): step is Step & {from: number; to: number} {\n // @ts-expect-error\n return typeof step.from === 'number' && typeof step.to === 'number';\n}\n\nfunction sortLangs(a: LangSelectItem, b: LangSelectItem): number {\n // plaintext always goes first\n if (a.value === PlainTextLang) return -1;\n if (b.value === PlainTextLang) return 1;\n return 0;\n}\n"]}
1
+ {"version":3,"file":"CodeBlockHighlight.js","sourceRoot":"../../../../../../src","sources":["extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.ts"],"names":[],"mappings":"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","sourcesContent":["import type {Node} from 'prosemirror-model';\nimport {Plugin, PluginKey} from 'prosemirror-state';\n// @ts-ignore // TODO: fix cjs build\nimport {findChildrenByType} from 'prosemirror-utils';\nimport {Decoration, DecorationSet} from 'prosemirror-view';\n\nimport type {ExtensionAuto} from '#core';\n\nimport {\n CodeBlockNodeAttr,\n type LineNumbersOptions,\n codeBlockNodeName,\n codeBlockType,\n} from '../CodeBlockSpecs';\n\nimport {CodeBlockNodeView} from './CodeBlockNodeView';\nimport {codeLangSelectTooltipViewCreator} from './TooltipPlugin';\nimport {\n type HighlightLangMap,\n type LLRoot,\n type Lowlight,\n codeBlockLangsPlugin,\n codeBlockLangsPluginKey,\n getCodeBlockLangsState,\n} from './plugins/codeBlockLangsPlugin';\nimport {codeBlockLineNumbersPlugin} from './plugins/codeBlockLineNumbersPlugin';\nimport {codeBlockLineWrappingPlugin} from './plugins/codeBlockLineWrappingPlugin';\nimport {processChangedCodeBlocks} from './utils';\n\nimport './CodeBlockHighlight.scss';\n\nexport type {HighlightLangMap};\n\nconst pluginKey = new PluginKey<PluginState>('code_block_highlight');\n\n// Cache for parsed highlight results, using ProseMirror nodes as keys\ntype HighlightCache = WeakMap<Node, HighlightParsedTree>;\n\ntype HighlightParsedTree = {text: string; classes: readonly string[]}[];\n\ntype PluginState = {\n cache: HighlightCache;\n decoSet: DecorationSet;\n};\n\nexport type CodeBlockHighlightOptions = {\n lineWrapping?: {\n enabled?: boolean;\n };\n lineNumbers?: LineNumbersOptions;\n langs?: HighlightLangMap;\n};\n\nexport const CodeBlockHighlight: ExtensionAuto<CodeBlockHighlightOptions> = (builder, opts) => {\n if (opts.lineWrapping?.enabled) builder.addPlugin(codeBlockLineWrappingPlugin);\n if (opts.lineNumbers?.enabled) builder.addPlugin(codeBlockLineNumbersPlugin);\n\n builder.addPlugin(() => codeBlockLangsPlugin(opts.langs, builder.logger));\n\n builder.addPlugin(() => {\n // TODO: add TAB key handler\n // TODO: Remove constant selection of block\n return new Plugin<PluginState>({\n key: pluginKey,\n state: {\n init: (_config, _state) => {\n const cache: HighlightCache = new WeakMap();\n return {cache, decoSet: DecorationSet.empty};\n },\n apply: (tr, {cache, decoSet}, _oldState, newState) => {\n const langsUpdate = tr.getMeta(codeBlockLangsPluginKey);\n if (langsUpdate?.loaded && langsUpdate.lowlight) {\n return {\n cache,\n decoSet: getDecorations(tr.doc, cache, langsUpdate.lowlight),\n };\n }\n\n const {lowlight} = getCodeBlockLangsState(newState);\n\n if (!lowlight) {\n return {cache, decoSet: DecorationSet.empty};\n }\n\n if (!tr.docChanged) return {cache, decoSet};\n\n decoSet = processChangedCodeBlocks(tr, decoSet, (node, pos, decoSet) => {\n const lang: string | undefined = node.attrs[CodeBlockNodeAttr.Lang];\n\n if (!lang || !lowlight.registered(lang)) {\n return decoSet.remove(decoSet.find(pos, pos + node.nodeSize));\n }\n\n const cached = cache.get(node);\n if (cached) {\n // node is in cache, but decorations may be missing (for example, after undo)\n if (!decoSet.find(pos, pos + node.nodeSize).length) {\n return decoSet.add(tr.doc, renderTree(cached, pos + 1));\n }\n return decoSet;\n }\n\n decoSet = decoSet.remove(decoSet.find(pos, pos + node.nodeSize));\n const ast = lowlight.highlight(lang, node.textContent);\n const parsed = parseNodes(ast.children);\n cache.set(node, parsed);\n return decoSet.add(tr.doc, renderTree(parsed, pos + 1));\n });\n\n return {cache, decoSet};\n },\n },\n view: (view) => {\n return codeLangSelectTooltipViewCreator(view, {\n showCodeWrapping: Boolean(opts.lineWrapping?.enabled),\n showLineNumbers: Boolean(opts.lineNumbers?.enabled),\n });\n },\n props: {\n decorations(state) {\n return pluginKey.getState(state)?.decoSet;\n },\n nodeViews: {\n [codeBlockNodeName]: CodeBlockNodeView.withOpts(opts),\n },\n },\n });\n });\n\n function getDecorations(doc: Node, cache: HighlightCache, lowlight: Lowlight) {\n const decos: Decoration[] = [];\n\n for (const {node, pos} of findChildrenByType(doc, codeBlockType(doc.type.schema), true)) {\n const lang: string | undefined = node.attrs[CodeBlockNodeAttr.Lang];\n if (!lang || !lowlight.registered(lang)) {\n continue;\n }\n\n // Try to get parsed result from cache using node as key\n let parsedNodes = cache.get(node);\n if (!parsedNodes) {\n // Compute, parse and cache using the node itself as key\n const nodes = lowlight.highlight(lang, node.textContent).children;\n parsedNodes = parseNodes(nodes);\n cache.set(node, parsedNodes);\n }\n\n decos.push(...renderTree(parsedNodes, pos + 1));\n }\n\n return DecorationSet.create(doc, decos);\n }\n};\n\nfunction renderTree(parsedNodes: HighlightParsedTree, from: number): Decoration[] {\n const decos: Decoration[] = [];\n\n for (const {text, classes} of parsedNodes) {\n const to = from + text.length;\n if (classes.length) {\n decos.push(\n Decoration.inline(from, to, {\n class: classes.join(' '),\n }),\n );\n }\n from = to;\n }\n\n return decos;\n}\n\nfunction parseNodes(\n nodes: LLRoot['children'],\n className: readonly string[] = [],\n): HighlightParsedTree {\n const result: HighlightParsedTree = [];\n collectNodes(nodes, className, result);\n return result;\n}\n\nfunction collectNodes(\n nodes: LLRoot['children'],\n className: readonly string[],\n result: HighlightParsedTree,\n): void {\n for (const node of nodes) {\n if (node.type === 'element') {\n const classes = className.concat((node.properties.className as string[]) ?? []);\n collectNodes(node.children, classes, result);\n } else {\n result.push({\n text: node.type === 'comment' || node.type === 'text' ? node.value : '',\n classes: className,\n });\n }\n }\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import { type SelectOption } from '@gravity-ui/uikit';
2
+ import type { Node } from "../../../../../pm/model.js";
3
+ import type { EditorView } from "../../../../../pm/view.js";
4
+ export type CodeBlockToolbarProps = {
5
+ node: Node;
6
+ pos: number;
7
+ editorView: EditorView;
8
+ langItems: SelectOption[];
9
+ mapping: Record<string, string>;
10
+ showCodeWrapping: boolean;
11
+ showLineNumbers: boolean;
12
+ rerenderTooltip?: () => void;
13
+ };
14
+ export declare function CodeBlockToolbar({ node, pos, editorView, langItems, mapping, showCodeWrapping, showLineNumbers, rerenderTooltip, }: CodeBlockToolbarProps): JSX.Element;
@@ -0,0 +1,114 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useMemo } from 'react';
3
+ import { ListOl as LineNumbersIcon, TrashBin as RemoveIcon, ArrowUturnCwLeft as WrappingIcon, } from '@gravity-ui/icons';
4
+ import { ClipboardButton } from '@gravity-ui/uikit';
5
+ import { useLatest } from 'react-use';
6
+ import { cn } from "../../../../../classname.js";
7
+ import { i18n } from "../../../../../i18n/codeblock/index.js";
8
+ import { typedMemo } from "../../../../../react-utils/memo.js";
9
+ import { Toolbar, ToolbarDataType } from "../../../../../toolbar/index.js";
10
+ import { ToolbarWrapToContext } from "../../../../../toolbar/ToolbarRerender.js";
11
+ import { removeNode } from "../../../../../utils/remove-node.js";
12
+ import { isTruthy } from "../../../../../utils/truthy.js";
13
+ import { CodeBlockNodeAttr } from "../../CodeBlockSpecs/index.js";
14
+ import { isNodeHasLineWrapping } from "../plugins/codeBlockLineWrappingPlugin.js";
15
+ import { CodeLangSelect } from "./CodeLangSelect.js";
16
+ import { isLineNumbersVisible, toggleLineNumbers, toggleLineWrapping } from "./utils.js";
17
+ const bToolbar = cn('code-block-toolbar');
18
+ const ToolbarMemoized = typedMemo(Toolbar);
19
+ export function CodeBlockToolbar({ node, pos, editorView, langItems, mapping, showCodeWrapping, showLineNumbers, rerenderTooltip, }) {
20
+ const posRef = useLatest(pos);
21
+ const nodeRef = useLatest(node);
22
+ const onFocus = useCallback(() => {
23
+ editorView.focus();
24
+ }, [editorView]);
25
+ const toolbarData = useMemo(() => {
26
+ const copyText = () => nodeRef.current.textContent;
27
+ const focus = () => editorView.focus();
28
+ const onLangChange = (value) => {
29
+ editorView.dispatch(editorView.state.tr.setNodeAttribute(posRef.current, CodeBlockNodeAttr.Lang, value));
30
+ };
31
+ return [
32
+ [
33
+ langItems.length > 0 &&
34
+ {
35
+ id: 'code-block-type',
36
+ type: ToolbarDataType.ReactComponent,
37
+ component: () => (_jsx(CodeLangSelect, { focus: focus, onChange: onLangChange, lang: nodeRef.current.attrs[CodeBlockNodeAttr.Lang], selectItems: langItems, mapping: mapping })),
38
+ width: 28,
39
+ },
40
+ showCodeWrapping &&
41
+ {
42
+ id: 'code-block-wrapping',
43
+ icon: { data: WrappingIcon },
44
+ title: i18n('code_wrapping'),
45
+ type: ToolbarDataType.SingleButton,
46
+ isActive: (view) => isNodeHasLineWrapping(view.state, posRef.current),
47
+ isEnable: () => true,
48
+ exec: (view) => {
49
+ toggleLineWrapping({
50
+ pos: posRef.current,
51
+ node: nodeRef.current,
52
+ state: view.state,
53
+ dispatch: view.dispatch,
54
+ });
55
+ // forcing rerender because editor's toolbar isn't updated when the decorations change
56
+ rerenderTooltip?.();
57
+ },
58
+ },
59
+ showLineNumbers &&
60
+ {
61
+ id: 'code-block-linenumbers',
62
+ icon: { data: LineNumbersIcon },
63
+ title: i18n('show_line_numbers'),
64
+ type: ToolbarDataType.SingleButton,
65
+ isActive: () => isLineNumbersVisible(nodeRef.current),
66
+ isEnable: () => true,
67
+ exec: (view) => {
68
+ toggleLineNumbers({
69
+ pos: posRef.current,
70
+ node: nodeRef.current,
71
+ state: view.state,
72
+ dispatch: view.dispatch,
73
+ });
74
+ },
75
+ },
76
+ {
77
+ id: 'code-block-copy',
78
+ type: ToolbarDataType.ReactNodeFn,
79
+ width: 28,
80
+ content: () => _jsx(ClipboardButton, { text: copyText }),
81
+ noRerenderOnUpdate: true,
82
+ },
83
+ ].filter(isTruthy),
84
+ [
85
+ {
86
+ id: 'code-block-remove',
87
+ icon: { data: RemoveIcon },
88
+ title: i18n('remove'),
89
+ theme: 'danger',
90
+ type: ToolbarDataType.SingleButton,
91
+ isActive: () => false,
92
+ isEnable: () => true,
93
+ exec: (view) => removeNode({
94
+ pos: posRef.current,
95
+ node: nodeRef.current,
96
+ tr: view.state.tr,
97
+ dispatch: view.dispatch,
98
+ }),
99
+ },
100
+ ],
101
+ ];
102
+ }, [
103
+ editorView,
104
+ langItems,
105
+ mapping,
106
+ nodeRef,
107
+ posRef,
108
+ rerenderTooltip,
109
+ showCodeWrapping,
110
+ showLineNumbers,
111
+ ]);
112
+ return (_jsx(ToolbarWrapToContext, { editor: editorView, children: _jsx(ToolbarMemoized, { editor: editorView, focus: onFocus, className: bToolbar(), data: toolbarData }) }));
113
+ }
114
+ //# sourceMappingURL=CodeBlockToolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlockToolbar.js","sourceRoot":"../../../../../../../src","sources":["extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useCallback, useMemo} from 'react';\n\nimport {\n ListOl as LineNumbersIcon,\n TrashBin as RemoveIcon,\n ArrowUturnCwLeft as WrappingIcon,\n} from '@gravity-ui/icons';\nimport {ClipboardButton, type SelectOption} from '@gravity-ui/uikit';\nimport {useLatest} from 'react-use';\n\nimport type {Node} from '#pm/model';\nimport type {EditorView} from '#pm/view';\nimport {cn} from 'src/classname';\nimport {i18n} from 'src/i18n/codeblock';\nimport {typedMemo} from 'src/react-utils/memo';\nimport {Toolbar, type ToolbarData, ToolbarDataType, type ToolbarGroupItemData} from 'src/toolbar';\nimport {ToolbarWrapToContext} from 'src/toolbar/ToolbarRerender';\nimport {removeNode} from 'src/utils/remove-node';\nimport {isTruthy} from 'src/utils/truthy';\n\nimport {CodeBlockNodeAttr} from '../../CodeBlockSpecs';\nimport {isNodeHasLineWrapping} from '../plugins/codeBlockLineWrappingPlugin';\n\nimport {CodeLangSelect} from './CodeLangSelect';\nimport {isLineNumbersVisible, toggleLineNumbers, toggleLineWrapping} from './utils';\n\nconst bToolbar = cn('code-block-toolbar');\nconst ToolbarMemoized = typedMemo(Toolbar);\n\nexport type CodeBlockToolbarProps = {\n node: Node;\n pos: number;\n editorView: EditorView;\n langItems: SelectOption[];\n mapping: Record<string, string>;\n showCodeWrapping: boolean;\n showLineNumbers: boolean;\n rerenderTooltip?: () => void;\n};\n\nexport function CodeBlockToolbar({\n node,\n pos,\n editorView,\n langItems,\n mapping,\n showCodeWrapping,\n showLineNumbers,\n rerenderTooltip,\n}: CodeBlockToolbarProps) {\n const posRef = useLatest(pos);\n const nodeRef = useLatest(node);\n\n const onFocus = useCallback(() => {\n editorView.focus();\n }, [editorView]);\n\n const toolbarData = useMemo<ToolbarData<EditorView>>(() => {\n const copyText = () => nodeRef.current.textContent;\n const focus = () => editorView.focus();\n const onLangChange = (value: string) => {\n editorView.dispatch(\n editorView.state.tr.setNodeAttribute(posRef.current, CodeBlockNodeAttr.Lang, value),\n );\n };\n\n return [\n [\n langItems.length > 0 &&\n ({\n id: 'code-block-type',\n type: ToolbarDataType.ReactComponent,\n component: () => (\n <CodeLangSelect\n focus={focus}\n onChange={onLangChange}\n lang={nodeRef.current.attrs[CodeBlockNodeAttr.Lang]}\n selectItems={langItems}\n mapping={mapping}\n />\n ),\n width: 28,\n } satisfies ToolbarGroupItemData<EditorView>),\n showCodeWrapping &&\n ({\n id: 'code-block-wrapping',\n icon: {data: WrappingIcon},\n title: i18n('code_wrapping'),\n type: ToolbarDataType.SingleButton,\n isActive: (view) => isNodeHasLineWrapping(view.state, posRef.current),\n isEnable: () => true,\n exec: (view) => {\n toggleLineWrapping({\n pos: posRef.current,\n node: nodeRef.current,\n state: view.state,\n dispatch: view.dispatch,\n });\n // forcing rerender because editor's toolbar isn't updated when the decorations change\n rerenderTooltip?.();\n },\n } satisfies ToolbarGroupItemData<EditorView>),\n showLineNumbers &&\n ({\n id: 'code-block-linenumbers',\n icon: {data: LineNumbersIcon},\n title: i18n('show_line_numbers'),\n type: ToolbarDataType.SingleButton,\n isActive: () => isLineNumbersVisible(nodeRef.current),\n isEnable: () => true,\n exec: (view) => {\n toggleLineNumbers({\n pos: posRef.current,\n node: nodeRef.current,\n state: view.state,\n dispatch: view.dispatch,\n });\n },\n } satisfies ToolbarGroupItemData<EditorView>),\n {\n id: 'code-block-copy',\n type: ToolbarDataType.ReactNodeFn,\n width: 28,\n content: () => <ClipboardButton text={copyText} />,\n noRerenderOnUpdate: true,\n } satisfies ToolbarGroupItemData<EditorView>,\n ].filter(isTruthy),\n [\n {\n id: 'code-block-remove',\n icon: {data: RemoveIcon},\n title: i18n('remove'),\n theme: 'danger',\n type: ToolbarDataType.SingleButton,\n isActive: () => false,\n isEnable: () => true,\n exec: (view) =>\n removeNode({\n pos: posRef.current,\n node: nodeRef.current,\n tr: view.state.tr,\n dispatch: view.dispatch,\n }),\n },\n ],\n ];\n }, [\n editorView,\n langItems,\n mapping,\n nodeRef,\n posRef,\n rerenderTooltip,\n showCodeWrapping,\n showLineNumbers,\n ]);\n\n return (\n <ToolbarWrapToContext editor={editorView}>\n <ToolbarMemoized\n editor={editorView}\n focus={onFocus}\n className={bToolbar()}\n data={toolbarData}\n />\n </ToolbarWrapToContext>\n );\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { type SelectOption } from '@gravity-ui/uikit';
2
+ export type CodeLangSelectProps = {
3
+ lang: string;
4
+ selectItems: SelectOption[];
5
+ mapping: Record<string, string>;
6
+ focus: () => void;
7
+ onChange: (value: string) => void;
8
+ };
9
+ export declare const CodeLangSelect: React.FC<CodeLangSelectProps>;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { memo } from 'react';
3
+ import { Select } from '@gravity-ui/uikit';
4
+ import { cn } from "../../../../../classname.js";
5
+ import { i18n } from "../../../../../i18n/codeblock/index.js";
6
+ import { i18n as i18nPlaceholder } from "../../../../../i18n/placeholder/index.js";
7
+ import { PlainTextLang } from "../const.js";
8
+ const bCodeBlock = cn('code-block');
9
+ export const CodeLangSelect = memo(function CodeLangSelect({ lang, focus, onChange, selectItems, mapping }) {
10
+ const value = mapping[lang] || lang || PlainTextLang;
11
+ const handleClick = (type) => {
12
+ focus();
13
+ if (type === value)
14
+ return;
15
+ onChange(type);
16
+ };
17
+ return (_jsx(Select, { size: "m", width: "max", disablePortal: true, value: [value], onUpdate: (v) => handleClick(v[0]), options: selectItems, filterable: true, filterPlaceholder: i18nPlaceholder('select_filter'), popupClassName: bCodeBlock('select-popup'), className: bCodeBlock('select-button'), renderEmptyOptions: () => (_jsx("div", { className: bCodeBlock('select-empty'), children: i18n('empty_option') })) }));
18
+ });
19
+ //# sourceMappingURL=CodeLangSelect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeLangSelect.js","sourceRoot":"../../../../../../../src","sources":["extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,OAAO,CAAC;AAE3B,OAAO,EAAC,MAAM,EAAoB,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAC,EAAE,EAAC,oCAAsB;AACjC,OAAO,EAAC,IAAI,EAAC,+CAA2B;AACxC,OAAO,EAAC,IAAI,IAAI,eAAe,EAAC,iDAA6B;AAE7D,OAAO,EAAC,aAAa,EAAC,oBAAiB;AAEvC,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC;AAUpC,MAAM,CAAC,MAAM,cAAc,GAAkC,IAAI,CAC7D,SAAS,cAAc,CAAC,EAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAC;IACjE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,aAAa,CAAC;IAErD,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAE;QACjC,KAAK,EAAE,CAAC;QACR,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO;QAC3B,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO,CACH,KAAC,MAAM,IACH,IAAI,EAAC,GAAG,EACR,KAAK,EAAC,KAAK,EACX,aAAa,QACb,KAAK,EAAE,CAAC,KAAK,CAAC,EACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAClC,OAAO,EAAE,WAAW,EACpB,UAAU,QACV,iBAAiB,EAAE,eAAe,CAAC,eAAe,CAAC,EACnD,cAAc,EAAE,UAAU,CAAC,cAAc,CAAC,EAC1C,SAAS,EAAE,UAAU,CAAC,eAAe,CAAC,EACtC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CACtB,cAAK,SAAS,EAAE,UAAU,CAAC,cAAc,CAAC,YAAG,IAAI,CAAC,cAAc,CAAC,GAAO,CAC3E,GAGH,CACL,CAAC;AACN,CAAC,CACJ,CAAC","sourcesContent":["import {memo} from 'react';\n\nimport {Select, type SelectOption} from '@gravity-ui/uikit';\n\nimport {cn} from 'src/classname';\nimport {i18n} from 'src/i18n/codeblock';\nimport {i18n as i18nPlaceholder} from 'src/i18n/placeholder';\n\nimport {PlainTextLang} from '../const';\n\nconst bCodeBlock = cn('code-block');\n\nexport type CodeLangSelectProps = {\n lang: string;\n selectItems: SelectOption[];\n mapping: Record<string, string>;\n focus: () => void;\n onChange: (value: string) => void;\n};\n\nexport const CodeLangSelect: React.FC<CodeLangSelectProps> = memo<CodeLangSelectProps>(\n function CodeLangSelect({lang, focus, onChange, selectItems, mapping}) {\n const value = mapping[lang] || lang || PlainTextLang;\n\n const handleClick = (type: string) => {\n focus();\n if (type === value) return;\n onChange(type);\n };\n\n return (\n <Select\n size=\"m\"\n width=\"max\"\n disablePortal\n value={[value]}\n onUpdate={(v) => handleClick(v[0])}\n options={selectItems}\n filterable\n filterPlaceholder={i18nPlaceholder('select_filter')}\n popupClassName={bCodeBlock('select-popup')}\n className={bCodeBlock('select-button')}\n renderEmptyOptions={() => (\n <div className={bCodeBlock('select-empty')}>{i18n('empty_option')}</div>\n )}\n // TODO: in onOpenChange return focus to view.dom after press Esc in Select\n // after https://github.com/gravity-ui/uikit/issues/2075\n />\n );\n },\n);\n"]}
@@ -1,10 +1,9 @@
1
- import { type SelectOption } from '@gravity-ui/uikit';
2
- import type { EditorView } from 'prosemirror-view';
1
+ import type { EditorView } from "../../../../../pm/view.js";
3
2
  import { BaseTooltipPluginView } from "../../../../../plugins/BaseTooltip/index.js";
4
3
  import "./TooltipView.css";
5
4
  type Options = {
6
5
  showCodeWrapping: boolean;
7
6
  showLineNumbers: boolean;
8
7
  };
9
- export declare const codeLangSelectTooltipViewCreator: (view: EditorView, langItems: SelectOption[], mapping: Record<string, string> | undefined, { showCodeWrapping, showLineNumbers }: Options) => BaseTooltipPluginView;
8
+ export declare const codeLangSelectTooltipViewCreator: (view: EditorView, { showCodeWrapping, showLineNumbers }: Options) => BaseTooltipPluginView;
10
9
  export {};