@openleaf-editor/core 0.1.0-beta.2 → 0.1.0-beta.4

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 (104) hide show
  1. package/README.md +127 -0
  2. package/dist/autolink.d.ts +7 -4
  3. package/dist/autolink.d.ts.map +1 -1
  4. package/dist/autolink.js +90 -11
  5. package/dist/autolink.js.map +1 -1
  6. package/dist/command-helpers.d.ts +8 -0
  7. package/dist/command-helpers.d.ts.map +1 -0
  8. package/dist/command-helpers.js +36 -0
  9. package/dist/command-helpers.js.map +1 -0
  10. package/dist/commands.d.ts +21 -63
  11. package/dist/commands.d.ts.map +1 -1
  12. package/dist/commands.js +430 -346
  13. package/dist/commands.js.map +1 -1
  14. package/dist/css.d.ts +1 -175
  15. package/dist/css.d.ts.map +1 -1
  16. package/dist/css.js +1 -516
  17. package/dist/css.js.map +1 -1
  18. package/dist/disclosure.d.ts +21 -0
  19. package/dist/disclosure.d.ts.map +1 -0
  20. package/dist/disclosure.js +144 -0
  21. package/dist/disclosure.js.map +1 -0
  22. package/dist/elements.d.ts +2 -0
  23. package/dist/elements.d.ts.map +1 -0
  24. package/dist/elements.js +2 -0
  25. package/dist/elements.js.map +1 -0
  26. package/dist/embed.d.ts +1 -51
  27. package/dist/embed.d.ts.map +1 -1
  28. package/dist/embed.js +1 -115
  29. package/dist/embed.js.map +1 -1
  30. package/dist/errors.d.ts +38 -0
  31. package/dist/errors.d.ts.map +1 -0
  32. package/dist/errors.js +40 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/extensions.d.ts +46 -5
  35. package/dist/extensions.d.ts.map +1 -1
  36. package/dist/extensions.js +272 -52
  37. package/dist/extensions.js.map +1 -1
  38. package/dist/figure-drag.d.ts +26 -0
  39. package/dist/figure-drag.d.ts.map +1 -0
  40. package/dist/figure-drag.js +75 -0
  41. package/dist/figure-drag.js.map +1 -0
  42. package/dist/formats.d.ts.map +1 -1
  43. package/dist/formats.js +19 -7
  44. package/dist/formats.js.map +1 -1
  45. package/dist/gapcursor.d.ts +14 -0
  46. package/dist/gapcursor.d.ts.map +1 -0
  47. package/dist/gapcursor.js +17 -0
  48. package/dist/gapcursor.js.map +1 -0
  49. package/dist/html.d.ts +32 -2
  50. package/dist/html.d.ts.map +1 -1
  51. package/dist/html.js +185 -31
  52. package/dist/html.js.map +1 -1
  53. package/dist/index.d.ts +23 -6
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +34 -6
  56. package/dist/index.js.map +1 -1
  57. package/dist/insert-commands.d.ts +172 -0
  58. package/dist/insert-commands.d.ts.map +1 -0
  59. package/dist/insert-commands.js +560 -0
  60. package/dist/insert-commands.js.map +1 -0
  61. package/dist/isolating-selection.d.ts +59 -0
  62. package/dist/isolating-selection.d.ts.map +1 -0
  63. package/dist/isolating-selection.js +251 -0
  64. package/dist/isolating-selection.js.map +1 -0
  65. package/dist/noneditable.d.ts.map +1 -1
  66. package/dist/noneditable.js +18 -4
  67. package/dist/noneditable.js.map +1 -1
  68. package/dist/plugins.d.ts +20 -2
  69. package/dist/plugins.d.ts.map +1 -1
  70. package/dist/plugins.js +27 -2
  71. package/dist/plugins.js.map +1 -1
  72. package/dist/preserve.d.ts +48 -17
  73. package/dist/preserve.d.ts.map +1 -1
  74. package/dist/preserve.js +214 -43
  75. package/dist/preserve.js.map +1 -1
  76. package/dist/schema.d.ts +15 -0
  77. package/dist/schema.d.ts.map +1 -1
  78. package/dist/schema.js +157 -28
  79. package/dist/schema.js.map +1 -1
  80. package/dist/structure.d.ts +32 -0
  81. package/dist/structure.d.ts.map +1 -1
  82. package/dist/structure.js +53 -10
  83. package/dist/structure.js.map +1 -1
  84. package/dist/tables.d.ts +47 -1
  85. package/dist/tables.d.ts.map +1 -1
  86. package/dist/tables.js +417 -40
  87. package/dist/tables.js.map +1 -1
  88. package/dist/testing.d.ts +3 -0
  89. package/dist/testing.d.ts.map +1 -0
  90. package/dist/testing.js +3 -0
  91. package/dist/testing.js.map +1 -0
  92. package/dist/tokens.d.ts +8 -0
  93. package/dist/tokens.d.ts.map +1 -1
  94. package/dist/tokens.js +54 -6
  95. package/dist/tokens.js.map +1 -1
  96. package/dist/url.d.ts +1 -25
  97. package/dist/url.d.ts.map +1 -1
  98. package/dist/url.js +1 -77
  99. package/dist/url.js.map +1 -1
  100. package/dist/visual-aids.d.ts +11 -1
  101. package/dist/visual-aids.d.ts.map +1 -1
  102. package/dist/visual-aids.js +124 -36
  103. package/dist/visual-aids.js.map +1 -1
  104. package/package.json +17 -1
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Dragging the image inside a captioned figure must move the figure.
3
+ *
4
+ * `image` is `draggable: true`; `figure` is not. ProseMirror's dragstart
5
+ * therefore builds a NodeSelection on the `<img>` (`pos.inside` is the image,
6
+ * not the figure), and the default drop moves only that node. The caption
7
+ * stays behind. An image-less `<figure><figcaption>` is illegal on the next
8
+ * parse.
9
+ *
10
+ * Marking `figure` draggable is not enough -- mousedown still resolves to the
11
+ * image. Making figure an atom would kill caption editing. Caption text
12
+ * drags are left alone: only a NodeSelection on the image whose parent is
13
+ * figure is claimed.
14
+ */
15
+ import { Fragment, Slice } from 'prosemirror-model';
16
+ import { NodeSelection, Plugin, PluginKey } from 'prosemirror-state';
17
+ import { dropPoint } from 'prosemirror-transform';
18
+ const key = new PluginKey('openleaf-figure-drag');
19
+ function draggedImageInFigure(view) {
20
+ const dragging = view.dragging;
21
+ if (!dragging)
22
+ return null;
23
+ // dragstart stores the image NodeSelection on `dragging.node` and does not
24
+ // dispatch it. A pre-selected image drag leaves `node` unset and uses the
25
+ // state's NodeSelection instead.
26
+ const sel = dragging.node ??
27
+ (view.state.selection instanceof NodeSelection ? view.state.selection : null);
28
+ if (!sel || sel.node.type.name !== 'image')
29
+ return null;
30
+ if (sel.$from.parent.type.name !== 'figure')
31
+ return null;
32
+ return sel;
33
+ }
34
+ /**
35
+ * If the drag is a NodeSelection on an image inside a figure, insert (or
36
+ * move) the whole figure at `pos`. Returns true when it handled the drop.
37
+ *
38
+ * `copy` is the inverse of ProseMirror's drop `moved` flag: Alt on Mac / Ctrl
39
+ * elsewhere copies. One transaction so undo is a single step.
40
+ */
41
+ export function dropFigureForDraggedImage(view, pos, copy) {
42
+ if (!view.editable)
43
+ return false;
44
+ const sel = draggedImageInFigure(view);
45
+ if (!sel)
46
+ return false;
47
+ const figure = sel.$from.parent;
48
+ const from = sel.$from.before(sel.$from.depth);
49
+ const slice = new Slice(Fragment.from(figure), 0, 0);
50
+ const insertPos = dropPoint(view.state.doc, pos, slice);
51
+ if (insertPos == null)
52
+ return false;
53
+ const tr = view.state.tr;
54
+ if (!copy)
55
+ tr.delete(from, from + figure.nodeSize);
56
+ const dest = tr.mapping.map(insertPos);
57
+ tr.insert(dest, figure);
58
+ tr.setSelection(NodeSelection.create(tr.doc, dest));
59
+ view.dispatch(tr.scrollIntoView());
60
+ return true;
61
+ }
62
+ export function figureDragPlugin() {
63
+ return new Plugin({
64
+ key,
65
+ props: {
66
+ handleDrop(view, event, _slice, moved) {
67
+ const coords = view.posAtCoords({ left: event.clientX, top: event.clientY });
68
+ if (!coords)
69
+ return false;
70
+ return dropFigureForDraggedImage(view, coords.pos, !moved);
71
+ },
72
+ },
73
+ });
74
+ }
75
+ //# sourceMappingURL=figure-drag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figure-drag.js","sourceRoot":"","sources":["../src/figure-drag.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"formats.d.ts","sourceRoot":"","sources":["../src/formats.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG7D,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAA;CACd;AAED,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,iFAAiF;IACjF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CActD;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,EAAE,CAgB9E;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIxD;AAaD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAMlE;AAYD,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAa/D"}
1
+ {"version":3,"file":"formats.d.ts","sourceRoot":"","sources":["../src/formats.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG7D,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAA;CACd;AAED,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,iFAAiF;IACjF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CActD;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,EAAE,CAgB9E;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIxD;AAyBD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAMlE;AAYD,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAa/D"}
package/dist/formats.js CHANGED
@@ -61,15 +61,27 @@ export function carriedClass(node) {
61
61
  const value = carried?.['class'];
62
62
  return value && value.trim() !== '' ? value : null;
63
63
  }
64
+ /**
65
+ * Every text block in the selection, over every selected RANGE.
66
+ *
67
+ * `selection.from`/`to` are one range's bounds, so a table column selection --
68
+ * which is one range per cell -- reported a single cell's paragraph and the
69
+ * format was applied to just that one. See `selectedRanges` in commands.ts.
70
+ */
64
71
  function textBlocks(state) {
65
72
  const found = [];
66
- const { from, to } = state.selection;
67
- state.doc.nodesBetween(from, to, (node, pos) => {
68
- if (!node.isTextblock)
69
- return true;
70
- found.push({ pos, node });
71
- return false;
72
- });
73
+ const seen = new Set();
74
+ for (const range of state.selection.ranges) {
75
+ state.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => {
76
+ if (!node.isTextblock)
77
+ return true;
78
+ if (!seen.has(pos)) {
79
+ seen.add(pos);
80
+ found.push({ pos, node });
81
+ }
82
+ return false;
83
+ });
84
+ }
73
85
  return found;
74
86
  }
