@openleaf-editor/core 0.1.0-beta.1 → 0.1.0-beta.3

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 (101) hide show
  1. package/README.md +115 -0
  2. package/dist/autolink.d.ts +12 -0
  3. package/dist/autolink.d.ts.map +1 -0
  4. package/dist/autolink.js +136 -0
  5. package/dist/autolink.js.map +1 -0
  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 +43 -22
  11. package/dist/commands.d.ts.map +1 -1
  12. package/dist/commands.js +513 -115
  13. package/dist/commands.js.map +1 -1
  14. package/dist/css.d.ts +1 -123
  15. package/dist/css.d.ts.map +1 -1
  16. package/dist/css.js +1 -214
  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 +2 -0
  27. package/dist/embed.d.ts.map +1 -0
  28. package/dist/embed.js +2 -0
  29. package/dist/embed.js.map +1 -0
  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 +292 -65
  37. package/dist/extensions.js.map +1 -1
  38. package/dist/formats.d.ts +44 -0
  39. package/dist/formats.d.ts.map +1 -0
  40. package/dist/formats.js +123 -0
  41. package/dist/formats.js.map +1 -0
  42. package/dist/html.d.ts +32 -2
  43. package/dist/html.d.ts.map +1 -1
  44. package/dist/html.js +185 -31
  45. package/dist/html.js.map +1 -1
  46. package/dist/index.d.ts +27 -6
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +44 -10
  49. package/dist/index.js.map +1 -1
  50. package/dist/insert-commands.d.ts +172 -0
  51. package/dist/insert-commands.d.ts.map +1 -0
  52. package/dist/insert-commands.js +560 -0
  53. package/dist/insert-commands.js.map +1 -0
  54. package/dist/isolating-selection.d.ts +41 -0
  55. package/dist/isolating-selection.d.ts.map +1 -0
  56. package/dist/isolating-selection.js +162 -0
  57. package/dist/isolating-selection.js.map +1 -0
  58. package/dist/keymap.d.ts.map +1 -1
  59. package/dist/keymap.js +6 -3
  60. package/dist/keymap.js.map +1 -1
  61. package/dist/noneditable.d.ts +14 -0
  62. package/dist/noneditable.d.ts.map +1 -0
  63. package/dist/noneditable.js +107 -0
  64. package/dist/noneditable.js.map +1 -0
  65. package/dist/plugins.d.ts +20 -2
  66. package/dist/plugins.d.ts.map +1 -1
  67. package/dist/plugins.js +27 -2
  68. package/dist/plugins.js.map +1 -1
  69. package/dist/preserve.d.ts +76 -0
  70. package/dist/preserve.d.ts.map +1 -1
  71. package/dist/preserve.js +308 -58
  72. package/dist/preserve.js.map +1 -1
  73. package/dist/schema.d.ts +15 -0
  74. package/dist/schema.d.ts.map +1 -1
  75. package/dist/schema.js +356 -76
  76. package/dist/schema.js.map +1 -1
  77. package/dist/structure.d.ts +76 -0
  78. package/dist/structure.d.ts.map +1 -0
  79. package/dist/structure.js +422 -0
  80. package/dist/structure.js.map +1 -0
  81. package/dist/tables.d.ts +60 -1
  82. package/dist/tables.d.ts.map +1 -1
  83. package/dist/tables.js +617 -35
  84. package/dist/tables.js.map +1 -1
  85. package/dist/testing.d.ts +3 -0
  86. package/dist/testing.d.ts.map +1 -0
  87. package/dist/testing.js +3 -0
  88. package/dist/testing.js.map +1 -0
  89. package/dist/tokens.d.ts +36 -0
  90. package/dist/tokens.d.ts.map +1 -0
  91. package/dist/tokens.js +116 -0
  92. package/dist/tokens.js.map +1 -0
  93. package/dist/url.d.ts +1 -25
  94. package/dist/url.d.ts.map +1 -1
  95. package/dist/url.js +1 -77
  96. package/dist/url.js.map +1 -1
  97. package/dist/visual-aids.d.ts +20 -0
  98. package/dist/visual-aids.d.ts.map +1 -0
  99. package/dist/visual-aids.js +149 -0
  100. package/dist/visual-aids.js.map +1 -0
  101. package/package.json +16 -1
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Structural nodes that belong in the base schema for the same reason tables
3
+ * do: without them, stored `<details>`, `<figure>` and a page break become
4
+ * opaque preserved atoms -- faithful, and uneditable.
5
+ *
6
+ * The editing chrome (dialogs, character map, resize handles) lives in
7
+ * `@openleaf-editor/plugins-insert`. What is here is the storage format.
8
+ */
9
+ import type { Attrs, NodeSpec } from 'prosemirror-model';
10
+ /**
11
+ * `<video>` and `<audio>`. `controls` defaults to on: an inserted player
12
+ * without controls is a rectangle that cannot be played from the keyboard,
13
+ * and authors rarely go back to add them.
14
+ */
15
+ export declare const video: NodeSpec;
16
+ export declare const audio: NodeSpec;
17
+ /**
18
+ * An allowlisted embed. Unsafe iframes are ignored by a sibling parse rule in
19
+ * preserve.ts rather than preserved: an iframe is a nested page, not an
20
+ * author's callout div.
21
+ */
22
+ export declare const iframe: NodeSpec;
23
+ export declare const details: NodeSpec;
24
+ export declare const summary: NodeSpec;
25
+ /**
26
+ * A captioned image. Figures that contain anything other than an image and an
27
+ * optional caption are left to the preservation layer: claiming them here
28
+ * would flatten a complex figure into a shape it cannot round-trip.
29
+ *
30
+ * `content: 'inline+'` makes this a textblock, the same as a paragraph. Block-
31
+ * type commands must not retype it: the destination cannot hold an image plus
32
+ * figcaption, and treating it as a paragraph is how a heading dropdown used to
33
+ * destroy the figure. The guards live on the commands (`validContent`, and
34
+ * `canInsert` stopping at `isolating`) rather than a tighter content
35
+ * expression, because stored `<figure><img>…<figcaption>` is inline children
36
+ * in this schema and changing that is a parse/serialize rewrite.
37
+ */
38
+ export declare const figure: NodeSpec;
39
+ /**
40
+ * Caption for a modelled figure, and only for a modelled figure.
41
+ *
42
+ * The node is inline because `figure` is `inline+` (an image plus this). The
43
+ * HTML parser does not agree: `figcaption` is in the "in body" start-tag list
44
+ * that closes an open `<p>`, so a caption parsed as ordinary inline content
45
+ * is wrapped in a paragraph on the way out, then split on the way back in,
46
+ * and each save adds an empty paragraph before the caption and one after.
47
+ * Restricting the parse rule to `figure/` is what stops that: an orphaned
48
+ * caption is declined here and claimed by the preservation layer as a block
49
+ * atom, which is markup the next parse can consume without wrapping it in a
50
+ * `<p>`. A nested figure stays editable.
51
+ */
52
+ export declare const figcaption: NodeSpec;
53
+ export declare const page_break: NodeSpec;
54
+ /**
55
+ * Whitespace-only interiors count as empty: pretty-printed `<a id="jump">\n</a>`
56
+ * has no modelled text (`parseHtml` does not preserve whitespace), and treating
57
+ * it as a link mark would drop the destination entirely.
58
+ */
59
+ export declare function isEmptyNamedAnchorElement(el: Element): boolean;
60
+ /**
61
+ * An empty named destination: `<a id="section"></a>`.
62
+ *
63
+ * A link with both `href` and `id` is a mark, not this node. This exists for
64
+ * the jump target that has no text of its own, which is what TinyMCE's
65
+ * anchor plugin inserts and what a decade of CMS content already contains.
66
+ *
67
+ * An atom cannot hold content. `<a id="sec">Section</a>` wrapping visible text
68
+ * is the pre-HTML5 in-page-anchor idiom; claiming it here discarded the text
69
+ * on parse. Those elements decline so the `link` mark (which already carries
70
+ * `id`, and `href` only when present) can keep the text editable.
71
+ */
72
+ export declare const named_anchor: NodeSpec;
73
+ /** Image attributes shared by parse and commands. */
74
+ export declare function imageParseAttrs(el: Element): Record<string, unknown> | false;
75
+ export declare function imageDomAttrs(attrs: Attrs): Record<string, string>;
76
+ //# sourceMappingURL=structure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAiB,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAqGvE;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE,QAyCnB,CAAA;AAED,eAAO,MAAM,KAAK,EAAE,QAgCnB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,QAyCpB,CAAA;AAED,eAAO,MAAM,OAAO,EAAE,QAerB,CAAA;AAED,eAAO,MAAM,OAAO,EAAE,QAKrB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,EAAE,QAgBpB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,EAAE,QAMxB,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,QAUxB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,EAAE,QAuB1B,CAAA;AAED,qDAAqD;AACrD,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAY5E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBlE"}
@@ -0,0 +1,422 @@
1
+ /**
2
+ * Structural nodes that belong in the base schema for the same reason tables
3
+ * do: without them, stored `<details>`, `<figure>` and a page break become
4
+ * opaque preserved atoms -- faithful, and uneditable.
5
+ *
6
+ * The editing chrome (dialogs, character map, resize handles) lives in
7
+ * `@openleaf-editor/plugins-insert`. What is here is the storage format.
8
+ */
9
+ import { safeAllowList, safeEmbedSrc } from './embed.js';
10
+ import { IMAGE_ALIGN_CLASS, IMAGE_ALIGN_CLASSES, imageAlignFromClass, safeClassList, safeId } from './tokens.js';
11
+ import { MEDIA_FURNITURE_TAGS, hasMediaFallback, scrub, serializationTarget, } from './preserve.js';
12
+ import { isSafeUrl } from './url.js';
13
+ function boolAttr(el, name) {
14
+ return el.hasAttribute(name);
15
+ }
16
+ function dimension(el, name) {
17
+ const value = el.getAttribute(name);
18
+ if (!value)
19
+ return null;
20
+ return /^\d+(?:\.\d+)?%?$/.test(value) ? value : null;
21
+ }
22
+ /**
23
+ * The `<source>`/`<track>` children of a media element, as scrubbed markup.
24
+ *
25
+ * Furniture rather than nodes for the same reason a table's `<colgroup>` is:
26
+ * authors never type into them, and a content expression for something nobody
27
+ * edits buys nothing. Storing them at all is what keeps
28
+ * `<video><source src="clip.webm"></video>` -- which has no `src` of its own --
29
+ * a real editable node. Without it the schema declined the element and the
30
+ * preservation layer's drop rule then deleted the whole thing.
31
+ */
32
+ function readMediaFurniture(el) {
33
+ let html = '';
34
+ for (const child of Array.from(el.children)) {
35
+ if (!MEDIA_FURNITURE_TAGS.has(child.nodeName.toLowerCase()))
36
+ continue;
37
+ // Dropped whole rather than scrubbed down to `<source>`: `scrub` would strip
38
+ // the unsafe address and leave an element that plays nothing and says
39
+ // nothing. A media element left with no usable source is then declined.
40
+ if (!isSafeUrl(child.getAttribute('src')))
41
+ continue;
42
+ html += scrub(child);
43
+ }
44
+ return html || null;
45
+ }
46
+ /**
47
+ * Rebuild stored furniture and append it to the element being serialized.
48
+ *
49
+ * `<template>` is the parsing context because a bare `<source>` is illegal
50
+ * inside a `<div>` and would be silently discarded there -- the same reason the
51
+ * preservation layer uses one.
52
+ */
53
+ function appendMediaFurniture(host, html, doc) {
54
+ const tpl = doc.createElement('template');
55
+ tpl.innerHTML = html;
56
+ for (const child of Array.from(tpl.content.children)) {
57
+ if (!MEDIA_FURNITURE_TAGS.has(child.nodeName.toLowerCase()))
58
+ continue;
59
+ // Scrubbed on the way out too. Furniture read from a parse has already been
60
+ // through `readMediaFurniture`, but a string written by a command or a
61
+ // dialog has not, and `<source src="x" onerror="...">` must not be stored.
62
+ const clean = doc.createElement('template');
63
+ clean.innerHTML = scrub(child);
64
+ const el = clean.content.firstElementChild;
65
+ if (el)
66
+ host.appendChild(el);
67
+ }
68
+ }
69
+ function mediaAttrs(el) {
70
+ // Fallback content has nowhere to live on an atom. Declining hands the element
71
+ // to the preservation layer, which keeps it whole -- see the priority-45 rule
72
+ // in preserve.ts.
73
+ if (hasMediaFallback(el))
74
+ return false;
75
+ const src = el.getAttribute('src');
76
+ if (src !== null && !isSafeUrl(src))
77
+ return false;
78
+ const furniture = readMediaFurniture(el);
79
+ // One or the other. A player with neither has nothing to play.
80
+ if (src === null && furniture === null)
81
+ return false;
82
+ return {
83
+ src,
84
+ furniture,
85
+ title: el.getAttribute('title'),
86
+ controls: boolAttr(el, 'controls'),
87
+ width: dimension(el, 'width'),
88
+ height: dimension(el, 'height'),
89
+ };
90
+ }
91
+ /**
92
+ * Serialize a media element, splicing its furniture back in as children.
93
+ *
94
+ * A real element rather than a spec array whenever there is furniture: an array
95
+ * cannot carry raw markup, and the `<source>` children have to be appended.
96
+ */
97
+ function mediaToDOM(tag, attrs, furniture) {
98
+ if (!furniture)
99
+ return [tag, attrs];
100
+ const doc = serializationTarget();
101
+ const el = doc.createElement(tag);
102
+ for (const [name, value] of Object.entries(attrs))
103
+ el.setAttribute(name, value);
104
+ appendMediaFurniture(el, furniture, doc);
105
+ return el;
106
+ }
107
+ /**
108
+ * `<video>` and `<audio>`. `controls` defaults to on: an inserted player
109
+ * without controls is a rectangle that cannot be played from the keyboard,
110
+ * and authors rarely go back to add them.
111
+ */
112
+ export const video = {
113
+ group: 'block',
114
+ atom: true,
115
+ selectable: true,
116
+ draggable: true,
117
+ attrs: {
118
+ // Optional: source-only media carries its addresses in `furniture` instead.
119
+ src: { default: null },
120
+ furniture: { default: null },
121
+ title: { default: null },
122
+ controls: { default: false },
123
+ width: { default: null },
124
+ height: { default: null },
125
+ poster: { default: null },
126
+ },
127
+ parseDOM: [
128
+ {
129
+ tag: 'video',
130
+ getAttrs(dom) {
131
+ const el = dom;
132
+ const base = mediaAttrs(el);
133
+ if (!base)
134
+ return false;
135
+ const poster = el.getAttribute('poster');
136
+ return {
137
+ ...base,
138
+ poster: poster && isSafeUrl(poster) ? poster : null,
139
+ };
140
+ },
141
+ },
142
+ ],
143
+ toDOM(node) {
144
+ const { src, title, controls, width, height, poster, furniture } = node.attrs;
145
+ const attrs = {};
146
+ if (src !== null)
147
+ attrs['src'] = src;
148
+ if (title !== null)
149
+ attrs['title'] = title;
150
+ if (controls)
151
+ attrs['controls'] = '';
152
+ if (width !== null)
153
+ attrs['width'] = width;
154
+ if (height !== null)
155
+ attrs['height'] = height;
156
+ if (poster !== null)
157
+ attrs['poster'] = poster;
158
+ return mediaToDOM('video', attrs, furniture);
159
+ },
160
+ };
161
+ export const audio = {
162
+ group: 'block',
163
+ atom: true,
164
+ selectable: true,
165
+ draggable: true,
166
+ attrs: {
167
+ src: { default: null },
168
+ furniture: { default: null },
169
+ title: { default: null },
170
+ controls: { default: false },
171
+ },
172
+ parseDOM: [
173
+ {
174
+ tag: 'audio',
175
+ getAttrs(dom) {
176
+ const base = mediaAttrs(dom);
177
+ if (!base)
178
+ return false;
179
+ // Audio has no intrinsic box, so the dimensions mediaAttrs read are not
180
+ // part of this node's shape.
181
+ const { width: _width, height: _height, ...rest } = base;
182
+ return rest;
183
+ },
184
+ },
185
+ ],
186
+ toDOM(node) {
187
+ const { src, title, controls, furniture } = node.attrs;
188
+ const attrs = {};
189
+ if (src !== null)
190
+ attrs['src'] = src;
191
+ if (title !== null)
192
+ attrs['title'] = title;
193
+ if (controls)
194
+ attrs['controls'] = '';
195
+ return mediaToDOM('audio', attrs, furniture);
196
+ },
197
+ };
198
+ /**
199
+ * An allowlisted embed. Unsafe iframes are ignored by a sibling parse rule in
200
+ * preserve.ts rather than preserved: an iframe is a nested page, not an
201
+ * author's callout div.
202
+ */
203
+ export const iframe = {
204
+ group: 'block',
205
+ atom: true,
206
+ selectable: true,
207
+ draggable: true,
208
+ attrs: {
209
+ src: {},
210
+ title: { default: null },
211
+ width: { default: null },
212
+ height: { default: null },
213
+ allow: { default: null },
214
+ allowfullscreen: { default: true },
215
+ },
216
+ parseDOM: [
217
+ {
218
+ tag: 'iframe',
219
+ getAttrs(dom) {
220
+ const el = dom;
221
+ const src = safeEmbedSrc(el.getAttribute('src'));
222
+ if (!src)
223
+ return false;
224
+ return {
225
+ src,
226
+ title: el.getAttribute('title'),
227
+ width: dimension(el, 'width'),
228
+ height: dimension(el, 'height'),
229
+ allow: safeAllowList(el.getAttribute('allow')),
230
+ allowfullscreen: el.hasAttribute('allowfullscreen'),
231
+ };
232
+ },
233
+ },
234
+ ],
235
+ toDOM(node) {
236
+ const { src, title, width, height, allow, allowfullscreen } = node.attrs;
237
+ const attrs = { src: src };
238
+ if (title !== null)
239
+ attrs['title'] = title;
240
+ if (width !== null)
241
+ attrs['width'] = width;
242
+ if (height !== null)
243
+ attrs['height'] = height;
244
+ if (allow !== null)
245
+ attrs['allow'] = allow;
246
+ if (allowfullscreen)
247
+ attrs['allowfullscreen'] = '';
248
+ return ['iframe', attrs];
249
+ },
250
+ };
251
+ export const details = {
252
+ group: 'block',
253
+ content: 'summary block+',
254
+ defining: true,
255
+ isolating: true,
256
+ attrs: { open: { default: false } },
257
+ parseDOM: [
258
+ {
259
+ tag: 'details',
260
+ getAttrs: (dom) => ({ open: dom.hasAttribute('open') }),
261
+ },
262
+ ],
263
+ toDOM(node) {
264
+ return node.attrs['open'] ? ['details', { open: '' }, 0] : ['details', 0];
265
+ },
266
+ };
267
+ export const summary = {
268
+ content: 'inline*',
269
+ defining: true,
270
+ parseDOM: [{ tag: 'summary' }],
271
+ toDOM: () => ['summary', 0],
272
+ };
273
+ /**
274
+ * A captioned image. Figures that contain anything other than an image and an
275
+ * optional caption are left to the preservation layer: claiming them here
276
+ * would flatten a complex figure into a shape it cannot round-trip.
277
+ *
278
+ * `content: 'inline+'` makes this a textblock, the same as a paragraph. Block-
279
+ * type commands must not retype it: the destination cannot hold an image plus
280
+ * figcaption, and treating it as a paragraph is how a heading dropdown used to
281
+ * destroy the figure. The guards live on the commands (`validContent`, and
282
+ * `canInsert` stopping at `isolating`) rather than a tighter content
283
+ * expression, because stored `<figure><img>…<figcaption>` is inline children
284
+ * in this schema and changing that is a parse/serialize rewrite.
285
+ */
286
+ export const figure = {
287
+ group: 'block',
288
+ content: 'inline+',
289
+ isolating: true,
290
+ parseDOM: [
291
+ {
292
+ tag: 'figure',
293
+ getAttrs(dom) {
294
+ const el = dom;
295
+ const children = Array.from(el.children).filter((child) => child.nodeName !== 'FIGCAPTION');
296
+ if (children.length !== 1 || children[0]?.nodeName !== 'IMG')
297
+ return false;
298
+ return {};
299
+ },
300
+ },
301
+ ],
302
+ toDOM: () => ['figure', 0],
303
+ };
304
+ /**
305
+ * Caption for a modelled figure, and only for a modelled figure.
306
+ *
307
+ * The node is inline because `figure` is `inline+` (an image plus this). The
308
+ * HTML parser does not agree: `figcaption` is in the "in body" start-tag list
309
+ * that closes an open `<p>`, so a caption parsed as ordinary inline content
310
+ * is wrapped in a paragraph on the way out, then split on the way back in,
311
+ * and each save adds an empty paragraph before the caption and one after.
312
+ * Restricting the parse rule to `figure/` is what stops that: an orphaned
313
+ * caption is declined here and claimed by the preservation layer as a block
314
+ * atom, which is markup the next parse can consume without wrapping it in a
315
+ * `<p>`. A nested figure stays editable.
316
+ */
317
+ export const figcaption = {
318
+ inline: true,
319
+ group: 'inline',
320
+ content: 'inline*',
321
+ parseDOM: [{ tag: 'figcaption', context: 'figure/' }],
322
+ toDOM: () => ['figcaption', 0],
323
+ };
324
+ export const page_break = {
325
+ group: 'block',
326
+ atom: true,
327
+ selectable: true,
328
+ parseDOM: [
329
+ { tag: 'div[data-pagebreak]' },
330
+ { tag: 'div.ol-pagebreak' },
331
+ { tag: 'hr.ol-pagebreak' },
332
+ ],
333
+ toDOM: () => ['hr', { class: 'ol-pagebreak' }],
334
+ };
335
+ /**
336
+ * Whitespace-only interiors count as empty: pretty-printed `<a id="jump">\n</a>`
337
+ * has no modelled text (`parseHtml` does not preserve whitespace), and treating
338
+ * it as a link mark would drop the destination entirely.
339
+ */
340
+ export function isEmptyNamedAnchorElement(el) {
341
+ return (el.textContent ?? '').trim() === '' && !el.firstElementChild;
342
+ }
343
+ /**
344
+ * An empty named destination: `<a id="section"></a>`.
345
+ *
346
+ * A link with both `href` and `id` is a mark, not this node. This exists for
347
+ * the jump target that has no text of its own, which is what TinyMCE's
348
+ * anchor plugin inserts and what a decade of CMS content already contains.
349
+ *
350
+ * An atom cannot hold content. `<a id="sec">Section</a>` wrapping visible text
351
+ * is the pre-HTML5 in-page-anchor idiom; claiming it here discarded the text
352
+ * on parse. Those elements decline so the `link` mark (which already carries
353
+ * `id`, and `href` only when present) can keep the text editable.
354
+ */
355
+ export const named_anchor = {
356
+ inline: true,
357
+ group: 'inline',
358
+ atom: true,
359
+ selectable: true,
360
+ attrs: { id: {} },
361
+ parseDOM: [
362
+ {
363
+ tag: 'a[id]',
364
+ getAttrs(dom) {
365
+ const el = dom;
366
+ if (el.hasAttribute('href'))
367
+ return false;
368
+ // An atom cannot hold content. An <a id> WITH text is a jump target
369
+ // wrapped around a heading -- the commonest legacy spelling -- and
370
+ // claiming it here deletes the text.
371
+ if (!isEmptyNamedAnchorElement(el))
372
+ return false;
373
+ const id = safeId(el.getAttribute('id'));
374
+ if (!id)
375
+ return false;
376
+ return { id };
377
+ },
378
+ },
379
+ ],
380
+ toDOM: (node) => ['a', { id: node.attrs['id'] }],
381
+ };
382
+ /** Image attributes shared by parse and commands. */
383
+ export function imageParseAttrs(el) {
384
+ if (!isSafeUrl(el.getAttribute('src')))
385
+ return false;
386
+ const className = el.getAttribute('class');
387
+ return {
388
+ src: el.getAttribute('src'),
389
+ alt: el.getAttribute('alt'),
390
+ title: el.getAttribute('title'),
391
+ width: el.getAttribute('width'),
392
+ height: el.getAttribute('height'),
393
+ align: imageAlignFromClass(className),
394
+ className: safeClassList(className, IMAGE_ALIGN_CLASSES),
395
+ };
396
+ }
397
+ export function imageDomAttrs(attrs) {
398
+ const classes = [];
399
+ const align = attrs.align;
400
+ if (align)
401
+ classes.push(IMAGE_ALIGN_CLASS[align]);
402
+ if (typeof attrs.className === 'string' && attrs.className !== '') {
403
+ classes.push(attrs.className);
404
+ }
405
+ // `class` first so round-trips match the stored spelling the tests pin
406
+ // (`class` then `src`). Putting `src` first is how GitHub Actions started
407
+ // failing those fixtures after DOMSerializer began honouring object order.
408
+ const out = {};
409
+ if (classes.length > 0)
410
+ out['class'] = classes.join(' ');
411
+ out['src'] = attrs.src;
412
+ if (attrs.alt !== null && attrs.alt !== undefined)
413
+ out['alt'] = attrs.alt;
414
+ if (attrs.title !== null && attrs.title !== undefined)
415
+ out['title'] = attrs.title;
416
+ if (attrs.width !== null && attrs.width !== undefined)
417
+ out['width'] = attrs.width;
418
+ if (attrs.height !== null && attrs.height !== undefined)
419
+ out['height'] = attrs.height;
420
+ return out;
421
+ }
422
+ //# sourceMappingURL=structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.js","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"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"}
package/dist/tables.d.ts CHANGED
@@ -35,8 +35,67 @@
35
35
  * is what tells a screen reader which cells a header governs. Dropping it turns
