edytor 1.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 (287) hide show
  1. package/README.md +26 -69
  2. package/dist/block/block.svelte.d.ts +6 -4
  3. package/dist/block/block.svelte.js +12 -8
  4. package/dist/block/inlineBlock.svelte.d.ts +6 -2
  5. package/dist/block/inlineBlock.svelte.js +7 -2
  6. package/dist/clipboard/htmlFlow.d.ts +20 -7
  7. package/dist/clipboard/htmlFlow.js +23 -15
  8. package/dist/clipboard/serializeClipboardFragment.d.ts +37 -4
  9. package/dist/clipboard/serializeClipboardFragment.js +6 -4
  10. package/dist/clipboard/textBlocks.d.ts +8 -0
  11. package/dist/clipboard/textBlocks.js +6 -2
  12. package/dist/cloudflare/room/admission.js +3 -3
  13. package/dist/cloudflare/room/context.d.ts +7 -1
  14. package/dist/cloudflare/routeDocumentSocket.d.ts +17 -0
  15. package/dist/cloudflare/routeDocumentSocket.js +53 -0
  16. package/dist/collaboration/awarenessSelection.d.ts +22 -1
  17. package/dist/collaboration/awarenessSelection.js +42 -0
  18. package/dist/collaboration/comments/client.d.ts +1 -1
  19. package/dist/collaboration/comments/client.js +1 -1
  20. package/dist/collaboration/remoteSelection.js +3 -3
  21. package/dist/components/Block.svelte +3 -1
  22. package/dist/components/Edytor.svelte +38 -20
  23. package/dist/components/Edytor.svelte.d.ts +9 -4
  24. package/dist/components/InlineBlock.svelte +1 -1
  25. package/dist/crdt/admission.d.ts +5 -10
  26. package/dist/crdt/admission.js +5 -11
  27. package/dist/crdt/data.d.ts +10 -0
  28. package/dist/crdt/data.js +20 -2
  29. package/dist/crdt/doc/funnel.d.ts +7 -6
  30. package/dist/crdt/doc/funnel.js +10 -9
  31. package/dist/crdt/doc/gate.d.ts +0 -17
  32. package/dist/crdt/doc/gate.js +2 -41
  33. package/dist/crdt/doc/history.js +2 -2
  34. package/dist/crdt/doc/reads.d.ts +7 -0
  35. package/dist/crdt/doc/reads.js +11 -1
  36. package/dist/crdt/document.d.ts +13 -14
  37. package/dist/crdt/document.js +17 -19
  38. package/dist/crdt/edytor-doc.d.ts +22 -4
  39. package/dist/crdt/edytor-doc.js +5 -8
  40. package/dist/crdt/index.d.ts +9 -3
  41. package/dist/crdt/index.js +2 -2
  42. package/dist/crdt/operations.d.ts +1 -1
  43. package/dist/crdt/operations.js +1 -0
  44. package/dist/crdt/props.d.ts +32 -0
  45. package/dist/crdt/props.js +172 -0
  46. package/dist/crdt/protocol.d.ts +2 -2
  47. package/dist/crdt/protocol.js +2 -2
  48. package/dist/crdt/providers/index.d.ts +1 -1
  49. package/dist/crdt/providers/room.d.ts +10 -9
  50. package/dist/crdt/providers/room.js +13 -10
  51. package/dist/crdt/providers/websocket.d.ts +1 -1
  52. package/dist/crdt/providers/websocket.js +28 -29
  53. package/dist/crdt/semantics.js +3 -1
  54. package/dist/dnd/autoScroll.d.ts +15 -7
  55. package/dist/dnd/autoScroll.js +10 -15
  56. package/dist/{plugins/blockHandles → dnd}/dropIndicator.d.ts +2 -2
  57. package/dist/{plugins/blockHandles → dnd}/dropIndicator.js +2 -5
  58. package/dist/dnd/external.d.ts +6 -0
  59. package/dist/dnd/external.js +17 -0
  60. package/dist/{plugins/blockHandles → dnd}/geometry.d.ts +4 -2
  61. package/dist/{plugins/blockHandles → dnd}/geometry.js +3 -4
  62. package/dist/dnd/placement.d.ts +200 -0
  63. package/dist/dnd/placement.js +426 -0
  64. package/dist/dnd/pragmatic.d.ts +3 -1
  65. package/dist/dnd/pragmatic.js +12 -2
  66. package/dist/dnd/vendor/pragmatic/UPSTREAM.md +51 -18
  67. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.d.ts +4 -0
  68. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js +6 -0
  69. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.d.ts +0 -2
  70. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.js +4 -22
  71. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter-types.d.ts +26 -0
  72. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.d.ts +30 -0
  73. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.js +203 -0
  74. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-items.js +13 -0
  75. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-types.js +9 -0
  76. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/is-an-available-type.js +19 -0
  77. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.d.ts +4 -0
  78. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.js +6 -0
  79. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/make-honey-pot-fix.js +4 -16
  80. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/internal-types.d.ts +1 -8
  81. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-drop-target.js +5 -6
  82. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-monitor.js +2 -3
  83. 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
  84. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +6 -24
  85. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.d.ts +2 -0
  86. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js +5 -0
  87. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.d.ts +3 -0
  88. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js +12 -0
  89. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/native-types.d.ts +12 -0
  90. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window-in-safari.js +10 -0
  91. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window.js +55 -0
  92. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.d.ts +4 -0
  93. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.js +8 -0
  94. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/internal-types.d.ts +0 -4
  95. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/get-scroll-by.js +16 -72
  96. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/try-scroll.js +1 -9
  97. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/configuration.js +4 -29
  98. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-scroll-change.js +2 -3
  99. package/dist/edytor.svelte.d.ts +19 -9
  100. package/dist/edytor.svelte.js +28 -33
  101. package/dist/events/beforeInputCommands.d.ts +2 -2
  102. package/dist/events/beforeInputCommands.js +8 -4
  103. package/dist/events/onBeforeInput.js +1 -1
  104. package/dist/events/onDrop.js +25 -10
  105. package/dist/events/onInput.d.ts +0 -12
  106. package/dist/events/onInput.js +1 -67
  107. package/dist/events/onPaste.d.ts +2 -1
  108. package/dist/events/onPaste.js +8 -3
  109. package/dist/export/forms.d.ts +627 -0
  110. package/dist/export/forms.js +749 -0
  111. package/dist/export/index.d.ts +170 -0
  112. package/dist/export/index.js +161 -0
  113. package/dist/export/markdown.d.ts +41 -0
  114. package/dist/export/markdown.js +585 -0
  115. package/dist/export/markdownWriter.d.ts +9 -0
  116. package/dist/export/markdownWriter.js +133 -0
  117. package/dist/export/mdx.d.ts +15 -0
  118. package/dist/export/mdx.js +33 -0
  119. package/dist/index.d.ts +4 -4
  120. package/dist/index.js +2 -2
  121. package/dist/kinds.js +1 -1
  122. package/dist/labels.d.ts +2 -0
  123. package/dist/labels.js +2 -1
  124. package/dist/plugins/anchored.svelte.d.ts +21 -25
  125. package/dist/plugins/anchored.svelte.js +23 -39
  126. package/dist/plugins/arrowMove/arrowMove.d.ts +1 -1
  127. package/dist/plugins/arrowMove/arrowMove.js +1 -1
  128. package/dist/plugins/blockHandles/BlockHandleController.svelte.d.ts +2 -122
  129. package/dist/plugins/blockHandles/BlockHandleController.svelte.js +48 -414
  130. package/dist/plugins/blockHandles/BlockHandles.svelte +14 -32
  131. package/dist/plugins/blockHandles/blockHandlesPlugin.js +2 -1
  132. package/dist/plugins/blockHandles/dragPreview.d.ts +26 -7
  133. package/dist/plugins/blockHandles/dragPreview.js +33 -0
  134. package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +5 -0
  135. package/dist/plugins/blockMenu/BlockMenuController.svelte.js +7 -2
  136. package/dist/plugins/blockMenu/blockMenuPlugin.js +5 -50
  137. package/dist/plugins/chrome.d.ts +27 -5
  138. package/dist/plugins/chrome.js +24 -9
  139. package/dist/plugins/code/CodeHeader.svelte +5 -3
  140. package/dist/plugins/code/CodePlugin.svelte +15 -12
  141. package/dist/plugins/code/header.svelte.js +7 -11
  142. package/dist/plugins/code/languageMenu.svelte.d.ts +5 -2
  143. package/dist/plugins/code/languageMenu.svelte.js +13 -20
  144. package/dist/plugins/code/languages.d.ts +0 -3
  145. package/dist/plugins/code/languages.js +0 -2
  146. package/dist/plugins/columns/ColumnResize.svelte +3 -2
  147. package/dist/plugins/columns/ColumnsPlugin.svelte +8 -21
  148. package/dist/plugins/columns/gaps.d.ts +7 -5
  149. package/dist/plugins/columns/gaps.js +11 -6
  150. package/dist/plugins/columns/resize.svelte.d.ts +5 -6
  151. package/dist/plugins/columns/resize.svelte.js +12 -14
  152. package/dist/plugins/comments/CommentsController.svelte.d.ts +6 -0
  153. package/dist/plugins/comments/CommentsController.svelte.js +20 -0
  154. package/dist/plugins/equation/EquationPlugin.svelte +13 -30
  155. package/dist/plugins/equation/EquationPlugin.svelte.d.ts +1 -0
  156. package/dist/plugins/equation/equation.css +7 -0
  157. package/dist/plugins/equation/equation.svelte.d.ts +7 -15
  158. package/dist/plugins/equation/equation.svelte.js +13 -50
  159. package/dist/plugins/equation/tex.d.ts +17 -0
  160. package/dist/plugins/equation/tex.js +42 -0
  161. package/dist/plugins/fileDrop.d.ts +43 -0
  162. package/dist/plugins/fileDrop.js +122 -0
  163. package/dist/plugins/find/FindController.svelte.d.ts +5 -0
  164. package/dist/plugins/find/FindController.svelte.js +14 -14
  165. package/dist/plugins/find/findPlugin.js +1 -15
  166. package/dist/plugins/image/ImageChrome.svelte +8 -2
  167. package/dist/plugins/image/ImagePlugin.svelte +56 -84
  168. package/dist/plugins/image/ImagePlugin.svelte.d.ts +13 -1
  169. package/dist/plugins/image/controls.svelte.js +16 -2
  170. package/dist/plugins/image/image.css +17 -0
  171. package/dist/plugins/image/toolbar.svelte.d.ts +5 -4
  172. package/dist/plugins/image/toolbar.svelte.js +21 -31
  173. package/dist/plugins/index.d.ts +4 -5
  174. package/dist/plugins/index.js +0 -1
  175. package/dist/plugins/list.svelte.d.ts +9 -0
  176. package/dist/plugins/list.svelte.js +18 -0
  177. package/dist/plugins/markdownShortcuts.js +5 -5
  178. package/dist/plugins/marquee/marqueePlugin.js +0 -4
  179. package/dist/plugins/media/AudioPlugin.svelte +13 -1
  180. package/dist/plugins/media/AudioPlugin.svelte.d.ts +11 -1
  181. package/dist/plugins/media/BookmarkPlugin.svelte +6 -97
  182. package/dist/plugins/media/EmbedPlugin.svelte +5 -90
  183. package/dist/plugins/media/EmptySlot.svelte +36 -20
  184. package/dist/plugins/media/EmptySlot.svelte.d.ts +6 -15
  185. package/dist/plugins/media/FilePlugin.svelte +12 -20
  186. package/dist/plugins/media/FilePlugin.svelte.d.ts +9 -0
  187. package/dist/plugins/media/MediaEmpty.svelte +2 -55
  188. package/dist/plugins/media/MediaEmpty.svelte.d.ts +18 -14
  189. package/dist/plugins/media/SourceBlock.svelte +178 -52
  190. package/dist/plugins/media/SourceBlock.svelte.d.ts +13 -6
  191. package/dist/plugins/media/UploadPreview.svelte +32 -0
  192. package/dist/plugins/media/UploadPreview.svelte.d.ts +11 -0
  193. package/dist/plugins/media/VideoPlugin.svelte +13 -1
  194. package/dist/plugins/media/VideoPlugin.svelte.d.ts +11 -1
  195. package/dist/plugins/media/empty.svelte.d.ts +13 -4
  196. package/dist/plugins/media/empty.svelte.js +32 -26
  197. package/dist/plugins/media/media.d.ts +9 -63
  198. package/dist/plugins/media/media.js +1 -194
  199. package/dist/plugins/media/sources.d.ts +60 -0
  200. package/dist/plugins/media/sources.js +165 -0
  201. package/dist/plugins/media/upload.css +23 -0
  202. package/dist/plugins/media/urlPaste.svelte.d.ts +2 -1
  203. package/dist/plugins/media/urlPaste.svelte.js +12 -21
  204. package/dist/plugins/mention/MentionPlugin.svelte +50 -38
  205. package/dist/plugins/mention/MentionPlugin.svelte.d.ts +11 -2
  206. package/dist/plugins/mention/mention.css +6 -0
  207. package/dist/plugins/page/PagePlugin.svelte +2 -9
  208. package/dist/plugins/page/page.js +1 -1
  209. package/dist/plugins/pageLink/PageLinkPlugin.svelte +126 -28
  210. package/dist/plugins/pageLink/PageLinkPlugin.svelte.d.ts +13 -1
  211. package/dist/plugins/pageLink/pageLink.css +6 -0
  212. package/dist/plugins/richtext/RichTextPlugin.svelte +99 -204
  213. package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +1 -0
  214. package/dist/plugins/richtext/body.js +1 -1
  215. package/dist/plugins/richtext/calloutIcons.svelte.d.ts +2 -2
  216. package/dist/plugins/richtext/calloutIcons.svelte.js +5 -7
  217. package/dist/plugins/richtext/richTextOperations.d.ts +1 -19
  218. package/dist/plugins/richtext/richTextOperations.js +3 -49
  219. package/dist/plugins/richtext/richtext.css +6 -0
  220. package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +2 -0
  221. package/dist/plugins/slashMenu/SlashMenuController.svelte.js +7 -0
  222. package/dist/plugins/slashMenu/slashMenuPlugin.js +5 -14
  223. package/dist/plugins/table/TableChrome.svelte +2 -3
  224. package/dist/plugins/table/TablePlugin.svelte +20 -54
  225. package/dist/plugins/table/chrome.svelte.d.ts +5 -2
  226. package/dist/plugins/table/chrome.svelte.js +33 -56
  227. package/dist/plugins/table/table.js +3 -3
  228. package/dist/plugins/toc/TocPlugin.svelte +2 -4
  229. package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +7 -0
  230. package/dist/plugins/toolbar/ToolbarController.svelte.js +20 -13
  231. package/dist/plugins/toolbar/toolbarPlugin.js +19 -53
  232. package/dist/plugins/triggers/TriggerController.svelte.d.ts +7 -2
  233. package/dist/plugins/triggers/TriggerController.svelte.js +11 -4
  234. package/dist/plugins/triggers/place.js +1 -2
  235. package/dist/plugins/triggers/triggers.d.ts +6 -1
  236. package/dist/plugins/triggers/triggers.js +12 -13
  237. package/dist/plugins/uploads.svelte.d.ts +48 -32
  238. package/dist/plugins/uploads.svelte.js +119 -43
  239. package/dist/plugins.d.ts +66 -14
  240. package/dist/plugins.js +0 -24
  241. package/dist/selection/replaceSelection.js +2 -2
  242. package/dist/selection/selection.svelte.d.ts +4 -10
  243. package/dist/selection/selection.svelte.js +7 -11
  244. package/dist/session/attempt.d.ts +16 -6
  245. package/dist/session/attempt.js +1 -0
  246. package/dist/session/bindings.js +35 -32
  247. package/dist/session/commands.d.ts +7 -11
  248. package/dist/session/commands.js +15 -19
  249. package/dist/session/history.js +1 -0
  250. package/dist/session/inputRules.d.ts +6 -3
  251. package/dist/session/inputRules.js +10 -6
  252. package/dist/session/moves.d.ts +33 -0
  253. package/dist/session/moves.js +71 -1
  254. package/dist/session/navigation.d.ts +7 -0
  255. package/dist/session/navigation.js +20 -11
  256. package/dist/session/props.d.ts +28 -0
  257. package/dist/session/props.js +65 -0
  258. package/dist/session/suggestions.svelte.d.ts +0 -11
  259. package/dist/session/suggestions.svelte.js +15 -3
  260. package/dist/session/uploads.d.ts +29 -0
  261. package/dist/session/uploads.js +10 -0
  262. package/dist/surface/lines.js +1 -3
  263. package/dist/surface/observer.svelte.d.ts +17 -1
  264. package/dist/surface/observer.svelte.js +72 -17
  265. package/dist/surface/overlay.d.ts +0 -14
  266. package/dist/surface/overlay.js +0 -25
  267. package/dist/surface/projector.svelte.js +1 -1
  268. package/dist/text/text.svelte.js +3 -13
  269. package/dist/themes/notion.css +9 -0
  270. package/dist/utils/sanitize.d.ts +38 -0
  271. package/dist/utils/sanitize.js +82 -0
  272. package/dist/utils.d.ts +2 -0
  273. package/dist/utils.js +5 -0
  274. package/package.json +18 -1
  275. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/max-z-index.js +0 -3
  276. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/supports-popover.js +0 -16
  277. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/is-axis-allowed.js +0 -3
  278. package/dist/plugins/code/LanguageMenu.svelte +0 -25
  279. package/dist/plugins/code/LanguageMenu.svelte.d.ts +0 -9
  280. package/dist/plugins/equation/EquationEditor.svelte +0 -27
  281. package/dist/plugins/equation/EquationEditor.svelte.d.ts +0 -9
  282. package/dist/plugins/image/ImageToolbarHost.svelte +0 -37
  283. package/dist/plugins/image/ImageToolbarHost.svelte.d.ts +0 -9
  284. package/dist/plugins/richtext/CalloutIconPicker.svelte +0 -26
  285. package/dist/plugins/richtext/CalloutIconPicker.svelte.d.ts +0 -9
  286. /package/dist/{plugins/columns → dnd}/stacking.d.ts +0 -0
  287. /package/dist/{plugins/columns → dnd}/stacking.js +0 -0
