@doist/typist 1.2.8 → 1.3.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 (62) hide show
  1. package/CHANGELOG.md +14 -2
  2. package/dist/constants/extension-priorities.d.ts +7 -1
  3. package/dist/constants/extension-priorities.d.ts.map +1 -1
  4. package/dist/constants/extension-priorities.js +7 -1
  5. package/dist/extensions/plain-text/plain-text-kit.d.ts +4 -0
  6. package/dist/extensions/plain-text/plain-text-kit.d.ts.map +1 -1
  7. package/dist/extensions/plain-text/plain-text-kit.js +5 -0
  8. package/dist/extensions/rich-text/rich-text-image.d.ts.map +1 -1
  9. package/dist/extensions/rich-text/rich-text-image.js +4 -0
  10. package/dist/extensions/rich-text/rich-text-kit.d.ts +4 -0
  11. package/dist/extensions/rich-text/rich-text-kit.d.ts.map +1 -1
  12. package/dist/extensions/rich-text/rich-text-kit.js +5 -0
  13. package/dist/extensions/shared/paste-html-table-as-string.d.ts +16 -0
  14. package/dist/extensions/shared/paste-html-table-as-string.d.ts.map +1 -0
  15. package/dist/extensions/shared/paste-html-table-as-string.js +64 -0
  16. package/dist/extensions/shared/paste-singleline-text.js +1 -1
  17. package/dist/helpers/unified.d.ts +11 -0
  18. package/dist/helpers/unified.d.ts.map +1 -0
  19. package/dist/helpers/unified.js +12 -0
  20. package/dist/serializers/html/html.d.ts +3 -10
  21. package/dist/serializers/html/html.d.ts.map +1 -1
  22. package/dist/serializers/html/html.js +66 -48
  23. package/dist/serializers/html/plugins/rehype-code-block.d.ts +10 -0
  24. package/dist/serializers/html/plugins/rehype-code-block.d.ts.map +1 -0
  25. package/dist/serializers/html/plugins/rehype-code-block.js +22 -0
  26. package/dist/serializers/html/plugins/rehype-image.d.ts +11 -0
  27. package/dist/serializers/html/plugins/rehype-image.d.ts.map +1 -0
  28. package/dist/serializers/html/plugins/rehype-image.js +34 -0
  29. package/dist/serializers/html/plugins/rehype-suggestions.d.ts +10 -0
  30. package/dist/serializers/html/plugins/rehype-suggestions.d.ts.map +1 -0
  31. package/dist/serializers/html/plugins/rehype-suggestions.js +36 -0
  32. package/dist/serializers/html/plugins/rehype-task-list.d.ts +7 -0
  33. package/dist/serializers/html/plugins/rehype-task-list.d.ts.map +1 -0
  34. package/dist/serializers/html/plugins/rehype-task-list.js +37 -0
  35. package/dist/serializers/html/plugins/remark-disable-constructs.d.ts +11 -0
  36. package/dist/serializers/html/plugins/remark-disable-constructs.d.ts.map +1 -0
  37. package/dist/serializers/html/plugins/remark-disable-constructs.js +48 -0
  38. package/dist/serializers/html/plugins/remark-strikethrough.d.ts +18 -0
  39. package/dist/serializers/html/plugins/remark-strikethrough.d.ts.map +1 -0
  40. package/dist/serializers/html/plugins/remark-strikethrough.js +26 -0
  41. package/package.json +37 -25
  42. package/dist/serializers/html/extensions/checkbox.d.ts +0 -8
  43. package/dist/serializers/html/extensions/checkbox.d.ts.map +0 -1
  44. package/dist/serializers/html/extensions/checkbox.js +0 -12
  45. package/dist/serializers/html/extensions/code.d.ts +0 -9
  46. package/dist/serializers/html/extensions/code.d.ts.map +0 -1
  47. package/dist/serializers/html/extensions/code.js +0 -20
  48. package/dist/serializers/html/extensions/disabled.d.ts +0 -13
  49. package/dist/serializers/html/extensions/disabled.d.ts.map +0 -1
  50. package/dist/serializers/html/extensions/disabled.js +0 -125
  51. package/dist/serializers/html/extensions/html.d.ts +0 -10
  52. package/dist/serializers/html/extensions/html.d.ts.map +0 -1
  53. package/dist/serializers/html/extensions/html.js +0 -15
  54. package/dist/serializers/html/extensions/link.d.ts +0 -11
  55. package/dist/serializers/html/extensions/link.d.ts.map +0 -1
  56. package/dist/serializers/html/extensions/link.js +0 -25
  57. package/dist/serializers/html/extensions/paragraph.d.ts +0 -12
  58. package/dist/serializers/html/extensions/paragraph.d.ts.map +0 -1
  59. package/dist/serializers/html/extensions/paragraph.js +0 -51
  60. package/dist/serializers/html/extensions/task-list.d.ts +0 -9
  61. package/dist/serializers/html/extensions/task-list.d.ts.map +0 -1
  62. package/dist/serializers/html/extensions/task-list.js +0 -31
