@gravity-ui/markdown-editor 15.36.0 → 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 (121) hide show
  1. package/README.md +87 -0
  2. package/build/cjs/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js +1 -0
  3. package/build/cjs/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js.map +1 -1
  4. package/build/cjs/extensions/behavior/Clipboard/clipboard.js +2 -13
  5. package/build/cjs/extensions/behavior/Clipboard/clipboard.js.map +1 -1
  6. package/build/cjs/extensions/behavior/Clipboard/selection-content.d.ts +1 -0
  7. package/build/cjs/extensions/behavior/Clipboard/selection-content.js +35 -0
  8. package/build/cjs/extensions/behavior/Clipboard/selection-content.js.map +1 -0
  9. package/build/cjs/extensions/behavior/Selection/commands.d.ts +2 -1
  10. package/build/cjs/extensions/behavior/Selection/commands.js +47 -1
  11. package/build/cjs/extensions/behavior/Selection/commands.js.map +1 -1
  12. package/build/cjs/extensions/behavior/Selection/selection.d.ts +15 -0
  13. package/build/cjs/extensions/behavior/Selection/selection.js +1 -0
  14. package/build/cjs/extensions/behavior/Selection/selection.js.map +1 -1
  15. package/build/cjs/extensions/markdown/Blockquote/BlockquoteSpecs/index.js +1 -0
  16. package/build/cjs/extensions/markdown/Blockquote/BlockquoteSpecs/index.js.map +1 -1
  17. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.d.ts +2 -2
  18. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js +17 -75
  19. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js.map +1 -1
  20. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.d.ts +14 -0
  21. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js +117 -0
  22. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js.map +1 -0
  23. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.d.ts +9 -0
  24. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js +22 -0
  25. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js.map +1 -0
  26. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.d.ts +2 -3
  27. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js +5 -93
  28. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js.map +1 -1
  29. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.d.ts +23 -0
  30. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js +88 -0
  31. package/build/cjs/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js.map +1 -0
  32. package/build/cjs/extensions/markdown/Deflist/DeflistSpecs/schema.js +2 -0
  33. package/build/cjs/extensions/markdown/Deflist/DeflistSpecs/schema.js.map +1 -1
  34. package/build/cjs/extensions/markdown/Table/TableSpecs/schema.js +1 -0
  35. package/build/cjs/extensions/markdown/Table/TableSpecs/schema.js.map +1 -1
  36. package/build/cjs/extensions/yfm/YfmCut/YfmCutSpecs/schema.js +2 -0
  37. package/build/cjs/extensions/yfm/YfmCut/YfmCutSpecs/schema.js.map +1 -1
  38. package/build/cjs/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js +2 -0
  39. package/build/cjs/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js.map +1 -1
  40. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.css +20 -0
  41. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.d.ts +9 -0
  42. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js +77 -0
  43. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js.map +1 -0
  44. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.d.ts +1 -2
  45. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js +5 -65
  46. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js.map +1 -1
  47. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +2 -0
  48. package/build/cjs/extensions/yfm/YfmTable/YfmTableSpecs/schema.js.map +1 -1
  49. package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js +3 -0
  50. package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js.map +1 -1
  51. package/build/cjs/plugins/BaseTooltip/index.d.ts +1 -0
  52. package/build/cjs/plugins/BaseTooltip/index.js +4 -3
  53. package/build/cjs/plugins/BaseTooltip/index.js.map +1 -1
  54. package/build/cjs/toolbar/ToolbarGroup.js +4 -3
  55. package/build/cjs/toolbar/ToolbarGroup.js.map +1 -1
  56. package/build/cjs/toolbar/types.d.ts +2 -0
  57. package/build/cjs/toolbar/types.js.map +1 -1
  58. package/build/cjs/version.js +1 -1
  59. package/build/cjs/version.js.map +1 -1
  60. package/build/esm/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js +1 -0
  61. package/build/esm/extensions/additional/QuoteLink/QuoteLinkSpecs/index.js.map +1 -1
  62. package/build/esm/extensions/behavior/Clipboard/clipboard.js +1 -12
  63. package/build/esm/extensions/behavior/Clipboard/clipboard.js.map +1 -1
  64. package/build/esm/extensions/behavior/Clipboard/selection-content.d.ts +1 -0
  65. package/build/esm/extensions/behavior/Clipboard/selection-content.js +32 -0
  66. package/build/esm/extensions/behavior/Clipboard/selection-content.js.map +1 -0
  67. package/build/esm/extensions/behavior/Selection/commands.d.ts +2 -1
  68. package/build/esm/extensions/behavior/Selection/commands.js +47 -2
  69. package/build/esm/extensions/behavior/Selection/commands.js.map +1 -1
  70. package/build/esm/extensions/behavior/Selection/selection.d.ts +15 -0
  71. package/build/esm/extensions/behavior/Selection/selection.js +2 -1
  72. package/build/esm/extensions/behavior/Selection/selection.js.map +1 -1
  73. package/build/esm/extensions/markdown/Blockquote/BlockquoteSpecs/index.js +1 -0
  74. package/build/esm/extensions/markdown/Blockquote/BlockquoteSpecs/index.js.map +1 -1
  75. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.d.ts +2 -2
  76. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js +17 -75
  77. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/CodeBlockHighlight.js.map +1 -1
  78. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.d.ts +14 -0
  79. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js +114 -0
  80. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeBlockToolbar.js.map +1 -0
  81. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.d.ts +9 -0
  82. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js +19 -0
  83. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/CodeLangSelect.js.map +1 -0
  84. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.d.ts +2 -3
  85. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js +6 -94
  86. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.js.map +1 -1
  87. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.d.ts +23 -0
  88. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js +83 -0
  89. package/build/esm/extensions/markdown/CodeBlock/CodeBlockHighlight/plugins/codeBlockLangsPlugin.js.map +1 -0
  90. package/build/esm/extensions/markdown/Deflist/DeflistSpecs/schema.js +2 -0
  91. package/build/esm/extensions/markdown/Deflist/DeflistSpecs/schema.js.map +1 -1
  92. package/build/esm/extensions/markdown/Table/TableSpecs/schema.js +1 -0
  93. package/build/esm/extensions/markdown/Table/TableSpecs/schema.js.map +1 -1
  94. package/build/esm/extensions/yfm/YfmCut/YfmCutSpecs/schema.js +2 -0
  95. package/build/esm/extensions/yfm/YfmCut/YfmCutSpecs/schema.js.map +1 -1
  96. package/build/esm/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js +2 -0
  97. package/build/esm/extensions/yfm/YfmNote/YfmNoteSpecs/schema.js.map +1 -1
  98. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.css +20 -0
  99. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.d.ts +9 -0
  100. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js +74 -0
  101. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/YfmNoteToolbar.js.map +1 -0
  102. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.d.ts +1 -2
  103. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js +4 -64
  104. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.js.map +1 -1
  105. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/schema.js +2 -0
  106. package/build/esm/extensions/yfm/YfmTable/YfmTableSpecs/schema.js.map +1 -1
  107. package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js +3 -0
  108. package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js.map +1 -1
  109. package/build/esm/plugins/BaseTooltip/index.d.ts +1 -0
  110. package/build/esm/plugins/BaseTooltip/index.js +4 -3
  111. package/build/esm/plugins/BaseTooltip/index.js.map +1 -1
  112. package/build/esm/toolbar/ToolbarGroup.js +4 -3
  113. package/build/esm/toolbar/ToolbarGroup.js.map +1 -1
  114. package/build/esm/toolbar/types.d.ts +2 -0
  115. package/build/esm/toolbar/types.js.map +1 -1
  116. package/build/esm/version.js +1 -1
  117. package/build/esm/version.js.map +1 -1
  118. package/build/styles.css +9 -5
  119. package/package.json +4 -3
  120. package/build/cjs/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.css +0 -16
  121. package/build/esm/extensions/yfm/YfmNote/plugins/YfmNoteTooltipPlugin/index.css +0 -16