@@ -3,8 +3,9 @@
3
3
 
4
4
  /**
5
5
  * The resize bands of the hovered layout and the guide of a drag
6
- * (`ColumnResize`), in the overlay: each band the gap's left part, above
7
- * the block handles (their `+` and grip together right of it, `gaps.ts`);
6
+ * (`ColumnResize`), in the overlay: each band centered in its gap, above
7
+ * the block handles (their `+` and grip flush with the
8
+ * column, `gaps.ts`);
8
9
  * hovered, it shows a gray guide in its middle: where the guide shows, a
9
10
  * press resizes. A band is a focusable separator: its arrows resize
10
11
  * (`resize.key`), focused it shows its guide in the resize color.
@@ -1,16 +1,17 @@
1
1
  <script module lang="ts">
2
+ import { columnsForms } from '../../export/forms.js';
2
3
  import './columns.css';
3
4
  import type { BlockSnippetPayload, BlockView, EditorCommand, Plugin } from '../../plugins.js';
4
5
  import type { Edytor } from '../../edytor.svelte.js';
5
6
  import type { Block } from '../../block/block.svelte.js';
6
- import { layoutKinds } from '../../crdt/semantics.js';
7
+
7
8
  import { convertToKind, wrapBlocks, wrappable, type KindRow } from '../../kinds.js';
8
9
  import {
9
10
  getSelectedBlocksInDocumentOrder,
10
11
  liftLayouts
11
12
  } from '../../selection/replaceSelection.js';
12
13
  import ColumnResizeStrips from './ColumnResize.svelte';
13
- import { ColumnResize, weightOf } from './resize.svelte.js';
14
+ import { ColumnResize } from './resize.svelte.js';
14
15
  import { hoverChrome } from '../bands.svelte.js';
15
16
  import { all, listen } from '../../utils/listen.js';
16
17
  import { columnsEnglish, keywordsOf, labelsOf } from '../../labels.js';
@@ -23,12 +24,6 @@
23
24
  minWidth?: number;
24
25
  };
25
26
 
26
- /** A weight read back from HTML (`data-width`), when it is one. */
27
- const parsedWidth = (element: HTMLElement): Record<string, number> => {
28
- const width = Number(element.getAttribute('data-width'));
29
- return Number.isFinite(width) && width > 0 ? { width } : {};
30
- };
31
-
32
27
  /**
33
28
  * Whether `block` sits in a layout's column, at any depth: no layout goes
34
29
  * there (`layout.nest`). A `+` menu's stand-in (no id yet) answers by
@@ -165,7 +160,7 @@
165
160
  ColumnResizeStrips,
166
161
  { resize },
167
162
  'edytor-column-resizers',
168
- // Above the block handles (5): the band is the gap's left part at every height.
163
+ // Above the block handles (5): the band centered in the gap at every height.
169
164
  6,
170
165
  resize.measure
171
166
  )
@@ -174,15 +169,12 @@
174
169
  },
175
170
  blocks: {
176
171
  columns: {
177
- ...layoutKinds.columns,
172
+ ...columnsForms().columns,
178
173
  snippet: columns,
179
- element: { tag: 'div', attributes: { 'data-edytor-columns': '' } },
180
- html: (_, __, children) => `<div data-edytor-columns>${children}</div>`,
181
- plain: (_, __, children) => children,
182
- parse: (element) => (element.hasAttribute('data-edytor-columns') ? {} : undefined)
174
+ element: { tag: 'div', attributes: { 'data-edytor-columns': '' } }
183
175
  },
184
176
  column: {
185
- ...layoutKinds.column,
177
+ ...columnsForms().column,
186
178
  snippet: column,
187
179
  // Its weight as shown: a resize drag's preview (this view only), else `data.width`.
188
180
  element: (data, id) => ({
@@ -191,12 +183,7 @@
191
183
  'data-edytor-column': '',
192
184
  style: `flex: ${resize.weight(id, data)} 1 0px`
193
185
  }
194
- }),
195
- html: (block, _, children) =>
196
- `<div data-edytor-column data-width="${weightOf(block.data)}">${children}</div>`,
197
- plain: (_, __, children) => children,
198
- parse: (element) =>
199
- element.hasAttribute('data-edytor-column') ? parsedWidth(element) : undefined
186
+ })
200
187
  }
201
188
  }
202
189
  };
@@ -19,11 +19,13 @@ export type Gap = {
19
19
  */
