edytor 2.0.0 → 3.0.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 (222) hide show
  1. package/README.md +19 -4
  2. package/dist/block/block.svelte.js +2 -4
  3. package/dist/clipboard/htmlFlow.d.ts +20 -7
  4. package/dist/clipboard/htmlFlow.js +23 -15
  5. package/dist/clipboard/serializeClipboardFragment.d.ts +37 -4
  6. package/dist/clipboard/serializeClipboardFragment.js +6 -4
  7. package/dist/clipboard/textBlocks.d.ts +8 -0
  8. package/dist/clipboard/textBlocks.js +6 -2
  9. package/dist/cloudflare/room/admission.js +3 -3
  10. package/dist/cloudflare/room/context.d.ts +1 -1
  11. package/dist/cloudflare/routeDocumentSocket.d.ts +17 -0
  12. package/dist/cloudflare/routeDocumentSocket.js +53 -0
  13. package/dist/collaboration/comments/client.d.ts +1 -1
  14. package/dist/collaboration/comments/client.js +1 -1
  15. package/dist/collaboration/remoteSelection.js +3 -3
  16. package/dist/components/Edytor.svelte +2 -10
  17. package/dist/components/Edytor.svelte.d.ts +1 -3
  18. package/dist/crdt/admission.d.ts +5 -10
  19. package/dist/crdt/admission.js +5 -11
  20. package/dist/crdt/doc/funnel.d.ts +7 -6
  21. package/dist/crdt/doc/funnel.js +10 -9
  22. package/dist/crdt/doc/gate.d.ts +0 -17
  23. package/dist/crdt/doc/gate.js +2 -41
  24. package/dist/crdt/doc/history.js +2 -2
  25. package/dist/crdt/document.d.ts +5 -14
  26. package/dist/crdt/document.js +5 -19
  27. package/dist/crdt/edytor-doc.d.ts +4 -4
  28. package/dist/crdt/edytor-doc.js +3 -7
  29. package/dist/crdt/index.d.ts +3 -3
  30. package/dist/crdt/index.js +2 -2
  31. package/dist/crdt/protocol.d.ts +2 -2
  32. package/dist/crdt/protocol.js +2 -2
  33. package/dist/crdt/providers/index.d.ts +1 -1
  34. package/dist/crdt/providers/room.d.ts +10 -9
  35. package/dist/crdt/providers/room.js +13 -10
  36. package/dist/crdt/providers/websocket.d.ts +1 -1
  37. package/dist/crdt/providers/websocket.js +28 -29
  38. package/dist/crdt/semantics.js +3 -1
  39. package/dist/dnd/autoScroll.d.ts +15 -7
  40. package/dist/dnd/autoScroll.js +10 -15
  41. package/dist/dnd/dropIndicator.js +2 -5
  42. package/dist/dnd/external.d.ts +6 -0
  43. package/dist/dnd/external.js +17 -0
  44. package/dist/dnd/geometry.d.ts +2 -0
  45. package/dist/dnd/geometry.js +3 -4
  46. package/dist/dnd/placement.d.ts +1 -1
  47. package/dist/dnd/pragmatic.d.ts +3 -1
  48. package/dist/dnd/pragmatic.js +12 -2
  49. package/dist/dnd/vendor/pragmatic/UPSTREAM.md +51 -18
  50. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.d.ts +4 -0
  51. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js +6 -0
  52. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.d.ts +0 -2
  53. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.js +4 -22
  54. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter-types.d.ts +26 -0
  55. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.d.ts +30 -0
  56. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.js +203 -0
  57. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-items.js +13 -0
  58. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-types.js +9 -0
  59. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/is-an-available-type.js +19 -0
  60. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.d.ts +4 -0
  61. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.js +6 -0
  62. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/make-honey-pot-fix.js +4 -16
  63. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/internal-types.d.ts +1 -8
  64. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-drop-target.js +5 -6
  65. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-monitor.js +2 -3
  66. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.d.ts +1 -1
  67. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +6 -24
  68. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.d.ts +2 -0
  69. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js +5 -0
  70. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.d.ts +3 -0
  71. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js +12 -0
  72. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/native-types.d.ts +12 -0
  73. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window-in-safari.js +10 -0
  74. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window.js +55 -0
  75. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.d.ts +4 -0
  76. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.js +8 -0
  77. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/internal-types.d.ts +0 -4
  78. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/get-scroll-by.js +16 -72
  79. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/try-scroll.js +1 -9
  80. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/configuration.js +4 -29
  81. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-scroll-change.js +2 -3
  82. package/dist/edytor.svelte.d.ts +2 -5
  83. package/dist/edytor.svelte.js +17 -31
  84. package/dist/events/onBeforeInput.js +1 -1
  85. package/dist/events/onDrop.d.ts +0 -6
  86. package/dist/events/onDrop.js +10 -23
  87. package/dist/events/onInput.d.ts +0 -12
  88. package/dist/events/onInput.js +1 -67
  89. package/dist/export/forms.d.ts +627 -0
  90. package/dist/export/forms.js +749 -0
  91. package/dist/export/index.d.ts +170 -0
  92. package/dist/export/index.js +161 -0
  93. package/dist/export/markdown.d.ts +41 -0
  94. package/dist/export/markdown.js +585 -0
  95. package/dist/export/markdownWriter.d.ts +9 -0
  96. package/dist/export/markdownWriter.js +133 -0
  97. package/dist/export/mdx.d.ts +15 -0
  98. package/dist/export/mdx.js +33 -0
  99. package/dist/index.d.ts +3 -3
  100. package/dist/index.js +1 -1
  101. package/dist/kinds.js +1 -1
  102. package/dist/plugins/anchored.svelte.d.ts +21 -25
  103. package/dist/plugins/anchored.svelte.js +23 -39
  104. package/dist/plugins/blockHandles/BlockHandleController.svelte.js +24 -32
  105. package/dist/plugins/blockHandles/dragPreview.d.ts +26 -7
  106. package/dist/plugins/blockHandles/dragPreview.js +33 -0
  107. package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +5 -0
  108. package/dist/plugins/blockMenu/BlockMenuController.svelte.js +7 -2
  109. package/dist/plugins/blockMenu/blockMenuPlugin.js +5 -50
  110. package/dist/plugins/chrome.d.ts +27 -5
  111. package/dist/plugins/chrome.js +24 -9
  112. package/dist/plugins/code/CodePlugin.svelte +12 -9
  113. package/dist/plugins/code/header.svelte.js +7 -11
  114. package/dist/plugins/code/languageMenu.svelte.d.ts +5 -2
  115. package/dist/plugins/code/languageMenu.svelte.js +13 -20
  116. package/dist/plugins/columns/ColumnsPlugin.svelte +7 -20
  117. package/dist/plugins/columns/resize.svelte.d.ts +2 -3
  118. package/dist/plugins/columns/resize.svelte.js +2 -5
  119. package/dist/plugins/comments/CommentsController.svelte.d.ts +6 -0
  120. package/dist/plugins/comments/CommentsController.svelte.js +20 -0
  121. package/dist/plugins/equation/EquationPlugin.svelte +12 -22
  122. package/dist/plugins/equation/equation.svelte.d.ts +7 -15
  123. package/dist/plugins/equation/equation.svelte.js +13 -50
  124. package/dist/plugins/equation/tex.d.ts +17 -0
  125. package/dist/plugins/equation/tex.js +42 -0
  126. package/dist/plugins/fileDrop.d.ts +38 -23
  127. package/dist/plugins/fileDrop.js +82 -76
  128. package/dist/plugins/find/FindController.svelte.d.ts +5 -0
  129. package/dist/plugins/find/FindController.svelte.js +14 -14
  130. package/dist/plugins/find/findPlugin.js +1 -15
  131. package/dist/plugins/image/ImageChrome.svelte +8 -2
  132. package/dist/plugins/image/ImagePlugin.svelte +15 -52
  133. package/dist/plugins/image/controls.svelte.js +16 -2
  134. package/dist/plugins/image/toolbar.svelte.d.ts +5 -4
  135. package/dist/plugins/image/toolbar.svelte.js +21 -31
  136. package/dist/plugins/index.d.ts +1 -1
  137. package/dist/plugins/list.svelte.d.ts +9 -0
  138. package/dist/plugins/list.svelte.js +18 -0
  139. package/dist/plugins/marquee/marqueePlugin.js +0 -4
  140. package/dist/plugins/media/AudioPlugin.svelte +1 -1
  141. package/dist/plugins/media/BookmarkPlugin.svelte +6 -97
  142. package/dist/plugins/media/EmbedPlugin.svelte +5 -90
  143. package/dist/plugins/media/EmptySlot.svelte +36 -20
  144. package/dist/plugins/media/EmptySlot.svelte.d.ts +6 -15
  145. package/dist/plugins/media/FilePlugin.svelte +1 -19
  146. package/dist/plugins/media/MediaEmpty.svelte +2 -55
  147. package/dist/plugins/media/MediaEmpty.svelte.d.ts +18 -14
  148. package/dist/plugins/media/SourceBlock.svelte +142 -52
  149. package/dist/plugins/media/SourceBlock.svelte.d.ts +10 -4
  150. package/dist/plugins/media/VideoPlugin.svelte +1 -1
  151. package/dist/plugins/media/empty.svelte.js +2 -7
  152. package/dist/plugins/media/media.d.ts +2 -63
  153. package/dist/plugins/media/media.js +1 -194
  154. package/dist/plugins/media/sources.d.ts +60 -0
  155. package/dist/plugins/media/sources.js +165 -0
  156. package/dist/plugins/media/urlPaste.svelte.d.ts +2 -1
  157. package/dist/plugins/media/urlPaste.svelte.js +12 -21
  158. package/dist/plugins/mention/MentionPlugin.svelte +8 -35
  159. package/dist/plugins/page/PagePlugin.svelte +2 -9
  160. package/dist/plugins/page/page.js +1 -1
  161. package/dist/plugins/pageLink/PageLinkPlugin.svelte +6 -13
  162. package/dist/plugins/richtext/RichTextPlugin.svelte +85 -197
  163. package/dist/plugins/richtext/body.js +1 -1
  164. package/dist/plugins/richtext/calloutIcons.svelte.d.ts +2 -2
  165. package/dist/plugins/richtext/calloutIcons.svelte.js +5 -7
  166. package/dist/plugins/richtext/richTextOperations.d.ts +1 -19
  167. package/dist/plugins/richtext/richTextOperations.js +3 -49
  168. package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +2 -0
  169. package/dist/plugins/slashMenu/SlashMenuController.svelte.js +7 -0
  170. package/dist/plugins/slashMenu/slashMenuPlugin.js +5 -14
  171. package/dist/plugins/table/TableChrome.svelte +2 -3
  172. package/dist/plugins/table/TablePlugin.svelte +20 -54
  173. package/dist/plugins/table/chrome.svelte.d.ts +5 -2
  174. package/dist/plugins/table/chrome.svelte.js +30 -54
  175. package/dist/plugins/table/table.js +3 -3
  176. package/dist/plugins/toc/TocPlugin.svelte +2 -4
  177. package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +7 -0
  178. package/dist/plugins/toolbar/ToolbarController.svelte.js +20 -13
  179. package/dist/plugins/toolbar/toolbarPlugin.js +19 -53
  180. package/dist/plugins/triggers/TriggerController.svelte.d.ts +7 -2
  181. package/dist/plugins/triggers/TriggerController.svelte.js +11 -4
  182. package/dist/plugins/triggers/place.js +1 -2
  183. package/dist/plugins/triggers/triggers.d.ts +6 -1
  184. package/dist/plugins/triggers/triggers.js +12 -13
  185. package/dist/plugins/uploads.svelte.d.ts +5 -2
  186. package/dist/plugins/uploads.svelte.js +25 -15
  187. package/dist/plugins.d.ts +26 -0
  188. package/dist/plugins.js +0 -24
  189. package/dist/selection/replaceSelection.js +2 -2
  190. package/dist/selection/selection.svelte.d.ts +4 -10
  191. package/dist/selection/selection.svelte.js +7 -11
  192. package/dist/session/bindings.js +1 -1
  193. package/dist/session/commands.d.ts +7 -11
  194. package/dist/session/commands.js +13 -19
  195. package/dist/session/inputRules.js +1 -1
  196. package/dist/session/navigation.js +1 -1
  197. package/dist/session/suggestions.svelte.d.ts +0 -11
  198. package/dist/session/suggestions.svelte.js +15 -3
  199. package/dist/session/uploads.d.ts +8 -8
  200. package/dist/surface/lines.js +1 -3
  201. package/dist/surface/observer.svelte.d.ts +17 -1
  202. package/dist/surface/observer.svelte.js +72 -17
  203. package/dist/surface/overlay.d.ts +0 -14
  204. package/dist/surface/overlay.js +0 -25
  205. package/dist/surface/projector.svelte.js +1 -1
  206. package/dist/text/text.svelte.js +3 -13
  207. package/dist/utils/sanitize.d.ts +38 -0
  208. package/dist/utils/sanitize.js +82 -0
  209. package/dist/utils.d.ts +2 -0
  210. package/dist/utils.js +5 -0
  211. package/package.json +18 -1
  212. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/max-z-index.js +0 -3
  213. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/supports-popover.js +0 -16
  214. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/is-axis-allowed.js +0 -3
  215. package/dist/plugins/code/LanguageMenu.svelte +0 -25
  216. package/dist/plugins/code/LanguageMenu.svelte.d.ts +0 -9
  217. package/dist/plugins/equation/EquationEditor.svelte +0 -27
  218. package/dist/plugins/equation/EquationEditor.svelte.d.ts +0 -9
  219. package/dist/plugins/image/ImageToolbarHost.svelte +0 -37
  220. package/dist/plugins/image/ImageToolbarHost.svelte.d.ts +0 -9
  221. package/dist/plugins/richtext/CalloutIconPicker.svelte +0 -26
  222. package/dist/plugins/richtext/CalloutIconPicker.svelte.d.ts +0 -9