36
36
  * a navigable table into a grid of unrelated values.
37
37
  */
38
- import type { NodeSpec } from 'prosemirror-model';
38
+ import type { Node as PMNode, NodeSpec } from 'prosemirror-model';
39
+ import { Plugin } from 'prosemirror-state';
40
+ import type { NodeView } from 'prosemirror-view';
41
+ /**
42
+ * The one validator for a table style declaration, on the way in or out.
43
+ *
44
+ * Exported because the property dialogs in `@openleaf-editor/plugins-table`
45
+ * write node attributes directly, which does not go through any parse rule. A
46
+ * dialog with its own idea of an acceptable padding would drift from this one,
47
+ * and `padding: 0;position:fixed;inset:0` is what that drift looks like: the
48
+ * value becomes two more declarations when the style attribute is serialized.
49
+ *
50
+ * Returns null for a property this schema does not model, so an unrecognised
51
+ * name is dropped rather than trusted.
52
+ */
53
+ export declare function safeTableStyleValue(property: string, value: string | undefined): string | null;
54
+ /** The residue scrubs for the table node types, keyed by schema node name. */
55
+ export declare const CARRIED_STYLE_SCRUBS: Record<string, (carried: Record<string, string>) => void>;
56
+ /**
57
+ * Row counts for a `<table>` element this module rendered, or undefined.
58
+ *
59
+ * The serialization pass in html.ts needs to know how many of a table's rows
60
+ * came out of a `<thead>`, and `toDOM` cannot tell it in the output: ProseMirror
61
+ * allows exactly one `contentDOM`, so rows cannot flow into two sections. The
62
+ * count therefore travels beside the DOM rather than inside it.
63
+ *
64
+ * Out of band for the same reason `preservedElements` is (see preserve.ts): a
65
+ * `data-` attribute stripped after the fact cannot distinguish the attribute
66
+ * this code just added from the identical attribute in a customer's document,
67
+ * and deleting theirs is a worse bug than the one being fixed. A WeakMap cannot
68
+ * collide with content and needs no cleanup pass.
69
+ */
70
+ export declare function tableSectionRowCounts(el: Element): {
71
+ header: number;
72
+ footer: number;
73
+ } | undefined;
39
74
  export declare const table: NodeSpec;