20
20
  export declare const gapBefore: (column: Block) => Gap | null;
21
21
  /**
22
- * The resize band of `gap`: its left part, `BAND` px (the gap's width when
23
- * narrower) from the column before it, where the guide shows. The handle of
24
- * a column's block takes the rest (`handleSpan`): its `+` and grip together
25
- * flush with the block (Notion's "+ ⋮⋮"), so at the default 46px gap
26
- * (`--edytor-columns-gap`: 10 + 18 + 18) neither is under the band.
22
+ * The resize band of `gap`: `BAND` px (the gap's width when narrower)
23
+ * centered in it, its guide on the gap's middle line (Notion's). The handle
24
+ * of a column's block takes the gap's right part (`handleSpan`): its box
25
+ * from the band to the block, its `+` and grip flush with the block
26
+ * (Notion's "+ ⋮⋮", over the band where the gap is narrower than they are).
27
+ * At the default 46px gap (`--edytor-columns-gap`): the band 18–28, the
28
+ * handle's box 28–46.
27
29
  */
28
30
  export declare const bandOf: ({ left, right }: Gap) => {
29
31
  left: number;
@@ -27,13 +27,18 @@ export const gapBefore = (column) => {
27
27
  return null;
28
28
  };
29
29
  /**
30
- * The resize band of `gap`: its left part, `BAND` px (the gap's width when
31
- * narrower) from the column before it, where the guide shows. The handle of
32
- * a column's block takes the rest (`handleSpan`): its `+` and grip together
33
- * flush with the block (Notion's "+ ⋮⋮"), so at the default 46px gap
34
- * (`--edytor-columns-gap`: 10 + 18 + 18) neither is under the band.
30
+ * The resize band of `gap`: `BAND` px (the gap's width when narrower)
31
+ * centered in it, its guide on the gap's middle line (Notion's). The handle
32
+ * of a column's block takes the gap's right part (`handleSpan`): its box
33
+ * from the band to the block, its `+` and grip flush with the block
34
+ * (Notion's "+ ⋮⋮", over the band where the gap is narrower than they are).
35
+ * At the default 46px gap (`--edytor-columns-gap`): the band 18–28, the
36
+ * handle's box 28–46.
35
37
  */
36
- export const bandOf = ({ left, right }) => ({ left, width: Math.min(BAND, right - left) });
38
+ export const bandOf = ({ left, right }) => {
39
+ const width = Math.min(BAND, right - left);
40
+ return { left: left + (right - left - width) / 2, width };
41
+ };
37
42
  /** The width a column block's handle spans in `gap`: from the band's right edge to the block at `blockLeft`. */
38
43
  export const handleSpan = (gap, blockLeft) => {
39
44
  const band = bandOf(gap);
@@ -3,8 +3,8 @@ import type { Edytor } from '../../edytor.svelte.js';
3
3
  import { BandDrag } from '../bands.svelte.js';
4
4
  /** The guide line's width (the hover guide's and the drag's). */
5
5
  export declare const GUIDE = 2;
6
- /** A column's weight: `data.width`, a positive number, else 1. */
7
- export declare const weightOf: (data: Record<string, unknown> | undefined) => number;
6
+ import { weightOf } from '../../export/forms.js';
7
+ export { weightOf };
8
8
  /** The resize band in the gap between the columns `left` and `right` (`bandOf`), layer-relative. */
9
9
  export type Strip = {
10
10
  /** The layout, and the columns on each side. */
@@ -40,9 +40,9 @@ type Drag = {
40
40
  /**
41
41
  * The column resize (`docs/columns-plan.md`, "Resize"), chrome in the
42
42
  * overlay: while the pointer is over a layout (not readonly, not stacked),
43
- * a band in each gap between two shown columns (`bandOf`: the gap's left
44
- * `BAND` px, the layout's height), above the block handles, whose `+` and
45
- * grip sit together right of it, flush with the block (`gaps.ts`, one
43
+ * a band in each gap between two shown columns (`bandOf`: `BAND` px centered
44
+ * in the gap, the layout's height), above the block handles,
45
+ * whose `+` and grip sit together flush with the block (`gaps.ts`, one
46
46
  * measurement):
47
47
  * wherever its gray guide shows (`--edytor-columns-resize-color`, Notion's,
48
48
  * at any height, block rows included), a press resizes. Dragging one
@@ -119,4 +119,3 @@ export declare class ColumnResize {
119
119
  /** A band took (`true`) or lost the focus: its layout's bands stay while it holds it. */
120
120
  focus: (strip: Strip, focused: boolean) => void;
121
121
  }
122
- export {};
@@ -1,21 +1,23 @@
1
1
  import { pin } from '../../surface/overlay.js';
2
2
  import { BandDrag, bandKey } from '../bands.svelte.js';
3
3
  import { bandOf, gapBefore } from './gaps.js';
4
- import { stacks } from './stacking.js';
4
+ import { stacks } from '../../dnd/stacking.js';
5
5
  import { columnsEnglish, labelsOf } from '../../labels.js';
6
6
  /** The guide line's width (the hover guide's and the drag's). */
7
7
  export const GUIDE = 2;
8
- /** A column's weight: `data.width`, a positive number, else 1. */
9
- export const weightOf = (data) => {
10
- const width = data?.width;
11
- return typeof width === 'number' && Number.isFinite(width) && width > 0 ? width : 1;
8
+ import { weightOf } from '../../export/forms.js';
9
+ export { weightOf };
10
+ /** The band's middle in a gap `width` px wide, from the gap's left. */
11
+ const middleOf = (width) => {
12
+ const band = bandOf({ left: 0, right: width });
13
+ return band.left + band.width / 2;
12
14
  };
13
15
  /**
14
16
  * The column resize (`docs/columns-plan.md`, "Resize"), chrome in the
15
17
  * overlay: while the pointer is over a layout (not readonly, not stacked),
16
- * a band in each gap between two shown columns (`bandOf`: the gap's left
17
- * `BAND` px, the layout's height), above the block handles, whose `+` and
18
- * grip sit together right of it, flush with the block (`gaps.ts`, one
18
+ * a band in each gap between two shown columns (`bandOf`: `BAND` px centered
19
+ * in the gap, the layout's height), above the block handles,
20
+ * whose `+` and grip sit together flush with the block (`gaps.ts`, one
19
21
  * measurement):
20
22
  * wherever its gray guide shows (`--edytor-columns-resize-color`, Notion's,
21
23
  * at any height, block rows included), a press resizes. Dragging one
@@ -119,12 +121,8 @@ export class ColumnResize {
119
121
  const strips = this.shown ? this.#gaps(origin) : [];
120
122
  const drag = this.band.drag;
121
123
  const guide = drag && {
122
- // Where the hover guide showed: the band's middle, never the gap's (it would jump onto the `+`).
123
- x: drag.start +
124
- this.#widthAt(drag) +
125
- bandOf({ left: 0, right: drag.gap }).width / 2 -
126
- GUIDE / 2 -
127
- origin.left,
124
+ // Where the hover guide showed: the band's middle, the gap's (`bandOf`).
125
+ x: drag.start + this.#widthAt(drag) + middleOf(drag.gap) - GUIDE / 2 - origin.left,
128
126
  top: drag.top - origin.top,
129
127
  height: drag.height
130
128
  };
@@ -74,6 +74,12 @@ export declare class CommentsController {
74
74
  readonly resolved: PlacedThread[];
75
75
  /** The threads the sidebar shows: the open ones, the resolved ones on demand, the active one. */
76
76
  readonly shown: PlacedThread[];
77
+ /**
78
+ * Where the thread being written, else the active one, stands
79
+ * (`ChromeAnchor`): the first line of its text, by which a card may
80
+ * place itself (the sidebar places its cards in the margin).
81
+ */
82
+ readonly anchor: import("../chrome.js").ChromeAnchor;
77
83
  /** The view may write: it may start, answer, resolve and delete comments. */
78
84
  get canComment(): boolean;
79
85
  /** One thread, by id. */
@@ -4,6 +4,9 @@ import { showText } from '../planned.js';
4
4
  import { COMMENT_MARK, blockCommentRuns, commentId, joinAnchors } from '../../crdt/protocols/comments.js';
5
5
  import { CommentThreads } from '../../collaboration/comments/threads.js';
6
6
  import { takeKeys } from '../../events/onFocus.js';
7
+ import { rangeRects } from '../../collaboration/remoteSelection.js';
8
+ import { runOf } from '../../components/Ranges.svelte';
9
+ import { virtualAnchor } from '../chrome.js';
7
10
  const avatarColors = ['#e16259', '#d9730d', '#cb912f', '#448361', '#337ea9', '#9065b0', '#c14c8a'];
8
11
  /**
9
12
  * The comments plugin's state and actions (`plugins/comments`): the
@@ -92,6 +95,23 @@ export class CommentsController {
92
95
  /** The threads the sidebar shows: the open ones, the resolved ones on demand, the active one. */
93
96
  shown = $derived(this.threads.filter((thread) => thread.runs.length > 0 &&
94
97
  (!thread.resolved || this.showResolved || thread.id === this.active)));
98
+ /**
99
+ * Where the thread being written, else the active one, stands
100
+ * (`ChromeAnchor`): the first line of its text, by which a card may
101
+ * place itself (the sidebar places its cards in the margin).
102
+ */
103
+ anchor = virtualAnchor(() => {
104
+ const { edytor } = this;
105
+ const run = this.draft
106
+ ? this.draftRuns()[0]
107
+ : this.active
108
+ ? this.anchors.get(this.active)?.[0]
109
+ : undefined;
110
+ const [rect] = run
111
+ ? runOf(edytor, run.block, run.offset, run.length).flatMap(({ start, end }) => rangeRects(edytor, start, end, new DOMRect()))
112
+ : [];
113
+ return rect && new DOMRect(rect.left, rect.top, rect.width, rect.height);
114
+ }, () => this.edytor.node);
95
115
  /** The view may write: it may start, answer, resolve and delete comments. */
96
116
  get canComment() {
97
117
  return this.edytor.dispatcher.permits();
@@ -1,4 +1,6 @@
1
1
  <script module lang="ts">
2
+ import { equationForms } from '../../export/forms.js';
3
+ import './equation.css';
2
4
  import type {
3
5
  BlockSnippetPayload,
4
6
  InlineBlockSnippetPayload,
@@ -7,17 +9,15 @@
7
9
  } from '../../plugins.js';
8
10
  import type { Edytor } from '../../edytor.svelte.js';
9
11
  import { InlineBlock } from '../../block/inlineBlock.svelte.js';
10
- import { equationKinds } from '../../crdt/semantics.js';
12
+
11
13
  import { equationEnglish, keywordsOf, labelsOf } from '../../labels.js';
12
14
  import { id } from '../../utils.js';
13
15
  import EquationView from './EquationView.svelte';
14
- import EquationEditorPanel from './EquationEditor.svelte';
15
16
  import {
16
17
  EquationEditor,
17
18
  EquationRenderer,
18
19
  equationViews,
19
20
  expressionOf,
20
- parseEquation,
21
21
  type EquationData,
22
22
  type EquationErrorPayload,
23
23
  type EquationPlaceholderPayload,
@@ -27,7 +27,7 @@
27
27
  type KatexLoader
28
28
  } from './equation.svelte.js';
29
29
  import { katexLoaderOf } from './katex.js';
30
- import { withRulesAndTriggers } from '../triggers/triggers.js';
30
+ import { placeAtom, withRulesAndTriggers } from '../triggers/triggers.js';
31
31
 
32
32
  export type {
33
33
  EquationData,
@@ -100,13 +100,8 @@
100
100
  /** `$$E=mc^2$$` typed in text: an inline equation (Notion). */
101
101
  const dollars: InputRule = {
102
102
  find: /\$\$([^$\n]*[^$\s][^$\n]*)\$\$$/,
103
- replace: ([, tex], { edytor, block, from, caret, remove }) =>
104
- remove(() => {
105
- const atom = { type: INLINE, data: { expression: tex!.trim() } };
106
- const written = edytor.insertInline(block.id, from, atom).status === 'applied';
107
- if (written) caret(from + 1);
108
- return written;
109
- })
103
+ replace: ([, tex], ctx) =>
104
+ ctx.remove(() => placeAtom(ctx, { type: INLINE, data: { expression: tex!.trim() } }))
110
105
  };
111
106
 
112
107
  /** The equation a block selection or an atom selection stands for, if any. */
@@ -142,6 +137,8 @@
142
137
  (edytor) => {
143
138
  const labels = labelsOf(edytor, 'equation', equationEnglish);
144
139
  const renderer = new EquationRenderer(katexLoaderOf(options.katex), options.macros);
140
+ /** The kinds' forms: MathML by KaTeX once it is loaded. */
141
+ const forms = equationForms(renderer.mathml);
145
142
  // The records read with no view (`plugin(undefined)`) keep no state.
146
143
  if (edytor && !equationViews.has(edytor))
147
144
  equationViews.set(edytor, {
@@ -159,7 +156,7 @@
159
156
  if (!view || !owns()) return;
160
157
  const { editor } = view;
161
158
  const { panel } = options;
162
- return panel && editor.panel.mount(node, EquationEditorPanel, { editor, panel });
159
+ return panel && editor.panel.mount(node, panel, editor, () => editor.target !== null);
163
160
  },
164
161
  // A block equation this view just created empty (a slash pick, Turn into) opens its editor.
165
162
  onAfterOperation: (change) => {
@@ -206,7 +203,7 @@
206
203
  ],
207
204
  blocks: {
208
205
  equation: {
209
- ...equationKinds.equation,
206
+ ...forms.blocks.equation,
210
207
  snippet: equation,
211
208
  empty: { content: [], children: [] },
212
209
  presets: [
@@ -223,19 +220,13 @@
223
220
  ]),
224
221
  group: 'Advanced blocks'
225
222
  }
226
- ],
227
- html: (block) =>
228
- `<div data-edytor-equation>${renderer.mathml(expressionOf(block.data), true)}</div>`,
229
- plain: (block) => expressionOf(block.data),
230
- parse: (element) => parseEquation(element, true)
223
+ ]
231
224
  }
232
225
  },
233
226
  inlineBlocks: {
234
227
  [INLINE]: {
235
- snippet: inlineEquation,
236
- plain: (data) => expressionOf(data),
237
- html: (data) => renderer.mathml(expressionOf(data), false),
238
- parse: (element) => parseEquation(element, false)
228
+ ...forms.inlineBlocks.inlineEquation,
229
+ snippet: inlineEquation
239
230
  }
240
231
  }
241
232
  },
@@ -273,11 +264,3 @@
273
264
  role="presentation"><EquationView expression={expressionOf(block.data)} display={false} /></span
274
265
  >
275
266
  {/snippet}
276
-
277
- <style>
278
- /* A wide equation scrolls in its block; its look is a theme's. */
279
- [data-edytor-equation] {
280
- overflow-x: auto;
281
- overflow-y: hidden;
282
- }
283
- </style>
@@ -1,3 +1,4 @@
1
+ import './equation.css';
1
2
  import type { Plugin } from '../../plugins.js';
2
3
  import { EquationEditor, type EquationData, type EquationErrorPayload, type EquationPlaceholderPayload, type EquationPluginOptions, type EquationTarget, type KatexLike, type KatexLoader } from './equation.svelte.js';
3
4
  export type { EquationData, EquationEditor, EquationErrorPayload, EquationPlaceholderPayload, EquationPluginOptions, EquationTarget, KatexLike, KatexLoader };
@@ -0,0 +1,7 @@
1
+ /* Loaded by the plugin's module (a component's own <style> is dropped when only
2
+ its module is used: the plugin factory, never the component). */
3
+ /* A wide equation scrolls in its block; its look is a theme's. */
4
+ [data-edytor-equation] {
5
+ overflow-x: auto;
6
+ overflow-y: hidden;
7
+ }
@@ -1,6 +1,7 @@
1
1
  import { type Snippet } from 'svelte';
2
2
  import type { Attachment } from 'svelte/attachments';
3
3
  import type { Edytor } from '../../edytor.svelte.js';
4
+ export { TEX, expressionOf, parseEquation, sourceMathml, type EquationData } from './tex.js';
4
5
  /** The part of KaTeX the plugin uses: `katex.renderToString`. */
5
6
  export type KatexLike = {
6
7
  renderToString: (tex: string, options?: Record<string, unknown>) => string;
@@ -66,20 +67,12 @@ export type EquationErrorPayload = {
66
67
  /** The view's word for it (`equation.invalid`). */
67
68
  label: string;
68
69
  };
69
- /** The data of a block equation and of an inline one: its TeX source. */
70
- export type EquationData = {
71
- expression?: string;
72
- };
73
70
  /** What drawing an equation gives: KaTeX's markup, its error, or nothing yet (the source shows). */
74
71
  export type Drawn = {
75
72
  html: string;
76
73
  } | {
77
74
  error: string;
78
75
  } | null;
79
- /** The MathML annotation that carries an equation's TeX source. */
80
- export declare const TEX = "application/x-tex";
81
- /** An equation's TeX source: its `expression`, a string. */
82
- export declare const expressionOf: (data: unknown) => string;
83
76
  /**
84
77
  * KaTeX for one plugin: loaded once, the first time an equation is drawn in
85
78
  * a browser, and reactive (an equation drawn before it loads shows its
@@ -104,13 +97,6 @@ export declare class EquationRenderer {
104
97
  mathml: (tex: string, display: boolean) => string;
105
98
  private options;
106
99
  }
107
- /**
108
- * HTML import: the TeX source an equation's element carries — a `<math>`'s
109
- * `application/x-tex` annotation (or its `alttext`), alone or in KaTeX's
110
- * markup (`.katex`, `.katex-display`) — when the element is an equation of
111
- * the display asked (`display="block"`: a block), else `undefined`.
112
- */
113
- export declare const parseEquation: (element: HTMLElement, display: boolean) => EquationData | undefined;
114
100
  /** The equation being edited: a block equation, or an inline one (`atom`) in block `block`. */
115
101
  export type EquationTarget = {
116
102
  block: string;
@@ -141,6 +127,12 @@ export declare class EquationEditor {
141
127
  target: EquationTarget | null;
142
128
  /** The view is readonly (reactive): the editor closes. */
143
129
  get readonly(): boolean;
130
+ /**
131
+ * Where the panel stands: the edited equation (`ChromeAnchor`; Notion
132
+ * centers it under a block equation, `display`, and starts it under an
133
+ * inline one).
134
+ */
135
+ get anchor(): import("../chrome.js").ChromeAnchor;
144
136
  /** A block equation is edited (a field of several lines). */
145
137
  get display(): boolean;
146
138
  /** The edited equation's TeX source (reactive through its block's cell). */
@@ -3,15 +3,10 @@ import { blockSelection } from '../../session/selection.js';
3
3
  import { InlineBlock } from '../../block/inlineBlock.svelte.js';
4
4
  import { takeKeys } from '../../events/onFocus.js';
5
5
  import { Anchored } from '../anchored.svelte.js';
6
- import { escapeHtml } from '../../clipboard/serializeClipboardFragment.js';
6
+ import { expressionOf, sourceMathml } from './tex.js';
7
+ export { TEX, expressionOf, parseEquation, sourceMathml } from './tex.js';
7
8
  import { all, listen } from '../../utils/listen.js';
8
- /** The MathML annotation that carries an equation's TeX source. */
9
- export const TEX = 'application/x-tex';
10
- /** An equation's TeX source: its `expression`, a string. */
11
- export const expressionOf = (data) => {
12
- const value = data?.expression;
13
- return typeof value === 'string' ? value : '';
14
- };
9
+ import { keysOf } from '../list.svelte.js';
15
10
  /** The cap of the drawings each renderer keeps. */
16
11
  const CACHE = 256;
17
12
  /**
@@ -73,9 +68,7 @@ export class EquationRenderer {
73
68
  // TeX KaTeX cannot read: the source as text, below.
74
69
  }
75
70
  }
76
- const source = escapeHtml(tex);
77
- return (`<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"${display ? ' display="block"' : ''}>` +
78
- `<semantics><mrow><mtext>${source}</mtext></mrow><annotation encoding="${TEX}">${source}</annotation></semantics></math></span>`);
71
+ return sourceMathml(tex, display);
79
72
  };
80
73
  options = (display, output) => ({
81
74
  displayMode: display,
@@ -97,29 +90,6 @@ export class EquationRenderer {
97
90
  }, (error) => console.error('[edytor] KaTeX failed to load', error));
98
91
  };
99
92
  }
100
- /**
101
- * HTML import: the TeX source an equation's element carries — a `<math>`'s
102
- * `application/x-tex` annotation (or its `alttext`), alone or in KaTeX's
103
- * markup (`.katex`, `.katex-display`) — when the element is an equation of
104
- * the display asked (`display="block"`: a block), else `undefined`.
105
- */
106
- export const parseEquation = (element, display) => {
107
- const own = element.localName === 'math';
108
- const wrapper = element.classList.contains('katex') ||
109
- element.classList.contains('katex-display') ||
110
- element.hasAttribute('data-edytor-equation');
111
- if (!own && !wrapper)
112
- return undefined;
113
- const math = own ? element : element.querySelector('math');
114
- if (!math)
115
- return undefined;
116
- const block = math.getAttribute('display') === 'block' || element.classList.contains('katex-display');
117
- if (block !== display)
118
- return undefined;
119
- const tex = math.querySelector(`annotation[encoding="${TEX}"]`)?.textContent ??
120
- math.getAttribute('alttext');
121
- return tex?.trim() ? { expression: tex.trim() } : undefined;
122
- };
123
93
  /**
124
94
  * One view's equation editor (Notion's): a click on an equation of an
125
95
  * editable view (Enter on a selected one, or a new empty one) opens its
@@ -161,12 +131,12 @@ export class EquationEditor {
161
131
  return this.edytor.readonly;
162
132
  }
163
133
  /**
164
- * Where the panel stands: under the edited equation (a block one's
165
- * middle, an inline one's start), layer-relative.
166
- * @internal
134
+ * Where the panel stands: the edited equation (`ChromeAnchor`; Notion
135
+ * centers it under a block equation, `display`, and starts it under an
136
+ * inline one).
167
137
  */
168
- get place() {
169
- return this.target && this.panel.place(6, this.display);
138
+ get anchor() {
139
+ return this.panel.anchor;
170
140
  }
171
141
  /** A block equation is edited (a field of several lines). */
172
142
  get display() {
@@ -216,7 +186,6 @@ export class EquationEditor {
216
186
  if (!target)
217
187
  return;
218
188
  this.target = null;
219
- this.panel.box = null;
220
189
  this.edytor.overlay.invalidate();
221
190
  const block = this.#block(target);
222
191
  if (!block)
@@ -248,16 +217,10 @@ export class EquationEditor {
248
217
  * them. Focus leaving the panel for somewhere else closes it.
249
218
  */
250
219
  field = (node) => untrack(() => {
251
- const keydown = (event) => {
252
- if (event.isComposing)
253
- return;
254
- const enter = event.key === 'Enter' && !(event.shiftKey && this.display);
255
- if (!enter && event.key !== 'Escape')
256
- return;
257
- event.preventDefault();
258
- event.stopPropagation();
259
- this.close();
260
- };
220
+ const keydown = keysOf({
221
+ Enter: (event) => !(event.shiftKey && this.display) && this.close(),
222
+ Escape: () => this.close()
223
+ }, true);
261
224
  const element = node;
262
225
  const off = listen(element, 'keydown', keydown);
263
226
  const off2 = listen(element, 'focusout', this.panel.blurred);
@@ -0,0 +1,17 @@
1
+ /** The data of a block equation and of an inline one: its TeX source. */
2
+ export type EquationData = {
3
+ expression?: string;
4
+ };
5
+ /** The MathML annotation that carries an equation's TeX source. */
6
+ export declare const TEX = "application/x-tex";
7
+ /** An equation's TeX source: its `expression`, a string. */
8
+ export declare const expressionOf: (data: unknown) => string;
9
+ /** MathML whose `application/x-tex` annotation is `tex`, the source as its text, in KaTeX's `katex` class. */
10
+ export declare const sourceMathml: (tex: string, display: boolean) => string;
11
+ /**
12
+ * HTML import: the TeX source an equation's element carries — a `<math>`'s
13
+ * `application/x-tex` annotation (or its `alttext`), alone or in KaTeX's
14
+ * markup (`.katex`, `.katex-display`) — when the element is an equation of
15
+ * the display asked (`display="block"`: a block), else `undefined`.
16
+ */
17
+ export declare const parseEquation: (element: HTMLElement, display: boolean) => EquationData | undefined;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * An equation's pure forms: its data, its TeX source, the MathML that
3
+ * carries the source (`sourceMathml`, the clipboard's form before KaTeX
4
+ * loads and the export's on a server) and its HTML import. No Svelte.
5
+ */
6
+ import { escapeHtml } from '../../clipboard/serializeClipboardFragment.js';
7
+ /** The MathML annotation that carries an equation's TeX source. */
8
+ export const TEX = 'application/x-tex';
9
+ /** An equation's TeX source: its `expression`, a string. */
10
+ export const expressionOf = (data) => {
11
+ const value = data?.expression;
12
+ return typeof value === 'string' ? value : '';
13
+ };
14
+ /** MathML whose `application/x-tex` annotation is `tex`, the source as its text, in KaTeX's `katex` class. */
15
+ export const sourceMathml = (tex, display) => {
16
+ const source = escapeHtml(tex);
17
+ return (`<span class="katex"><math xmlns="http://www.w3.org/1998/Math/MathML"${display ? ' display="block"' : ''}>` +
18
+ `<semantics><mrow><mtext>${source}</mtext></mrow><annotation encoding="${TEX}">${source}</annotation></semantics></math></span>`);
19
+ };
20
+ /**
21
+ * HTML import: the TeX source an equation's element carries — a `<math>`'s
22
+ * `application/x-tex` annotation (or its `alttext`), alone or in KaTeX's
23
+ * markup (`.katex`, `.katex-display`) — when the element is an equation of
24
+ * the display asked (`display="block"`: a block), else `undefined`.
25
+ */
26
+ export const parseEquation = (element, display) => {
27
+ const own = element.localName === 'math';
28
+ const wrapper = element.classList.contains('katex') ||
29
+ element.classList.contains('katex-display') ||
30
+ element.hasAttribute('data-edytor-equation');
31
+ if (!own && !wrapper)
32
+ return undefined;
33
+ const math = own ? element : element.querySelector('math');
34
+ if (!math)
35
+ return undefined;
36
+ const block = math.getAttribute('display') === 'block' || element.classList.contains('katex-display');
37
+ if (block !== display)
38
+ return undefined;
39
+ const tex = math.querySelector(`annotation[encoding="${TEX}"]`)?.textContent ??
40
+ math.getAttribute('alttext');
41
+ return tex?.trim() ? { expression: tex.trim() } : undefined;
42
+ };