@@ -5,88 +5,42 @@ const prosemirror_state_1 = require("prosemirror-state");
5
5
  // @ts-ignore // TODO: fix cjs build
6
6
  const prosemirror_utils_1 = require("prosemirror-utils");
7
7
  const prosemirror_view_1 = require("prosemirror-view");
8
- const lodash_1 = require("../../../../lodash.js");
9
- const logger_1 = require("../../../../logger.js");
10
8
  const CodeBlockSpecs_1 = require("../CodeBlockSpecs/index.js");
11
9
  const CodeBlockNodeView_1 = require("./CodeBlockNodeView.js");
12
10
  const TooltipPlugin_1 = require("./TooltipPlugin/index.js");
13
- const const_1 = require("./const.js");
11
+ const codeBlockLangsPlugin_1 = require("./plugins/codeBlockLangsPlugin.js");
14
12
  const codeBlockLineNumbersPlugin_1 = require("./plugins/codeBlockLineNumbersPlugin.js");
15
13
  const codeBlockLineWrappingPlugin_1 = require("./plugins/codeBlockLineWrappingPlugin.js");
16
14
  const utils_1 = require("./utils.js");
17
15
  require("./CodeBlockHighlight.css");
18
16
  const pluginKey = new prosemirror_state_1.PluginKey('code_block_highlight');
