@pie-lib/editable-html-tip-tap 3.0.1-next.20261004173930 → 3.0.1-next.20261004200555
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/dist/components/EditableHtml.js +155 -140
- package/dist/extensions/extended-table-cell.js +13 -4
- package/dist/extensions/extended-table.js +19 -12
- package/dist/extensions/table-semantics.d.ts +28 -0
- package/dist/extensions/table-semantics.js +42 -0
- package/dist/external-paste.d.ts +26 -0
- package/dist/external-paste.js +185 -0
- package/dist/word-lists.d.ts +10 -0
- package/dist/word-lists.js +91 -0
- package/package.json +4 -4
- package/dist/plain-text-paste.d.ts +0 -12
- package/dist/plain-text-paste.js +0 -75
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExternalPaste as e } from "../external-paste.js";
|
|
2
2
|
import { normalizeInitialMarkup as t } from "../utils/helper.js";
|
|
3
3
|
import n from "../extensions/extended-table.js";
|
|
4
4
|
import { ExtendedTableCell as r, ExtendedTableHeader as i } from "../extensions/extended-table-cell.js";
|
|
5
5
|
import { DivNode as a } from "../extensions/div-node.js";
|
|
6
|
-
import { EnsureEmptyRootIsDiv as
|
|
7
|
-
import { EnsureListItemContentIsDiv as
|
|
8
|
-
import { DragInTheBlankNode as
|
|
9
|
-
import { MathNode as
|
|
10
|
-
import { ImageUploadNode as
|
|
11
|
-
import { Media as
|
|
12
|
-
import { CSSMark as
|
|
13
|
-
import { ExtendedListItem as
|
|
14
|
-
import { HeadingParagraph as
|
|
15
|
-
import { valueToSize as
|
|
16
|
-
import
|
|
17
|
-
import { PLUGINS_MAP as
|
|
18
|
-
import { useCallback as
|
|
19
|
-
import { debounce as
|
|
20
|
-
import { EditorContent as
|
|
21
|
-
import { styled as
|
|
22
|
-
import
|
|
23
|
-
import { TextStyleKit as
|
|
24
|
-
import { CharacterCount as
|
|
25
|
-
import
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import
|
|
30
|
-
import { TableRow as
|
|
31
|
-
import { jsx as
|
|
6
|
+
import { EnsureEmptyRootIsDiv as ee } from "../extensions/ensure-empty-root-div.js";
|
|
7
|
+
import { EnsureListItemContentIsDiv as te } from "../extensions/ensure-list-item-content-is-div.js";
|
|
8
|
+
import { DragInTheBlankNode as ne, ExplicitConstructedResponseNode as re, InlineDropdownNode as ie, MathTemplatedNode as ae, ResponseAreaExtension as o } from "../extensions/responseArea.js";
|
|
9
|
+
import { MathNode as s } from "../extensions/math.js";
|
|
10
|
+
import { ImageUploadNode as c } from "../extensions/image.js";
|
|
11
|
+
import { Media as l } from "../extensions/media.js";
|
|
12
|
+
import { CSSMark as oe } from "../extensions/css.js";
|
|
13
|
+
import { ExtendedListItem as u } from "../extensions/extended-list-item.js";
|
|
14
|
+
import { HeadingParagraph as se } from "../extensions/heading-paragraph.js";
|
|
15
|
+
import { valueToSize as d } from "../utils/size.js";
|
|
16
|
+
import ce from "./TiptapContainer.js";
|
|
17
|
+
import { PLUGINS_MAP as le, buildExtensions as ue } from "../extensions/index.js";
|
|
18
|
+
import { useCallback as f, useEffect as p, useMemo as m, useRef as de, useState as h } from "react";
|
|
19
|
+
import { debounce as fe } from "@pie-element/shared-lodash";
|
|
20
|
+
import { EditorContent as g, useEditor as _, useEditorState as v } from "@tiptap/react";
|
|
21
|
+
import { styled as y } from "@mui/material/styles";
|
|
22
|
+
import b from "@tiptap/starter-kit";
|
|
23
|
+
import { TextStyleKit as x } from "@tiptap/extension-text-style";
|
|
24
|
+
import { CharacterCount as S } from "@tiptap/extension-character-count";
|
|
25
|
+
import C from "@tiptap/extension-superscript";
|
|
26
|
+
import w from "@tiptap/extension-subscript";
|
|
27
|
+
import T from "@tiptap/extension-text-align";
|
|
28
|
+
import E from "@tiptap/extension-image";
|
|
29
|
+
import D from "@tiptap/extension-placeholder";
|
|
30
|
+
import { TableRow as O } from "@tiptap/extension-table-row";
|
|
31
|
+
import { jsx as k } from "react/jsx-runtime";
|
|
32
32
|
//#region src/components/EditableHtml.tsx
|
|
33
|
-
var
|
|
33
|
+
var A = {
|
|
34
34
|
position: "bottom",
|
|
35
35
|
alignment: "left",
|
|
36
36
|
alwaysVisible: !1,
|
|
37
37
|
showDone: !0,
|
|
38
38
|
doneOn: "blur"
|
|
39
|
-
},
|
|
39
|
+
}, j = {
|
|
40
40
|
options: {},
|
|
41
41
|
respAreaToolbar: () => {},
|
|
42
42
|
onHandleAreaChange: () => {}
|
|
43
|
-
},
|
|
43
|
+
}, M = [
|
|
44
44
|
"bold",
|
|
45
45
|
"italic",
|
|
46
46
|
"underline",
|
|
@@ -62,7 +62,17 @@ var P = {
|
|
|
62
62
|
"h3",
|
|
63
63
|
"undo",
|
|
64
64
|
"redo"
|
|
65
|
-
],
|
|
65
|
+
], N = {
|
|
66
|
+
bold: "bold",
|
|
67
|
+
italic: "italic",
|
|
68
|
+
underline: "underline",
|
|
69
|
+
strikethrough: "strike",
|
|
70
|
+
superscript: "superscript",
|
|
71
|
+
subscript: "subscript",
|
|
72
|
+
"bulleted-list": "bulletList",
|
|
73
|
+
"numbered-list": "orderedList",
|
|
74
|
+
table: "table"
|
|
75
|
+
}, P = {
|
|
66
76
|
"--white": "#fff",
|
|
67
77
|
"--black": "#2e2b29",
|
|
68
78
|
"--black-contrast": "#110f0e",
|
|
@@ -81,7 +91,7 @@ var P = {
|
|
|
81
91
|
"--red": "#ff5c33",
|
|
82
92
|
"--red-light": "#ffebe5",
|
|
83
93
|
"--shadow": "0px 12px 33px 0px rgba(0, 0, 0, .06),\n 0px 3.618px 9.949px 0px rgba(0, 0, 0, .04)"
|
|
84
|
-
},
|
|
94
|
+
}, F = (e, t, n) => ({
|
|
85
95
|
role: "textbox",
|
|
86
96
|
"data-pie-editor": "true",
|
|
87
97
|
class: "mathjax_ignore",
|
|
@@ -90,50 +100,55 @@ var P = {
|
|
|
90
100
|
autocapitalize: e ? "on" : "off",
|
|
91
101
|
...t && { "aria-label": t },
|
|
92
102
|
...n && { "aria-labelledby": n }
|
|
93
|
-
}),
|
|
94
|
-
let { showParagraphs:
|
|
95
|
-
|
|
103
|
+
}), I = ["aria-label", "aria-labelledby"], L = (g) => {
|
|
104
|
+
let { showParagraphs: y, separateParagraphs: L } = g.pluginProps || {}, [pe, z] = h([]), [B, V] = h(!1), { toolbarOpts: me } = g, H = f((e) => {
|
|
105
|
+
z((t) => {
|
|
96
106
|
let n = t.filter((t) => t.pos !== e);
|
|
97
|
-
return n.length === 0 &&
|
|
107
|
+
return n.length === 0 && V(!1), n;
|
|
98
108
|
});
|
|
99
|
-
}, [
|
|
100
|
-
...
|
|
101
|
-
...
|
|
102
|
-
},
|
|
109
|
+
}, [z]), U = {
|
|
110
|
+
...A,
|
|
111
|
+
...me
|
|
112
|
+
}, W = f((e) => {
|
|
103
113
|
let t = e.getHTML();
|
|
104
|
-
|
|
114
|
+
g.markup !== t && g.onChange?.(t), U.doneOn === "blur" && g.onDone?.(t);
|
|
105
115
|
}, [
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
]),
|
|
111
|
-
...
|
|
112
|
-
...
|
|
113
|
-
onInlineDropdownToolbarClose:
|
|
114
|
-
}), [
|
|
115
|
-
let { customPlugins: e, ...t } =
|
|
116
|
+
g.markup,
|
|
117
|
+
g.onChange,
|
|
118
|
+
g.onDone,
|
|
119
|
+
U.doneOn
|
|
120
|
+
]), G = m(() => ({
|
|
121
|
+
...j,
|
|
122
|
+
...g.responseAreaProps,
|
|
123
|
+
onInlineDropdownToolbarClose: W
|
|
124
|
+
}), [g.responseAreaProps, W]), K = m(() => {
|
|
125
|
+
let { customPlugins: e, ...t } = g.pluginProps || {};
|
|
116
126
|
e ||= [];
|
|
117
|
-
let n = (
|
|
118
|
-
let n =
|
|
127
|
+
let n = (g.activePlugins || M)?.filter((e) => {
|
|
128
|
+
let n = le[e] || e, r = t[n] || {};
|
|
119
129
|
return !r || !r.disabled;
|
|
120
130
|
});
|
|
121
|
-
return
|
|
131
|
+
return ue(n, e, {
|
|
122
132
|
math: {},
|
|
123
|
-
textAlign:
|
|
133
|
+
textAlign: g.textAlign,
|
|
124
134
|
html: {},
|
|
125
|
-
extraCSSRules:
|
|
126
|
-
image: { ...
|
|
135
|
+
extraCSSRules: g.extraCSSRules || {},
|
|
136
|
+
image: { ...g.imageSupport },
|
|
127
137
|
toolbar: {},
|
|
128
138
|
table: {},
|
|
129
|
-
responseArea: { type:
|
|
130
|
-
languageCharacters:
|
|
139
|
+
responseArea: { type: G.type },
|
|
140
|
+
languageCharacters: g.languageCharactersProps,
|
|
131
141
|
keyPadCharacterRef: {},
|
|
132
142
|
setKeypadInteraction: {},
|
|
133
143
|
media: {}
|
|
134
144
|
});
|
|
135
|
-
}, [
|
|
136
|
-
|
|
145
|
+
}, [g, G.type]), q = de(null);
|
|
146
|
+
q.current = {
|
|
147
|
+
plainText: g.pluginProps?.pasteFormatting?.disabled === !0,
|
|
148
|
+
formatting: K.map((e) => N[e]).filter(Boolean)
|
|
149
|
+
};
|
|
150
|
+
let J = [
|
|
151
|
+
T.configure({
|
|
137
152
|
types: [
|
|
138
153
|
"heading",
|
|
139
154
|
"paragraph",
|
|
@@ -155,10 +170,10 @@ var P = {
|
|
|
155
170
|
"justify"
|
|
156
171
|
]
|
|
157
172
|
}),
|
|
158
|
-
|
|
159
|
-
e,
|
|
160
|
-
|
|
161
|
-
|
|
173
|
+
x,
|
|
174
|
+
e.configure({ settings: () => q.current }),
|
|
175
|
+
S.configure({ limit: g.charactersLimit || 1e6 }),
|
|
176
|
+
b.configure({
|
|
162
177
|
trailingNode: {
|
|
163
178
|
node: "paragraph",
|
|
164
179
|
notAfter: ["paragraph", "div"]
|
|
@@ -168,95 +183,95 @@ var P = {
|
|
|
168
183
|
linkOnPaste: !1
|
|
169
184
|
}
|
|
170
185
|
}),
|
|
171
|
-
|
|
186
|
+
u,
|
|
172
187
|
a,
|
|
173
|
-
|
|
174
|
-
o,
|
|
188
|
+
se,
|
|
175
189
|
ee,
|
|
176
|
-
|
|
177
|
-
|
|
190
|
+
te,
|
|
191
|
+
D.configure({
|
|
192
|
+
placeholder: g.placeholder,
|
|
178
193
|
showOnlyWhenEditable: !0,
|
|
179
194
|
showOnlyCurrent: !1,
|
|
180
195
|
includeChildren: !0
|
|
181
196
|
}),
|
|
182
197
|
n,
|
|
183
|
-
|
|
198
|
+
O,
|
|
184
199
|
i,
|
|
185
200
|
r,
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
toolbarOpts:
|
|
193
|
-
math:
|
|
201
|
+
o.configure(G),
|
|
202
|
+
re.configure(G),
|
|
203
|
+
ne.configure(G),
|
|
204
|
+
ie.configure(G),
|
|
205
|
+
ae.configure(G),
|
|
206
|
+
s.configure({
|
|
207
|
+
toolbarOpts: U,
|
|
208
|
+
math: g.pluginProps?.math || {}
|
|
194
209
|
}),
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
toolbarOpts:
|
|
210
|
+
w,
|
|
211
|
+
C,
|
|
212
|
+
E,
|
|
213
|
+
c.configure({
|
|
214
|
+
toolbarOpts: U,
|
|
200
215
|
imageHandling: {
|
|
201
|
-
disableImageAlignmentButtons:
|
|
202
|
-
onDone: (e) =>
|
|
203
|
-
onDelete:
|
|
216
|
+
disableImageAlignmentButtons: g.disableImageAlignmentButtons,
|
|
217
|
+
onDone: (e) => g.onDone?.(e.getHTML()),
|
|
218
|
+
onDelete: g.imageSupport && g.imageSupport.delete && ((e) => {
|
|
204
219
|
let { src: t } = e.attrs;
|
|
205
|
-
|
|
206
|
-
|
|
220
|
+
g.imageSupport.delete(t, (t) => {
|
|
221
|
+
H(e.pos);
|
|
207
222
|
});
|
|
208
223
|
}),
|
|
209
|
-
insertImageRequested:
|
|
224
|
+
insertImageRequested: g.imageSupport && ((e, t, n) => {
|
|
210
225
|
let [r, i] = t, a = (t) => {
|
|
211
226
|
let n;
|
|
212
|
-
|
|
227
|
+
B && t && (n = g.onChange), H(i), n?.(e.getHTML());
|
|
213
228
|
};
|
|
214
|
-
e._insertingImage = !0,
|
|
215
|
-
let t = n(a), r =
|
|
229
|
+
e._insertingImage = !0, z((e) => [...e, r]), (() => {
|
|
230
|
+
let t = n(a), r = fe(() => {
|
|
216
231
|
let t = () => window.removeEventListener("focus", r);
|
|
217
232
|
if (!e._insertingImage) {
|
|
218
233
|
t();
|
|
219
234
|
return;
|
|
220
235
|
}
|
|
221
|
-
|
|
236
|
+
H(i), e._insertingImage = !1, t();
|
|
222
237
|
}, 500);
|
|
223
|
-
window.addEventListener("focus", r),
|
|
238
|
+
window.addEventListener("focus", r), g.imageSupport.add(t);
|
|
224
239
|
})();
|
|
225
240
|
}),
|
|
226
|
-
maxImageWidth:
|
|
227
|
-
maxImageHeight:
|
|
241
|
+
maxImageWidth: g.maxImageWidth,
|
|
242
|
+
maxImageHeight: g.maxImageHeight
|
|
228
243
|
},
|
|
229
244
|
limit: 3
|
|
230
245
|
}),
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
], Y =
|
|
234
|
-
extensions:
|
|
246
|
+
l.configure({ uploadSoundSupport: g.uploadSoundSupport }),
|
|
247
|
+
oe.configure({ extraCSSRules: g.extraCSSRules })
|
|
248
|
+
], Y = g.spellCheck !== !1, { ariaLabel: X, ariaLabelledBy: Z } = g, Q = _({
|
|
249
|
+
extensions: J,
|
|
235
250
|
immediatelyRender: !1,
|
|
236
251
|
editorProps: {
|
|
237
|
-
attributes:
|
|
252
|
+
attributes: F(Y, X, Z),
|
|
238
253
|
handleKeyDown(e, t) {
|
|
239
|
-
return
|
|
254
|
+
return g.onKeyDown ? g.onKeyDown(t) : !1;
|
|
240
255
|
}
|
|
241
256
|
},
|
|
242
|
-
editable: !
|
|
243
|
-
content: t(
|
|
257
|
+
editable: !g.disabled,
|
|
258
|
+
content: t(g.markup),
|
|
244
259
|
onUpdate: ({ editor: e, transaction: t }) => {
|
|
245
|
-
t.isDone &&
|
|
260
|
+
t.isDone && g.onChange?.(e.getHTML());
|
|
246
261
|
},
|
|
247
262
|
onBlur: ({ editor: e }) => {
|
|
248
|
-
e._insertingImage || e._toolbarOpened || e.isActive("inline_dropdown") || e.isActive("explicit_constructed_response") || !e.schema ||
|
|
263
|
+
e._insertingImage || e._toolbarOpened || e.isActive("inline_dropdown") || e.isActive("explicit_constructed_response") || !e.schema || W(e);
|
|
249
264
|
}
|
|
250
|
-
}, [
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}, [
|
|
254
|
-
Q?.setEditable(!
|
|
255
|
-
}, [
|
|
265
|
+
}, [g.charactersLimit]);
|
|
266
|
+
p(() => {
|
|
267
|
+
g.editorRef && g.editorRef(Q);
|
|
268
|
+
}, [g.editorRef, Q]), p(() => {
|
|
269
|
+
Q?.setEditable(!g.disabled);
|
|
270
|
+
}, [g.disabled, Q]), p(() => {
|
|
256
271
|
if (!Q) return;
|
|
257
|
-
let e = Q.options?.editorProps, t = e?.attributes || {}, n =
|
|
258
|
-
if (["spellcheck", ...
|
|
259
|
-
let r = Object.fromEntries(Object.entries(t).filter(([e]) => !
|
|
272
|
+
let e = Q.options?.editorProps, t = e?.attributes || {}, n = F(Y, X, Z);
|
|
273
|
+
if (["spellcheck", ...I].every((e) => t[e] === n[e])) return;
|
|
274
|
+
let r = Object.fromEntries(Object.entries(t).filter(([e]) => !I.includes(e)));
|
|
260
275
|
Q.setOptions({ editorProps: {
|
|
261
276
|
...e,
|
|
262
277
|
attributes: {
|
|
@@ -269,47 +284,47 @@ var P = {
|
|
|
269
284
|
X,
|
|
270
285
|
Z,
|
|
271
286
|
Q
|
|
272
|
-
]),
|
|
287
|
+
]), p(() => {
|
|
273
288
|
if (!Q) return;
|
|
274
|
-
let e = t(
|
|
289
|
+
let e = t(g.markup);
|
|
275
290
|
e !== Q.getHTML() && Q.commands.setContent(e, { emitUpdate: !1 });
|
|
276
|
-
}, [
|
|
277
|
-
Object.entries(
|
|
291
|
+
}, [g.markup, Q]), p(() => {
|
|
292
|
+
Object.entries(P).forEach(([e, t]) => {
|
|
278
293
|
document.documentElement.style.setProperty(e, t);
|
|
279
294
|
});
|
|
280
295
|
}, []);
|
|
281
|
-
let
|
|
296
|
+
let he = v({
|
|
282
297
|
editor: Q,
|
|
283
298
|
selector: (e) => ({ isFocused: e.editor?.isFocused })
|
|
284
|
-
}), $ =
|
|
285
|
-
let { minWidth: e, width: t, maxWidth: n, minHeight: r, height: i, maxHeight: a } =
|
|
299
|
+
}), $ = m(() => {
|
|
300
|
+
let { minWidth: e, width: t, maxWidth: n, minHeight: r, height: i, maxHeight: a } = g;
|
|
286
301
|
return {
|
|
287
|
-
width:
|
|
288
|
-
minWidth:
|
|
289
|
-
maxWidth:
|
|
290
|
-
height:
|
|
291
|
-
minHeight:
|
|
292
|
-
maxHeight:
|
|
302
|
+
width: d(t),
|
|
303
|
+
minWidth: d(e),
|
|
304
|
+
maxWidth: d(n),
|
|
305
|
+
height: d(i),
|
|
306
|
+
minHeight: d(r),
|
|
307
|
+
maxHeight: d(a)
|
|
293
308
|
};
|
|
294
|
-
}, [
|
|
295
|
-
return /* @__PURE__ */
|
|
296
|
-
...
|
|
297
|
-
activePlugins:
|
|
298
|
-
toolbarOpts:
|
|
299
|
-
editorState:
|
|
309
|
+
}, [g]);
|
|
310
|
+
return /* @__PURE__ */ k(ce, {
|
|
311
|
+
...g,
|
|
312
|
+
activePlugins: K,
|
|
313
|
+
toolbarOpts: U,
|
|
314
|
+
editorState: he,
|
|
300
315
|
editor: Q,
|
|
301
|
-
children: Q && /* @__PURE__ */
|
|
316
|
+
children: Q && /* @__PURE__ */ k(R, {
|
|
302
317
|
style: {
|
|
303
318
|
minHeight: $.minHeight,
|
|
304
319
|
height: $.height,
|
|
305
320
|
maxHeight: $.maxHeight
|
|
306
321
|
},
|
|
307
|
-
showParagraph:
|
|
308
|
-
separateParagraph:
|
|
322
|
+
showParagraph: y && !y.disabled,
|
|
323
|
+
separateParagraph: L && !L.disabled,
|
|
309
324
|
editor: Q
|
|
310
325
|
})
|
|
311
326
|
});
|
|
312
|
-
},
|
|
327
|
+
}, R = y(g, { shouldForwardProp: (e) => !["showParagraph", "separateParagraph"].includes(e) })(({ showParagraph: e, separateParagraph: t }) => ({
|
|
313
328
|
display: "flex",
|
|
314
329
|
outline: "none !important",
|
|
315
330
|
"& .ProseMirror": {
|
|
@@ -339,4 +354,4 @@ var P = {
|
|
|
339
354
|
}
|
|
340
355
|
}));
|
|
341
356
|
//#endregion
|
|
342
|
-
export {
|
|
357
|
+
export { L as EditableHtml, L as default };
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { scopeAttribute as e } from "./table-semantics.js";
|
|
2
|
+
import { TableCell as t } from "@tiptap/extension-table-cell";
|
|
3
|
+
import { TableHeader as n } from "@tiptap/extension-table-header";
|
|
3
4
|
//#region src/extensions/extended-table-cell.ts
|
|
4
|
-
var
|
|
5
|
+
var r = "(div | paragraph | heading | bulletList | orderedList | blockquote | codeBlock | horizontalRule | image | imageUploadNode)+", i = t.extend({ content: r }), a = n.extend({
|
|
6
|
+
content: r,
|
|
7
|
+
addAttributes() {
|
|
8
|
+
return {
|
|
9
|
+
...this.parent?.(),
|
|
10
|
+
scope: e
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
});
|
|
5
14
|
//#endregion
|
|
6
|
-
export {
|
|
15
|
+
export { i as ExtendedTableCell, a as ExtendedTableHeader };
|
|
@@ -1,34 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { captionAttribute as e, captionParseRule as t, syncCaption as n, withCaption as r } from "./table-semantics.js";
|
|
2
|
+
import { Table as i, TableView as a } from "@tiptap/extension-table";
|
|
2
3
|
//#region src/extensions/extended-table.tsx
|
|
3
|
-
var
|
|
4
|
+
var o = (e, t) => {
|
|
4
5
|
let n = t?.border != null && t.border !== "" ? t.border : "1";
|
|
5
6
|
e.setAttribute("border", n), e.style.setProperty("color", "var(--pie-text, black)"), e.style.setProperty("background-color", "var(--pie-background, rgba(255, 255, 255))");
|
|
6
|
-
},
|
|
7
|
+
}, s = class extends a {
|
|
7
8
|
constructor(e, t, r) {
|
|
8
|
-
super(e, t, r), n(this.table, e.attrs);
|
|
9
|
+
super(e, t, r), o(this.table, e.attrs), n(this.table, e.attrs.caption);
|
|
9
10
|
}
|
|
10
11
|
update(e) {
|
|
11
12
|
let t = super.update(e);
|
|
12
|
-
return t && n(this.table, e.attrs), t;
|
|
13
|
+
return t && (o(this.table, e.attrs), n(this.table, e.attrs.caption)), t;
|
|
13
14
|
}
|
|
14
|
-
},
|
|
15
|
+
}, c = i.extend({
|
|
15
16
|
addOptions() {
|
|
16
17
|
return {
|
|
17
18
|
...this.parent?.(),
|
|
18
19
|
resizable: !0,
|
|
19
20
|
handleWidth: 0,
|
|
20
|
-
View:
|
|
21
|
+
View: s
|
|
21
22
|
};
|
|
22
23
|
},
|
|
23
24
|
addAttributes() {
|
|
24
|
-
return {
|
|
25
|
+
return {
|
|
26
|
+
border: { default: "1" },
|
|
27
|
+
caption: e
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
parseHTML() {
|
|
31
|
+
return [...this.parent(), t];
|
|
25
32
|
},
|
|
26
33
|
renderHTML(e) {
|
|
27
|
-
let t = this.parent(e), { border: n } = e.HTMLAttributes,
|
|
28
|
-
return t[1].style = `${
|
|
34
|
+
let t = this.parent(e), { border: n } = e.HTMLAttributes, i = `${t[1].style}${t[1].style.match(/.*; */) ? "" : ";"}`;
|
|
35
|
+
return t[1].style = `${i}
|
|
29
36
|
color: var(--pie-text, black);
|
|
30
|
-
background-color: var(--pie-background, rgba(255, 255, 255))`, t[1].border = n || "1", t;
|
|
37
|
+
background-color: var(--pie-background, rgba(255, 255, 255))`, t[1].border = n || "1", r(t, e.node.attrs.caption);
|
|
31
38
|
}
|
|
32
39
|
});
|
|
33
40
|
//#endregion
|
|
34
|
-
export {
|
|
41
|
+
export { s as ExtendedTableView, o as applyPresentationToTableElement, c as default };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DOMOutputSpec } from '@tiptap/pm/model';
|
|
2
|
+
export declare const captionAttribute: {
|
|
3
|
+
default: null;
|
|
4
|
+
parseHTML: (table: HTMLElement) => string | null;
|
|
5
|
+
renderHTML: () => {};
|
|
6
|
+
};
|
|
7
|
+
export declare const captionParseRule: {
|
|
8
|
+
tag: string;
|
|
9
|
+
ignore: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** A table's DOM spec with its caption as the first child, where HTML requires it. */
|
|
12
|
+
export declare function withCaption(spec: DOMOutputSpec, caption: string | null): DOMOutputSpec;
|
|
13
|
+
/**
|
|
14
|
+
* Shows the caption in a table view. It is not editable there: it is not document content, and
|
|
15
|
+
* TableView ignores DOM changes outside the table body.
|
|
16
|
+
*/
|
|
17
|
+
export declare function syncCaption(table: HTMLTableElement, caption: string | null): void;
|
|
18
|
+
export declare const scopeAttribute: {
|
|
19
|
+
default: null;
|
|
20
|
+
parseHTML: (cell: HTMLElement) => string | null;
|
|
21
|
+
renderHTML: (attributes: {
|
|
22
|
+
scope?: string | null;
|
|
23
|
+
}) => {
|
|
24
|
+
scope: string;
|
|
25
|
+
} | {
|
|
26
|
+
scope?: undefined;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/extensions/table-semantics.ts
|
|
2
|
+
var e = (e) => Array.from(e.children).find((e) => e.tagName === "CAPTION"), t = {
|
|
3
|
+
default: null,
|
|
4
|
+
parseHTML: (t) => e(t)?.textContent?.replace(/\s+/g, " ").trim() || null,
|
|
5
|
+
renderHTML: () => ({})
|
|
6
|
+
}, n = {
|
|
7
|
+
tag: "caption",
|
|
8
|
+
ignore: !0
|
|
9
|
+
};
|
|
10
|
+
function r(e, t) {
|
|
11
|
+
if (!t || !Array.isArray(e)) return e;
|
|
12
|
+
let [n, r, ...i] = e;
|
|
13
|
+
return [
|
|
14
|
+
n,
|
|
15
|
+
r,
|
|
16
|
+
["caption", t],
|
|
17
|
+
...i
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
function i(t, n) {
|
|
21
|
+
let r = e(t);
|
|
22
|
+
if (!n) {
|
|
23
|
+
r?.remove();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
r || (r = t.ownerDocument.createElement("caption"), r.setAttribute("contenteditable", "false"), t.insertBefore(r, t.firstChild)), r.textContent !== n && (r.textContent = n);
|
|
27
|
+
}
|
|
28
|
+
var a = [
|
|
29
|
+
"row",
|
|
30
|
+
"col",
|
|
31
|
+
"rowgroup",
|
|
32
|
+
"colgroup"
|
|
33
|
+
], o = {
|
|
34
|
+
default: null,
|
|
35
|
+
parseHTML: (e) => {
|
|
36
|
+
let t = e.getAttribute("scope")?.trim().toLowerCase() ?? "";
|
|
37
|
+
return a.includes(t) ? t : null;
|
|
38
|
+
},
|
|
39
|
+
renderHTML: (e) => e.scope ? { scope: e.scope } : {}
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
42
|
+
export { t as captionAttribute, n as captionParseRule, o as scopeAttribute, i as syncCaption, r as withCaption };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
/** The formatting that content pasted from outside a PIE editor can keep, by mark or node name. */
|
|
3
|
+
export declare const PASTED_FORMATTING: readonly ["bold", "italic", "underline", "strike", "superscript", "subscript", "bulletList", "orderedList", "table"];
|
|
4
|
+
export type PastedFormatting = (typeof PASTED_FORMATTING)[number];
|
|
5
|
+
export type ExternalPasteSettings = {
|
|
6
|
+
/** Paste as plain text, as the Slate editor did. Math copied from rendered PIE content stays math. */
|
|
7
|
+
plainText: boolean;
|
|
8
|
+
/** The formatting a paste keeps. The rest becomes text: a list its items, a table its rows. */
|
|
9
|
+
formatting: readonly PastedFormatting[];
|
|
10
|
+
};
|
|
11
|
+
export type ExternalPasteOptions = {
|
|
12
|
+
/** Read at each paste and drop, so a mounted editor follows a change of toolbar or setting. */
|
|
13
|
+
settings: () => ExternalPasteSettings;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Pastes and drops content from outside a PIE editor, such as from Word or Google Docs, with its
|
|
17
|
+
* paragraphs, line breaks and math, and with the bold, italics, underline, strikethrough,
|
|
18
|
+
* superscript, subscript, lists and tables in `formatting`. Its fonts, sizes, colours, alignment,
|
|
19
|
+
* headings, links and class names go, which TextStyleKit, TextAlign and CSSMark would otherwise keep
|
|
20
|
+
* (PIE-1145). Word for Windows and Mac copies lists as styled paragraphs, which are rebuilt as
|
|
21
|
+
* lists first. With `plainText` set it pastes plain text. Copies from a PIE editor and pasted
|
|
22
|
+
* images are left to ProseMirror and the image upload handler.
|
|
23
|
+
*
|
|
24
|
+
* Mirrored in `packages/lib-svelte/editable-html-tiptap-svelte/src/external-paste.ts`.
|
|
25
|
+
*/
|
|
26
|
+
export declare const ExternalPaste: Extension<ExternalPasteOptions, any>;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { rebuildWordLists as e } from "./word-lists.js";
|
|
2
|
+
import { Extension as t } from "@tiptap/core";
|
|
3
|
+
import { Plugin as n, PluginKey as r, TextSelection as i } from "@tiptap/pm/state";
|
|
4
|
+
//#region src/external-paste.ts
|
|
5
|
+
var a = [
|
|
6
|
+
"bold",
|
|
7
|
+
"italic",
|
|
8
|
+
"underline",
|
|
9
|
+
"strike",
|
|
10
|
+
"superscript",
|
|
11
|
+
"subscript",
|
|
12
|
+
"bulletList",
|
|
13
|
+
"orderedList",
|
|
14
|
+
"table"
|
|
15
|
+
], o = (e) => Array.from(e.items ?? []).some((e) => e.kind === "file" && e.type.startsWith("image/")), s = (e, t) => new DOMParser().parseFromString(e, "text/html").querySelector(t) !== null, c = (e) => e.includes("data-pm-slice") && s(e, "[data-pm-slice]"), l = (e) => /data-latex|data-type="?mathml/.test(e) && s(e, "[data-latex], [data-type=\"mathml\"]"), u = null, d = (e) => e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"), f = (e) => e.replace(/\r*\n|\r/g, "\n").replace(/\n+$/, ""), p = (e) => {
|
|
16
|
+
let t = [];
|
|
17
|
+
return e.forEach((e) => {
|
|
18
|
+
t.push(e);
|
|
19
|
+
}), t;
|
|
20
|
+
};
|
|
21
|
+
function m(e, t) {
|
|
22
|
+
let n = e.topNodeType.create(null, t), r = (e) => {
|
|
23
|
+
let t = 0;
|
|
24
|
+
for (let r = n[e]; r && !r.isLeaf && !r.type.spec.isolating; r = r[e]) t += 1;
|
|
25
|
+
return t;
|
|
26
|
+
};
|
|
27
|
+
return t.length ? n.slice(r("firstChild"), n.content.size - r("lastChild"), !0) : n.slice(0, 0);
|
|
28
|
+
}
|
|
29
|
+
var h = [
|
|
30
|
+
[1e3, "m"],
|
|
31
|
+
[900, "cm"],
|
|
32
|
+
[500, "d"],
|
|
33
|
+
[400, "cd"],
|
|
34
|
+
[100, "c"],
|
|
35
|
+
[90, "xc"],
|
|
36
|
+
[50, "l"],
|
|
37
|
+
[40, "xl"],
|
|
38
|
+
[10, "x"],
|
|
39
|
+
[9, "ix"],
|
|
40
|
+
[5, "v"],
|
|
41
|
+
[4, "iv"],
|
|
42
|
+
[1, "i"]
|
|
43
|
+
], g = (e) => h.reduce(({ numeral: e, rest: t }, [n, r]) => ({
|
|
44
|
+
numeral: e + r.repeat(Math.floor(t / n)),
|
|
45
|
+
rest: t % n
|
|
46
|
+
}), {
|
|
47
|
+
numeral: "",
|
|
48
|
+
rest: e
|
|
49
|
+
}).numeral, _ = (e) => (e > 26 ? _(Math.floor((e - 1) / 26)) : "") + String.fromCharCode(97 + (e - 1) % 26);
|
|
50
|
+
function v(e, t) {
|
|
51
|
+
if (t < 1 || !e || !/^[aAiI]$/.test(e)) return String(t);
|
|
52
|
+
let n = /^[aA]$/.test(e) ? _(t) : g(t);
|
|
53
|
+
return e === e.toUpperCase() ? n.toUpperCase() : n;
|
|
54
|
+
}
|
|
55
|
+
function y(e) {
|
|
56
|
+
let t = e?.getData("text/html");
|
|
57
|
+
if (!e || !t || c(t)) return null;
|
|
58
|
+
let n = e.getData("text/plain"), r = Array.from(e.types).includes("text/rtf") && n.trim() !== "";
|
|
59
|
+
return !n || o(e) && !r ? null : {
|
|
60
|
+
text: n,
|
|
61
|
+
html: t
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
var b = (e) => (t, n) => {
|
|
65
|
+
let { schema: r } = n, { paragraph: i, hardBreak: a, math: o } = r.nodes, s = (e) => i.create(null, e), c = (t) => t.filter((t) => e.has(t.type.name)).map((e) => e.type.create()), l = (e) => p(e).flatMap((e) => {
|
|
66
|
+
if (e.isText) {
|
|
67
|
+
let t = c(e.marks);
|
|
68
|
+
return (e.text ?? "").split("\n").flatMap((e, n) => [...n && a ? [a.create(null, null, t)] : [], ...e ? [r.text(e, t)] : []]);
|
|
69
|
+
}
|
|
70
|
+
return e.type === a || o && e.type === o ? [e.mark(c(e.marks))] : e.isLeaf ? [] : l(e);
|
|
71
|
+
}), u = (e) => {
|
|
72
|
+
let t = [];
|
|
73
|
+
return e.descendants((e) => e.isTextblock ? (t.length && t.push(r.text(" ")), t.push(...l(e)), !1) : !0), t;
|
|
74
|
+
}, d = (t) => {
|
|
75
|
+
let n = t.type.name === "orderedList";
|
|
76
|
+
if (e.has(t.type.name)) {
|
|
77
|
+
let e = p(t).flatMap((e) => e.type.createAndFill(null, h(e)) ?? []), r = n ? {
|
|
78
|
+
start: t.attrs.start,
|
|
79
|
+
type: t.attrs.type
|
|
80
|
+
} : null;
|
|
81
|
+
return e.length ? [t.type.create(r, e)] : [];
|
|
82
|
+
}
|
|
83
|
+
let a = n ? t.attrs.start ?? 1 : 0;
|
|
84
|
+
return p(t).flatMap((e) => {
|
|
85
|
+
let o = r.text(n ? `${v(t.attrs.type, a++)}. ` : "• "), [c, ...l] = h(e);
|
|
86
|
+
return c?.type === i ? [s([o, ...p(c)]), ...l] : [
|
|
87
|
+
s([o]),
|
|
88
|
+
...c ? [c] : [],
|
|
89
|
+
...l
|
|
90
|
+
];
|
|
91
|
+
});
|
|
92
|
+
}, f = (t) => {
|
|
93
|
+
let n = t.attrs.caption ?? null;
|
|
94
|
+
if (e.has("table")) {
|
|
95
|
+
let e = p(t).flatMap((e) => {
|
|
96
|
+
let t = p(e).flatMap((e) => {
|
|
97
|
+
let { colspan: t, rowspan: n, scope: r } = e.attrs;
|
|
98
|
+
return e.type.createAndFill({
|
|
99
|
+
colspan: t,
|
|
100
|
+
rowspan: n,
|
|
101
|
+
scope: r
|
|
102
|
+
}, h(e)) ?? [];
|
|
103
|
+
});
|
|
104
|
+
return t.length ? [e.type.create(null, t)] : [];
|
|
105
|
+
});
|
|
106
|
+
return e.length ? [t.type.create({ caption: n }, e)] : [];
|
|
107
|
+
}
|
|
108
|
+
return [...n ? [s([r.text(n)])] : [], ...p(t).map((e) => s(p(e).flatMap((e, t) => t ? [r.text(" "), ...u(e)] : u(e))))];
|
|
109
|
+
}, h = (e) => p(e).flatMap((e) => e.isTextblock ? [s(l(e))] : e.type.spec.tableRole === "table" ? f(e) : e.type.name === "bulletList" || e.type.name === "orderedList" ? d(e) : e.isLeaf ? [] : h(e));
|
|
110
|
+
return m(r, t.content.firstChild?.isInline ? [s(l(t.content))] : h(t.content));
|
|
111
|
+
};
|
|
112
|
+
function x(e, t) {
|
|
113
|
+
let { schema: n } = t, r = t.selection.$from.marks(), i = (e) => {
|
|
114
|
+
let t = [];
|
|
115
|
+
return e.descendants((e) => (e.isTextblock && t.length && t.push(n.text(" ", r)), e.isText && e.text && t.push(n.text(e.text, r)), e.type === n.nodes.math && t.push(e.mark([])), !e.isInline)), t;
|
|
116
|
+
}, a = [];
|
|
117
|
+
return e.content.firstChild?.isInline ? a.push(i(n.nodes.paragraph.create(null, e.content))) : e.content.descendants((e) => {
|
|
118
|
+
if (e.type.spec.tableRole === "row") {
|
|
119
|
+
let t = [];
|
|
120
|
+
return e.forEach((e) => {
|
|
121
|
+
t.push(i(e));
|
|
122
|
+
}), a.push(t.flatMap((e, t) => t ? [n.text(" ", r), ...e] : e)), !1;
|
|
123
|
+
}
|
|
124
|
+
return e.isTextblock ? (a.push(i(e)), !1) : !0;
|
|
125
|
+
}), m(n, a.map((e) => n.nodes.paragraph.create(null, e)));
|
|
126
|
+
}
|
|
127
|
+
function S(e, t, n) {
|
|
128
|
+
u = n;
|
|
129
|
+
try {
|
|
130
|
+
e.pasteHTML(t);
|
|
131
|
+
} finally {
|
|
132
|
+
u = null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function C(t, { text: n, html: r }, i) {
|
|
136
|
+
let { selection: a, schema: o } = t.state, c = new Set(i.plainText ? [] : i.formatting);
|
|
137
|
+
if ("$anchorCell" in a && !(c.has("table") && s(r, "table"))) {
|
|
138
|
+
let e = f(n).split("\n").map((e) => `<tr>${e.split(" ").map((e) => `<td>${d(e)}</td>`).join("")}</tr>`);
|
|
139
|
+
t.pasteHTML(`<table><tbody>${e.join("")}</tbody></table>`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (!i.plainText) {
|
|
143
|
+
S(t, e(r), b(c));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (o.nodes.math && l(r)) {
|
|
147
|
+
S(t, r, x);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
t.pasteText(a.$from.parent.type.spec.code ? f(n) : f(n).replace(/^$/gm, "\xA0"));
|
|
151
|
+
}
|
|
152
|
+
var w = t.create({
|
|
153
|
+
name: "externalPaste",
|
|
154
|
+
priority: 1e3,
|
|
155
|
+
addOptions() {
|
|
156
|
+
return { settings: () => ({
|
|
157
|
+
plainText: !1,
|
|
158
|
+
formatting: a
|
|
159
|
+
}) };
|
|
160
|
+
},
|
|
161
|
+
addProseMirrorPlugins() {
|
|
162
|
+
let { settings: e } = this.options;
|
|
163
|
+
return [new n({
|
|
164
|
+
key: new r("externalPaste"),
|
|
165
|
+
props: {
|
|
166
|
+
transformPasted(e, t) {
|
|
167
|
+
return u ? u(e, t.state) : e;
|
|
168
|
+
},
|
|
169
|
+
handlePaste(t, n) {
|
|
170
|
+
let r = y(n.clipboardData);
|
|
171
|
+
return r === null ? !1 : (C(t, r, e()), !0);
|
|
172
|
+
},
|
|
173
|
+
handleDrop(t, n) {
|
|
174
|
+
let r = t.dragging ? null : y(n.dataTransfer), a = r === null ? null : t.posAtCoords({
|
|
175
|
+
left: n.clientX,
|
|
176
|
+
top: n.clientY
|
|
177
|
+
});
|
|
178
|
+
return r === null || !a ? !1 : (t.dispatch(t.state.tr.setSelection(i.near(t.state.doc.resolve(a.pos)))), C(t, r, e()), t.focus(), !0);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
})];
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
//#endregion
|
|
185
|
+
export { w as ExternalPaste, a as PASTED_FORMATTING };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Word for Windows and Mac copies a list as paragraphs, each styled `mso-list:l<list> level<n>`
|
|
3
|
+
* and led by its bullet or number as text in a `mso-list:Ignore` span. `rebuildWordLists` turns
|
|
4
|
+
* them into `<ul>` and `<ol>`, nested by level, with an ordered list's `type` and `start` read from
|
|
5
|
+
* its first number. Word for the web and Google Docs copy lists as lists.
|
|
6
|
+
*
|
|
7
|
+
* Mirrored in `packages/lib-svelte/editable-html-tiptap-svelte/src/word-lists.ts`.
|
|
8
|
+
*/
|
|
9
|
+
/** `html` with Word's list paragraphs rebuilt as lists, or `html` itself when it has none. */
|
|
10
|
+
export declare function rebuildWordLists(html: string): string;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
//#region src/word-lists.ts
|
|
2
|
+
var e = /mso-list:\s*(l\d+)\s+level(\d+)/i, t = /^\(?(?:\d+(?:\.\d+)*|[a-z]+|[A-Z]+)[.)]$|^\d+(?:\.\d+)+$/, n = /^[ivxlcdm]+$/i, r = {
|
|
3
|
+
i: 1,
|
|
4
|
+
v: 5,
|
|
5
|
+
x: 10,
|
|
6
|
+
l: 50,
|
|
7
|
+
c: 100,
|
|
8
|
+
d: 500,
|
|
9
|
+
m: 1e3
|
|
10
|
+
}, i = (t) => {
|
|
11
|
+
let n = e.exec(t.getAttribute("style") ?? "");
|
|
12
|
+
return n ? {
|
|
13
|
+
paragraph: t,
|
|
14
|
+
list: n[1],
|
|
15
|
+
level: Number(n[2])
|
|
16
|
+
} : null;
|
|
17
|
+
}, a = (e) => Array.from(e.toLowerCase()).reduce((e, t, n, i) => {
|
|
18
|
+
let a = r[t];
|
|
19
|
+
return a < (r[i[n + 1]] ?? 0) ? e - a : e + a;
|
|
20
|
+
}, 0), o = (e) => Array.from(e.toLowerCase()).reduce((e, t) => e * 26 + t.charCodeAt(0) - 96, 0);
|
|
21
|
+
function s(e) {
|
|
22
|
+
let t = e.replace(/^\(|[.)]$/g, "");
|
|
23
|
+
return /^\d/.test(t) ? {
|
|
24
|
+
type: null,
|
|
25
|
+
start: Number(t.split(".").pop())
|
|
26
|
+
} : n.test(t) && (t.length > 1 || /^i$/i.test(t)) ? {
|
|
27
|
+
type: t === t.toLowerCase() ? "i" : "I",
|
|
28
|
+
start: a(t)
|
|
29
|
+
} : {
|
|
30
|
+
type: t === t.toLowerCase() ? "a" : "A",
|
|
31
|
+
start: o(t)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function c(e) {
|
|
35
|
+
let t = e.querySelector("span[style*=\"mso-list:Ignore\"]"), n = t?.textContent?.replace(/\s+/g, " ").trim() ?? "";
|
|
36
|
+
return t?.remove(), n;
|
|
37
|
+
}
|
|
38
|
+
function l(e, n) {
|
|
39
|
+
if (!t.test(n)) return e.createElement("ul");
|
|
40
|
+
let r = e.createElement("ol"), { type: i, start: a } = s(n);
|
|
41
|
+
return i && r.setAttribute("type", i), a !== 1 && r.setAttribute("start", String(a)), r;
|
|
42
|
+
}
|
|
43
|
+
function u(e, n) {
|
|
44
|
+
let r = e.createDocumentFragment(), i = [];
|
|
45
|
+
for (let { paragraph: a, level: o } of n) {
|
|
46
|
+
let n = c(a), s = t.test(n);
|
|
47
|
+
for (; i.length && i[i.length - 1].level > o;) i.pop();
|
|
48
|
+
let u = i[i.length - 1];
|
|
49
|
+
if (u && u.level === o && u.element.tagName === "OL" !== s) {
|
|
50
|
+
i.pop();
|
|
51
|
+
let t = i[i.length - 1], a = l(e, n);
|
|
52
|
+
(t?.lastItem ?? r).appendChild(a), u = {
|
|
53
|
+
level: o,
|
|
54
|
+
element: a,
|
|
55
|
+
lastItem: null
|
|
56
|
+
}, i.push(u);
|
|
57
|
+
}
|
|
58
|
+
if (!u || u.level < o) {
|
|
59
|
+
let t = l(e, n);
|
|
60
|
+
(u?.lastItem ?? r).appendChild(t), u = {
|
|
61
|
+
level: o,
|
|
62
|
+
element: t,
|
|
63
|
+
lastItem: null
|
|
64
|
+
}, i.push(u);
|
|
65
|
+
}
|
|
66
|
+
let d = e.createElement("li"), f = e.createElement("p");
|
|
67
|
+
f.append(...Array.from(a.childNodes)), d.appendChild(f), u.element.appendChild(d), u.lastItem = d;
|
|
68
|
+
}
|
|
69
|
+
return r;
|
|
70
|
+
}
|
|
71
|
+
var d = (e) => e !== null && (e.nodeType === Node.COMMENT_NODE || e.nodeType === Node.TEXT_NODE && !e.textContent?.trim());
|
|
72
|
+
function f(e, t) {
|
|
73
|
+
let n = e.nextSibling;
|
|
74
|
+
for (; d(n);) n = n?.nextSibling ?? null;
|
|
75
|
+
return n === t;
|
|
76
|
+
}
|
|
77
|
+
function p(t) {
|
|
78
|
+
if (!e.test(t)) return t;
|
|
79
|
+
let n = new DOMParser().parseFromString(t, "text/html"), r = Array.from(n.body.querySelectorAll("p")).map(i).filter((e) => e !== null), a = [];
|
|
80
|
+
for (let e of r) {
|
|
81
|
+
let t = a[a.length - 1], n = t?.[t.length - 1];
|
|
82
|
+
n && n.list === e.list && f(n.paragraph, e.paragraph) ? t.push(e) : a.push([e]);
|
|
83
|
+
}
|
|
84
|
+
for (let e of a) {
|
|
85
|
+
e[0].paragraph.replaceWith(u(n, e));
|
|
86
|
+
for (let { paragraph: t } of e.slice(1)) t.remove();
|
|
87
|
+
}
|
|
88
|
+
return n.body.innerHTML;
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { p as rebuildWordLists };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-lib/editable-html-tip-tap",
|
|
3
|
-
"version": "3.0.1-next.
|
|
3
|
+
"version": "3.0.1-next.20261004200555",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"@mui/icons-material": "^7.3.4",
|
|
15
15
|
"@mui/material": "^7.3.4",
|
|
16
16
|
"@pie-lib/drag": "5.0.1-next.20261004173930",
|
|
17
|
-
"@pie-lib/math-input": "9.0.1-next.
|
|
18
|
-
"@pie-lib/math-toolbar": "4.0.1-next.
|
|
17
|
+
"@pie-lib/math-input": "9.0.1-next.20261004181842",
|
|
18
|
+
"@pie-lib/math-toolbar": "4.0.1-next.20261004181842",
|
|
19
19
|
"@pie-lib/render-ui": "8.0.1-next.20261004165705",
|
|
20
|
-
"@pie-lib/translator": "5.0.1-next.
|
|
20
|
+
"@pie-lib/translator": "5.0.1-next.20261004181842",
|
|
21
21
|
"@tiptap/core": "3.31.3",
|
|
22
22
|
"@tiptap/extension-character-count": "3.31.3",
|
|
23
23
|
"@tiptap/extension-color": "3.31.3",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Extension } from '@tiptap/core';
|
|
2
|
-
/**
|
|
3
|
-
* Pastes and drops rich text from outside a PIE editor as plain text, as the Slate editor did,
|
|
4
|
-
* except that math copied from rendered PIE content stays math. Parsed as HTML, content from Word
|
|
5
|
-
* keeps its fonts, sizes, colours, alignment and class names through TextStyleKit, TextAlign and
|
|
6
|
-
* CSSMark (PIE-1145).
|
|
7
|
-
*
|
|
8
|
-
* Mirrored in `packages/lib-svelte/editable-html-tiptap-svelte/src/plain-text-paste.ts`. Upstream
|
|
9
|
-
* pie-lib has no such file, so upstream sync preserves this one and re-registers it in
|
|
10
|
-
* `EditableHtml.tsx` (`preserve.editable-html-tip-tap.plain-text-paste`).
|
|
11
|
-
*/
|
|
12
|
-
export declare const PlainTextPaste: Extension<any, any>;
|
package/dist/plain-text-paste.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { Extension as e } from "@tiptap/core";
|
|
2
|
-
import { Plugin as t, PluginKey as n, TextSelection as r } from "@tiptap/pm/state";
|
|
3
|
-
//#region src/plain-text-paste.ts
|
|
4
|
-
var i = (e) => Array.from(e.items ?? []).some((e) => e.kind === "file" && e.type.startsWith("image/")), a = (e, t) => new DOMParser().parseFromString(e, "text/html").querySelector(t) !== null, o = (e) => e.includes("data-pm-slice") && a(e, "[data-pm-slice]"), s = (e) => /data-latex|data-type="?mathml/.test(e) && a(e, "[data-latex], [data-type=\"mathml\"]"), c = !1, l = (e) => e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"), u = (e) => e.replace(/\r*\n|\r/g, "\n").replace(/\n+$/, "");
|
|
5
|
-
function d(e) {
|
|
6
|
-
let t = e?.getData("text/html");
|
|
7
|
-
if (!e || !t || o(t)) return null;
|
|
8
|
-
let n = e.getData("text/plain"), r = Array.from(e.types).includes("text/rtf") && n.trim() !== "";
|
|
9
|
-
return !n || i(e) && !r ? null : {
|
|
10
|
-
text: n,
|
|
11
|
-
html: t
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
function f(e, t) {
|
|
15
|
-
let { schema: n } = t, r = t.selection.$from.marks(), i = (e) => {
|
|
16
|
-
let t = [];
|
|
17
|
-
return e.descendants((e) => (e.isTextblock && t.length && t.push(n.text(" ", r)), e.isText && e.text && t.push(n.text(e.text, r)), e.type === n.nodes.math && t.push(e.mark([])), !e.isInline)), t;
|
|
18
|
-
}, a = [];
|
|
19
|
-
e.content.firstChild?.isInline ? a.push(i(n.nodes.paragraph.create(null, e.content))) : e.content.descendants((e) => {
|
|
20
|
-
if (e.type.spec.tableRole === "row") {
|
|
21
|
-
let t = [];
|
|
22
|
-
return e.forEach((e) => {
|
|
23
|
-
t.push(i(e));
|
|
24
|
-
}), a.push(t.flatMap((e, t) => t ? [n.text(" ", r), ...e] : e)), !1;
|
|
25
|
-
}
|
|
26
|
-
return e.isTextblock ? (a.push(i(e)), !1) : !0;
|
|
27
|
-
});
|
|
28
|
-
let o = n.topNodeType.create(null, a.map((e) => n.nodes.paragraph.create(null, e)));
|
|
29
|
-
return a.length ? o.slice(1, o.content.size - 1) : o.slice(0, 0);
|
|
30
|
-
}
|
|
31
|
-
function p(e, { text: t, html: n }) {
|
|
32
|
-
let { selection: r } = e.state;
|
|
33
|
-
if ("$anchorCell" in r) {
|
|
34
|
-
let n = u(t).split("\n").map((e) => `<tr>${e.split(" ").map((e) => `<td>${l(e)}</td>`).join("")}</tr>`);
|
|
35
|
-
e.pasteHTML(`<table><tbody>${n.join("")}</tbody></table>`);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
if (e.state.schema.nodes.math && s(n)) {
|
|
39
|
-
c = !0;
|
|
40
|
-
try {
|
|
41
|
-
e.pasteHTML(n);
|
|
42
|
-
} finally {
|
|
43
|
-
c = !1;
|
|
44
|
-
}
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
e.pasteText(r.$from.parent.type.spec.code ? u(t) : u(t).replace(/^$/gm, "\xA0"));
|
|
48
|
-
}
|
|
49
|
-
var m = e.create({
|
|
50
|
-
name: "plainTextPaste",
|
|
51
|
-
priority: 1e3,
|
|
52
|
-
addProseMirrorPlugins() {
|
|
53
|
-
return [new t({
|
|
54
|
-
key: new n("plainTextPaste"),
|
|
55
|
-
props: {
|
|
56
|
-
transformPasted(e, t) {
|
|
57
|
-
return c ? f(e, t.state) : e;
|
|
58
|
-
},
|
|
59
|
-
handlePaste(e, t) {
|
|
60
|
-
let n = d(t.clipboardData);
|
|
61
|
-
return n === null ? !1 : (p(e, n), !0);
|
|
62
|
-
},
|
|
63
|
-
handleDrop(e, t) {
|
|
64
|
-
let n = e.dragging ? null : d(t.dataTransfer), i = n === null ? null : e.posAtCoords({
|
|
65
|
-
left: t.clientX,
|
|
66
|
-
top: t.clientY
|
|
67
|
-
});
|
|
68
|
-
return n === null || !i ? !1 : (e.dispatch(e.state.tr.setSelection(r.near(e.state.doc.resolve(i.pos)))), p(e, n), e.focus(), !0);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
})];
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
//#endregion
|
|
75
|
-
export { m as PlainTextPaste };
|