75
+ /**
76
+ * Editor-only table node view: same DOM as `toDOM`, plus `contenteditable="false"`
77
+ * on a preserved caption.
78
+ *
79
+ * A caption sits inside the editable area but outside the node's `contentDOM`,
80
+ * so without the marker a caret can enter text ProseMirror will discard on its
81
+ * next redraw. Serializers (`serializeHtml`, clipboard `DOMSerializer`) never
82
+ * consult node views, so the marker cannot reach stored or clipboard HTML.
83
+ *
84
+ * `@openleaf-editor/plugins-table` replaces this with `CaptionedTableView`, which
85
+ * stamps the same attribute on the caption it rebuilds. Until that bundle loads,
86
+ * this is the view the core editor uses.
87
+ */
88
+ export declare function tableCaptionNodeView(node: PMNode): NodeView;
89
+ /**
90
+ * Registers `tableCaptionNodeView` for editors that have not loaded
91
+ * `@openleaf-editor/plugins-table`.
92
+ *
93
+ * Must sit *before* that bundle's plugins in the editor stack.
94
+ * `EditorView.someProp` walks plugins from the end, so `columnResizing`'s
95
+ * `CaptionedTableView` still wins when both are present. Putting this view
96
+ * later is how it once shadowed column resize.
97
+ */
98
+ export declare function tableCaptionPlugin(): Plugin;
40
99
  export declare const table_row: NodeSpec;
41
100
  export declare const table_cell: NodeSpec;
42
101
  export declare const table_header: NodeSpec;
@@ -1 +1 @@
1
- {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AA2EjD,eAAO,MAAM,KAAK,EAAE,QA0CnB,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,QAQvB,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,QAOxB,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,QAO1B,CAAA"}
1
+ {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAiB,IAAI,IAAI,MAAM,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEhF,OAAO,EAAE,MAAM,EAAa,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AA+ChD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAM9F;AAqFD,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAK1F,CAAA;AAiUD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAEjG;AAqCD,eAAO,MAAM,KAAK,EAAE,QA8GnB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAa3D;AAID;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAW3C;AAED,eAAO,MAAM,SAAS,EAAE,QAmBvB,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,QAOxB,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,QAO1B,CAAA"}