@krainovsd/markdown-editor 0.3.2 → 0.4.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 (55) hide show
  1. package/lib/cjs/{index-DU8JMAfc.js → index-CXENq_0E.js} +10 -6
  2. package/lib/cjs/index-CXENq_0E.js.map +1 -0
  3. package/lib/cjs/{index-BgxbH3r2.js → index-Dj0jRUGF.js} +427 -13
  4. package/lib/cjs/index-Dj0jRUGF.js.map +1 -0
  5. package/lib/cjs/index.js +2 -1
  6. package/lib/cjs/index.js.map +1 -1
  7. package/lib/esm/extensions/auto-completes/custom/tag-auto-complete.js +33 -0
  8. package/lib/esm/extensions/auto-completes/custom/tag-auto-complete.js.map +1 -0
  9. package/lib/esm/extensions/auto-completes/init-auto-complete.js +27 -0
  10. package/lib/esm/extensions/auto-completes/init-auto-complete.js.map +1 -0
  11. package/lib/esm/extensions/init-extensions.js +3 -1
  12. package/lib/esm/extensions/init-extensions.js.map +1 -1
  13. package/lib/esm/extensions/keymaps/custom/bold-key-map.js +56 -0
  14. package/lib/esm/extensions/keymaps/custom/bold-key-map.js.map +1 -0
  15. package/lib/esm/extensions/keymaps/custom/italic-key-map.js +57 -0
  16. package/lib/esm/extensions/keymaps/custom/italic-key-map.js.map +1 -0
  17. package/lib/esm/extensions/keymaps/custom/link-key-map.js +28 -0
  18. package/lib/esm/extensions/keymaps/custom/link-key-map.js.map +1 -0
  19. package/lib/esm/extensions/keymaps/init-key-map.js +4 -1
  20. package/lib/esm/extensions/keymaps/init-key-map.js.map +1 -1
  21. package/lib/esm/extensions/markdown/blockquote/blockquote-constants.js +1 -1
  22. package/lib/esm/extensions/markdown/blockquote/blockquote-constants.js.map +1 -1
  23. package/lib/esm/extensions/markdown/bold/bold-constants.js +1 -1
  24. package/lib/esm/extensions/markdown/bold/bold-constants.js.map +1 -1
  25. package/lib/esm/extensions/markdown/code/code-constants.js +3 -1
  26. package/lib/esm/extensions/markdown/code/code-constants.js.map +1 -1
  27. package/lib/esm/extensions/markdown/code/code-decoration.js +32 -1
  28. package/lib/esm/extensions/markdown/code/code-decoration.js.map +1 -1
  29. package/lib/esm/extensions/markdown/image/image-widget.js +24 -1
  30. package/lib/esm/extensions/markdown/image/image-widget.js.map +1 -1
  31. package/lib/esm/extensions/markdown/link/link-widget.js +23 -0
  32. package/lib/esm/extensions/markdown/link/link-widget.js.map +1 -1
  33. package/lib/esm/extensions/markdown/mention/mention-constants.js +4 -3
  34. package/lib/esm/extensions/markdown/mention/mention-constants.js.map +1 -1
  35. package/lib/esm/extensions/markdown/mention/mention-parser.js +8 -5
  36. package/lib/esm/extensions/markdown/mention/mention-parser.js.map +1 -1
  37. package/lib/esm/extensions/markdown/styles.module.scss.js +2 -2
  38. package/lib/esm/extensions/theme/theme-constants.js +2 -0
  39. package/lib/esm/extensions/theme/theme-constants.js.map +1 -1
  40. package/lib/esm/extensions/theme/themes/get-dark-theme.js +2 -0
  41. package/lib/esm/extensions/theme/themes/get-dark-theme.js.map +1 -1
  42. package/lib/esm/extensions/theme/themes/get-light-theme.js +2 -0
  43. package/lib/esm/extensions/theme/themes/get-light-theme.js.map +1 -1
  44. package/lib/esm/extensions/theme/themes/get-theme-template.js +6 -0
  45. package/lib/esm/extensions/theme/themes/get-theme-template.js.map +1 -1
  46. package/lib/esm/index.js +1 -0
  47. package/lib/esm/index.js.map +1 -1
  48. package/lib/esm/lib/utils/overlap-mark.js +148 -0
  49. package/lib/esm/lib/utils/overlap-mark.js.map +1 -0
  50. package/lib/esm/module/Editor/Editor.js +1 -0
  51. package/lib/esm/module/Editor/Editor.js.map +1 -1
  52. package/lib/index.d.ts +9 -1
  53. package/package.json +2 -1
  54. package/lib/cjs/index-BgxbH3r2.js.map +0 -1
  55. package/lib/cjs/index-DU8JMAfc.js.map +0 -1
@@ -4,8 +4,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const langMarkdown = require('@codemirror/lang-markdown');
6
6
  require('@codemirror/state');
7
- const index = require('./index-BgxbH3r2.js');
7
+ const index = require('./index-Dj0jRUGF.js');
8
8
  require('@codemirror/view');
9
+ require('@codemirror/autocomplete');
9
10
  require('@codemirror/commands');
10
11
  require('@codemirror/language');
11
12
  require('@lezer/highlight');
