@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.
- package/README.md +115 -0
- package/dist/autolink.d.ts +12 -0
- package/dist/autolink.d.ts.map +1 -0
- package/dist/autolink.js +136 -0
- package/dist/autolink.js.map +1 -0
- package/dist/command-helpers.d.ts +8 -0
- package/dist/command-helpers.d.ts.map +1 -0
- package/dist/command-helpers.js +36 -0
- package/dist/command-helpers.js.map +1 -0
- package/dist/commands.d.ts +43 -22
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +513 -115
- package/dist/commands.js.map +1 -1
- package/dist/css.d.ts +1 -123
- package/dist/css.d.ts.map +1 -1
- package/dist/css.js +1 -214
- package/dist/css.js.map +1 -1
- package/dist/disclosure.d.ts +21 -0
- package/dist/disclosure.d.ts.map +1 -0
- package/dist/disclosure.js +144 -0
- package/dist/disclosure.js.map +1 -0
- package/dist/elements.d.ts +2 -0
- package/dist/elements.d.ts.map +1 -0
- package/dist/elements.js +2 -0
- package/dist/elements.js.map +1 -0
- package/dist/embed.d.ts +2 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/embed.js +2 -0
- package/dist/embed.js.map +1 -0
- package/dist/errors.d.ts +38 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +40 -0
- package/dist/errors.js.map +1 -0
- package/dist/extensions.d.ts +46 -5
- package/dist/extensions.d.ts.map +1 -1
- package/dist/extensions.js +292 -65
- package/dist/extensions.js.map +1 -1
- package/dist/formats.d.ts +44 -0
- package/dist/formats.d.ts.map +1 -0
- package/dist/formats.js +123 -0
- package/dist/formats.js.map +1 -0
- package/dist/html.d.ts +32 -2
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +185 -31
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +27 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -10
- package/dist/index.js.map +1 -1
- package/dist/insert-commands.d.ts +172 -0
- package/dist/insert-commands.d.ts.map +1 -0
- package/dist/insert-commands.js +560 -0
- package/dist/insert-commands.js.map +1 -0
- package/dist/isolating-selection.d.ts +41 -0
- package/dist/isolating-selection.d.ts.map +1 -0
- package/dist/isolating-selection.js +162 -0
- package/dist/isolating-selection.js.map +1 -0
- package/dist/keymap.d.ts.map +1 -1
- package/dist/keymap.js +6 -3
- package/dist/keymap.js.map +1 -1
- package/dist/noneditable.d.ts +14 -0
- package/dist/noneditable.d.ts.map +1 -0
- package/dist/noneditable.js +107 -0
- package/dist/noneditable.js.map +1 -0
- package/dist/plugins.d.ts +20 -2
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +27 -2
- package/dist/plugins.js.map +1 -1
- package/dist/preserve.d.ts +76 -0
- package/dist/preserve.d.ts.map +1 -1
- package/dist/preserve.js +308 -58
- package/dist/preserve.js.map +1 -1
- package/dist/schema.d.ts +15 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +356 -76
- package/dist/schema.js.map +1 -1
- package/dist/structure.d.ts +76 -0
- package/dist/structure.d.ts.map +1 -0
- package/dist/structure.js +422 -0
- package/dist/structure.js.map +1 -0
- package/dist/tables.d.ts +60 -1
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +617 -35
- package/dist/tables.js.map +1 -1
- package/dist/testing.d.ts +3 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +3 -0
- package/dist/testing.js.map +1 -0
- package/dist/tokens.d.ts +36 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +116 -0
- package/dist/tokens.js.map +1 -0
- package/dist/url.d.ts +1 -25
- package/dist/url.d.ts.map +1 -1
- package/dist/url.js +1 -77
- package/dist/url.js.map +1 -1
- package/dist/visual-aids.d.ts +20 -0
- package/dist/visual-aids.d.ts.map +1 -0
- package/dist/visual-aids.js +149 -0
- package/dist/visual-aids.js.map +1 -0
- 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":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,EAAmB,MAAM,aAAa,CAAA;AACjI,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,EACL,mBAAmB,GACpB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC,SAAS,QAAQ,CAAC,EAAW,EAAE,IAAY;IACzC,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;AAC9B,CAAC;AAED,SAAS,SAAS,CAAC,EAAW,EAAE,IAAY;IAC1C,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;IACnC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,OAAO,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;AACvD,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,kBAAkB,CAAC,EAAW;IACrC,IAAI,IAAI,GAAG,EAAE,CAAA;IACb,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YAAE,SAAQ;QACrE,6EAA6E;QAC7E,sEAAsE;QACtE,wEAAwE;QACxE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAAE,SAAQ;QACnD,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC;IACD,OAAO,IAAI,IAAI,IAAI,CAAA;AACrB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,IAAa,EAAE,IAAY,EAAE,GAAa;IACtE,MAAM,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;IACzC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAA;IACpB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAE,GAA2B,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9E,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YAAE,SAAQ;QACrE,4EAA4E;QAC5E,uEAAuE;QACvE,2EAA2E;QAC3E,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;QAC3C,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;QAC9B,MAAM,EAAE,GAAI,KAA6B,CAAC,OAAO,CAAC,iBAAiB,CAAA;QACnE,IAAI,EAAE;YAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;IAC9B,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAW;IAC7B,+EAA+E;IAC/E,8EAA8E;IAC9E,kBAAkB;IAClB,IAAI,gBAAgB,CAAC,EAAE,CAAC;QAAE,OAAO,KAAK,CAAA;IACtC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IAClC,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IACjD,MAAM,SAAS,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAA;IACxC,+DAA+D;IAC/D,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IACpD,OAAO;QACL,GAAG;QACH,SAAS;QACT,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;QAC/B,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC;QAClC,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC;QAC7B,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC;KAChC,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,GAAsB,EAAE,KAA6B,EAAE,SAAwB;IACjG,IAAI,CAAC,SAAS;QAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACnC,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAA;IACjC,MAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IACjC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC/E,oBAAoB,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;IACxC,OAAO,EAAE,CAAA;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAa;IAC7B,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAI;IACf,KAAK,EAAE;QACL,4EAA4E;QAC5E,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACtB,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QAC5B,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACxB,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;QAC5B,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACxB,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACzB,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;KAC1B;IACD,QAAQ,EAAE;QACR;YACE,GAAG,EAAE,OAAO;YACZ,QAAQ,CAAC,GAAG;gBACV,MAAM,EAAE,GAAG,GAAc,CAAA;gBACzB,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,CAAC,CAAA;gBAC3B,IAAI,CAAC,IAAI;oBAAE,OAAO,KAAK,CAAA;gBACvB,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;gBACxC,OAAO;oBACL,GAAG,IAAI;oBACP,MAAM,EAAE,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;iBACpD,CAAA;YACH,CAAC;SACF;KACF;IACD,KAAK,CAAC,IAAI;QACR,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QAC7E,MAAM,KAAK,GAA2B,EAAE,CAAA;QACxC,IAAI,GAAG,KAAK,IAAI;YAAE,KAAK,CAAC,KAAK,CAAC,GAAG,GAAa,CAAA;QAC9C,IAAI,KAAK,KAAK,IAAI;YAAE,KAAK,CAAC,OAAO,CAAC,GAAG,KAAe,CAAA;QACpD,IAAI,QAAQ;YAAE,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,CAAA;QACpC,IAAI,KAAK,KAAK,IAAI;YAAE,KAAK,CAAC,OAAO,CAAC,GAAG,KAAe,CAAA;QACpD,IAAI,MAAM,KAAK,IAAI;YAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,MAAgB,CAAA;QACvD,IAAI,MAAM,KAAK,IAAI;YAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,MAAgB,CAAA;QACvD,OAAO,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,SAA0B,CAAC,CAAA;IAC/D,CAAC;CACF,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAa;IAC7B,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAI;IACf,KAAK,EAAE;QACL,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACtB,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QAC5B,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACxB,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;KAC7B;IACD,QAAQ,EAAE;QACR;YACE,GAAG,EAAE,OAAO;YACZ,QAAQ,CAAC,GAAG;gBACV,MAAM,IAAI,GAAG,UAAU,CAAC,GAAc,CAAC,CAAA;gBACvC,IAAI,CAAC,IAAI;oBAAE,OAAO,KAAK,CAAA;gBACvB,wEAAwE;gBACxE,6BAA6B;gBAC7B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;gBACxD,OAAO,IAAI,CAAA;YACb,CAAC;SACF;KACF;IACD,KAAK,CAAC,IAAI;QACR,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QACtD,MAAM,KAAK,GAA2B,EAAE,CAAA;QACxC,IAAI,GAAG,KAAK,IAAI;YAAE,KAAK,CAAC,KAAK,CAAC,GAAG,GAAa,CAAA;QAC9C,IAAI,KAAK,KAAK,IAAI;YAAE,KAAK,CAAC,OAAO,CAAC,GAAG,KAAe,CAAA;QACpD,IAAI,QAAQ;YAAE,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,CAAA;QACpC,OAAO,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,SAA0B,CAAC,CAAA;IAC/D,CAAC;CACF,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAa;IAC9B,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAI;IACf,KAAK,EAAE;QACL,GAAG,EAAE,EAAE;QACP,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACxB,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACxB,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACzB,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;QACxB,eAAe,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;KACnC;IACD,QAAQ,EAAE;QACR;YACE,GAAG,EAAE,QAAQ;YACb,QAAQ,CAAC,GAAG;gBACV,MAAM,EAAE,GAAG,GAAc,CAAA;gBACzB,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;gBAChD,IAAI,CAAC,GAAG;oBAAE,OAAO,KAAK,CAAA;gBACtB,OAAO;oBACL,GAAG;oBACH,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;oBAC/B,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC;oBAC7B,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC;oBAC/B,KAAK,EAAE,aAAa,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;oBAC9C,eAAe,EAAE,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC;iBACpD,CAAA;YACH,CAAC;SACF;KACF;IACD,KAAK,CAAC,IAAI;QACR,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QACxE,MAAM,KAAK,GAA2B,EAAE,GAAG,EAAE,GAAa,EAAE,CAAA;QAC5D,IAAI,KAAK,KAAK,IAAI;YAAE,KAAK,CAAC,OAAO,CAAC,GAAG,KAAe,CAAA;QACpD,IAAI,KAAK,KAAK,IAAI;YAAE,KAAK,CAAC,OAAO,CAAC,GAAG,KAAe,CAAA;QACpD,IAAI,MAAM,KAAK,IAAI;YAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,MAAgB,CAAA;QACvD,IAAI,KAAK,KAAK,IAAI;YAAE,KAAK,CAAC,OAAO,CAAC,GAAG,KAAe,CAAA;QACpD,IAAI,eAAe;YAAE,KAAK,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAA;QAClD,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IAC1B,CAAC;CACF,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAa;IAC/B,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,IAAI;IACd,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;IACnC,QAAQ,EAAE;QACR;YACE,GAAG,EAAE,SAAS;YACd,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAG,GAAe,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;SACrE;KACF;IACD,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IAC3E,CAAC;CACF,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAa;IAC/B,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;IAC9B,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;CAC5B,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,MAAM,GAAa;IAC9B,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,IAAI;IACf,QAAQ,EAAE;QACR;YACE,GAAG,EAAE,QAAQ;YACb,QAAQ,CAAC,GAAG;gBACV,MAAM,EAAE,GAAG,GAAc,CAAA;gBACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAA;gBAC3F,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,KAAK,KAAK;oBAAE,OAAO,KAAK,CAAA;gBAC1E,OAAO,EAAE,CAAA;YACX,CAAC;SACF;KACF;IACD,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;CAC3B,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,UAAU,GAAa;IAClC,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IACrD,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;CAC/B,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAa;IAClC,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE;QACR,EAAE,GAAG,EAAE,qBAAqB,EAAE;QAC9B,EAAE,GAAG,EAAE,kBAAkB,EAAE;QAC3B,EAAE,GAAG,EAAE,iBAAiB,EAAE;KAC3B;IACD,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;CAC/C,CAAA;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,EAAW;IACnD,OAAO,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAA;AACtE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,YAAY,GAAa;IACpC,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;IACjB,QAAQ,EAAE;QACR;YACE,GAAG,EAAE,OAAO;YACZ,QAAQ,CAAC,GAAG;gBACV,MAAM,EAAE,GAAG,GAAc,CAAA;gBACzB,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC;oBAAE,OAAO,KAAK,CAAA;gBACzC,oEAAoE;gBACpE,mEAAmE;gBACnE,qCAAqC;gBACrC,IAAI,CAAC,yBAAyB,CAAC,EAAE,CAAC;oBAAE,OAAO,KAAK,CAAA;gBAChD,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;gBACxC,IAAI,CAAC,EAAE;oBAAE,OAAO,KAAK,CAAA;gBACrB,OAAO,EAAE,EAAE,EAAE,CAAA;YACf,CAAC;SACF;KACF;IACD,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAW,EAAE,CAAC;CAC3D,CAAA;AAED,qDAAqD;AACrD,MAAM,UAAU,eAAe,CAAC,EAAW;IACzC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IACpD,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IAC1C,OAAO;QACL,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC;QAC3B,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC;QAC3B,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;QAC/B,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;QAC/B,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC;QACjC,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC;QACrC,SAAS,EAAE,aAAa,CAAC,SAAS,EAAE,mBAAmB,CAAC;KACzD,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAY;IACxC,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,KAA0B,CAAA;IAC9C,IAAI,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAA;IACjD,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,SAAS,KAAK,EAAE,EAAE,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAC/B,CAAC;IACD,uEAAuE;IACvE,0EAA0E;IAC1E,2EAA2E;IAC3E,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxD,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAa,CAAA;IAChC,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;QAAE,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAa,CAAA;IACnF,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAe,CAAA;IAC3F,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAe,CAAA;IAC3F,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,MAAgB,CAAA;IAC/F,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
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;
|
package/dist/tables.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|