package/CHANGELOG.md CHANGED
@@ -1,8 +1,20 @@
1
+ ## [1.3.0](https://github.com/Doist/typist/compare/v1.2.9...v1.3.0) (2023-06-12)
2
+
3
+ ### Features
4
+
5
+ - Add the `PasteHTMLTableAsString` extension ([#290](https://github.com/Doist/typist/issues/290)) ([ee90014](https://github.com/Doist/typist/commit/ee90014c4c8bfa8c80b11ab5cae01ba434f942b6))
6
+
7
+ ## [1.2.9](https://github.com/Doist/typist/compare/v1.2.8...v1.2.9) (2023-06-01)
8
+
9
+ ### Bug Fixes
10
+
11
+ - **html-serializer:** Don't share instances between editors ([#275](https://github.com/Doist/typist/issues/275)) ([3aba8c7](https://github.com/Doist/typist/commit/3aba8c7b00b44e22a14ea2bc6d6dcad0f4f5ed80))
12
+
1
13
  ## [1.2.8](https://github.com/Doist/typist/compare/v1.2.7...v1.2.8) (2023-05-30)
2
14
 
3
- ### Reverts
15
+ ### Notes
4
16
 
5
- - Revert "ci: Add support to publish experimental releases" (#279) ([dc57964](https://github.com/Doist/typist/commit/dc57964c08f34606fa5070898f0415b4b8340190)), closes [#279](https://github.com/Doist/typist/issues/279) [#278](https://github.com/Doist/typist/issues/278)
17
+ - This version was published by mistake because we were unware that a `revert:` commit would publish a new version. There's no difference between `v1.2.7` and `v1.2.8`, the distributed code is exactly the same.
6
18
 
7
19
  ## [1.2.7](https://github.com/Doist/typist/compare/v1.2.6...v1.2.7) (2023-05-22)
8
20
 
@@ -10,6 +10,12 @@ declare const SUGGESTION_EXTENSION_PRIORITY = 1000;
10
10
  * extension can take precedence over the `ViewEventHandlers` extension event handlers.
11
11
  */
12
12
  declare const SMART_MARKDOWN_TYPING_PRIORITY = 110;
13
+ /**
14
+ * Priority for the `PasteHTMLTableAsString` extension. This needs to be higher than most paste
15
+ * extensions (e.g., `PasteSinglelineText`, `PasteMarkdown`, etc.), so that the extension can first
16
+ * parse HTML tables that might exist in the clipboard data.
17
+ */
18
+ declare const PASTE_EXTENSION_PRIORITY = 105;
13
19
  /**
14
20
  * Priority for the `ViewEventHandlers` extension. This needs to be higher than the default for most
15
21
  * of the built-in and official extensions (i.e. `100`), so that the event handlers from the
@@ -22,5 +28,5 @@ declare const VIEW_EVENT_HANDLERS_PRIORITY = 105;
22
28
  * precedence over the `Bold` extension keyboard shortcut.
23
29
  */
24
30
  declare const BLOCKQUOTE_EXTENSION_PRIORITY = 101;
25
- export { BLOCKQUOTE_EXTENSION_PRIORITY, SMART_MARKDOWN_TYPING_PRIORITY, SUGGESTION_EXTENSION_PRIORITY, VIEW_EVENT_HANDLERS_PRIORITY, };
31
+ export { BLOCKQUOTE_EXTENSION_PRIORITY, PASTE_EXTENSION_PRIORITY, SMART_MARKDOWN_TYPING_PRIORITY, SUGGESTION_EXTENSION_PRIORITY, VIEW_EVENT_HANDLERS_PRIORITY, };
26
32
  //# sourceMappingURL=extension-priorities.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension-priorities.d.ts","sourceRoot":"","sources":["../../src/constants/extension-priorities.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,QAAA,MAAM,6BAA6B,OAAO,CAAA;AAE1C;;;;GAIG;AACH,QAAA,MAAM,8BAA8B,MAAM,CAAA;AAE1C;;;;GAIG;AACH,QAAA,MAAM,4BAA4B,MAAM,CAAA;AAExC;;;;GAIG;AACH,QAAA,MAAM,6BAA6B,MAAM,CAAA;AAEzC,OAAO,EACH,6BAA6B,EAC7B,8BAA8B,EAC9B,6BAA6B,EAC7B,4BAA4B,GAC/B,CAAA"}
1
+ {"version":3,"file":"extension-priorities.d.ts","sourceRoot":"","sources":["../../src/constants/extension-priorities.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,QAAA,MAAM,6BAA6B,OAAO,CAAA;AAE1C;;;;GAIG;AACH,QAAA,MAAM,8BAA8B,MAAM,CAAA;AAE1C;;;;GAIG;AACH,QAAA,MAAM,wBAAwB,MAAM,CAAA;AAEpC;;;;GAIG;AACH,QAAA,MAAM,4BAA4B,MAAM,CAAA;AAExC;;;;GAIG;AACH,QAAA,MAAM,6BAA6B,MAAM,CAAA;AAEzC,OAAO,EACH,6BAA6B,EAC7B,wBAAwB,EACxB,8BAA8B,EAC9B,6BAA6B,EAC7B,4BAA4B,GAC/B,CAAA"}
@@ -10,6 +10,12 @@ const SUGGESTION_EXTENSION_PRIORITY = 1000;
10
10
  * extension can take precedence over the `ViewEventHandlers` extension event handlers.
11
11
  */
12
12
  const SMART_MARKDOWN_TYPING_PRIORITY = 110;
13
+ /**
14
+ * Priority for the `PasteHTMLTableAsString` extension. This needs to be higher than most paste
15
+ * extensions (e.g., `PasteSinglelineText`, `PasteMarkdown`, etc.), so that the extension can first
16
+ * parse HTML tables that might exist in the clipboard data.
17
+ */
18
+ const PASTE_EXTENSION_PRIORITY = 105;
13
19
  /**
14
20
  * Priority for the `ViewEventHandlers` extension. This needs to be higher than the default for most
15
21
  * of the built-in and official extensions (i.e. `100`), so that the event handlers from the
@@ -22,4 +28,4 @@ const VIEW_EVENT_HANDLERS_PRIORITY = 105;
22
28
  * precedence over the `Bold` extension keyboard shortcut.
23
29
  */
24
30
  const BLOCKQUOTE_EXTENSION_PRIORITY = 101;
25
- export { BLOCKQUOTE_EXTENSION_PRIORITY, SMART_MARKDOWN_TYPING_PRIORITY, SUGGESTION_EXTENSION_PRIORITY, VIEW_EVENT_HANDLERS_PRIORITY, };
31
+ export { BLOCKQUOTE_EXTENSION_PRIORITY, PASTE_EXTENSION_PRIORITY, SMART_MARKDOWN_TYPING_PRIORITY, SUGGESTION_EXTENSION_PRIORITY, VIEW_EVENT_HANDLERS_PRIORITY, };
@@ -18,6 +18,10 @@ type PlainTextKitOptions = {
18
18
  * Set options for the `Paragraph` extension, or `false` to disable.
19
19
  */
20
20
  paragraph: Partial<PlainTextParagraphOptions> | false;
21
+ /**
22
+ * Set to `false` to disable the `PasteHTMLTableAsString` extension.
23
+ */
24
+ pasteHTMLTableAsString: false;
21
25
  /**
22
26
  * Set to `false` to disable the `Text` extension.
23
27
  */
@@ -1 +1 @@
1
- {"version":3,"file":"plain-text-kit.d.ts","sourceRoot":"","sources":["../../../src/extensions/plain-text/plain-text-kit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAW,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAanE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAEvE;;GAEG;AACH,KAAK,mBAAmB,GAAG;IACvB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAA;IAEnD;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,KAAK,CAAA;IAExC;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,KAAK,CAAA;IAErD;;OAEG;IACH,IAAI,EAAE,KAAK,CAAA;IAEX;;OAEG;IACH,UAAU,EAAE,KAAK,CAAA;IAEjB;;OAEG;IACH,mBAAmB,EAAE,KAAK,CAAA;CAC7B,CAAA;AAED;;;;GAIG;AACH,QAAA,MAAM,YAAY,qCAyChB,CAAA;AAEF,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB,YAAY,EAAE,mBAAmB,EAAE,CAAA"}
1
+ {"version":3,"file":"plain-text-kit.d.ts","sourceRoot":"","sources":["../../../src/extensions/plain-text/plain-text-kit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAW,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAcnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAEvE;;GAEG;AACH,KAAK,mBAAmB,GAAG;IACvB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAA;IAEnD;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,KAAK,CAAA;IAExC;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,KAAK,CAAA;IAErD;;OAEG;IACH,sBAAsB,EAAE,KAAK,CAAA;IAE7B;;OAEG;IACH,IAAI,EAAE,KAAK,CAAA;IAEX;;OAEG;IACH,UAAU,EAAE,KAAK,CAAA;IAEjB;;OAEG;IACH,mBAAmB,EAAE,KAAK,CAAA;CAC7B,CAAA;AAED;;;;GAIG;AACH,QAAA,MAAM,YAAY,qCA8ChB,CAAA;AAEF,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB,YAAY,EAAE,mBAAmB,EAAE,CAAA"}
@@ -3,6 +3,7 @@ import { History } from '@tiptap/extension-history';
3
3
  import { Text } from '@tiptap/extension-text';
4
4
  import { Typography } from '@tiptap/extension-typography';
5
5
  import { CopyMarkdownSource } from '../shared/copy-markdown-source';
6
+ import { PasteHTMLTableAsString } from '../shared/paste-html-table-as-string';
6
7
  import { PasteSinglelineText } from '../shared/paste-singleline-text';
7
8
  import { SmartMarkdownTyping } from './smart-markdown-typing/smart-markdown-typing';
8
9
  import { PasteMultilineText } from './paste-multiline-text';
@@ -25,6 +26,10 @@ const PlainTextKit = Extension.create({
25
26
  this.options?.document?.multiline === false
26
27
  ? PasteSinglelineText
27
28
  : PasteMultilineText);
29
+ if (this.options?.pasteHTMLTableAsString !== false) {
30
+ // Supports pasting tables (from spreadsheets and websites) into the editor
31
+ extensions.push(PasteHTMLTableAsString);
32
+ }
28
33
  }
29
34
  if (this.options.history !== false) {
30
35
  extensions.push(History.configure(this.options?.history));
@@ -1 +1 @@
1
- {"version":3,"file":"rich-text-image.d.ts","sourceRoot":"","sources":["../../../src/extensions/rich-text/rich-text-image.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAElD;;GAEG;AACH,KAAK,uBAAuB,GAAG;IAC3B;;OAEG;IACH,QAAQ,CAAC,EAAE;QACP;;WAEG;QACH,YAAY,EAAE,MAAM,CAAA;QAEpB;;WAEG;QACH,cAAc,EAAE,OAAO,CAAA;QAEvB;;WAEG;QACH,cAAc,EAAE,MAAM,CAAA;KACzB,CAAA;CACJ,GAAG,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,GAC7B,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,CAAA;AAEpD;;;GAGG;AACH,OAAO,QAAQ,cAAc,CAAC;IAC1B,UAAU,QAAQ,CAAC,UAAU;QACzB,aAAa,EAAE;YACX;;eAEG;YACH,WAAW,EAAE,CAAC,UAAU,EAAE,uBAAuB,KAAK,UAAU,CAAA;YAEhE;;eAEG;YACH,WAAW,EAAE,CACT,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,GACxC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAC,KACtD,UAAU,CAAA;SAClB,CAAA;KACJ;CACJ;AAED;;GAEG;AACH,KAAK,oBAAoB,GAAG;IACxB;;OAEG;IACH,sBAAsB,EAAE,MAAM,EAAE,CAAA;IAEhC;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAA;IAEf;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEtC;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,CAAA;IAEtD;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAEvC;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;CACrD,CAAA;AAED;;;GAGG;AACH,QAAA,MAAM,aAAa,yDAoHjB,CAAA;AAEF,OAAO,EAAE,aAAa,EAAE,CAAA;AAExB,YAAY,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,CAAA"}
1
+ {"version":3,"file":"rich-text-image.d.ts","sourceRoot":"","sources":["../../../src/extensions/rich-text/rich-text-image.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAElD;;GAEG;AACH,KAAK,uBAAuB,GAAG;IAC3B;;OAEG;IACH,QAAQ,CAAC,EAAE;QACP;;WAEG;QACH,YAAY,EAAE,MAAM,CAAA;QAEpB;;WAEG;QACH,cAAc,EAAE,OAAO,CAAA;QAEvB;;WAEG;QACH,cAAc,EAAE,MAAM,CAAA;KACzB,CAAA;CACJ,GAAG,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,GAC7B,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,CAAA;AAEpD;;;GAGG;AACH,OAAO,QAAQ,cAAc,CAAC;IAC1B,UAAU,QAAQ,CAAC,UAAU;QACzB,aAAa,EAAE;YACX;;eAEG;YACH,WAAW,EAAE,CAAC,UAAU,EAAE,uBAAuB,KAAK,UAAU,CAAA;YAEhE;;eAEG;YACH,WAAW,EAAE,CACT,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,GACxC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAC,KACtD,UAAU,CAAA;SAClB,CAAA;KACJ;CACJ;AAED;;GAEG;AACH,KAAK,oBAAoB,GAAG;IACxB;;OAEG;IACH,sBAAsB,EAAE,MAAM,EAAE,CAAA;IAEhC;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAA;IAEf;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEtC;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC,CAAA;IAEtD;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAEvC;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;CACrD,CAAA;AAED;;;GAGG;AACH,QAAA,MAAM,aAAa,yDAyHjB,CAAA;AAEF,OAAO,EAAE,aAAa,EAAE,CAAA;AAExB,YAAY,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,CAAA"}
@@ -85,6 +85,10 @@ const RichTextImage = Image.extend({
85
85
  if (!onImageFilePaste) {
86
86
  return false;
87
87
  }
88
+ // Do not handle the event if there are multiple clipboard types
89
+ if ((event.clipboardData?.types || []).length > 1) {
90
+ return false;
91
+ }
88
92
  const pastedFiles = Array.from(event.clipboardData?.files || []);
89
93
  // Do not handle the event if no files were pasted
90
94
  if (pastedFiles.length === 0) {
@@ -105,6 +105,10 @@ type RichTextKitOptions = {
105
105
  * Set to `false` to disable the `PasteSinglelineText` extension.
106
106
  */
107
107
  pasteSinglelineText: false;
108
+ /**
109
+ * Set to `false` to disable the `PasteHTMLTableAsString` extension.
110
+ */
111
+ pasteHTMLTableAsString: false;
108
112
  /**
109
113
  * Set options for the `Strike` extension, or `false` to disable.
110
114
  */
@@ -1 +1 @@
1
- {"version":3,"file":"rich-text-kit.d.ts","sourceRoot":"","sources":["../../../src/extensions/rich-text/rich-text-kit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rich-text-kit.d.ts","sourceRoot":"","sources":["../../../src/extensions/rich-text/rich-text-kit.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ import { Text } from '@tiptap/extension-text';
19
19
  import { Typography } from '@tiptap/extension-typography';
20
20
  import { BLOCKQUOTE_EXTENSION_PRIORITY } from '../../constants/extension-priorities';
21
21
  import { CopyMarkdownSource } from '../shared/copy-markdown-source';
22
+ import { PasteHTMLTableAsString } from '../shared/paste-html-table-as-string';
22
23
  import { PasteSinglelineText } from '../shared/paste-singleline-text';
23
24
  import { BoldAndItalics } from './bold-and-italics';
24
25
  import { CurvenoteCodemark } from './curvenote-codemark';
@@ -75,6 +76,10 @@ const RichTextKit = Extension.create({
75
76
  // pasted lines together
76
77
  extensions.push(PasteSinglelineText);
77
78
  }
79
+ if (this.options?.pasteHTMLTableAsString !== false) {
80
+ // Supports pasting tables (from spreadsheets and websites) into the editor
81
+ extensions.push(PasteHTMLTableAsString);
82
+ }
78
83
  }
79
84
  if (this.options.dropCursor !== false) {
80
85
  extensions.push(Dropcursor.configure(this.options?.dropCursor));
@@ -0,0 +1,16 @@
1
+ import { Extension } from '@tiptap/core';
2
+ /**
3
+ * The `PasteHTMLTableAsString` extension adds the ability to paste a table copied from a spreadsheet
4
+ * web app (e.g., Google Sheets, Microsoft Excel), along with tables rendered by GitHub Flavored
5
+ * Markdown (GFM), into the editor.
6
+ *
7
+ * Since Typist does not yet support tables, this extension simply pastes the table as a string of
8
+ * paragraphs (one paragraph per row), with each cell separated by a space character. However,
9
+ * whenever we do add support for tables, this extension will need to be completely rewritten.
10
+ *
11
+ * Lastly, please note that formatting is lost when the copied table comes from Google Sheets or
12
+ * Microsoft Excel, because unfortunately, these apps style the cell contents using CSS.
13
+ */
14
+ declare const PasteHTMLTableAsString: Extension<any, any>;
15
+ export { PasteHTMLTableAsString };
16
+ //# sourceMappingURL=paste-html-table-as-string.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paste-html-table-as-string.d.ts","sourceRoot":"","sources":["../../../src/extensions/shared/paste-html-table-as-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAMxC;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,sBAAsB,qBAwD1B,CAAA;AAEF,OAAO,EAAE,sBAAsB,EAAE,CAAA"}
@@ -0,0 +1,64 @@
1
+ import { Extension } from '@tiptap/core';
2
+ import { Plugin, PluginKey } from 'prosemirror-state';
3
+ import { PASTE_EXTENSION_PRIORITY } from '../../constants/extension-priorities';
4
+ import { parseHtmlToElement } from '../../helpers/dom';
5
+ /**
6
+ * The `PasteHTMLTableAsString` extension adds the ability to paste a table copied from a spreadsheet
7
+ * web app (e.g., Google Sheets, Microsoft Excel), along with tables rendered by GitHub Flavored
8
+ * Markdown (GFM), into the editor.
9
+ *
10
+ * Since Typist does not yet support tables, this extension simply pastes the table as a string of
11
+ * paragraphs (one paragraph per row), with each cell separated by a space character. However,
12
+ * whenever we do add support for tables, this extension will need to be completely rewritten.
13
+ *
14
+ * Lastly, please note that formatting is lost when the copied table comes from Google Sheets or
15
+ * Microsoft Excel, because unfortunately, these apps style the cell contents using CSS.
16
+ */
17
+ const PasteHTMLTableAsString = Extension.create({
18
+ name: 'pasteHTMLTableAsString',
19
+ priority: PASTE_EXTENSION_PRIORITY,
20
+ addProseMirrorPlugins() {
21
+ return [
22
+ new Plugin({
23
+ key: new PluginKey('pasteHTMLTableAsString'),
24
+ props: {
25
+ transformPastedHTML(html) {
26
+ // Attempt to extract table(s) HTML from the pasted HTML
27
+ const tableHTML = html.match(/<table[^>]+>[\s\S]*?<\/table>/gi);
28
+ // Do not handle the event if no table HTML was found
29
+ if (!tableHTML) {
30
+ return html;
31
+ }
32
+ // Concatenate all tables into a single string of paragraphs
33
+ return tableHTML.reduce((result, table) => {
34
+ const { firstElementChild: tableElement } = parseHtmlToElement(table);
35
+ if (!tableElement) {
36
+ return result;
37
+ }
38
+ // Transform the table element into a string of paragraphs
39
+ return (result +
40
+ Array.from(tableElement.rows)
41
+ // Join each cell into a single string for each row
42
+ .reduce((acc, row) => {
43
+ return [
44
+ ...acc,
45
+ // Use `innerHTML` instead of `innerText` to preserve
46
+ // potential formatting (e.g., GFM) within each cell
47
+ Array.from(row.cells)
48
+ .map((cell) => cell.innerHTML)
49
+ .join(' '),
50
+ ];
51
+ }, [])
52
+ // Discard rows that are completely empty
53
+ .filter((row) => row.trim().length > 0)
54
+ // Wrap each row in a paragraph
55
+ .map((row) => `<p>${row}</p>`)
56
+ .join(''));
57
+ }, '');
58
+ },
59
+ },
60
+ }),
61
+ ];
62
+ },
63
+ });
64
+ export { PasteHTMLTableAsString };
@@ -23,7 +23,7 @@ const PasteSinglelineText = Extension.create({
23
23
  // Join break lines with a space character in-between
24
24
  .replace(/<br>/g, ' ')
25
25
  // Join paragraphs with a space character in-between
26
- .replace(/<p[^>]+>(.*?)<\/p>/g, '$1 ');
26
+ .replace(/<p[^>]*>(.*?)<\/p>/g, '$1 ');
27
27
  return isPlainTextDocument(view.state.schema)
28
28
  ? escape(bodyElement.innerText)
29
29
  : bodyElement.innerHTML;
@@ -0,0 +1,11 @@
1
+ import type { Node, Text } from 'hast';
2
+ /**
3
+ * Check if a given node is a unist text node.
4
+ *
5
+ * @param node The node to check.
6
+ *
7
+ * @returns `true` if the node is a unist text node, `false` otherwise.
8
+ */
9
+ declare function isTextNode(node: Node): node is Text;
10
+ export { isTextNode };
11
+ //# sourceMappingURL=unified.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified.d.ts","sourceRoot":"","sources":["../../src/helpers/unified.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAEtC;;;;;;GAMG;AACH,iBAAS,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,IAAI,CAE5C;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { is } from 'unist-util-is';
2
+ /**
3
+ * Check if a given node is a unist text node.
4
+ *
5
+ * @param node The node to check.
6
+ *
7
+ * @returns `true` if the node is a unist text node, `false` otherwise.
8
+ */
9
+ function isTextNode(node) {
10
+ return is(node, { type: 'text' });
11
+ }
12
+ export { isTextNode };
@@ -1,4 +1,3 @@
1
- import { marked } from 'marked';
2
1
  import type { Schema } from 'prosemirror-model';
3
2
  /**
4
3
  * The return type for the `createHTMLSerializer` function.
@@ -14,15 +13,9 @@ type HTMLSerializerReturnType = {
14
13
  serialize: (markdown: string) => string;
15
14
  };
16
15
  /**
17
- * Sensible default options to initialize the Marked parser with.
18
- *
19
- * @see https://marked.js.org/using_advanced#options
20
- */
21
- declare const INITIAL_MARKED_OPTIONS: marked.MarkedOptions;
22
- /**
23
- * Create a Markdown to HTML serializer with the Marked library for a rich-text editor, or use a
16
+ * Create a Markdown to HTML serializer with the unified ecosystem for a rich-text editor, or use a
24
17
  * custom serializer for a plain-text editor. The editor schema is used to detect which nodes and
25
- * marks are available in the editor, and only parses the input with the minimal required rules.
18
+ * marks are available in the editor, and only parses the input with the minimal required plugins.
26
19
  *
27
20
  * @param schema The editor schema to be used for nodes and marks detection.
28
21
  *
@@ -37,6 +30,6 @@ declare function createHTMLSerializer(schema: Schema): HTMLSerializerReturnType;
37
30
  * @returns The HTML serializer instance for the given editor schema.
38
31
  */
39
32
  declare function getHTMLSerializerInstance(schema: Schema): HTMLSerializerReturnType;
40
- export { createHTMLSerializer, getHTMLSerializerInstance, INITIAL_MARKED_OPTIONS };
33
+ export { createHTMLSerializer, getHTMLSerializerInstance };
41
34
  export type { HTMLSerializerReturnType };
42
35
  //# sourceMappingURL=html.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../src/serializers/html/html.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAc/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE/C;;GAEG;AACH,KAAK,wBAAwB,GAAG;IAC5B;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAA;CAC1C,CAAA;AASD;;;;GAIG;AACH,QAAA,MAAM,sBAAsB,EAAE,MAAM,CAAC,aAMpC,CAAA;AAmCD;;;;;;;;GAQG;AACH,iBAAS,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,wBAAwB,CAiDtE;AAOD;;;;;;GAMG;AACH,iBAAS,yBAAyB,CAAC,MAAM,EAAE,MAAM,4BAQhD;AAED,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,CAAA;AAElF,YAAY,EAAE,wBAAwB,EAAE,CAAA"}
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../src/serializers/html/html.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE/C;;GAEG;AACH,KAAK,wBAAwB,GAAG;IAC5B;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAA;CAC1C,CAAA;AA0CD;;;;;;;;GAQG;AACH,iBAAS,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,wBAAwB,CA2EtE;AAOD;;;;;;GAMG;AACH,iBAAS,yBAAyB,CAAC,MAAM,EAAE,MAAM,4BAQhD;AAED,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,CAAA;AAE1D,YAAY,EAAE,wBAAwB,EAAE,CAAA"}
@@ -1,27 +1,17 @@
1
1
  import { escape, kebabCase } from 'lodash-es';
2
- import { marked } from 'marked';
3
- import { REGEX_LINE_BREAKS } from '../../constants/regular-expressions';
2
+ import rehypeMinifyWhitespace from 'rehype-minify-whitespace';
3
+ import rehypeStringify from 'rehype-stringify';
4
+ import remarkBreaks from 'remark-breaks';
5
+ import remarkParse from 'remark-parse';
6
+ import remarkRehype from 'remark-rehype';
7
+ import { unified } from 'unified';
4
8
  import { computeSchemaId, isPlainTextDocument } from '../../helpers/schema';
5
- import { buildSuggestionSchemaPartialRegex } from '../../helpers/serializer';
6
- import { checkbox } from './extensions/checkbox';
7
- import { code } from './extensions/code';
8
- import { disabled } from './extensions/disabled';
9
- import { html } from './extensions/html';
10
- import { link } from './extensions/link';
11
- import { paragraph } from './extensions/paragraph';
12
- import { taskList } from './extensions/task-list';
13
- /**
14
- * Sensible default options to initialize the Marked parser with.
15
- *
16
- * @see https://marked.js.org/using_advanced#options
17
- */
18
- const INITIAL_MARKED_OPTIONS = {
19
- ...marked.getDefaults(),
20
- breaks: true,
21
- gfm: true,
22
- headerIds: false,
23
- silent: true,
24
- };
9
+ import { rehypeCodeBlock } from './plugins/rehype-code-block';
10
+ import { rehypeImage } from './plugins/rehype-image';
11
+ import { rehypeSuggestions } from './plugins/rehype-suggestions';
12
+ import { rehypeTaskList } from './plugins/rehype-task-list';
13
+ import { remarkDisableConstructs } from './plugins/remark-disable-constructs';
14
+ import { remarkStrikethrough } from './plugins/remark-strikethrough';
25
15
  /**
26
16
  * Create a custom Markdown to HTML serializer for plain-text editors only.
27
17
  *
@@ -49,9 +39,9 @@ function createHTMLSerializerForPlainTextEditor(schema) {
49
39
  };
50
40
  }
51
41
  /**
52
- * Create a Markdown to HTML serializer with the Marked library for a rich-text editor, or use a
42
+ * Create a Markdown to HTML serializer with the unified ecosystem for a rich-text editor, or use a
53
43
  * custom serializer for a plain-text editor. The editor schema is used to detect which nodes and
54
- * marks are available in the editor, and only parses the input with the minimal required rules.
44
+ * marks are available in the editor, and only parses the input with the minimal required plugins.
55
45
  *
56
46
  * @param schema The editor schema to be used for nodes and marks detection.
57
47
  *
@@ -62,35 +52,63 @@ function createHTMLSerializer(schema) {
62
52
  if (isPlainTextDocument(schema)) {
63
53
  return createHTMLSerializerForPlainTextEditor(schema);
64
54
  }
65
- // Reset Marked instance to the initial options
66
- marked.setOptions(INITIAL_MARKED_OPTIONS);
67
- // Disable built-in rules that are not supported by the schema
68
- marked.use(disabled(schema));
69
- // Overwrite some built-in rules for handling of special behaviours
70
- // (see documentation for each extension for more details)
71
- marked.use(checkbox, html, paragraph(schema.nodes.image));
72
- // Overwrite the built-in `code` rule if the corresponding node exists in the schema
55
+ // Initialize a unified processor with a remark plugin for parsing Markdown
56
+ const unifiedProcessor = unified().use(remarkParse);
57
+ // Configure the unified processor to use a custom plugin to disable constructs based on the
58
+ // supported extensions that are enabled in the editor schema
59
+ unifiedProcessor.use(remarkDisableConstructs, schema);
60
+ // Configure the unified processor to use a third-party plugin to turn soft line endings into
61
+ // hard breaks (i.e. `<br>`), which will display user content closer to how it was authored
62
+ // (although not CommonMark compliant, this resembles the behaviour we always supported)
63
+ if (schema.nodes.hardBreak) {
64
+ unifiedProcessor.use(remarkBreaks);
65
+ }
66
+ // Configure the unified processor to use a custom plugin to add support for the strikethrough
67
+ // extension from the GitHub Flavored Markdown (GFM) specification
68
+ if (schema.marks.strike) {
69
+ unifiedProcessor.use(remarkStrikethrough);
70
+ }
71
+ // Configure the unified processor with an official plugin to convert Markdown into HTML to
72
+ // support rehype (a tool that transforms HTML with plugins), followed by another official
73
+ // plugin to minify whitespace between tags (prevents line feeds from appearing as blank)
74
+ unifiedProcessor
75
+ .use(remarkRehype, {
76
+ // Persist raw HTML (disables support for custom elements/tags)
77
+ // ref: https://github.com/Doist/Issues/issues/5689
78
+ allowDangerousHtml: true,
79
+ })
80
+ // This must come before all rehype plugins that transform the HTML output
81
+ .use(rehypeMinifyWhitespace, {
82
+ // Preserve line breaks when collapsing whitespace (e.g., line feeds)
83
+ newlines: true,
84
+ });
85
+ // Configure the unified processor with a custom plugin to remove the trailing newline from code
86
+ // blocks (i.e. the newline between the last code line and `</code></pre>`)
73
87
  if (schema.nodes.codeBlock) {
74
- marked.use(code);
88
+ unifiedProcessor.use(rehypeCodeBlock);
75
89
  }
76
- // Add a rule for a task list if the corresponding nodes exists in the schema
77
- if (schema.nodes.taskList && schema.nodes.taskItem) {
78
- marked.use(taskList);
90
+ // Configure the unified processor with a custom plugin to remove the wrapping paragraph from
91
+ // images and to remove all inline images based on inline images support in the editor schema
92
+ if (schema.nodes.paragraph && schema.nodes.image) {
93
+ unifiedProcessor.use(rehypeImage, schema);
79
94
  }
80
- // Build a regular expression with all the available suggestion nodes from the schema
81
- const suggestionSchemaPartialRegex = buildSuggestionSchemaPartialRegex(schema);
82
- // Overwrite the built-in link rule if any suggestion node exists in the schema
83
- if (suggestionSchemaPartialRegex) {
84
- marked.use(link(new RegExp(`^${suggestionSchemaPartialRegex}`)));
95
+ // Configure the unified processor with a custom plugin to add support Tiptap task lists
96
+ if (schema.nodes.taskList && schema.nodes.taskItem) {
97
+ unifiedProcessor.use(rehypeTaskList);
85
98
  }
99
+ // Configure the unified processor with a custom plugin to add support for suggestions nodes
100
+ unifiedProcessor.use(rehypeSuggestions, schema);
101
+ // Configure the unified processor with an official plugin that defines how to take a syntax
102
+ // tree as input and turn it into serialized HTML
103
+ unifiedProcessor.use(rehypeStringify, {
104
+ entities: {
105
+ // Compatibility with the previous implementation in Marked
106
+ useNamedReferences: true,
107
+ },
108
+ });
86
109
  return {
87
110
  serialize(markdown) {
88
- return (marked
89
- .parse(markdown)
90
- // Removes line breaks after HTML tags from the HTML output with a specially
91
- // crafted RegExp (this is needed to prevent the editor from converting newline
92
- // control characters to blank paragraphs).
93
- .replace(new RegExp(`>${REGEX_LINE_BREAKS.source}`, REGEX_LINE_BREAKS.flags), '>'));
111
+ return unifiedProcessor.processSync(markdown).toString();
94
112
  },
95
113
  };
96
114
  }
@@ -112,4 +130,4 @@ function getHTMLSerializerInstance(schema) {
112
130
  }
113
131
  return htmlSerializerInstanceById[id];
114
132
  }
115
- export { createHTMLSerializer, getHTMLSerializerInstance, INITIAL_MARKED_OPTIONS };
133
+ export { createHTMLSerializer, getHTMLSerializerInstance };
@@ -0,0 +1,10 @@
1
+ import type { Transformer } from 'unified';
2
+ /**
3
+ * A rehype plugin to remove the trailing newline from code blocks (i.e. the newline between the
4
+ * last code line and `</code></pre>`). Although that newline is part of the CommonMark
5
+ * specification, this custom plugin is required to prevent Tiptap from rendering a blank line at
6
+ * the end of the code block.
7
+ */
8
+ declare function rehypeCodeBlock(): Transformer;
9
+ export { rehypeCodeBlock };
10
+ //# sourceMappingURL=rehype-code-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rehype-code-block.d.ts","sourceRoot":"","sources":["../../../../src/serializers/html/plugins/rehype-code-block.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;GAKG;AACH,iBAAS,eAAe,IAAI,WAAW,CAiBtC;AAED,OAAO,EAAE,eAAe,EAAE,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { isElement } from 'hast-util-is-element';
2
+ import { visit } from 'unist-util-visit';
3
+ import { isTextNode } from '../../../helpers/unified';
4
+ /**
5
+ * A rehype plugin to remove the trailing newline from code blocks (i.e. the newline between the
6
+ * last code line and `</code></pre>`). Although that newline is part of the CommonMark
7
+ * specification, this custom plugin is required to prevent Tiptap from rendering a blank line at
8
+ * the end of the code block.
9
+ */
10
+ function rehypeCodeBlock() {
11
+ return (...[tree]) => {
12
+ visit(tree, 'element', (node) => {
13
+ if (isElement(node, 'pre') &&
14
+ isElement(node.children[0], 'code') &&
15
+ isTextNode(node.children[0].children[0])) {
16
+ node.children[0].children[0].value = node.children[0].children[0].value.replace(/\n$/, '');
17
+ }
18
+ });
19
+ return tree;
20
+ };
21
+ }
22
+ export { rehypeCodeBlock };
@@ -0,0 +1,11 @@
1
+ import type { Schema } from 'prosemirror-model';
2
+ import type { Transformer } from 'unified';
3
+ /**
4
+ * A rehype plugin to remove the wrapping paragraph from images and to remove all inline images if
5
+ * the editor was configured without inline image support (Tiptap default).
6
+ *
7
+ * @param schema The editor schema to be used for nodes and marks detection.
8
+ */
9
+ declare function rehypeImage(schema: Schema): Transformer;
10
+ export { rehypeImage };
11
+ //# sourceMappingURL=rehype-image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rehype-image.d.ts","sourceRoot":"","sources":["../../../../src/serializers/html/plugins/rehype-image.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;GAKG;AACH,iBAAS,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CA0BhD;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { isElement } from 'hast-util-is-element';
2
+ import { remove } from 'unist-util-remove';
3
+ import { visit } from 'unist-util-visit';
4
+ /**
5
+ * A rehype plugin to remove the wrapping paragraph from images and to remove all inline images if
6
+ * the editor was configured without inline image support (Tiptap default).
7
+ *
8
+ * @param schema The editor schema to be used for nodes and marks detection.
9
+ */
10
+ function rehypeImage(schema) {
11
+ const allowInlineImages = schema.nodes.image ? schema.nodes.image.spec.inline : false;
12
+ // Return the tree as-is if the editor does not support inline images
13
+ if (allowInlineImages) {
14
+ return (tree) => tree;
15
+ }
16
+ return (...[tree]) => {
17
+ visit(tree, 'element', (node, index, parent) => {
18
+ if (isElement(node, 'p')) {
19
+ const areAllChildrenImages = node.children.every((c) => isElement(c, 'img'));
20
+ // Replace the paragraph with the image children if all children are images, or
21
+ // remove all images from the paragraph if it contains non-image children since the
22
+ // editor does not support inline images
23
+ if (areAllChildrenImages) {
24
+ parent.children.splice(index, 1, ...node.children);
25
+ }
26
+ else {
27
+ remove(node, (n) => isElement(n, 'img'));
28
+ }
29
+ }
30
+ });
31
+ return tree;
32
+ };
33
+ }
34
+ export { rehypeImage };
@@ -0,0 +1,10 @@
1
+ import type { Schema } from 'prosemirror-model';
2
+ import type { Transformer } from 'unified';
3
+ /**
4
+ * A rehype plugin to add support for suggestions nodes (e.g., `@username` or `#channel).
5
+ *
6
+ * @param schema The editor schema to be used for suggestion nodes detection.
7
+ */
8
+ declare function rehypeSuggestions(schema: Schema): Transformer;
9
+ export { rehypeSuggestions };
10
+ //# sourceMappingURL=rehype-suggestions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rehype-suggestions.d.ts","sourceRoot":"","sources":["../../../../src/serializers/html/plugins/rehype-suggestions.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;GAIG;AACH,iBAAS,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CA+BtD;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAA"}