@@ -17,13 +18,16 @@ const mentionParser = {
17
18
  parseInline: [
18
19
  {
19
20
  name: index.NAME_OF_MENTION,
20
- parse(cx, next, pos) {
21
- if (next != index.CODE_OF_START_MENTION)
21
+ parse(cx, code, pos) {
22
+ if (code != index.CODE_OF_START_MENTION)
23
+ return -1;
24
+ const nextCode = cx.char(pos + 1);
25
+ if (nextCode === -1 || nextCode === index.CODE_OF_SPACE || nextCode === index.CODE_OF_LINE_BREAK)
22
26
  return -1;
23
27
  let end = pos + 1;
24
28
  for (let i = pos + 1; i < cx.end; i++) {
25
- const next = cx.char(i);
26
- if (next === index.CODE_OF_SPACE)
29
+ const nextCode = cx.char(i);
30
+ if (nextCode === -1 || nextCode === index.CODE_OF_SPACE || nextCode === index.CODE_OF_LINE_BREAK)
27
31
  break;
28
32
  end++;
29
33
  }
@@ -49,4 +53,4 @@ const initMarkdown = ({ languages, imageSrcGetter }) => {
49
53
  };
50
54
 
51
55
  exports.initMarkdown = initMarkdown;
52
- //# sourceMappingURL=index-DU8JMAfc.js.map
56
+ //# sourceMappingURL=index-CXENq_0E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CXENq_0E.js","sources":["../../src/extensions/markdown/mention/mention-parser.ts","../../src/extensions/markdown/markdown-parser.ts","../../src/extensions/markdown/init-markdown.ts"],"sourcesContent":["import type { MarkdownConfig } from \"@lezer/markdown\";\nimport {\n CODE_OF_LINE_BREAK,\n CODE_OF_SPACE,\n CODE_OF_START_MENTION,\n NAME_OF_MENTION,\n} from \"./mention-constants\";\n\nexport const mentionParser: MarkdownConfig = {\n defineNodes: [{ name: NAME_OF_MENTION }],\n parseInline: [\n {\n name: NAME_OF_MENTION,\n parse(cx, code, pos) {\n if (code != CODE_OF_START_MENTION) return -1;\n const nextCode = cx.char(pos + 1);\n if (nextCode === -1 || nextCode === CODE_OF_SPACE || nextCode === CODE_OF_LINE_BREAK)\n return -1;\n\n let end: number = pos + 1;\n for (let i = pos + 1; i < cx.end; i++) {\n const nextCode = cx.char(i);\n if (nextCode === -1 || nextCode === CODE_OF_SPACE || nextCode === CODE_OF_LINE_BREAK)\n break;\n end++;\n }\n\n return cx.addElement(cx.elt(NAME_OF_MENTION, pos, end));\n },\n },\n ],\n};\n","import type { MarkdownExtension } from \"@lezer/markdown\";\nimport { mentionParser } from \"./mention\";\n\nexport const markdownParserPlugin: MarkdownExtension = [mentionParser];\n","import { markdown, markdownLanguage } from \"@codemirror/lang-markdown\";\nimport { type Extension } from \"@codemirror/state\";\nimport { markdownDecorationPlugin } from \"./markdown-decoration\";\nimport { markdownParserPlugin } from \"./markdown-parser\";\nimport { markdownState } from \"./markdown-state\";\nimport type { InitMarkdownOptions } from \"./markdown-types\";\n\nexport const initMarkdown = ({ languages, imageSrcGetter }: InitMarkdownOptions): Extension => {\n return [\n markdownState,\n markdown({\n base: markdownLanguage,\n codeLanguages: languages,\n addKeymap: true,\n extensions: [markdownParserPlugin],\n }),\n markdownDecorationPlugin({ imageSrcGetter }),\n ];\n};\n"],"names":["NAME_OF_MENTION","CODE_OF_START_MENTION","CODE_OF_SPACE","CODE_OF_LINE_BREAK","markdownState","markdown","markdownLanguage","markdownDecorationPlugin"],"mappings":";;;;;;;;;;;;;;;AAQO,MAAM,aAAa,GAAmB;AAC3C,IAAA,WAAW,EAAE,CAAC,EAAE,IAAI,EAAEA,qBAAe,EAAE,CAAC;AACxC,IAAA,WAAW,EAAE;AACX,QAAA;AACE,YAAA,IAAI,EAAEA,qBAAe;AACrB,YAAA,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAA;gBACjB,IAAI,IAAI,IAAIC,2BAAqB;oBAAE,OAAO,CAAC,CAAC;gBAC5C,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;gBACjC,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,KAAKC,mBAAa,IAAI,QAAQ,KAAKC,wBAAkB;oBAClF,OAAO,CAAC,CAAC;AAEX,gBAAA,IAAI,GAAG,GAAW,GAAG,GAAG,CAAC;AACzB,gBAAA,KAAK,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;oBACrC,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC3B,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,KAAKD,mBAAa,IAAI,QAAQ,KAAKC,wBAAkB;wBAClF;AACF,oBAAA,GAAG,EAAE;;AAGP,gBAAA,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAACH,qBAAe,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;aACxD;AACF,SAAA;AACF,KAAA;CACF;;AC5BM,MAAM,oBAAoB,GAAsB,CAAC,aAAa,CAAC;;ACIzD,MAAA,YAAY,GAAG,CAAC,EAAE,SAAS,EAAE,cAAc,EAAuB,KAAe;IAC5F,OAAO;QACLI,mBAAa;AACb,QAAAC,qBAAQ,CAAC;AACP,YAAA,IAAI,EAAEC,6BAAgB;AACtB,YAAA,aAAa,EAAE,SAAS;AACxB,YAAA,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,CAAC,oBAAoB,CAAC;SACnC,CAAC;AACF,QAAAC,8BAAwB,CAAC,EAAE,cAAc,EAAE,CAAC;KAC7C;AACH;;;;"}
@@ -2,6 +2,7 @@
2
2
 
3
3
  const view = require('@codemirror/view');
4
4
  const state = require('@codemirror/state');
5
+ const autocomplete = require('@codemirror/autocomplete');
5
6
  const commands = require('@codemirror/commands');
6
7
  const language = require('@codemirror/language');
7
8
  const highlight = require('@lezer/highlight');
@@ -13,6 +14,59 @@ const ReadonlyCompartment = new state.Compartment();
13
14
  const VimModeCompartment = new state.Compartment();
14
15
  const ThemeCompartment = new state.Compartment();
15
16
 
17
+ const CODE_OF_START_MENTION$1 = "@".codePointAt(0); // @
18
+ const CODE_OF_SPACE$3 = " ".codePointAt(0);
19
+ const CODE_OF_LINE_BREAK$1 = "\n".codePointAt(0);
20
+ const tagAutoComplete = (tagOptions) => {
21
+ const options = tagOptions.map((user) => ({
22
+ label: `@${user}`,
23
+ type: "text",
24
+ }));
25
+ return (context) => {
26
+ const line = context.view?.lineBlockAt?.(context.pos);
27
+ if (!line)
28
+ return null;
29
+ const content = context.state.sliceDoc(line.from, context.pos);
30
+ let pos = content.length - 1;
31
+ while (pos > -1) {
32
+ const code = content.codePointAt(pos);
33
+ if (!code || code === CODE_OF_SPACE$3 || code === CODE_OF_LINE_BREAK$1)
34
+ return null;
35
+ if (code == CODE_OF_START_MENTION$1)
36
+ break;
37
+ pos--;
38
+ }
39
+ if (pos === -1)
40
+ return null;
41
+ return {
42
+ from: line.from + pos,
43
+ options,
44
+ };
45
+ };
46
+ };
47
+
48
+ const initAutoComplete = ({ autoCompleteTagOptions, autoCompleteConfig = {}, }) => {
49
+ if (!autoCompleteTagOptions)
50
+ return [];
51
+ return [
52
+ autocomplete.autocompletion({
53
+ activateOnTyping: true,
54
+ activateOnTypingDelay: 100,
55
+ selectOnOpen: true,
56
+ closeOnBlur: true,
57
+ maxRenderedOptions: 20,
58
+ aboveCursor: false,
59
+ defaultKeymap: true,
60
+ icons: false,
61
+ filterStrict: false,
62
+ interactionDelay: 75,
63
+ updateSyncTime: 100,
64
+ ...autoCompleteConfig,
65
+ override: [tagAutoComplete(autoCompleteTagOptions)],
66
+ }),
67
+ ];
68
+ };
69
+
16
70
  function copyToClipboard(content) {
17
71
  if (navigator.clipboard && window.isSecureContext) {
18
72
  return navigator.clipboard.writeText(content);
@@ -92,6 +146,152 @@ function saveDispatch(dispatch) {
92
146
  });
93
147
  }
94
148
 
149
+ function overlapMark({ marks, shift, state, requireMatched }) {
150
+ const { from, to, shiftAfterInner, shiftAfterOuter, shiftBeforeInner, shiftBeforeOuter, text } = processShiftContent(state, shift, marks);
151
+ const startIndex = findMarkIndex(text.substring(0, shiftBeforeInner + shiftBeforeOuter), marks, requireMatched, "right");
152
+ const endIndex = findMarkIndex(text.substring(text.length - shiftAfterInner - shiftAfterOuter), marks, requireMatched, "left");
153
+ const start = ~startIndex ? from - shiftBeforeOuter + startIndex : -1;
154
+ const end = ~endIndex ? to - shiftAfterInner + endIndex : -1;
155
+ // console.log({
156
+ // from,
157
+ // to,
158
+ // shiftAfterInner,
159
+ // shiftAfterOuter,
160
+ // shiftBeforeInner,
161
+ // shiftBeforeOuter,
162
+ // text,
163
+ // textStart: text.substring(0, shiftBeforeInner + shiftBeforeOuter),
164
+ // textEnd: text.substring(text.length - shiftAfterInner - shiftAfterOuter),
165
+ // startIndex,
166
+ // endIndex,
167
+ // end,
168
+ // start,
169
+ // });
170
+ return {
171
+ start,
172
+ end,
173
+ marked: Boolean(~start || ~end),
174
+ originalText: text.substring(shiftBeforeOuter, text.length - shiftAfterOuter),
175
+ };
176
+ }
177
+ function findMarkIndex(text, marks, requireMatched, direction = "right") {
178
+ if (text.length === 0)
179
+ return -1;
180
+ const maxRequired = Math.max(...requireMatched);
181
+ const minRequired = Math.min(...requireMatched);
182
+ let pos = 0;
183
+ let matched = 0;
184
+ let start = -1;
185
+ for (const mark of marks) {
186
+ if (!mark)
187
+ continue;
188
+ while (pos < text.length) {
189
+ if (text.codePointAt(pos) === mark)
190
+ matched++;
191
+ else {
192
+ if (
193
+ // eslint-disable-next-line no-loop-func -- https://eslint.org/docs/latest/rules/no-loop-func#known-limitations
194
+ requireMatched.some((rm) => rm === matched) &&
195
+ ((direction === "right" && pos - matched > start) ||
196
+ (direction === "left" && (pos - matched < start || start === -1)))) {
197
+ start = direction === "right" ? pos - minRequired : pos - matched;
198
+ // console.log({ pos, matched, start, minRequired, maxRequired, direction });
199
+ }
200
+ else if (maxRequired < matched) {
201
+ const posMin = pos - minRequired;
202
+ const posMax = pos - matched;
203
+ // console.log({ posMin, posMax, pos, minRequired, maxRequired, direction, matched });
204
+ if (direction === "right" && posMin > start)
205
+ start = posMin;
206
+ if (direction === "left" && (posMax < start || start === -1))
207
+ start = posMax;
208
+ }
209
+ matched = 0;
210
+ }
211
+ pos++;
212
+ }
213
+ if (
214
+ // eslint-disable-next-line no-loop-func -- https://eslint.org/docs/latest/rules/no-loop-func#known-limitations
215
+ requireMatched.some((rm) => rm === matched) &&
216
+ ((direction === "right" && pos - matched > start) ||
217
+ (direction === "left" && (pos - matched < start || start === -1)))) {
218
+ start = direction === "right" ? pos - minRequired : pos - matched;
219
+ // console.log({ pos, matched, start, minRequired, maxRequired, direction });
220
+ }
221
+ else if (maxRequired < matched) {
222
+ const posMin = pos - minRequired;
223
+ const posMax = pos - matched;
224
+ // console.log({ posMin, posMax, pos, minRequired, maxRequired, direction, matched });
225
+ if (direction === "right" && posMin > start)
226
+ start = posMin;
227
+ if (direction === "left" && (posMax < start || start === -1))
228
+ start = posMax;
229
+ }
230
+ pos = 0;
231
+ matched = 0;
232
+ }
233
+ return start;
234
+ }
235
+ function processShiftContent(state, shift, marks) {
236
+ const { from, to } = state.selection.ranges[0];
237
+ const linePoint = state.lineBreak.codePointAt(0);
238
+ let pos = 0;
239
+ /** processing outer shifts */
240
+ const initialTextBefore = state.sliceDoc(from - shift, from);
241
+ let shiftBeforeOuter = 0;
242
+ pos = initialTextBefore.length - 1;
243
+ while (pos > -1) {
244
+ if (initialTextBefore.codePointAt(pos) === linePoint)
245
+ break;
246
+ shiftBeforeOuter++;
247
+ pos--;
248
+ }
249
+ const initialTextAfter = state.sliceDoc(to, to + shift);
250
+ let shiftAfterOuter = 0;
251
+ pos = 0;
252
+ while (pos < initialTextAfter.length) {
253
+ if (initialTextAfter.codePointAt(pos) === linePoint)
254
+ break;
255
+ shiftAfterOuter++;
256
+ pos++;
257
+ }
258
+ /** processing inner shifts */
259
+ const initialText = state.sliceDoc(from, to);
260
+ let shiftBeforeInner = 0;
261
+ pos = 0;
262
+ if (initialText.length > 1)
263
+ while (pos < initialText.length) {
264
+ // eslint-disable-next-line no-loop-func -- https://eslint.org/docs/latest/rules/no-loop-func#known-limitations
265
+ if (marks.some((m) => m === initialText.codePointAt(pos)))
266
+ shiftBeforeInner++;
267
+ else
268
+ break;
269
+ pos++;
270
+ }
271
+ const initialTextWithoutBeforeShift = initialText.substring(shiftBeforeInner + 1);
272
+ let shiftAfterInner = 0;
273
+ pos = initialTextWithoutBeforeShift.length - 1;
274
+ if (initialText.length > 1 || shiftBeforeInner > 0)
275
+ while (pos > -1) {
276
+ // eslint-disable-next-line no-loop-func -- https://eslint.org/docs/latest/rules/no-loop-func#known-limitations
277
+ if (marks.some((m) => m === initialTextWithoutBeforeShift.codePointAt(pos)))
278
+ shiftAfterInner++;
279
+ else
280
+ break;
281
+ pos--;
282
+ }
283
+ const text = state.sliceDoc(from - shiftBeforeOuter, to + shiftAfterOuter);
284
+ return {
285
+ from,
286
+ to,
287
+ shiftBeforeOuter,
288
+ shiftBeforeInner,
289
+ shiftAfterOuter,
290
+ shiftAfterInner,
291
+ text,
292
+ };
293
+ }
294
+
95
295
  /**
96
296
  * t.processingInstruction, t.meta - # () []
97
297
  * t.url, t.link - links
@@ -125,6 +325,8 @@ function getHighlightTemplate(config) {
125
325
  const CLASSES = {
126
326
  listCommon: "cm-list-common",
127
327
  code: "cm-code",
328
+ codeBlockLine: "cm-code-block-line",
329
+ codeBlock: "cm-code-block",
128
330
  codeButton: "cm-code-button",
129
331
  codeButtonSuccess: "cm-code-button-success",
130
332
  codeButtonFail: "cm-code-button-fail",
@@ -198,6 +400,12 @@ function getThemeTemplate(dark, config) {
198
400
  [`.${CLASSES.mention}`]: {
199
401
  color: config.mentionColor,
200
402
  },
403
+ [`.${CLASSES.codeBlockLine}`]: {
404
+ borderColor: config.codeBlockBorderColor,
405
+ },
406
+ [`.${CLASSES.codeBlock}`]: {
407
+ background: config.codeBlockBackground,
408
+ },
201
409
  }, { dark });
202
410
  }
203
411
 
@@ -229,6 +437,8 @@ const THEME_CONFIG$1 = {
229
437
  mentionColor: "#8A5CF5",
230
438
  vimSelection: "#1A1919FF",
231
439
  vimSelectionFocused: "#2E4B4BFF",
440
+ codeBlockBorderColor: "#7b7e81",
441
+ codeBlockBackground: "#24292e",
232
442
  };
233
443
  function getDarkTheme({ dark }) {
234
444
  const highlightConfig = { ...HIGHLIGHT_CONFIG$1, ...(dark?.highlightConfig || {}) };
@@ -264,6 +474,8 @@ const THEME_CONFIG = {
264
474
  mentionColor: "#8A5CF5",
265
475
  vimSelection: "#d9d9d9",
266
476
  vimSelectionFocused: "#d7d4f0",
477
+ codeBlockBackground: "#e1e2e7",
478
+ codeBlockBorderColor: "##CCCCCDFF",
267
479
  };
268
480
  function getLightTheme({ light }) {
269
481
  const highlightConfig = { ...HIGHLIGHT_CONFIG, ...(light?.highlightConfig || {}) };
@@ -279,13 +491,135 @@ const initTheme = (options) => {
279
491
  return extensions;
280
492
  };
281
493
 
494
+ const BOLD_MARK_STAR = "*".codePointAt(0);
495
+ const BOLD_MARK_DASH = "_".codePointAt(0);
496
+ const SHIFT = 2;
497
+ const insertBoldMarker = ({ state, dispatch }) => {
498
+ const changes = [];
499
+ const { from, to } = state.selection.ranges[0];
500
+ if (from === to)
501
+ return true;
502
+ const { end, start, marked, originalText } = overlapMark({
503
+ marks: [BOLD_MARK_DASH, BOLD_MARK_STAR],
504
+ requireMatched: [SHIFT],
505
+ shift: SHIFT,
506
+ state,
507
+ });
508
+ if (marked) {
509
+ if (~start) {
510
+ changes.push({ from: start, to: start + SHIFT, insert: "" });
511
+ }
512
+ if (~end) {
513
+ changes.push({ from: end, to: end + SHIFT, insert: "" });
514
+ }
515
+ }
516
+ else {
517
+ const markedText = `**${originalText}**`;
518
+ changes.push({ from, to, insert: markedText });
519
+ }
520
+ saveDispatch(() => {
521
+ const startSelection = ~start ? start : from;
522
+ const endSelection = ~end ? end - (~start ? SHIFT : 0) : to - (~start ? SHIFT : 0);
523
+ dispatch(state.update({
524
+ changes,
525
+ selection: !marked
526
+ ? {
527
+ anchor: from + SHIFT,
528
+ head: to + SHIFT,
529
+ }
530
+ : {
531
+ anchor: startSelection,
532
+ head: endSelection,
533
+ },
534
+ }));
535
+ });
536
+ return true;
537
+ };
538
+ const boldKeymap = {
539
+ key: "Mod-b",
540
+ run: insertBoldMarker,
541
+ };
542
+
543
+ const ITALIC_MARK_STAR = "*".codePointAt(0);
544
+ const ITALIC_MARK_DASH = "_".codePointAt(0);
545
+ const SHIFT_COUPLE = 3;
546
+ const SHIFT_ALONE = 1;
547
+ const insertItalicMarker = ({ state, dispatch }) => {
548
+ const changes = [];
549
+ const { from, to } = state.selection.ranges[0];
550
+ if (from === to)
551
+ return true;
552
+ const { end, start, marked, originalText } = overlapMark({
553
+ marks: [ITALIC_MARK_STAR, ITALIC_MARK_DASH],
554
+ requireMatched: [SHIFT_ALONE, SHIFT_COUPLE],
555
+ shift: SHIFT_COUPLE,
556
+ state,
557
+ });
558
+ if (marked) {
559
+ if (~start) {
560
+ changes.push({ from: start, to: start + SHIFT_ALONE, insert: "" });
561
+ }
562
+ if (~end) {
563
+ changes.push({ from: end, to: end + SHIFT_ALONE, insert: "" });
564
+ }
565
+ }
566
+ else {
567
+ const markedText = `*${originalText}*`;
568
+ changes.push({ from, to, insert: markedText });
569
+ }
570
+ saveDispatch(() => {
571
+ const startSelection = ~start ? start : from;
572
+ const endSelection = ~end ? end - (~start ? SHIFT_ALONE : 0) : to - (~start ? SHIFT_ALONE : 0);
573
+ dispatch(state.update({
574
+ changes,
575
+ selection: !marked
576
+ ? {
577
+ anchor: from + SHIFT_ALONE,
578
+ head: to + SHIFT_ALONE,
579
+ }
580
+ : {
581
+ anchor: startSelection,
582
+ head: endSelection,
583
+ },
584
+ }));
585
+ });
586
+ return true;
587
+ };
588
+ const italicKeymap = {
589
+ key: "Mod-i",
590
+ run: insertItalicMarker,
591
+ };
592
+
593
+ const insertLinkWrapper = ({ state, dispatch }) => {
594
+ const changes = [];
595
+ const { from, to } = state.selection.ranges[0];
596
+ if (from === to)
597
+ return true;
598
+ const content = state.sliceDoc(from, to);
599
+ const wrapper = `[${content}]()`;
600
+ changes.push({ from, to, insert: wrapper });
601
+ saveDispatch(() => {
602
+ dispatch(state.update({
603
+ changes,
604
+ selection: {
605
+ anchor: to + 3,
606
+ },
607
+ }));
608
+ });
609
+ return true;
610
+ };
611
+ const linkKeymap = {
612
+ key: "Mod-k",
613
+ run: insertLinkWrapper,
614
+ };
615
+
282
616
  let vimMode = false;
283
617
  let theme = "light";
284
618
  const initKeyMaps = async ({ onEnter, onEscape, multiCursorMode, keyMaps, defaultKeyMaps, theme: initialTheme, vimMode: initialVimMode, dark, light, }) => {
285
619
  vimMode = initialVimMode;
286
620
  theme = initialTheme;
287
621
  /** tab */
288
- const keyBindings = [commands.indentWithTab];
622
+ const keyBindings = [commands.indentWithTab, boldKeymap, italicKeymap, linkKeymap];
289
623
  /** standard */
290
624
  keyBindings.push(...commands.standardKeymap.map((keyMap) => {
291
625
  if (keyMap.key === "Enter" && onEnter) {
@@ -419,12 +753,12 @@ function styleInject(css, ref) {
419
753
  }
420
754
  }
421
755
 
422
- var css_248z = "._header_XFwV5{font-weight:700}._header_XFwV5._level_1_-KPph{font-size:2rem}._header_XFwV5._level_2_ecHlB{font-size:1.8rem}._header_XFwV5._level_3_SYcVr{font-size:1.6rem}._header_XFwV5._level_4_V3o5m{font-size:1.4rem}._header_XFwV5._level_5_I7eVk{font-size:1.3rem}._header_XFwV5._level_6_A3lbK{font-size:1.2rem}._bold_I8DT-{font-weight:700}._italic_72qBe{font-style:italic}._blockquote_Xq6O4{border-left:3px solid;margin-left:5px}._blockquote__inner_mjT0h{margin-left:1px;padding-left:5px;position:relative}._blockquote__inner_mjT0h:before{border-left:3px solid;content:\"\";height:140%;left:0;position:absolute;top:-3px}._blockquote__inner-deep_s6tNj{margin-left:5px}._strike-through_U64jP{text-decoration:line-through}._list_MHIjT._common_0GdDi{position:relative;visibility:hidden}._list_MHIjT._common_0GdDi:after{border-radius:100%;content:\"\";height:5px;left:0;position:absolute;top:50%;transform:translateY(-50%);visibility:visible;width:5px}._link_7U9wl{text-decoration:none;text-decoration:underline}._link__label_dHGGf{font-size:12px;position:relative;top:-4px}._image_KmBM8{display:inline-flex}._code__line_m3IiO{padding:5px;position:relative}._code__line_m3IiO,._code__single_hbMte{font-family:monospace}._code__button_WwYE-{background-color:transparent;border:none;border-radius:4px;box-shadow:none;cursor:pointer;min-width:30px;outline:none;padding:4px 10px;position:absolute;right:5px;top:5px;transition:all .3s ease;z-index:1}._code__button_WwYE-._pending_fgHgD:before{animation:_loading-btn--fade-in_8z5an .33s ease,_loading-btn--rotation_QaopN .66s linear 0s infinite;border:2px solid hsla(0,0%,100%,.33);border-radius:50%;border-top-color:#000;content:\"\";display:inline-block;height:10.5px;left:50%;position:absolute;top:50%;width:10.5px}._code__button_WwYE-._success_kUPnO:after{animation:_loading-btn--fade-in_8z5an .6s ease;border-color:currentcolor;border-style:solid;border-width:0 0 1px 1px;content:\"\";display:inline-block;height:7px;left:50%;position:absolute;top:50%;transform:translate(-50%,-75%) rotate(-45deg);width:11px}._code__button_WwYE-._fail_cOpap:after,._code__button_WwYE-._fail_cOpap:before{content:\" \";height:13px;left:50%;position:absolute;top:50%;width:1px}._code__button_WwYE-._fail_cOpap:before{transform:translate(-50%,-50%) rotate(45deg)}._code__button_WwYE-._fail_cOpap:after{transform:translate(-50%,-50%) rotate(-45deg)}@keyframes _loading-btn--fade-in_8z5an{0%{opacity:0}to{opacity:1}}@keyframes _loading-btn--rotation_QaopN{0%{transform:translate(-50%,-50%) rotate(0deg)}to{transform:translate(-50%,-50%) rotate(1turn)}}._code__span_iSCmj{opacity:1;transition:opacity .3s ease}._code__span_iSCmj._hide_uqpax{opacity:0}._horizontal_J1jU-{border-bottom:1px solid;margin:0 5px;position:relative;width:calc(100% - 10px)}._todo_m6MIP{align-items:flex-end;display:inline-flex;height:100%;padding-left:3px;padding-right:3px}._todo_m6MIP>input{margin:0}._todo__checked_kemjy{text-decoration:line-through}._mention_cpzik{font-weight:700}";
423
- const styles = {"header":"_header_XFwV5","level_1":"_level_1_-KPph","level_2":"_level_2_ecHlB","level_3":"_level_3_SYcVr","level_4":"_level_4_V3o5m","level_5":"_level_5_I7eVk","level_6":"_level_6_A3lbK","bold":"_bold_I8DT-","italic":"_italic_72qBe","blockquote":"_blockquote_Xq6O4","blockquote__inner":"_blockquote__inner_mjT0h","blockquote__inner-deep":"_blockquote__inner-deep_s6tNj","strike-through":"_strike-through_U64jP","list":"_list_MHIjT","common":"_common_0GdDi","link":"_link_7U9wl","link__label":"_link__label_dHGGf","image":"_image_KmBM8","code__line":"_code__line_m3IiO","code__single":"_code__single_hbMte","code__button":"_code__button_WwYE-","pending":"_pending_fgHgD","loading-btn--fade-in":"_loading-btn--fade-in_8z5an","loading-btn--rotation":"_loading-btn--rotation_QaopN","success":"_success_kUPnO","fail":"_fail_cOpap","code__span":"_code__span_iSCmj","hide":"_hide_uqpax","horizontal":"_horizontal_J1jU-","todo":"_todo_m6MIP","todo__checked":"_todo__checked_kemjy","mention":"_mention_cpzik"};
756
+ var css_248z = "._header_XFwV5{font-weight:700}._header_XFwV5._level_1_-KPph{font-size:2em}._header_XFwV5._level_2_ecHlB{font-size:1.8em}._header_XFwV5._level_3_SYcVr{font-size:1.6em}._header_XFwV5._level_4_V3o5m{font-size:1.4em}._header_XFwV5._level_5_I7eVk{font-size:1.3em}._header_XFwV5._level_6_A3lbK{font-size:1.2em}._bold_I8DT-{font-weight:700}._italic_72qBe{font-style:italic}._blockquote_Xq6O4{border-left:3px solid;margin-left:5px}._blockquote__inner_mjT0h{margin-left:1px;padding-left:5px;position:relative}._blockquote__inner_mjT0h:before{border-left:3px solid;content:\"\";height:140%;left:0;position:absolute;top:-3px}._blockquote__inner-deep_s6tNj{margin-left:5px}._strike-through_U64jP{text-decoration:line-through}._list_MHIjT._common_0GdDi{position:relative;visibility:hidden}._list_MHIjT._common_0GdDi:after{border-radius:100%;content:\"\";height:5px;left:0;position:absolute;top:50%;transform:translateY(-50%);visibility:visible;width:5px}._link_7U9wl{text-decoration:none;text-decoration:underline}._link__label_dHGGf{font-size:12px;position:relative;top:-4px}._image_KmBM8{display:inline-flex}._code__line_m3IiO{padding:5px;position:relative}._code__line_m3IiO,._code__single_hbMte{font-family:monospace}._code__button_WwYE-{background-color:transparent;border:none;border-radius:4px;box-shadow:none;cursor:pointer;min-width:30px;outline:none;padding:4px 10px;position:absolute;right:5px;top:5px;transition:all .3s ease;z-index:1}._code__button_WwYE-._pending_fgHgD:before{animation:_loading-btn--fade-in_8z5an .33s ease,_loading-btn--rotation_QaopN .66s linear 0s infinite;border:2px solid hsla(0,0%,100%,.33);border-radius:50%;border-top-color:#000;content:\"\";display:inline-block;height:10.5px;left:50%;position:absolute;top:50%;width:10.5px}._code__button_WwYE-._success_kUPnO:after{animation:_loading-btn--fade-in_8z5an .6s ease;border-color:currentcolor;border-style:solid;border-width:0 0 1px 1px;content:\"\";display:inline-block;height:7px;left:50%;position:absolute;top:50%;transform:translate(-50%,-75%) rotate(-45deg);width:11px}._code__button_WwYE-._fail_cOpap:after,._code__button_WwYE-._fail_cOpap:before{content:\" \";height:13px;left:50%;position:absolute;top:50%;width:1px}._code__button_WwYE-._fail_cOpap:before{transform:translate(-50%,-50%) rotate(45deg)}._code__button_WwYE-._fail_cOpap:after{transform:translate(-50%,-50%) rotate(-45deg)}@keyframes _loading-btn--fade-in_8z5an{0%{opacity:0}to{opacity:1}}@keyframes _loading-btn--rotation_QaopN{0%{transform:translate(-50%,-50%) rotate(0deg)}to{transform:translate(-50%,-50%) rotate(1turn)}}._code__span_iSCmj{opacity:1;transition:opacity .3s ease}._code__span_iSCmj._hide_uqpax{opacity:0}._code__block_JehA4{padding:1px 5px}._code__block_line_U7lcQ{border-left:1px solid;margin-left:5px}._horizontal_J1jU-{border-bottom:1px solid;margin:0 5px;position:relative;width:calc(100% - 10px)}._todo_m6MIP{align-items:flex-end;display:inline-flex;height:100%;padding-left:3px;padding-right:3px}._todo_m6MIP>input{margin:0}._todo__checked_kemjy{text-decoration:line-through}._mention_cpzik{font-weight:700}";
757
+ const styles = {"header":"_header_XFwV5","level_1":"_level_1_-KPph","level_2":"_level_2_ecHlB","level_3":"_level_3_SYcVr","level_4":"_level_4_V3o5m","level_5":"_level_5_I7eVk","level_6":"_level_6_A3lbK","bold":"_bold_I8DT-","italic":"_italic_72qBe","blockquote":"_blockquote_Xq6O4","blockquote__inner":"_blockquote__inner_mjT0h","blockquote__inner-deep":"_blockquote__inner-deep_s6tNj","strike-through":"_strike-through_U64jP","list":"_list_MHIjT","common":"_common_0GdDi","link":"_link_7U9wl","link__label":"_link__label_dHGGf","image":"_image_KmBM8","code__line":"_code__line_m3IiO","code__single":"_code__single_hbMte","code__button":"_code__button_WwYE-","pending":"_pending_fgHgD","loading-btn--fade-in":"_loading-btn--fade-in_8z5an","loading-btn--rotation":"_loading-btn--rotation_QaopN","success":"_success_kUPnO","fail":"_fail_cOpap","code__span":"_code__span_iSCmj","hide":"_hide_uqpax","code__block":"_code__block_JehA4","code__block_line":"_code__block_line_U7lcQ","horizontal":"_horizontal_J1jU-","todo":"_todo_m6MIP","todo__checked":"_todo__checked_kemjy","mention":"_mention_cpzik"};
424
758
  styleInject(css_248z);
425
759
 
426
760
  const NAME_OF_BLOCKQUOTE_MARK = "QuoteMark";
427
- const CODE_OF_SPACE$1 = 32;
761
+ const CODE_OF_SPACE$2 = " ".codePointAt(0);
428
762
  const CODE_OF_BLOCKQUOTE_MARK = 62; // >
429
763
 
430
764
  class BlockquoteWidget extends view.WidgetType {
@@ -456,7 +790,7 @@ function getBlockquoteDecorations({ decorations, node, view }) {
456
790
  while (pos >= 0) {
457
791
  pos--;
458
792
  const currentCode = content.charCodeAt(pos);
459
- if (currentCode === CODE_OF_SPACE$1)
793
+ if (currentCode === CODE_OF_SPACE$2)
460
794
  continue;
461
795
  if (currentCode === CODE_OF_BLOCKQUOTE_MARK) {
462
796
  if (!isHasMark) {
@@ -492,7 +826,7 @@ function getBlockquoteSelectionDecorations({ decorations, node, view, forceActiv
492
826
  while (pos >= 0) {
493
827
  pos--;
494
828
  const currentCode = content.charCodeAt(pos);
495
- if (currentCode === CODE_OF_SPACE$1)
829
+ if (currentCode === CODE_OF_SPACE$2)
496
830
  continue;
497
831
  if (currentCode === CODE_OF_BLOCKQUOTE_MARK) {
498
832
  if (!isHasMark) {
@@ -529,7 +863,7 @@ const blockquoteDecorationPlugin = {
529
863
  };
530
864
 
531
865
  const NAME_OF_BOLD = "StrongEmphasis";
532
- const LIST_OF_BOLD_MARKS = new Set([95, 42]); // _ *
866
+ const LIST_OF_BOLD_MARKS = new Set(["_".codePointAt(0), "*".codePointAt(0)]);
533
867
 
534
868
  function getBoldDecorations({ decorations, node, view }) {
535
869
  if (node.name !== NAME_OF_BOLD) {
@@ -566,6 +900,8 @@ const boldDecorationPlugin = {
566
900
 
567
901
  const NAME_OF_FENCED_CODE = "FencedCode";
568
902
  const NAME_OF_INLINE_CODE = "InlineCode";
903
+ const NAME_OF_BLOCK_CODE = "CodeBlock";
904
+ const CODE_OF_SPACE$1 = " ".codePointAt(0);
569
905
  const CODE_OF_CODE_MARK = 96; // `
570
906
 
571
907
  class CodeWidget extends view.WidgetType {
@@ -731,8 +1067,39 @@ function getCodeSelectionDecorations({ decorations, node, view, forceActive, })
731
1067
  decorations.push(getHideDecoration({ range: [endMarkPosition.from, endMarkPosition.to] }));
732
1068
  }
733
1069
  }
1070
+ function getCodeBlockDecorations({ decorations, node, view }) {
1071
+ if (node.name !== NAME_OF_BLOCK_CODE)
1072
+ return;
1073
+ const lines = view.viewportLineBlocks.filter((line) => {
1074
+ const isOverlap = isRangeOverlap([node.from, node.to], [line.from, line.to]);
1075
+ return isOverlap;
1076
+ });
1077
+ lines.forEach((line) => {
1078
+ const content = view.state.sliceDoc(line.from, line.to);
1079
+ let startContent = 0;
1080
+ let pos = 0;
1081
+ while (pos < content.length) {
1082
+ if (content.codePointAt(pos) === CODE_OF_SPACE$1) {
1083
+ pos++;
1084
+ }
1085
+ else {
1086
+ startContent = pos;
1087
+ break;
1088
+ }
1089
+ }
1090
+ decorations.push(getMarkDecoration({
1091
+ range: [line.from + startContent, line.to],
1092
+ style: clsx(styles.code__block, CLASSES.codeBlock),
1093
+ }));
1094
+ decorations.push(getLineDecoration({
1095
+ range: [line.from],
1096
+ style: clsx(styles.code__block_line, CLASSES.codeBlockLine),
1097
+ }));
1098
+ });
1099
+ }
734
1100
  const codeDecorationPlugin = {
735
1101
  selectionDecorations: [getCodeSelectionDecorations],
1102
+ decorations: [getCodeBlockDecorations],
736
1103
  };
737
1104
 
738
1105
  const NAME_OF_HEADER = "ATXHeading";
@@ -889,7 +1256,7 @@ class ImageWidget extends view.WidgetType {
889
1256
  this.from = widget.from;
890
1257
  this.to = widget.to;
891
1258
  this.registerListeners(image);
892
- IMAGE_NODES[this.key] = image;
1259
+ IMAGE_NODES[this.key] = container;
893
1260
  EXISTING_WIDGETS.add(this.key);
894
1261
  return true;
895
1262
  }
@@ -997,6 +1364,28 @@ function isCorrectNode$1(text, link, node) {
997
1364
  function selectLink$1({ link, node, selection, start }) {
998
1365
  const startPosition = start ?? (node.textContent?.indexOf?.(link) || 0);
999
1366
  const endPosition = startPosition + link.length;
1367
+ if (startPosition === 0 && endPosition === 0) {
1368
+ const content = node.textContent;
1369
+ if (!content)
1370
+ return;
1371
+ let startPosition = 0;
1372
+ let pos = 0;
1373
+ while (pos < content.length) {
1374
+ if (content.codePointAt(pos) !== CODE_OF_START_IMAGE_URL) {
1375
+ pos++;
1376
+ }
1377
+ else {
1378
+ startPosition = pos + 1;
1379
+ break;
1380
+ }
1381
+ }
1382
+ const range = document.createRange();
1383
+ range.setStart(node, startPosition);
1384
+ range.collapse(true);
1385
+ selection.removeAllRanges();
1386
+ selection.addRange(range);
1387
+ return;
1388
+ }
1000
1389
  const range = document.createRange();
1001
1390
  range.setStart(node, startPosition);
1002
1391
  range.setEnd(node, endPosition);
@@ -1325,6 +1714,28 @@ function isCorrectNode(text, link, node) {
1325
1714
  function selectLink({ link, node, selection, start }) {
1326
1715
  const startPosition = start ?? (node.textContent?.indexOf?.(link) || 0);
1327
1716
  const endPosition = startPosition + link.length;
1717
+ if (startPosition === 0 && endPosition === 0) {
1718
+ const content = node.textContent;
1719
+ if (!content)
1720
+ return;
1721
+ let startPosition = 0;
1722
+ let pos = 0;
1723
+ while (pos < content.length) {
1724
+ if (content.codePointAt(pos) !== CODE_OF_START_LINK_URL) {
1725
+ pos++;
1726
+ }
1727
+ else {
1728
+ startPosition = pos + 1;
1729
+ break;
1730
+ }
1731
+ }
1732
+ const range = document.createRange();
1733
+ range.setStart(node, startPosition);
1734
+ range.collapse(true);
1735
+ selection.removeAllRanges();
1736
+ selection.addRange(range);
1737
+ return;
1738
+ }
1328
1739
  const range = document.createRange();
1329
1740
  range.setStart(node, startPosition);
1330
1741
  range.setEnd(node, endPosition);
@@ -1536,8 +1947,9 @@ const listDecorationPlugin = {
1536
1947
  selectionDecorations: [getListSelectionDecorations],
1537
1948
  };
1538
1949
 
1539
- const CODE_OF_START_MENTION = 64; // @
1540
- const CODE_OF_SPACE = 32;
1950
+ const CODE_OF_START_MENTION = "@".codePointAt(0); // @
1951
+ const CODE_OF_SPACE = " ".codePointAt(0);
1952
+ const CODE_OF_LINE_BREAK = "\n".codePointAt(0);
1541
1953
  const NAME_OF_MENTION = "Mention";
1542
1954
 
1543
1955
  function getMentionDecorations({ decorations, node }) {
@@ -1808,7 +2220,7 @@ async function InitSettings({ readonly, vimMode, }) {
1808
2220
  ];
1809
2221
  }
1810
2222
 
1811
- const initExtensions = async ({ onBlur, onChange, onFocus, onEnter, onEscape, readonly = true, vimMode = false, multiCursorText, provider, theme = "light", dark, light, languages, keyMaps, defaultKeyMaps, imageSrcGetter, }) => {
2223
+ const initExtensions = async ({ onBlur, onChange, onFocus, onEnter, onEscape, readonly = true, vimMode = false, multiCursorText, provider, theme = "light", dark, light, languages, keyMaps, defaultKeyMaps, imageSrcGetter, autoCompleteTagOptions, autoCompleteConfig, }) => {
1812
2224
  const multiCursorMode = Boolean(multiCursorText && provider);
1813
2225
  const asyncPlugins = await Promise.all([
1814
2226
  InitSettings({ readonly, vimMode }),
@@ -1824,10 +2236,11 @@ const initExtensions = async ({ onBlur, onChange, onFocus, onEnter, onEscape, re
1824
2236
  light,
1825
2237
  }),
1826
2238
  new Promise((resolve) => {
1827
- void Promise.resolve().then(() => require('./index-DU8JMAfc.js')).then(({ initMarkdown }) => {
2239
+ void Promise.resolve().then(() => require('./index-CXENq_0E.js')).then(({ initMarkdown }) => {
1828
2240
  resolve(initMarkdown({ languages, imageSrcGetter }));
1829
2241
  });
1830
2242
  }),
2243
+ initAutoComplete({ autoCompleteConfig, autoCompleteTagOptions }),
1831
2244
  ]);
1832
2245
  const extensions = [
1833
2246
  ...asyncPlugins,
@@ -2019,10 +2432,11 @@ class Editor {
2019
2432
  };
2020
2433
  }
2021
2434
 
2435
+ exports.CODE_OF_LINE_BREAK = CODE_OF_LINE_BREAK;
2022
2436
  exports.CODE_OF_SPACE = CODE_OF_SPACE;
2023
2437
  exports.CODE_OF_START_MENTION = CODE_OF_START_MENTION;
2024
2438
  exports.Editor = Editor;
2025
2439
  exports.NAME_OF_MENTION = NAME_OF_MENTION;
2026
2440
  exports.markdownDecorationPlugin = markdownDecorationPlugin;
2027
2441
  exports.markdownState = markdownState;
2028
- //# sourceMappingURL=index-BgxbH3r2.js.map
2442
+ //# sourceMappingURL=index-Dj0jRUGF.js.map