75
87
  /** The class shared by every selected text block, or null if mixed or absent. */
@@ -1 +1 @@
1
- {"version":3,"file":"formats.js","sourceRoot":"","sources":["../src/formats.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"formats.js","sourceRoot":"","sources":["../src/formats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A caret beside a block atom or isolating node.
3
+ *
4
+ * Several core nodes are leaves (`page_break`, `video`, `audio`, `iframe`) or
5
+ * isolating blocks (`details`, preserved unknown blocks). The document can be
6
+ * *only* one of those, or two of them adjacent, and there is then no textblock
7
+ * for the caret. ArrowLeft on a selected page-break stayed a `NodeSelection`;
8
+ * the next keystroke replaced the atom (#164).
9
+ *
10
+ * `prosemirror-gapcursor` is the plugin this schema shape exists for. Tab is
11
+ * not bound by it — that key remains the way out of the editor.
12
+ */
13
+ export declare function gapCursorPlugin(): import("prosemirror-state").Plugin<any>;
14
+ //# sourceMappingURL=gapcursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gapcursor.d.ts","sourceRoot":"","sources":["../src/gapcursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,wBAAgB,eAAe,4CAE9B"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * A caret beside a block atom or isolating node.
3
+ *
4
+ * Several core nodes are leaves (`page_break`, `video`, `audio`, `iframe`) or
5
+ * isolating blocks (`details`, preserved unknown blocks). The document can be
6
+ * *only* one of those, or two of them adjacent, and there is then no textblock
7
+ * for the caret. ArrowLeft on a selected page-break stayed a `NodeSelection`;
8
+ * the next keystroke replaced the atom (#164).
9
+ *
10
+ * `prosemirror-gapcursor` is the plugin this schema shape exists for. Tab is
11
+ * not bound by it — that key remains the way out of the editor.
12
+ */
13
+ import { gapCursor } from 'prosemirror-gapcursor';
14
+ export function gapCursorPlugin() {
15
+ return gapCursor();
16
+ }
17
+ //# sourceMappingURL=gapcursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gapcursor.js","sourceRoot":"","sources":["../src/gapcursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEjD,MAAM,UAAU,eAAe;IAC7B,OAAO,SAAS,EAAE,CAAA;AACpB,CAAC"}
package/dist/html.d.ts CHANGED
@@ -13,9 +13,39 @@ export interface HtmlIOOptions {
13
13
  /** Schema to parse against. Defaults to the built-in one. */
14
14
  schema?: Schema;
15
15
  }
16
- /** Parse an HTML string into an OpenLeaf document. */
16
+ /**
17
+ * How deep a parsed tree may nest.
18
+ *
19
+ * ProseMirror's DOM parser recurses once per element, and so does the serializer
20
+ * on the way back, so a document deep enough overflows the JavaScript stack
21
+ * before either finishes. Measured on Node 26 at the default stack size:
22
+ * `'<div>'.repeat(5000)` -- 30 KB of markup -- throws `RangeError: Maximum call
23
+ * stack size exceeded`, while a 2 MB *flat* document parses without complaint.
24
+ * Depth is the problem, not size, which is what makes it reachable by an
25
+ * attacker with a small payload.
26
+ *
27
+ * 500 is far above anything authored and far below where any engine gives out.
28
+ * The deepest structure real content produces is quoted email, and that runs to
29
+ * tens of levels, not hundreds.
30
+ */
31
+ export declare const MAX_PARSE_DEPTH = 500;
32
+ /**
33
+ * Parse an HTML string into an OpenLeaf document.
34
+ *
35
+ * Throws `OpenLeafError` with code `invalid-argument` for a non-string, and
36
+ * `depth-limit` for input nested past {@link MAX_PARSE_DEPTH}. It used to coerce
37
+ * anything at all -- `parseHtml(42)` returned an empty document -- which turned
38
+ * a caller's type error into silent content loss.
39
+ */
17
40
  export declare function parseHtml(html: string, opts?: HtmlIOOptions): PMNode;
18
- /** Serialize an OpenLeaf document back to an HTML string. */
41
+ /**
42
+ * Serialize an OpenLeaf document back to an HTML string.
43
+ *
44
+ * Throws `OpenLeafError` with code `invalid-argument` for anything that is not a
45
+ * ProseMirror node. `serializeHtml(null)` used to surface a raw
46
+ * `TypeError: Cannot read properties of null (reading 'type')` from inside
47
+ * ProseMirror, with nothing in it naming OpenLeaf or the call that was wrong.
48
+ */
19
49
  export declare function serializeHtml(node: PMNode, opts?: HtmlIOOptions): string;
20
50
  /** Convenience: one full parse/serialize cycle. */
21
51
  export declare function roundTrip(html: string, opts?: HtmlIOOptions): string;
@@ -1 +1 @@
1
- {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAA4B,KAAK,IAAI,IAAI,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAqC9F,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAaD,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAOpE;AAqCD,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAaxE;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAEpE"}
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAA4B,KAAK,IAAI,IAAI,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAuC9F,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAcD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,eAAe,MAAM,CAAA;AAkClC;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CA2BpE;AA8GD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAqBxE;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAEpE"}
package/dist/html.js CHANGED
@@ -9,6 +9,8 @@
9
9
  import { DOMParser, DOMSerializer } from 'prosemirror-model';
10
10
  import { isInsidePreserved, withSerializationDocument } from './preserve.js';
11
11
  import { coreSchema } from './extensions.js';
12
+ import { OpenLeafError } from './errors.js';
13
+ import { tableSectionRowCounts } from './tables.js';
12
14
  /**
13
15
  * Parsers and serializers are resolved per schema rather than built once.
14
16
  *
@@ -42,61 +44,212 @@ function serializerFor(target) {
42
44
  function resolveDocument(opts) {
43
45
  const doc = opts?.document ?? (typeof document !== 'undefined' ? document : undefined);
44
46
  if (!doc) {
45
- throw new Error('@openleaf-editor/core: no Document available. Pass { document } when ' +
47
+ throw new OpenLeafError('no-document', '@openleaf-editor/core: no Document available. Pass { document } when ' +
46
48
  'running outside a browser.');
47
49
  }
48
50
  return doc;
49
51
  }
50
- /** Parse an HTML string into an OpenLeaf document. */
52
+ /**
53
+ * How deep a parsed tree may nest.
54
+ *
55
+ * ProseMirror's DOM parser recurses once per element, and so does the serializer
56
+ * on the way back, so a document deep enough overflows the JavaScript stack
57
+ * before either finishes. Measured on Node 26 at the default stack size:
58
+ * `'<div>'.repeat(5000)` -- 30 KB of markup -- throws `RangeError: Maximum call
59
+ * stack size exceeded`, while a 2 MB *flat* document parses without complaint.
60
+ * Depth is the problem, not size, which is what makes it reachable by an
61
+ * attacker with a small payload.
62
+ *
63
+ * 500 is far above anything authored and far below where any engine gives out.
64
+ * The deepest structure real content produces is quoted email, and that runs to
65
+ * tens of levels, not hundreds.
66
+ */
67
+ export const MAX_PARSE_DEPTH = 500;
68
+ /**
69
+ * Reject over-deep input before the recursive parse meets it.
70
+ *
71
+ * An explicit stack, so measuring the depth cannot itself overflow. Two parallel
72
+ * arrays rather than an array of pairs: a 2 MB document has ~110,000 elements
73
+ * and the object churn was measurable where two number pushes are not.
74
+ */
75
+ function assertDepthWithin(root, limit) {
76
+ const nodes = [];
77
+ const depths = [];
78
+ for (const child of Array.from(root.children)) {
79
+ nodes.push(child);
80
+ depths.push(1);
81
+ }
82
+ while (nodes.length > 0) {
83
+ const node = nodes.pop();
84
+ const depth = depths.pop();
85
+ if (depth > limit) {
86
+ throw new OpenLeafError('depth-limit', `@openleaf-editor/core: HTML nests more than ${limit} elements deep. Parsing it ` +
87
+ 'recurses once per level and would overflow the stack. This is almost always ' +
88
+ 'adversarial input rather than a document somebody wrote.');
89
+ }
90
+ for (const child of Array.from(node.children)) {
91
+ nodes.push(child);
92
+ depths.push(depth + 1);
93
+ }
94
+ }
95
+ }
96
+ /**
97
+ * Parse an HTML string into an OpenLeaf document.
98
+ *
99
+ * Throws `OpenLeafError` with code `invalid-argument` for a non-string, and
100
+ * `depth-limit` for input nested past {@link MAX_PARSE_DEPTH}. It used to coerce
101
+ * anything at all -- `parseHtml(42)` returned an empty document -- which turned
102
+ * a caller's type error into silent content loss.
103
+ */
51
104
  export function parseHtml(html, opts) {
105
+ if (typeof html !== 'string') {
106
+ throw new OpenLeafError('invalid-argument', `@openleaf-editor/core: parseHtml expects an HTML string, received ${typeof html}.`);
107
+ }
52
108
  const doc = resolveDocument(opts);
53
109
  const tpl = doc.createElement('template');
54
- tpl.innerHTML = html;
110
+ // The DOM parser is itself recursive and gives out at around 20,000 levels,
111
+ // which is *before* the depth check below could run. Its `RangeError` says
112
+ // nothing about what happened or which call caused it, so it is converted
113
+ // rather than allowed to escape.
114
+ try {
115
+ tpl.innerHTML = html;
116
+ }
117
+ catch (error) {
118
+ throw new OpenLeafError('depth-limit', '@openleaf-editor/core: the HTML could not be parsed -- it is nested too deeply, or too ' +
119
+ 'large, for this DOM implementation to handle.', { cause: error });
120
+ }
121
+ assertDepthWithin(tpl.content, MAX_PARSE_DEPTH);
55
122
  return parserFor(opts?.schema ?? coreSchema()).parse(tpl.content, {
56
123
  preserveWhitespace: false,
57
124
  });
58
125
  }
59
126
  /**
60
- * Collapse `<td><p>text</p></td>` back to `<td>text</td>`.
127
+ * Collapse a sole attribute-free `<p>` back to its container's direct children.
61
128
  *
62
- * Table cells hold `block+` content, because real tables contain paragraphs and
63
- * lists. The consequence is that parsing the overwhelmingly common legacy form
64
- * `<td>text</td>` produces a cell containing a paragraph, and serializing it
65
- * back would write `<td><p>text</p></td>` -- rewriting every cell of every table
66
- * in a CMS the first time each post is opened and saved.
129
+ * Several containers hold block content (`table_cell` is `block+`, `list_item`
130
+ * is `paragraph block*`, `blockquote` is `block+`, `details` is `summary
131
+ * block+`). Parsing the overwhelmingly common legacy form -- `<td>text</td>`,
132
+ * `<li>text</li>`, `<blockquote>quoted</blockquote>`, a details body that is
133
+ * just text -- therefore produces a paragraph, and serializing it back would
134
+ * write the wrapper into every list, quote, disclosure and table in a CMS the
135
+ * first time each post is opened and saved.
67
136
  *
68
137
  * That is a normalization rather than information loss, but "we changed every
69
- * table in your archive" is not a thing this project gets to do quietly. So a
70
- * cell holding exactly one attribute-free paragraph is unwrapped on the way out.
138
+ * list in your archive" is not a thing this project gets to do quietly. So a
139
+ * container whose modelled content is exactly one attribute-free paragraph is
140
+ * unwrapped on the way out. For `<details>` that means the body after
141
+ * `<summary>`, not the whole element.
71
142
  *
72
- * The asymmetry is deliberate and worth stating: a cell that was authored as
73
- * `<td><p>text</p></td>` also comes back as `<td>text</td>`. That form is rare
74
- * in the content this editor inherits, and the alternative is rewriting the
75
- * common case instead of the rare one.
143
+ * The same rule as cells still applies to mixed content: `<li>a<ul><li>b</li>
144
+ * </ul></li>` parses to a paragraph plus a nested list, so the outer paragraph
145
+ * stays. The inner item is a sole paragraph and unwraps.
146
+ *
147
+ * The asymmetry is deliberate and worth stating: a container that was authored
148
+ * as `<li><p>text</p></li>` also comes back as `<li>text</li>`. That form is
149
+ * rare in the content this editor inherits, and the alternative is rewriting
150
+ * the common case instead of the rare one.
76
151
  */
77
- function unwrapSoleCellParagraph(host) {
78
- for (const cell of Array.from(host.querySelectorAll('td, th'))) {
79
- // Never reach inside preserved markup. A table nested in an unrecognised
152
+ function unwrapSoleParagraph(host) {
153
+ for (const container of Array.from(host.querySelectorAll('td, th, li, blockquote, details'))) {
154
+ // Never reach inside preserved markup. A list nested in an unrecognised
80
155
  // wrapper is content we undertook to return byte-identical, and a
81
- // normalization that is right for our own tables is a broken promise there.
82
- if (isInsidePreserved(cell))
156
+ // normalization that is right for our own nodes is a broken promise there.
157
+ if (isInsidePreserved(container))
83
158
  continue;
84
- if (cell.childElementCount !== 1)
159
+ const only = soleAttributeFreeParagraph(container);
160
+ if (!only)
85
161
  continue;
86
- const only = cell.firstElementChild;
87
- if (!only || only.nodeName !== 'P' || only.attributes.length > 0)
162
+ while (only.firstChild)
163
+ container.insertBefore(only.firstChild, only);
164
+ container.removeChild(only);
165
+ }
166
+ }
167
+ /**
168
+ * The paragraph this pass is allowed to unwrap, or null.
169
+ *
170
+ * `details` always has a `<summary>` sibling, so "entire content is one `<p>`"
171
+ * would never fire there. Everything else uses the cell rule: one child node,
172
+ * and it is an attribute-free `<p>`.
173
+ */
174
+ function soleAttributeFreeParagraph(container) {
175
+ const candidates = container.nodeName === 'DETAILS'
176
+ ? Array.from(container.childNodes).filter((node) => !(node.nodeType === 1 && node.nodeName === 'SUMMARY'))
177
+ : Array.from(container.childNodes);
178
+ if (candidates.length !== 1)
179
+ return null;
180
+ const only = candidates[0];
181
+ if (!only || only.nodeType !== 1)
182
+ return null;
183
+ const el = only;
184
+ if (el.nodeName !== 'P' || el.attributes.length > 0)
185
+ return null;
186
+ return el;
187
+ }
188
+ /**
189
+ * Put a table's rows back into the `<thead>` and `<tfoot>` they came from.
190
+ *
191
+ * A table node holds nothing but rows -- `prosemirror-tables` requires that, see
192
+ * tables.ts -- and a node renders through a single `contentDOM`, so `toDOM` can
193
+ * emit one section and no more. The grouping is therefore restored here, from
194
+ * the row counts tables.ts recorded against the element it built.
195
+ *
196
+ * Only for tables that HAD a section. Deriving a `<thead>` from the presence of
197
+ * `<th>` cells would look like an improvement and would rewrite every table in
198
+ * an archive that never used one, which is the change `unwrapSoleParagraph`
199
+ * argues at length this project does not get to make quietly.
200
+ *
201
+ * The counts are clamped rather than trusted, because the document can have
202
+ * changed since it was parsed: an author who deletes the header row of a table
203
+ * whose node still says `headerRows: 1` gets a table with one fewer section, not
204
+ * a `<thead>` built out of their first data row and not a thrown error. The
205
+ * `<tbody>` goes away entirely if every row left it, so a table that was all
206
+ * `<thead>` does not come back with an empty body it never had.
207
+ */
208
+ function restoreTableSections(host, doc) {
209
+ for (const table of Array.from(host.querySelectorAll('table'))) {
210
+ // Same rule as the cell pass: a table inside preserved markup is content we
211
+ // undertook to hand back byte-identical, and its sections are already in the
212
+ // preserved string. Restructuring there would be a broken promise.
213
+ if (isInsidePreserved(table))
88
214
  continue;
89
- // Only when the paragraph is the cell's entire content; a stray text node
90
- // beside it means the markup is doing something we should not touch.
91
- if (cell.childNodes.length !== 1)
215
+ const counts = tableSectionRowCounts(table);
216
+ if (!counts)
92
217
  continue;
93
- while (only.firstChild)
94
- cell.insertBefore(only.firstChild, only);
95
- cell.removeChild(only);
218
+ const tbody = Array.from(table.children).find((child) => child.nodeName === 'TBODY');
219
+ if (!tbody)
220
+ continue;
221
+ const rows = Array.from(tbody.children).filter((child) => child.nodeName === 'TR');
222
+ const header = Math.min(counts.header, rows.length);
223
+ const footer = Math.min(counts.footer, rows.length - header);
224
+ if (header > 0) {
225
+ const thead = doc.createElement('thead');
226
+ for (const row of rows.slice(0, header))
227
+ thead.appendChild(row);
228
+ table.insertBefore(thead, tbody);
229
+ }
230
+ if (footer > 0) {
231
+ const tfoot = doc.createElement('tfoot');
232
+ for (const row of rows.slice(rows.length - footer))
233
+ tfoot.appendChild(row);
234
+ table.insertBefore(tfoot, tbody.nextSibling);
235
+ }
236
+ if (!tbody.hasChildNodes())
237
+ table.removeChild(tbody);
96
238
  }
97
239
  }
98
- /** Serialize an OpenLeaf document back to an HTML string. */
240
+ /**
241
+ * Serialize an OpenLeaf document back to an HTML string.
242
+ *
243
+ * Throws `OpenLeafError` with code `invalid-argument` for anything that is not a
244
+ * ProseMirror node. `serializeHtml(null)` used to surface a raw
245
+ * `TypeError: Cannot read properties of null (reading 'type')` from inside
246
+ * ProseMirror, with nothing in it naming OpenLeaf or the call that was wrong.
247
+ */
99
248
  export function serializeHtml(node, opts) {
249
+ if (node === null || typeof node !== 'object' || !('type' in node) || !('content' in node)) {
250
+ throw new OpenLeafError('invalid-argument', '@openleaf-editor/core: serializeHtml expects a ProseMirror node, such as ' +
251
+ '`view.state.doc`.');
252
+ }
100
253
  const doc = resolveDocument(opts);
101
254
  return withSerializationDocument(doc, () => {
102
255
  // Taken from the document itself, so a document built on an extended schema
@@ -106,7 +259,8 @@ export function serializeHtml(node, opts) {
106
259
  const fragment = serializerFor(target).serializeFragment(node.content, { document: doc });
107
260
  const host = doc.createElement('div');
108
261
  host.appendChild(fragment);
109
- unwrapSoleCellParagraph(host);
262
+ unwrapSoleParagraph(host);
263
+ restoreTableSections(host, doc);
110
264
  return host.innerHTML;
111
265
  });
112
266
  }
package/dist/html.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"html.js","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,17 +1,34 @@
1
+ /**
2
+ * ProseMirror types re-exported so a plugin needs no direct dependency on
3
+ * ProseMirror to be written against this API.
4
+ *
5
+ * Type-only, so they add nothing to any bundle. Without them, writing a
6
+ * `Command` or a `NodeSpec` meant adding `prosemirror-state` and
7
+ * `prosemirror-model` to the plugin's own package -- and getting a *second*
8
+ * copy of either of them is how a node built by one schema stops being a node
9
+ * type the editor accepts.
10
+ */
11
+ export type { Command } from 'prosemirror-state';
12
+ export type { MarkSpec, NodeSpec, Schema } from 'prosemirror-model';
13
+ export { OpenLeafError, isOpenLeafError, type OpenLeafErrorCode } from './errors.js';
1
14
  export { baseSchema, coreMarks, coreNodes } from './schema.js';
2
15
  export { ALIGNMENTS, COLOUR_PROPERTIES, FONT_FAMILIES, FONT_SIZE_PRESETS, INDENT_EM, INLINE_STYLE_PROPERTIES, LINE_HEIGHT_PRESETS, LIST_STYLES, MAX_INDENT, MODELLED_PROPERTIES, indentCss, indentLevels, isFullyModelledStyle, modelledValue, parseDeclarations, safeAlign, safeColor, safeDir, safeFontFamily, safeFontSize, safeLang, safeLineHeight, safeListStyle, serializeDeclarations, type Align, type Dir, type ListStyle, } from './css.js';
3
- export { parseHtml, serializeHtml, roundTrip, type HtmlIOOptions } from './html.js';
4
- export { isLosslesslyUnwrappable, unknownBlock, unknownInline } from './preserve.js';
16
+ export { MAX_PARSE_DEPTH, parseHtml, serializeHtml, roundTrip, type HtmlIOOptions } from './html.js';
17
+ export { isLosslesslyUnwrappable, isInsidePreserved, unknownBlock, unknownInline, } from './preserve.js';
5
18
  export { URL_ATTRIBUTES, isEventHandlerAttribute, isSafeUrl, safeUrlOrNull, } from './url.js';
6
- export { EMBED_HOSTS, isAllowedEmbedSrc, safeAllowList, safeEmbedSrc, type EmbedHostRule, } from './embed.js';
19
+ export { EMBED_HOSTS, embedSrcFor, isAllowedEmbedSrc, safeAllowList, safeEmbedSrc, type EmbedHostRule, } from './embed.js';
7
20
  export { IMAGE_ALIGNMENTS, IMAGE_ALIGN_CLASS, IMAGE_ALIGN_CLASSES, imageAlignFromClass, safeClassList, safeId, type ImageAlign, } from './tokens.js';
8
- export { activeBackgroundColor, activeDir, activeFontFamily, activeFontSize, activeHeadingLevel, activeIndent, activeLanguage, activeLineHeight, activeLink, activeListStyle, activeTextAlign, activeTextColor, canInsert, canRedo, canUndo, isMarkActive, isNodeActive, toggleBold, toggleInlineCode, toggleItalic, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline, clearBackgroundColor, clearTextColor, setBackgroundColor, setTextColor, setFontFamily, setFontSize, setLanguage, clearFormatting, insertHorizontalRule, setDir, setHeading, setLineHeight, setParagraph, setTextAlign, toggleBlockquote, toggleCodeBlock, toggleDir, toggleHeading, toggleTextAlign, wrapInBlockquote, insertAudio, insertDetails, insertHtml, insertIframe, insertNamedAnchor, insertNonBreakingSpace, insertPageBreak, insertText, insertVideo, setHeadingId, indent, indentListItem, outdent, outdentListItem, setListStyle, splitListItemCommand, toggleBulletList, toggleOrderedList, insertImage, setLink, unsetLink, type ImageAttrs, type LinkAttrs, type MediaAttrs, redo, undo, } from './commands.js';
21
+ export { activeBackgroundColor, activeDir, activeFontFamily, activeFontSize, activeHeadingLevel, activeIndent, activeLanguage, activeLineHeight, activeLink, activeListStyle, activeTextAlign, activeTextColor, canInsert, canRedo, canUndo, isMarkActive, isNodeActive, toggleBold, toggleInlineCode, toggleItalic, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline, clearBackgroundColor, clearTextColor, setBackgroundColor, setTextColor, setFontFamily, setFontSize, setLanguage, clearFormatting, insertHorizontalRule, setDir, setHeading, setLineHeight, setParagraph, setTextAlign, toggleBlockquote, toggleCodeBlock, toggleDir, toggleHeading, toggleTextAlign, wrapInBlockquote, insertAudio, insertDetails, insertHtml, insertIframe, insertNamedAnchor, insertNonBreakingSpace, insertPageBreak, insertText, insertVideo, setHeadingId, indent, indentListItem, outdent, outdentListItem, setListStyle, splitListItemCommand, toggleBulletList, toggleOrderedList, insertImage, selectedImage, selectedMedia, setLink, unsetLink, updateImage, updateMedia, type ImageAttrs, type LinkAttrs, type MediaAttrs, type MediaSource, type SelectedImage, type SelectedMedia, redo, undo, } from './commands.js';
9
22
  export { buildKeymap, shortcutFor, shortcuts, type Shortcut, } from './keymap.js';
10
23
  export { autolinkPlugin, hrefFromTypedUrl } from './autolink.js';
11
24
  export { visualAidsPlugin } from './visual-aids.js';
25
+ export { disclosurePlugin } from './disclosure.js';
26
+ export { gapCursorPlugin } from './gapcursor.js';
27
+ export { clampIsolatingTextSelection, innermostIsolatingDepth, isolatingSelectionPlugin, textSelectionCrossesIsolating, } from './isolating-selection.js';
28
+ export { figureDragPlugin } from './figure-drag.js';
12
29
  export { isNonEditableNode, nonEditablePlugin } from './noneditable.js';
13
30
  export { activeBlockClass, carriedClass, formatParts, parseFormatList, setBlockClass, type FormatParts, type FormatSpec, } from './formats.js';
14
31
  export { createRegisteredPlugins, onEditorPluginsChange, registerEditorPlugin, type EditorPluginFactory, } from './plugins.js';
15
- export { safeTableStyleValue, table, table_cell, table_header, table_row } from './tables.js';
16
- export { CARRIED_ATTR, clearSchemaExtensions, coreSchema, createSchema, onSchemaExtensionsChange, registerSchemaExtension, registeredSchemaExtensions, type SchemaExtension, } from './extensions.js';
32
+ export { safeTableStyleValue, tableCaptionPlugin } from './tables.js';
33
+ export { coreSchema, createSchema, onSchemaExtensionsChange, registerSchemaExtension, registeredSchemaExtensions, type SchemaExtension, } from './extensions.js';
17
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAEnE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACpF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,uBAAuB,EACvB,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,SAAS,EACT,YAAY,EACZ,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,OAAO,EACP,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,SAAS,GACf,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAA;AACpG,OAAO,EACL,uBAAuB,EAKvB,iBAAiB,EACjB,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,SAAS,EACT,aAAa,GACd,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,KAAK,aAAa,GACnB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,MAAM,EACN,KAAK,UAAU,GAChB,MAAM,aAAa,CAAA;AACpB,OAAO,EAEL,qBAAqB,EACrB,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,eAAe,EACf,eAAe,EACf,SAAS,EACT,OAAO,EACP,OAAO,EACP,YAAY,EACZ,YAAY,EAEZ,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,eAAe,EAEf,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,YAAY,EAEZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,eAAe,EAEf,oBAAoB,EACpB,MAAM,EACN,UAAU,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EACf,UAAU,EACV,WAAW,EACX,YAAY,EAEZ,MAAM,EACN,cAAc,EACd,OAAO,EACP,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EAEjB,WAAW,EACX,aAAa,EACb,aAAa,EACb,OAAO,EACP,SAAS,EACT,WAAW,EACX,WAAW,EACX,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAElB,IAAI,EACJ,IAAI,GACL,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,WAAW,EACX,WAAW,EACX,SAAS,EACT,KAAK,QAAQ,GACd,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACvE,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,UAAU,GAChB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,mBAAmB,GACzB,MAAM,cAAc,CAAA;AASrB,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAKrE,OAAO,EACL,UAAU,EACV,YAAY,EAMZ,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAA"}