@@ -0,0 +1,170 @@
1
+ /**
2
+ * `edytor/export`: a document as HTML or Markdown, and HTML or Markdown
3
+ * as a document, by each kind's own forms (the clipboard's: `html`,
4
+ * `plain`, `markdown`, `parse`). Svelte-free and Worker-safe: it runs in a
5
+ * browser, in Node and in a Worker. Without `kinds` it reads the bundled
6
+ * kinds' forms ({@link bundledForms}); in a view, pass the view
7
+ * (`kinds: edytor`) to read its own records, your kinds included.
8
+ */
9
+ import type { JSONBlock, JSONDoc } from '../utils/json.js';
10
+ import { type ExportKinds } from '../clipboard/serializeClipboardFragment.js';
11
+ import { type HtmlParser } from '../clipboard/htmlFlow.js';
12
+ import { bundledRead, type KindForms } from './forms.js';
13
+ import { type MarkdownComponents, type MarkdownOptions } from './markdown.js';
14
+ import type { BlockForms } from './forms.js';
15
+ export { escapeHtml } from '../clipboard/serializeClipboardFragment.js';
16
+ export { textToBlocks, type MarkdownComponents, type MarkdownIssue, type MarkdownOptions } from './markdown.js';
17
+ export { mdxComponent } from './mdx.js';
18
+ export { codeForms, columnsForms, equationForms, imageForms, mediaForms, mentionForms, pageForms, pageLinkForms, richTextForms, richTextMarkForms, tableForms, tocForms, type AtomForms, type BlockForms, type KindForms, type MarkForms, type MathML } from './forms.js';
19
+ export type { ExportKinds, HtmlParser };
20
+ export type { MarkdownContext } from '../plugins.js';
21
+ /**
22
+ * Every bundled kind's, mark's and atom's forms, with each plugin's
23
+ * default options: what `toHTML`, `toMarkdown` and `fromHTML` read when
24
+ * given no `kinds` (each its own direction of them). A view's own records
25
+ * (`kinds: edytor`) carry its options (its callout icon, its embed
26
+ * providers, its page links).
27
+ */
28
+ export declare const bundledForms: {
29
+ blocks: Record<keyof ReturnType<typeof bundledRead>["blocks"], BlockForms>;
30
+ marks: {
31
+ bold: {
32
+ tag: string;
33
+ parse: (el: HTMLElement) => true | undefined;
34
+ };
35
+ italic: {
36
+ tag: string;
37
+ parse: (el: HTMLElement) => true | undefined;
38
+ };
39
+ underline: {
40
+ tag: string;
41
+ parse: (el: HTMLElement) => true | undefined;
42
+ };
43
+ strike: {
44
+ tag: string;
45
+ parse: (el: HTMLElement) => true | undefined;
46
+ };
47
+ code: {
48
+ tag: string;
49
+ };
50
+ link: {
51
+ tag: string;
52
+ attributes: (mark: {
53
+ href?: unknown;
54
+ target?: string;
55
+ }) => {
56
+ href: string | undefined;
57
+ target: string | undefined;
58
+ };
59
+ parse: (el: HTMLElement) => {
60
+ target?: string | undefined;
61
+ href: string;
62
+ } | undefined;
63
+ edge: "side-dependent";
64
+ };
65
+ superscript: {
66
+ tag: string;
67
+ };
68
+ subscript: {
69
+ tag: string;
70
+ };
71
+ color: {
72
+ tag: string;
73
+ attributes: (value: unknown) => {
74
+ style: string | undefined;
75
+ };
76
+ parse: (el: HTMLElement) => string | undefined;
77
+ };
78
+ highlight: {
79
+ tag: string;
80
+ attributes: (value: unknown) => {
81
+ style: string | undefined;
82
+ };
83
+ parse: (el: HTMLElement) => string | undefined;
84
+ };
85
+ };
86
+ inlineBlocks: {
87
+ inlineEquation: {
88
+ html?: (data: import("../utils/json.js").JSONInlineBlock["data"]) => string;
89
+ markdown?: (data: import("../utils/json.js").JSONInlineBlock["data"]) => string;
90
+ plain?: (data: import("../utils/json.js").JSONInlineBlock["data"]) => string;
91
+ parse?: (element: HTMLElement) => Record<string, import("../utils/json.js").SerializableContent> | undefined;
92
+ };
93
+ mention: import("../clipboard/serializeClipboardFragment.js").AtomForms;
94
+ pageLink: import("../clipboard/serializeClipboardFragment.js").AtomForms;
95
+ };
96
+ };
97
+ /** Which forms a conversion reads. */
98
+ export type ExportOptions = {
99
+ /**
100
+ * The kinds, marks and atoms to read: a view (`edytor`, its own records),
101
+ * or forms by name. A section left out is the bundled one; listed, it is
102
+ * exactly those (`{ blocks: { ...bundledForms.blocks, mine } }` adds yours;
103
+ * a shorter list allows only those). Default {@link bundledForms}.
104
+ */
105
+ kinds?: KindForms | ExportKinds;
106
+ /**
107
+ * MDX-lite, for `toMarkdown`: the tags to write, each the kind it stands
108
+ * for (`{ Endpoint: 'endpoint' }`), the map `fromMarkdown` reads. A block
109
+ * of a listed kind is its tag, its data the attributes (see
110
+ * {@link mdxComponent}); its kind's own `markdown` form is not used.
111
+ */
112
+ components?: MarkdownComponents;
113
+ };
114
+ /** What {@link fromHTML} reads. */
115
+ export type ImportOptions = ExportOptions & {
116
+ /**
117
+ * The HTML parser: the browser's `DOMParser` by default. On a server pass
118
+ * one (`import { DOMParser } from 'linkedom'`, or jsdom's
119
+ * `new JSDOM().window.DOMParser`). It only parses: nothing in the HTML
120
+ * runs or loads.
121
+ */
122
+ DOMParser?: HtmlParser;
123
+ };
124
+ /**
125
+ * A document (or blocks) as HTML: each block by its kind's `html` form, a
126
+ * run of list items in their list's element, text by its marks' elements.
127
+ * Values are escaped and links through the link sanitizer; ids and empty
128
+ * data are never written.
129
+ *
130
+ * ```ts
131
+ * import { toHTML } from 'edytor/export';
132
+ * const html = toHTML(value);
133
+ * ```
134
+ */
135
+ export declare const toHTML: (doc: JSONDoc | readonly JSONBlock[], options?: ExportOptions) => string;
136
+ /**
137
+ * A document (or blocks) as Markdown (CommonMark with GFM tables, task
138
+ * lists and strikethrough): each block by its kind's `markdown` form (else
139
+ * its `plain` form), marks by theirs, atoms by theirs (else their `plain`
140
+ * form). A toggle is a `<details>` disclosure, a callout a `> [!NOTE]`
141
+ * alert; `textToBlocks` reads both back.
142
+ */
143
+ export declare const toMarkdown: (doc: JSONDoc | readonly JSONBlock[], options?: ExportOptions) => string;
144
+ /**
145
+ * Markdown as a document: {@link textToBlocks}'s reading, as a `JSONDoc`.
146
+ * With `components`, MDX-lite tags (`<Endpoint operationId="getPet" />`)
147
+ * are blocks of the kinds they name; a tag it does not name, an
148
+ * expression, an import or an export stays text and is told to `onUnknown`.
149
+ *
150
+ * ```ts
151
+ * import { fromMarkdown } from 'edytor/export';
152
+ * const value = fromMarkdown(source, { components: { Endpoint: 'endpoint' } });
153
+ * ```
154
+ */
155
+ export declare const fromMarkdown: (source: string, options?: MarkdownOptions) => JSONDoc;
156
+ /**
157
+ * HTML as a document, the paste's reading (`flow.html.*`): only the kinds,
158
+ * marks and atoms of `kinds` survive (an unknown element is its text, a
159
+ * `script` or `style` nothing), every value through its record's `parse`
160
+ * hook (a link's href through the link sanitizer: `javascript:` drops the
161
+ * link, an image's source through the image's), and nothing executes: the
162
+ * parser only parses, no attribute is copied (`onerror`, `style`).
163
+ *
164
+ * ```ts
165
+ * import { DOMParser } from 'linkedom'; // on a server; the browser has its own
166
+ * import { fromHTML } from 'edytor/export';
167
+ * const value = fromHTML(html, { DOMParser });
168
+ * ```
169
+ */
170
+ export declare const fromHTML: (html: string, options?: ImportOptions) => JSONDoc;
@@ -0,0 +1,161 @@
1
+ import { blocksToHtml } from '../clipboard/serializeClipboardFragment.js';
2
+ import { blocksToMarkdown } from './markdownWriter.js';
3
+ import { linesOfHtml } from '../clipboard/htmlFlow.js';
4
+ import { bundledMarkdown, bundledRead, bundledWrite, codeForms, columnsForms, equationForms, htmlExtras, imageForms, listSiblings, markdownExtras, mediaForms, mentionForms, pageForms, pageLinkForms, parseExtras, richTextForms, richTextMarkForms, tableForms, tocForms } from './forms.js';
5
+ import { textToBlocks } from './markdown.js';
6
+ import { mdxComponent } from './mdx.js';
7
+ import { iconOf } from '../plugins/richtext/callouts.js';
8
+ export { escapeHtml } from '../clipboard/serializeClipboardFragment.js';
9
+ export { textToBlocks } from './markdown.js';
10
+ export { mdxComponent } from './mdx.js';
11
+ export { codeForms, columnsForms, equationForms, imageForms, mediaForms, mentionForms, pageForms, pageLinkForms, richTextForms, richTextMarkForms, tableForms, tocForms } from './forms.js';
12
+ /**
13
+ * Every bundled kind's, mark's and atom's forms, with each plugin's
14
+ * default options: what `toHTML`, `toMarkdown` and `fromHTML` read when
15
+ * given no `kinds` (each its own direction of them). A view's own records
16
+ * (`kinds: edytor`) carry its options (its callout icon, its embed
17
+ * providers, its page links).
18
+ */
19
+ export const bundledForms = /* @__PURE__ */ (() => {
20
+ const read = bundledRead().blocks;
21
+ const rich = { paragraph: {}, ...richTextForms(iconOf) };
22
+ // A rich text kind's presets' data, as its plugin lists them: HTML import finds a kind by a
23
+ // preset's tag (an `h2`, a `blockquote`). A view's records carry their own.
24
+ for (const type in rich)
25
+ if (read[type]?.presets)
26
+ rich[type] = { ...rich[type], presets: read[type].presets };
27
+ const equation = equationForms();
28
+ return {
29
+ blocks: {
30
+ ...rich,
31
+ ...codeForms(),
32
+ ...tableForms(),
33
+ ...imageForms(),
34
+ ...mediaForms(),
35
+ ...pageForms(),
36
+ ...tocForms(),
37
+ ...equation.blocks,
38
+ ...columnsForms()
39
+ },
40
+ marks: richTextMarkForms,
41
+ inlineBlocks: { mention: mentionForms(), pageLink: pageLinkForms(), ...equation.inlineBlocks }
42
+ };
43
+ })();
44
+ const isView = (kinds) => kinds.blocks instanceof Map;
45
+ /**
46
+ * `kinds` as the records a conversion reads, each with the forms of
47
+ * `extras` (by name) it lacks: its own win. A section left out is the
48
+ * direction's bundled one.
49
+ */
50
+ const recordsOf = (kinds, defaults, extras) => {
51
+ const own = kinds && isView(kinds) ? kinds : undefined;
52
+ const forms = (kinds ?? {});
53
+ let bundled;
54
+ const section = (key) => new Map([...(own?.[key] ?? Object.entries(forms[key] ?? (bundled ??= defaults())[key]))].map(([name, form]) => [
55
+ name,
56
+ {
57
+ ...(Object.hasOwn(extras[key], name) && extras[key][name]),
58
+ ...Object.fromEntries(Object.entries(form).filter(([, value]) => value !== undefined))
59
+ }
60
+ ]));
61
+ return {
62
+ blocks: section('blocks'),
63
+ marks: section('marks'),
64
+ inlineBlocks: section('inlineBlocks')
65
+ };
66
+ };
67
+ const blocksOf = (doc) => (Array.isArray(doc) ? doc : doc.children) ?? [];
68
+ /**
69
+ * A document (or blocks) as HTML: each block by its kind's `html` form, a
70
+ * run of list items in their list's element, text by its marks' elements.
71
+ * Values are escaped and links through the link sanitizer; ids and empty
72
+ * data are never written.
73
+ *
74
+ * ```ts
75
+ * import { toHTML } from 'edytor/export';
76
+ * const html = toHTML(value);
77
+ * ```
78
+ */
79
+ export const toHTML = (doc, options = {}) => {
80
+ const records = recordsOf(options.kinds, bundledWrite, {
81
+ blocks: htmlExtras(),
82
+ marks: {},
83
+ inlineBlocks: {}
84
+ });
85
+ return blocksToHtml([...blocksOf(doc)], records, listSiblings(records));
86
+ };
87
+ /**
88
+ * A document (or blocks) as Markdown (CommonMark with GFM tables, task
89
+ * lists and strikethrough): each block by its kind's `markdown` form (else
90
+ * its `plain` form), marks by theirs, atoms by theirs (else their `plain`
91
+ * form). A toggle is a `<details>` disclosure, a callout a `> [!NOTE]`
92
+ * alert; `textToBlocks` reads both back.
93
+ */
94
+ export const toMarkdown = (doc, options = {}) => {
95
+ const records = recordsOf(options.kinds, bundledMarkdown, markdownExtras());
96
+ // Each kind `components` lists written as its tag (the first tag naming it).
97
+ for (const [tag, type] of Object.entries(options.components ?? {}).reverse())
98
+ records.blocks.set(type, {
99
+ ...records.blocks.get(type),
100
+ markdown: (block, content, children) => mdxComponent(tag, block.data, content, children)
101
+ });
102
+ const md = blocksToMarkdown([...blocksOf(doc)], records);
103
+ return md ? `${md}\n` : '';
104
+ };
105
+ /**
106
+ * Markdown as a document: {@link textToBlocks}'s reading, as a `JSONDoc`.
107
+ * With `components`, MDX-lite tags (`<Endpoint operationId="getPet" />`)
108
+ * are blocks of the kinds they name; a tag it does not name, an
109
+ * expression, an import or an export stays text and is told to `onUnknown`.
110
+ *
111
+ * ```ts
112
+ * import { fromMarkdown } from 'edytor/export';
113
+ * const value = fromMarkdown(source, { components: { Endpoint: 'endpoint' } });
114
+ * ```
115
+ */
116
+ export const fromMarkdown = (source, options = {}) => ({
117
+ children: textToBlocks(source, options)
118
+ });
119
+ /** A parsed line's type resolved (its parent's default child), its empty data and children dropped. */
120
+ const settle = (line, parent, defaultChild) => {
121
+ const type = line.type ?? defaultChild(parent);
122
+ const block = { type, content: line.content ?? [] };
123
+ if (line.data && Object.keys(line.data).length)
124
+ block.data = line.data;
125
+ if (line.children?.length)
126
+ block.children = line.children.map((child) => settle(child, type, defaultChild));
127
+ return block;
128
+ };
129
+ /**
130
+ * HTML as a document, the paste's reading (`flow.html.*`): only the kinds,
131
+ * marks and atoms of `kinds` survive (an unknown element is its text, a
132
+ * `script` or `style` nothing), every value through its record's `parse`
133
+ * hook (a link's href through the link sanitizer: `javascript:` drops the
134
+ * link, an image's source through the image's), and nothing executes: the
135
+ * parser only parses, no attribute is copied (`onerror`, `style`).
136
+ *
137
+ * ```ts
138
+ * import { DOMParser } from 'linkedom'; // on a server; the browser has its own
139
+ * import { fromHTML } from 'edytor/export';
140
+ * const value = fromHTML(html, { DOMParser });
141
+ * ```
142
+ */
143
+ export const fromHTML = (html, options = {}) => {
144
+ const records = recordsOf(options.kinds, bundledRead, {
145
+ blocks: parseExtras(),
146
+ marks: {},
147
+ inlineBlocks: {}
148
+ });
149
+ const own = options.kinds?.document;
150
+ const defaultChild = own?.defaultChild.bind(own) ??
151
+ ((parent) => (parent !== null && records.blocks.get(parent)?.defaultChild) || 'paragraph');
152
+ const parser = options.DOMParser ?? globalThis.DOMParser;
153
+ if (!parser)
154
+ throw new Error("fromHTML: no DOMParser here; pass one (`import { DOMParser } from 'linkedom'`).");
155
+ // A fragment as a document's body: a server parser (linkedom) reads only whole documents.
156
+ const whole = /<(?:html|body)[\s>]/i.test(html)
157
+ ? html
158
+ : `<!doctype html><html><head></head><body>${html}</body></html>`;
159
+ const lines = linesOfHtml({ ...records, document: { defaultChild } }, whole, parser) ?? [];
160
+ return { children: lines.map((line) => settle(line, null, defaultChild)) };
161
+ };
@@ -0,0 +1,41 @@
1
+ import type { JSONBlock } from '../utils/json.js';
2
+ /** MDX-lite tags by name, each the kind it reads as: `{ Endpoint: 'endpoint' }`. */
3
+ export type MarkdownComponents = Readonly<Record<string, string>>;
4
+ /** A tag or line `fromMarkdown` kept as text, with why. */
5
+ export type MarkdownIssue = {
6
+ /**
7
+ * `component`: a tag `components` does not name; `expression`: an
8
+ * attribute whose value is not a string, a number, `true` or `false`
9
+ * (`{a + b}`, `{...props}`); `unclosed`: a tag without its closing tag;
10
+ * `import` / `export`: an MDX import or export line.
11
+ */
12
+ reason: 'component' | 'expression' | 'unclosed' | 'import' | 'export';
13
+ /** The line kept as text. */
14
+ source: string;
15
+ /** The tag's name, for a tag. */
16
+ name?: string;
17
+ };
18
+ export type MarkdownOptions = {
19
+ /** Read markdown (default `true`); `false` keeps every character as text. */
20
+ markdown?: boolean;
21
+ /** The kind of a paragraph (default `paragraph`). */
22
+ type?: string;
23
+ /**
24
+ * The text is still arriving (default `false`): hold back an unfinished
25
+ * last line's block marker or unclosed inline marker, and a table header
26
+ * row without its separator yet, so a streamed preview never shows raw
27
+ * markdown that the next chunk turns into a kind or a mark.
28
+ */
29
+ streaming?: boolean;
30
+ /**
31
+ * MDX-lite: the tags to read, each as the kind it names
32
+ * (`{ Endpoint: 'endpoint', Callout: 'callout' }`). Literal attributes
33
+ * (`"text"`, `{1}`, `{true}`) become the block's data; the tag's
34
+ * markdown its text (one line) or its text and children (lines).
35
+ */
36
+ components?: MarkdownComponents;
37
+ /** Told of each tag, expression, import or export kept as text. */
38
+ onUnknown?: (issue: MarkdownIssue) => void;
39
+ };
40
+ /** `text` as blocks (see the module comment). */
41
+ export declare const textToBlocks: (text: string, { markdown, type, streaming, components, onUnknown }?: MarkdownOptions) => JSONBlock[];