19
17
  const CodeBlockHighlight = (builder, opts) => {
20
- let langs;
21
- let lowlight;
22
- let hljs;
23
- const loadModules = async () => {
24
- try {
25
- hljs = (await import('highlight.js/lib/core')).default;
26
- const low = await import('lowlight');
27
- const all = low.all;
28
- const create = low.createLowlight;
29
- langs = { ...all, ...opts.langs };
30
- lowlight = create(langs);
31
- return true;
32
- }
33
- catch (e) {
34
- logger_1.globalLogger.info('Skip code_block highlighting');
35
- builder.logger.log('Skip code_block highlighting');
36
- return false;
37
- }
38
- };
39
18
  if (opts.lineWrapping?.enabled)
40
19
  builder.addPlugin(codeBlockLineWrappingPlugin_1.codeBlockLineWrappingPlugin);
41
20
  if (opts.lineNumbers?.enabled)
42
21
  builder.addPlugin(codeBlockLineNumbersPlugin_1.codeBlockLineNumbersPlugin);
22
+ builder.addPlugin(() => (0, codeBlockLangsPlugin_1.codeBlockLangsPlugin)(opts.langs, builder.logger));
43
23
  builder.addPlugin(() => {
44
- let modulesLoaded = false;
45
- let view = null;
46
- // empty array by default, but is filled after loading modules
47
- const selectItems = [];
48
- const mapping = {};
49
24
  // TODO: add TAB key handler
50
25
  // TODO: Remove constant selection of block
51
26
  return new prosemirror_state_1.Plugin({
52
27
  key: pluginKey,
53
28
  state: {
54
- init: (_, state) => {
55
- loadModules().then((loaded) => {
56
- modulesLoaded = loaded;
57
- if (modulesLoaded) {
58
- for (const lang of Object.keys(langs)) {
59
- const defs = langs[lang](hljs);
60
- selectItems.push({
61
- value: lang,
62
- content: defs.name || (0, lodash_1.capitalize)(lang),
63
- });
64
- if (defs.aliases) {
65
- for (const alias of defs.aliases) {
66
- mapping[alias] = lang;
67
- }
68
- }
69
- }
70
- selectItems.sort(sortLangs);
71
- if (view && !view.isDestroyed) {
72
- view.dispatch(view.state.tr.setMeta(pluginKey, { modulesLoaded }));
73
- }
74
- }
75
- });
29
+ init: (_config, _state) => {
76
30
  const cache = new WeakMap();
77
- return {
78
- cache,
79
- decoSet: modulesLoaded
80
- ? prosemirror_view_1.DecorationSet.empty
81
- : getDecorations(state.doc, cache),
82
- };
31
+ return { cache, decoSet: prosemirror_view_1.DecorationSet.empty };
83
32
  },
84
- apply: (tr, { cache, decoSet }) => {
85
- if (!modulesLoaded) {
86
- return { cache, decoSet: prosemirror_view_1.DecorationSet.empty };
33
+ apply: (tr, { cache, decoSet }, _oldState, newState) => {
34
+ const langsUpdate = tr.getMeta(codeBlockLangsPlugin_1.codeBlockLangsPluginKey);
35
+ if (langsUpdate?.loaded && langsUpdate.lowlight) {
36
+ return {
37
+ cache,
38
+ decoSet: getDecorations(tr.doc, cache, langsUpdate.lowlight),
39
+ };
87
40
  }
88
- if (tr.getMeta(pluginKey)?.modulesLoaded) {
89
- return { cache, decoSet: getDecorations(tr.doc, cache) };
41
+ const { lowlight } = (0, codeBlockLangsPlugin_1.getCodeBlockLangsState)(newState);
42
+ if (!lowlight) {
43
+ return { cache, decoSet: prosemirror_view_1.DecorationSet.empty };
90
44
  }
91
45
  if (!tr.docChanged)
92
46
  return { cache, decoSet };
@@ -112,9 +66,8 @@ const CodeBlockHighlight = (builder, opts) => {
112
66
  return { cache, decoSet };
113
67
  },
114
68
  },
115
- view: (v) => {
116
- view = v;
117
- return (0, TooltipPlugin_1.codeLangSelectTooltipViewCreator)(view, selectItems, mapping, {
69
+ view: (view) => {
70
+ return (0, TooltipPlugin_1.codeLangSelectTooltipViewCreator)(view, {
118
71
  showCodeWrapping: Boolean(opts.lineWrapping?.enabled),
119
72
  showLineNumbers: Boolean(opts.lineNumbers?.enabled),
120
73
  });
@@ -129,10 +82,7 @@ const CodeBlockHighlight = (builder, opts) => {
129
82
  },
130
83
  });
131
84
  });
132
- function getDecorations(doc, cache) {
133
- if (!lowlight) {
134
- return prosemirror_view_1.DecorationSet.empty;
135
- }
85
+ function getDecorations(doc, cache, lowlight) {
136
86
  const decos = [];
137
87
  for (const { node, pos } of (0, prosemirror_utils_1.findChildrenByType)(doc, (0, CodeBlockSpecs_1.codeBlockType)(doc.type.schema), true)) {
138
88
  const lang = node.attrs[CodeBlockSpecs_1.CodeBlockNodeAttr.Lang];
@@ -185,12 +135,4 @@ function collectNodes(nodes, className, result) {
185
135
  }
186
136
  }
187
137
  }
188
- function sortLangs(a, b) {
189
- // plaintext always goes first
190
- if (a.value === const_1.PlainTextLang)
191
- return -1;
192
- if (b.value === const_1.PlainTextLang)
193
- return 1;
194
- return 0;
195
- }
196
138
  //# 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';\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';\nimport {processChangedCodeBlocks} from './utils';\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 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 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<PluginState>({\n key: pluginKey,\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(pluginKey, {modulesLoaded}));\n }\n }\n });\n\n const cache: HighlightCache = new WeakMap();\n\n return {\n cache,\n decoSet: modulesLoaded\n ? DecorationSet.empty\n : getDecorations(state.doc, cache),\n };\n },\n apply: (tr, {cache, decoSet}) => {\n if (!modulesLoaded) {\n return {cache, decoSet: DecorationSet.empty};\n }\n\n if (tr.getMeta(pluginKey)?.modulesLoaded) {\n return {cache, decoSet: getDecorations(tr.doc, cache)};\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: (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 pluginKey.getState(state)?.decoSet;\n },\n nodeViews: {\n [codeBlockNodeName]: CodeBlockNodeView.withOpts(opts),\n },\n },\n });\n });\n\n function getDecorations(doc: Node, cache: HighlightCache) {\n if (!lowlight) {\n return DecorationSet.empty;\n }\n\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: Root['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: Root['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\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,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodeBlockToolbar = CodeBlockToolbar;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const icons_1 = require("@gravity-ui/icons");
7
+ const uikit_1 = require("@gravity-ui/uikit");
8
+ const react_use_1 = require("react-use");
9
+ const classname_1 = require("../../../../../classname.js");
10
+ const codeblock_1 = require("../../../../../i18n/codeblock/index.js");
11
+ const memo_1 = require("../../../../../react-utils/memo.js");
12
+ const toolbar_1 = require("../../../../../toolbar/index.js");
13
+ const ToolbarRerender_1 = require("../../../../../toolbar/ToolbarRerender.js");
14
+ const remove_node_1 = require("../../../../../utils/remove-node.js");
15
+ const truthy_1 = require("../../../../../utils/truthy.js");
16
+ const CodeBlockSpecs_1 = require("../../CodeBlockSpecs/index.js");
17
+ const codeBlockLineWrappingPlugin_1 = require("../plugins/codeBlockLineWrappingPlugin.js");
18
+ const CodeLangSelect_1 = require("./CodeLangSelect.js");
19
+ const utils_1 = require("./utils.js");
20
+ const bToolbar = (0, classname_1.cn)('code-block-toolbar');
21
+ const ToolbarMemoized = (0, memo_1.typedMemo)(toolbar_1.Toolbar);
22
+ function CodeBlockToolbar({ node, pos, editorView, langItems, mapping, showCodeWrapping, showLineNumbers, rerenderTooltip, }) {
23
+ const posRef = (0, react_use_1.useLatest)(pos);
24
+ const nodeRef = (0, react_use_1.useLatest)(node);
25
+ const onFocus = (0, react_1.useCallback)(() => {
26
+ editorView.focus();
27
+ }, [editorView]);
28
+ const toolbarData = (0, react_1.useMemo)(() => {
29
+ const copyText = () => nodeRef.current.textContent;
30
+ const focus = () => editorView.focus();
31
+ const onLangChange = (value) => {
32
+ editorView.dispatch(editorView.state.tr.setNodeAttribute(posRef.current, CodeBlockSpecs_1.CodeBlockNodeAttr.Lang, value));
33
+ };
34
+ return [
35
+ [
36
+ langItems.length > 0 &&
37
+ {
38
+ id: 'code-block-type',
39
+ type: toolbar_1.ToolbarDataType.ReactComponent,
40
+ component: () => ((0, jsx_runtime_1.jsx)(CodeLangSelect_1.CodeLangSelect, { focus: focus, onChange: onLangChange, lang: nodeRef.current.attrs[CodeBlockSpecs_1.CodeBlockNodeAttr.Lang], selectItems: langItems, mapping: mapping })),
41
+ width: 28,
42
+ },
43
+ showCodeWrapping &&
44
+ {
45
+ id: 'code-block-wrapping',
46
+ icon: { data: icons_1.ArrowUturnCwLeft },
47
+ title: (0, codeblock_1.i18n)('code_wrapping'),
48
+ type: toolbar_1.ToolbarDataType.SingleButton,
49
+ isActive: (view) => (0, codeBlockLineWrappingPlugin_1.isNodeHasLineWrapping)(view.state, posRef.current),
50
+ isEnable: () => true,
51
+ exec: (view) => {
52
+ (0, utils_1.toggleLineWrapping)({
53
+ pos: posRef.current,
54
+ node: nodeRef.current,
55
+ state: view.state,
56
+ dispatch: view.dispatch,
57
+ });
58
+ // forcing rerender because editor's toolbar isn't updated when the decorations change
59
+ rerenderTooltip?.();
60
+ },
61
+ },
62
+ showLineNumbers &&
63
+ {
64
+ id: 'code-block-linenumbers',
65
+ icon: { data: icons_1.ListOl },
66
+ title: (0, codeblock_1.i18n)('show_line_numbers'),
67
+ type: toolbar_1.ToolbarDataType.SingleButton,
68
+ isActive: () => (0, utils_1.isLineNumbersVisible)(nodeRef.current),
69
+ isEnable: () => true,
70
+ exec: (view) => {
71
+ (0, utils_1.toggleLineNumbers)({
72
+ pos: posRef.current,
73
+ node: nodeRef.current,
74
+ state: view.state,
75
+ dispatch: view.dispatch,
76
+ });
77
+ },
78
+ },
79
+ {
80
+ id: 'code-block-copy',
81
+ type: toolbar_1.ToolbarDataType.ReactNodeFn,
82
+ width: 28,
83
+ content: () => (0, jsx_runtime_1.jsx)(uikit_1.ClipboardButton, { text: copyText }),
84
+ noRerenderOnUpdate: true,
85
+ },
86
+ ].filter(truthy_1.isTruthy),
87
+ [
88
+ {
89
+ id: 'code-block-remove',
90
+ icon: { data: icons_1.TrashBin },
91
+ title: (0, codeblock_1.i18n)('remove'),
92
+ theme: 'danger',
93
+ type: toolbar_1.ToolbarDataType.SingleButton,
94
+ isActive: () => false,
95
+ isEnable: () => true,
96
+ exec: (view) => (0, remove_node_1.removeNode)({
97
+ pos: posRef.current,
98
+ node: nodeRef.current,
99
+ tr: view.state.tr,
100
+ dispatch: view.dispatch,
101
+ }),
102
+ },
103
+ ],
104
+ ];
105
+ }, [
106
+ editorView,
107
+ langItems,
108
+ mapping,
109
+ nodeRef,
110
+ posRef,
111
+ rerenderTooltip,
112
+ showCodeWrapping,
113
+ showLineNumbers,
114
+ ]);
115
+ return ((0, jsx_runtime_1.jsx)(ToolbarRerender_1.ToolbarWrapToContext, { editor: editorView, children: (0, jsx_runtime_1.jsx)(ToolbarMemoized, { editor: editorView, focus: onFocus, className: bToolbar(), data: toolbarData }) }));
116
+ }
117
+ //# 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,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodeLangSelect = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const uikit_1 = require("@gravity-ui/uikit");
7
+ const classname_1 = require("../../../../../classname.js");
8
+ const codeblock_1 = require("../../../../../i18n/codeblock/index.js");
9
+ const placeholder_1 = require("../../../../../i18n/placeholder/index.js");
10
+ const const_1 = require("../const.js");
11
+ const bCodeBlock = (0, classname_1.cn)('code-block');
12
+ exports.CodeLangSelect = (0, react_1.memo)(function CodeLangSelect({ lang, focus, onChange, selectItems, mapping }) {
13
+ const value = mapping[lang] || lang || const_1.PlainTextLang;
14
+ const handleClick = (type) => {
15
+ focus();
16
+ if (type === value)
17
+ return;
18
+ onChange(type);
19
+ };
20
+ return ((0, jsx_runtime_1.jsx)(uikit_1.Select, { size: "m", width: "max", disablePortal: true, value: [value], onUpdate: (v) => handleClick(v[0]), options: selectItems, filterable: true, filterPlaceholder: (0, placeholder_1.i18n)('select_filter'), popupClassName: bCodeBlock('select-popup'), className: bCodeBlock('select-button'), renderEmptyOptions: () => ((0, jsx_runtime_1.jsx)("div", { className: bCodeBlock('select-empty'), children: (0, codeblock_1.i18n)('empty_option') })) }));
21
+ });
22
+ //# 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,iCAA2B;AAE3B,6CAA4D;AAE5D,2DAAiC;AACjC,sEAAwC;AACxC,0EAA6D;AAE7D,uCAAuC;AAEvC,MAAM,UAAU,GAAG,IAAA,cAAE,EAAC,YAAY,CAAC,CAAC;AAUvB,QAAA,cAAc,GAAkC,IAAA,YAAI,EAC7D,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,qBAAa,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,uBAAC,cAAM,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,IAAA,kBAAe,EAAC,eAAe,CAAC,EACnD,cAAc,EAAE,UAAU,CAAC,cAAc,CAAC,EAC1C,SAAS,EAAE,UAAU,CAAC,eAAe,CAAC,EACtC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CACtB,gCAAK,SAAS,EAAE,UAAU,CAAC,cAAc,CAAC,YAAG,IAAA,gBAAI,EAAC,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 {};
@@ -2,107 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.codeLangSelectTooltipViewCreator = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const icons_1 = require("@gravity-ui/icons");
6
- const uikit_1 = require("@gravity-ui/uikit");
7
- const classname_1 = require("../../../../../classname.js");
8
- const codeblock_1 = require("../../../../../i18n/codeblock/index.js");
9
- const placeholder_1 = require("../../../../../i18n/placeholder/index.js");
10
5
  const BaseTooltip_1 = require("../../../../../plugins/BaseTooltip/index.js");
11
- const toolbar_1 = require("../../../../../toolbar/index.js");
12
- const remove_node_1 = require("../../../../../utils/remove-node.js");
13
- const truthy_1 = require("../../../../../utils/truthy.js");
14
6
  const CodeBlockSpecs_1 = require("../../CodeBlockSpecs/index.js");
15
- const const_1 = require("../const.js");
16
- const codeBlockLineWrappingPlugin_1 = require("../plugins/codeBlockLineWrappingPlugin.js");
17
- const utils_1 = require("./utils.js");
7
+ const codeBlockLangsPlugin_1 = require("../plugins/codeBlockLangsPlugin.js");
8
+ const CodeBlockToolbar_1 = require("./CodeBlockToolbar.js");
18
9
  require("./TooltipView.css");
19
- const bCodeBlock = (0, classname_1.cn)('code-block');
20
- const bToolbar = (0, classname_1.cn)('code-block-toolbar');
21
- const CodeMenu = ({ view, pos, node, selectItems, mapping }) => {
22
- const lang = node.attrs[CodeBlockSpecs_1.CodeBlockNodeAttr.Lang];
23
- const value = mapping[lang] || lang || const_1.PlainTextLang;
24
- const handleClick = (type) => {
25
- view.focus();
26
- if (type === value)
27
- return;
28
- view.dispatch(view.state.tr.setNodeAttribute(pos, CodeBlockSpecs_1.CodeBlockNodeAttr.Lang, type));
29
- };
30
- return ((0, jsx_runtime_1.jsx)(uikit_1.Select, { size: "m", width: "max", disablePortal: true, value: [value], onUpdate: (v) => handleClick(v[0]), options: selectItems, filterable: true, filterPlaceholder: (0, placeholder_1.i18n)('select_filter'), popupClassName: bCodeBlock('select-popup'), className: bCodeBlock('select-button'), renderEmptyOptions: () => ((0, jsx_runtime_1.jsx)("div", { className: bCodeBlock('select-empty'), children: (0, codeblock_1.i18n)('empty_option') })) }));
31
- };
32
- const codeLangSelectTooltipViewCreator = (view, langItems, mapping = {}, { showCodeWrapping, showLineNumbers }) => {
10
+ const codeLangSelectTooltipViewCreator = (view, { showCodeWrapping, showLineNumbers }) => {
33
11
  return new BaseTooltip_1.BaseTooltipPluginView(view, {
34
12
  idPrefix: 'code-block-tooltip',
35
13
  nodeType: (0, CodeBlockSpecs_1.codeBlockType)(view.state.schema),
36
14
  popupPlacement: ['bottom', 'top'],
37
15
  content: (view, { node, pos }, _onChange, _forceEdit, _onOutsideClick, rerender) => {
38
- return ((0, jsx_runtime_1.jsx)(toolbar_1.Toolbar, { editor: {}, focus: () => view.focus(), className: bToolbar(), data: [
39
- [
40
- langItems.length > 0 &&
41
- {
42
- id: 'code-block-type',
43
- type: toolbar_1.ToolbarDataType.ReactComponent,
44
- component: () => ((0, jsx_runtime_1.jsx)(CodeMenu, { view: view, pos: pos, node: node, selectItems: langItems, mapping: mapping })),
45
- width: 28,
46
- },
47
- showCodeWrapping &&
48
- {
49
- id: 'code-block-wrapping',
50
- icon: { data: icons_1.ArrowUturnCwLeft },
51
- title: (0, codeblock_1.i18n)('code_wrapping'),
52
- type: toolbar_1.ToolbarDataType.SingleButton,
53
- isActive: () => (0, codeBlockLineWrappingPlugin_1.isNodeHasLineWrapping)(view.state, pos),
54
- isEnable: () => true,
55
- exec: () => {
56
- (0, utils_1.toggleLineWrapping)({
57
- pos,
58
- node,
59
- state: view.state,
60
- dispatch: view.dispatch,
61
- });
62
- // forcing rerender because editor's toolbar isn't updated when the decorations change
63
- rerender?.();
64
- },
65
- },
66
- showLineNumbers &&
67
- {
68
- id: 'code-block-linenumbers',
69
- icon: { data: icons_1.ListOl },
70
- title: (0, codeblock_1.i18n)('show_line_numbers'),
71
- type: toolbar_1.ToolbarDataType.SingleButton,
72
- isActive: () => (0, utils_1.isLineNumbersVisible)(node),
73
- isEnable: () => true,
74
- exec: () => (0, utils_1.toggleLineNumbers)({
75
- pos,
76
- node,
77
- state: view.state,
78
- dispatch: view.dispatch,
79
- }),
80
- },
81
- {
82
- id: 'code-block-copy',
83
- type: toolbar_1.ToolbarDataType.ReactNodeFn,
84
- width: 28,
85
- content: () => (0, jsx_runtime_1.jsx)(uikit_1.ClipboardButton, { text: node.textContent }),
86
- },
87
- ].filter(truthy_1.isTruthy),
88
- [
89
- {
90
- id: 'code-block-remove',
91
- icon: { data: icons_1.TrashBin },
92
- title: (0, codeblock_1.i18n)('remove'),
93
- theme: 'danger',
94
- type: toolbar_1.ToolbarDataType.SingleButton,
95
- isActive: () => false,
96
- isEnable: () => true,
97
- exec: () => (0, remove_node_1.removeNode)({
98
- pos: pos,
99
- node: node,
100
- tr: view.state.tr,
101
- dispatch: view.dispatch.bind(view),
102
- }),
103
- },
104
- ],
105
- ] }));
16
+ const { langItems, aliasMapping } = (0, codeBlockLangsPlugin_1.getCodeBlockLangsState)(view.state);
17
+ return ((0, jsx_runtime_1.jsx)(CodeBlockToolbar_1.CodeBlockToolbar, { pos: pos, node: node, editorView: view, mapping: aliasMapping, langItems: langItems, rerenderTooltip: rerender, showLineNumbers: showLineNumbers, showCodeWrapping: showCodeWrapping }));
106
18
  },
107
19
  });
108
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"../../../../../../../src","sources":["extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n ListOl as LineNumbersIcon,\n TrashBin as RemoveIcon,\n ArrowUturnCwLeft as WrappingIcon,\n} from '@gravity-ui/icons';\nimport {ClipboardButton, Select, type SelectOption} from '@gravity-ui/uikit';\nimport type {Node} from 'prosemirror-model';\nimport type {EditorView} from 'prosemirror-view';\n\nimport {cn} from 'src/classname';\nimport {i18n} from 'src/i18n/codeblock';\nimport {i18n as i18nPlaceholder} from 'src/i18n/placeholder';\nimport {BaseTooltipPluginView} from 'src/plugins/BaseTooltip';\nimport {Toolbar, ToolbarDataType, type ToolbarGroupItemData} from 'src/toolbar';\nimport {removeNode} from 'src/utils/remove-node';\nimport {isTruthy} from 'src/utils/truthy';\n\nimport {CodeBlockNodeAttr, codeBlockType} from '../../CodeBlockSpecs';\nimport {PlainTextLang} from '../const';\nimport {isNodeHasLineWrapping} from '../plugins/codeBlockLineWrappingPlugin';\n\nimport {isLineNumbersVisible, toggleLineNumbers, toggleLineWrapping} from './utils';\n\nimport './TooltipView.scss';\n\nconst bCodeBlock = cn('code-block');\nconst bToolbar = cn('code-block-toolbar');\n\ntype CodeMenuProps = {\n view: EditorView;\n pos: number;\n node: Node;\n selectItems: SelectOption[];\n mapping: Record<string, string>;\n};\n\nconst CodeMenu: React.FC<CodeMenuProps> = ({view, pos, node, selectItems, mapping}) => {\n const lang = node.attrs[CodeBlockNodeAttr.Lang];\n const value = mapping[lang] || lang || PlainTextLang;\n\n const handleClick = (type: string) => {\n view.focus();\n if (type === value) return;\n\n view.dispatch(view.state.tr.setNodeAttribute(pos, CodeBlockNodeAttr.Lang, 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\ntype Options = {\n showCodeWrapping: boolean;\n showLineNumbers: boolean;\n};\n\nexport const codeLangSelectTooltipViewCreator = (\n view: EditorView,\n langItems: SelectOption[],\n mapping: Record<string, string> = {},\n {showCodeWrapping, showLineNumbers}: Options,\n) => {\n return new BaseTooltipPluginView(view, {\n idPrefix: 'code-block-tooltip',\n nodeType: codeBlockType(view.state.schema),\n popupPlacement: ['bottom', 'top'],\n content: (view, {node, pos}, _onChange, _forceEdit, _onOutsideClick, rerender) => {\n return (\n <Toolbar\n editor={{}}\n focus={() => view.focus()}\n className={bToolbar()}\n data={[\n [\n langItems.length > 0 &&\n ({\n id: 'code-block-type',\n type: ToolbarDataType.ReactComponent,\n component: () => (\n <CodeMenu\n view={view}\n pos={pos}\n node={node}\n selectItems={langItems}\n mapping={mapping}\n />\n ),\n width: 28,\n } satisfies ToolbarGroupItemData<{}>),\n showCodeWrapping &&\n ({\n id: 'code-block-wrapping',\n icon: {data: WrappingIcon},\n title: i18n('code_wrapping'),\n type: ToolbarDataType.SingleButton,\n isActive: () => isNodeHasLineWrapping(view.state, pos),\n isEnable: () => true,\n exec: () => {\n toggleLineWrapping({\n pos,\n node,\n state: view.state,\n dispatch: view.dispatch,\n });\n // forcing rerender because editor's toolbar isn't updated when the decorations change\n rerender?.();\n },\n } satisfies ToolbarGroupItemData<{}>),\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(node),\n isEnable: () => true,\n exec: () =>\n toggleLineNumbers({\n pos,\n node,\n state: view.state,\n dispatch: view.dispatch,\n }),\n } satisfies ToolbarGroupItemData<{}>),\n {\n id: 'code-block-copy',\n type: ToolbarDataType.ReactNodeFn,\n width: 28,\n content: () => <ClipboardButton text={node.textContent} />,\n } satisfies ToolbarGroupItemData<{}>,\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: () =>\n removeNode({\n pos: pos,\n node: node,\n tr: view.state.tr,\n dispatch: view.dispatch.bind(view),\n }),\n },\n ],\n ]}\n />\n );\n },\n });\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"../../../../../../../src","sources":["extensions/markdown/CodeBlock/CodeBlockHighlight/TooltipPlugin/index.tsx"],"names":[],"mappings":";;;;AACA,6EAA8D;AAE9D,kEAAmD;AACnD,6EAAuE;AAEvE,4DAAoD;AAEpD,6BAA4B;AAOrB,MAAM,gCAAgC,GAAG,CAC5C,IAAgB,EAChB,EAAC,gBAAgB,EAAE,eAAe,EAAU,EAC9C,EAAE;IACA,OAAO,IAAI,mCAAqB,CAAC,IAAI,EAAE;QACnC,QAAQ,EAAE,oBAAoB;QAC9B,QAAQ,EAAE,IAAA,8BAAa,EAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAC1C,cAAc,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;QACjC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAC,IAAI,EAAE,GAAG,EAAC,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAE,EAAE;YAC7E,MAAM,EAAC,SAAS,EAAE,YAAY,EAAC,GAAG,IAAA,6CAAsB,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAErE,OAAO,CACH,uBAAC,mCAAgB,IACb,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,QAAQ,EACzB,eAAe,EAAE,eAAe,EAChC,gBAAgB,EAAE,gBAAgB,GACpC,CACL,CAAC;QACN,CAAC;KACJ,CAAC,CAAC;AACP,CAAC,CAAC;AAzBW,QAAA,gCAAgC,oCAyB3C","sourcesContent":["import type {EditorView} from '#pm/view';\nimport {BaseTooltipPluginView} from 'src/plugins/BaseTooltip';\n\nimport {codeBlockType} from '../../CodeBlockSpecs';\nimport {getCodeBlockLangsState} from '../plugins/codeBlockLangsPlugin';\n\nimport {CodeBlockToolbar} from './CodeBlockToolbar';\n\nimport './TooltipView.scss';\n\ntype Options = {\n showCodeWrapping: boolean;\n showLineNumbers: boolean;\n};\n\nexport const codeLangSelectTooltipViewCreator = (\n view: EditorView,\n {showCodeWrapping, showLineNumbers}: Options,\n) => {\n return new BaseTooltipPluginView(view, {\n idPrefix: 'code-block-tooltip',\n nodeType: codeBlockType(view.state.schema),\n popupPlacement: ['bottom', 'top'],\n content: (view, {node, pos}, _onChange, _forceEdit, _onOutsideClick, rerender) => {\n const {langItems, aliasMapping} = getCodeBlockLangsState(view.state);\n\n return (\n <CodeBlockToolbar\n pos={pos}\n node={node}\n editorView={view}\n mapping={aliasMapping}\n langItems={langItems}\n rerenderTooltip={rerender}\n showLineNumbers={showLineNumbers}\n showCodeWrapping={showCodeWrapping}\n />\n );\n },\n });\n};\n"]}
@@ -0,0 +1,23 @@
1
+ import type { Options } from '@diplodoc/transform';
2
+ import type { createLowlight } from 'lowlight' with { 'resolution-mode': 'import' };
3
+ import type { EditorState } from "../../../../../pm/state.js";
4
+ import { Plugin, PluginKey } from "../../../../../pm/state.js";
5
+ export type HighlightLangMap = Options['highlightLangs'];
6
+ export type Lowlight = ReturnType<typeof createLowlight>;
7
+ export type LLRoot = ReturnType<Lowlight['highlight']>;
8
+ type LangItem = {
9
+ value: string;
10
+ content: string;
11
+ };
12
+ type CodeBlockLangsState = {
13
+ langItems: LangItem[];
14
+ aliasMapping: Record<string, string>;
15
+ lowlight: Lowlight | null;
16
+ loaded: boolean;
17
+ };
18
+ export declare const codeBlockLangsPluginKey: PluginKey<CodeBlockLangsState>;
19
+ export declare function getCodeBlockLangsState(state: EditorState): CodeBlockLangsState;
20
+ export declare function codeBlockLangsPlugin(langsConfig: HighlightLangMap | undefined, logger: {
21
+ log: (msg: string) => void;
22
+ }): Plugin<CodeBlockLangsState>;
23
+ export {};