@shadow-garden/bapbong-model 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +123 -23
- package/dist/index.js +123 -23
- package/dist/lib/model.d.ts +1 -0
- package/dist/lib/model.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,30 @@ module.exports = __toCommonJS(index_exports);
|
|
|
28
28
|
|
|
29
29
|
// packages/model/src/lib/model.ts
|
|
30
30
|
var import_prosemirror_model = require("prosemirror-model");
|
|
31
|
+
function pastedParagraphAttrs(el, heading) {
|
|
32
|
+
const style = el.getAttribute("style") ?? "";
|
|
33
|
+
const m = /(?:^|;)\s*text-align\s*:\s*(center|right|justify)/i.exec(style);
|
|
34
|
+
return { heading, align: m ? m[1].toLowerCase() : null };
|
|
35
|
+
}
|
|
36
|
+
function pastedImageAttrs(el) {
|
|
37
|
+
const e = el;
|
|
38
|
+
const src = e.getAttribute("src") ?? "";
|
|
39
|
+
if (!/^data:image\//i.test(src)) return false;
|
|
40
|
+
const dim = (v) => {
|
|
41
|
+
const n = parseFloat(v ?? "");
|
|
42
|
+
return Number.isFinite(n) && n > 0 ? Math.round(n) : null;
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
src,
|
|
46
|
+
alt: e.getAttribute("alt") ?? "",
|
|
47
|
+
width: dim(e.getAttribute("width")),
|
|
48
|
+
height: dim(e.getAttribute("height"))
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function pastedLinkAttrs(el) {
|
|
52
|
+
const href = (el.getAttribute("href") ?? "").trim();
|
|
53
|
+
return /^(https?:|mailto:|#)/i.test(href) ? { href } : false;
|
|
54
|
+
}
|
|
31
55
|
var schema = new import_prosemirror_model.Schema({
|
|
32
56
|
nodes: {
|
|
33
57
|
doc: {
|
|
@@ -63,6 +87,11 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
63
87
|
// an <h1>–<h6> in toDOM so the a11y mirror is semantic), or null for a
|
|
64
88
|
// body paragraph.
|
|
65
89
|
heading: { default: null },
|
|
90
|
+
// Named Word paragraph style with no outline level: 'Title' |
|
|
91
|
+
// 'Subtitle', or null. Mutually exclusive with `heading` — the
|
|
92
|
+
// setParagraphStyle command is the only writer and keeps the
|
|
93
|
+
// invariant (styleId set ⇒ heading null).
|
|
94
|
+
styleId: { default: null },
|
|
66
95
|
// w:tabs — [{ pos, val: 'left'|'right'|'center'|'decimal', leader? }]
|
|
67
96
|
// in px from the paragraph's content left edge, or null. Importer-set.
|
|
68
97
|
tabs: { default: null },
|
|
@@ -71,15 +100,23 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
71
100
|
// w:pageBreakBefore — start this paragraph on a new page.
|
|
72
101
|
pageBreakBefore: { default: false }
|
|
73
102
|
},
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
parseDOM: [
|
|
103
|
+
// HTML paste path: recover heading level from h1–h6 and alignment from
|
|
104
|
+
// inline style. Other attrs (list/indent/tabs/spacing) stay importer-only
|
|
105
|
+
// — pasted HTML rarely carries them faithfully.
|
|
106
|
+
parseDOM: [
|
|
107
|
+
{ tag: "p", getAttrs: (el) => pastedParagraphAttrs(el, null) },
|
|
108
|
+
...[1, 2, 3, 4, 5, 6].map((level) => ({
|
|
109
|
+
tag: `h${level}`,
|
|
110
|
+
getAttrs: (el) => pastedParagraphAttrs(el, level)
|
|
111
|
+
}))
|
|
112
|
+
],
|
|
78
113
|
toDOM(node) {
|
|
79
114
|
const attrs = node.attrs;
|
|
80
115
|
const style = paragraphStyle(attrs);
|
|
81
116
|
const tag = attrs.heading ? `h${attrs.heading}` : "p";
|
|
82
|
-
|
|
117
|
+
const dom = style ? { style } : {};
|
|
118
|
+
if (attrs.styleId) dom["data-style"] = attrs.styleId;
|
|
119
|
+
return [tag, dom, 0];
|
|
83
120
|
}
|
|
84
121
|
},
|
|
85
122
|
text: { group: "inline" },
|
|
@@ -119,9 +156,13 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
119
156
|
// Paint-only: the layout box stays axis-aligned.
|
|
120
157
|
rotation: { default: 0 }
|
|
121
158
|
},
|
|
159
|
+
parseDOM: [{ tag: "img[src]", getAttrs: pastedImageAttrs }],
|
|
122
160
|
toDOM(node) {
|
|
123
161
|
const a = node.attrs;
|
|
124
|
-
const attrs = {
|
|
162
|
+
const attrs = {
|
|
163
|
+
src: a["src"],
|
|
164
|
+
alt: a["alt"]
|
|
165
|
+
};
|
|
125
166
|
if (a["width"] != null) attrs["width"] = String(a["width"]);
|
|
126
167
|
if (a["height"] != null) attrs["height"] = String(a["height"]);
|
|
127
168
|
return ["img", attrs];
|
|
@@ -158,7 +199,11 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
158
199
|
align: { default: null }
|
|
159
200
|
},
|
|
160
201
|
parseDOM: [{ tag: "table" }],
|
|
161
|
-
toDOM: (node) => [
|
|
202
|
+
toDOM: (node) => [
|
|
203
|
+
"table",
|
|
204
|
+
node.attrs["borders"] ? { "data-borders": "1" } : {},
|
|
205
|
+
["tbody", 0]
|
|
206
|
+
]
|
|
162
207
|
},
|
|
163
208
|
table_row: {
|
|
164
209
|
content: "table_cell+",
|
|
@@ -194,9 +239,12 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
194
239
|
parseDOM: [{ tag: "td" }, { tag: "th" }],
|
|
195
240
|
toDOM(node) {
|
|
196
241
|
const attrs = {};
|
|
197
|
-
if (node.attrs["colspan"] !== 1)
|
|
198
|
-
|
|
199
|
-
if (node.attrs["
|
|
242
|
+
if (node.attrs["colspan"] !== 1)
|
|
243
|
+
attrs["colspan"] = String(node.attrs["colspan"]);
|
|
244
|
+
if (node.attrs["rowspan"] !== 1)
|
|
245
|
+
attrs["rowspan"] = String(node.attrs["rowspan"]);
|
|
246
|
+
if (node.attrs["background"])
|
|
247
|
+
attrs["style"] = `background-color: ${node.attrs["background"]}`;
|
|
200
248
|
return ["td", attrs, 0];
|
|
201
249
|
}
|
|
202
250
|
}
|
|
@@ -225,9 +273,15 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
225
273
|
// w:color — hex "#RRGGBB"
|
|
226
274
|
textColor: {
|
|
227
275
|
attrs: { color: {} },
|
|
228
|
-
parseDOM: [
|
|
276
|
+
parseDOM: [
|
|
277
|
+
{ style: "color", getAttrs: (value) => ({ color: value }) }
|
|
278
|
+
],
|
|
229
279
|
toDOM(mark) {
|
|
230
|
-
return [
|
|
280
|
+
return [
|
|
281
|
+
"span",
|
|
282
|
+
{ style: `color: ${mark.attrs["color"]}` },
|
|
283
|
+
0
|
|
284
|
+
];
|
|
231
285
|
}
|
|
232
286
|
},
|
|
233
287
|
// w:sz — size in points
|
|
@@ -243,7 +297,11 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
243
297
|
}
|
|
244
298
|
],
|
|
245
299
|
toDOM(mark) {
|
|
246
|
-
return [
|
|
300
|
+
return [
|
|
301
|
+
"span",
|
|
302
|
+
{ style: `font-size: ${mark.attrs["size"]}pt` },
|
|
303
|
+
0
|
|
304
|
+
];
|
|
247
305
|
}
|
|
248
306
|
},
|
|
249
307
|
// w:vertAlign — superscript / subscript
|
|
@@ -260,26 +318,51 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
260
318
|
highlight: {
|
|
261
319
|
attrs: { color: {} },
|
|
262
320
|
parseDOM: [
|
|
263
|
-
{
|
|
321
|
+
{
|
|
322
|
+
style: "background-color",
|
|
323
|
+
getAttrs: (value) => ({ color: value })
|
|
324
|
+
}
|
|
264
325
|
],
|
|
265
326
|
toDOM(mark) {
|
|
266
|
-
return [
|
|
327
|
+
return [
|
|
328
|
+
"span",
|
|
329
|
+
{ style: `background-color: ${mark.attrs["color"]}` },
|
|
330
|
+
0
|
|
331
|
+
];
|
|
267
332
|
}
|
|
268
333
|
},
|
|
269
334
|
// w:rFonts — font family
|
|
270
335
|
fontFamily: {
|
|
271
336
|
attrs: { family: {} },
|
|
272
|
-
parseDOM: [
|
|
337
|
+
parseDOM: [
|
|
338
|
+
{
|
|
339
|
+
style: "font-family",
|
|
340
|
+
getAttrs: (value) => ({ family: value })
|
|
341
|
+
}
|
|
342
|
+
],
|
|
273
343
|
toDOM(mark) {
|
|
274
|
-
return [
|
|
344
|
+
return [
|
|
345
|
+
"span",
|
|
346
|
+
{ style: `font-family: ${mark.attrs["family"]}` },
|
|
347
|
+
0
|
|
348
|
+
];
|
|
275
349
|
}
|
|
276
350
|
},
|
|
277
351
|
// w:hyperlink — external URL or "#anchor"
|
|
278
352
|
link: {
|
|
279
353
|
attrs: { href: {} },
|
|
280
354
|
inclusive: false,
|
|
355
|
+
parseDOM: [{ tag: "a[href]", getAttrs: pastedLinkAttrs }],
|
|
281
356
|
toDOM(mark) {
|
|
282
|
-
return [
|
|
357
|
+
return [
|
|
358
|
+
"a",
|
|
359
|
+
{
|
|
360
|
+
href: mark.attrs["href"],
|
|
361
|
+
rel: "noopener",
|
|
362
|
+
target: "_blank"
|
|
363
|
+
},
|
|
364
|
+
0
|
|
365
|
+
];
|
|
283
366
|
}
|
|
284
367
|
},
|
|
285
368
|
// w:footnoteReference — the carrier text is the superscript number; `num`
|
|
@@ -293,12 +376,20 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
293
376
|
// `el` is an HTMLElement at runtime; this package has no DOM lib, so
|
|
294
377
|
// narrow structurally rather than naming the type.
|
|
295
378
|
getAttrs: (el) => ({
|
|
296
|
-
num: Number(
|
|
379
|
+
num: Number(
|
|
380
|
+
el.getAttribute(
|
|
381
|
+
"data-footnote"
|
|
382
|
+
)
|
|
383
|
+
) || 0
|
|
297
384
|
})
|
|
298
385
|
}
|
|
299
386
|
],
|
|
300
387
|
toDOM(mark) {
|
|
301
|
-
return [
|
|
388
|
+
return [
|
|
389
|
+
"sup",
|
|
390
|
+
{ "data-footnote": String(mark.attrs["num"]) },
|
|
391
|
+
0
|
|
392
|
+
];
|
|
302
393
|
}
|
|
303
394
|
}
|
|
304
395
|
// The `comment` mark (w:commentRangeStart/End) is contributed by the comment
|
|
@@ -311,7 +402,12 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
311
402
|
var commentSchema = new import_prosemirror_model.Schema({
|
|
312
403
|
nodes: {
|
|
313
404
|
doc: { content: "block+" },
|
|
314
|
-
paragraph: {
|
|
405
|
+
paragraph: {
|
|
406
|
+
group: "block",
|
|
407
|
+
content: "inline*",
|
|
408
|
+
parseDOM: [{ tag: "p" }],
|
|
409
|
+
toDOM: () => ["p", 0]
|
|
410
|
+
},
|
|
315
411
|
text: { group: "inline" },
|
|
316
412
|
// @mention: an inline atom carrying the mentioned user's id + display name.
|
|
317
413
|
// `leafText` lets textContent include "@Name" (search / plain-text preview).
|
|
@@ -332,7 +428,10 @@ var commentSchema = new import_prosemirror_model.Schema({
|
|
|
332
428
|
tag: "span.mention",
|
|
333
429
|
getAttrs: (el) => {
|
|
334
430
|
const e = el;
|
|
335
|
-
return {
|
|
431
|
+
return {
|
|
432
|
+
id: e.getAttribute("data-id"),
|
|
433
|
+
label: (e.textContent ?? "").replace(/^@/, "")
|
|
434
|
+
};
|
|
336
435
|
}
|
|
337
436
|
}
|
|
338
437
|
]
|
|
@@ -354,7 +453,8 @@ function paragraphStyle(attrs) {
|
|
|
354
453
|
if (sp) {
|
|
355
454
|
if (sp.before) parts.push(`margin-top: ${sp.before}px`);
|
|
356
455
|
if (sp.after) parts.push(`margin-bottom: ${sp.after}px`);
|
|
357
|
-
if (sp.line && sp.lineRule === "auto")
|
|
456
|
+
if (sp.line && sp.lineRule === "auto")
|
|
457
|
+
parts.push(`line-height: ${sp.line}`);
|
|
358
458
|
else if (sp.line) parts.push(`line-height: ${sp.line}px`);
|
|
359
459
|
}
|
|
360
460
|
return parts.join("; ");
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
// packages/model/src/lib/model.ts
|
|
2
2
|
import { Schema } from "prosemirror-model";
|
|
3
|
+
function pastedParagraphAttrs(el, heading) {
|
|
4
|
+
const style = el.getAttribute("style") ?? "";
|
|
5
|
+
const m = /(?:^|;)\s*text-align\s*:\s*(center|right|justify)/i.exec(style);
|
|
6
|
+
return { heading, align: m ? m[1].toLowerCase() : null };
|
|
7
|
+
}
|
|
8
|
+
function pastedImageAttrs(el) {
|
|
9
|
+
const e = el;
|
|
10
|
+
const src = e.getAttribute("src") ?? "";
|
|
11
|
+
if (!/^data:image\//i.test(src)) return false;
|
|
12
|
+
const dim = (v) => {
|
|
13
|
+
const n = parseFloat(v ?? "");
|
|
14
|
+
return Number.isFinite(n) && n > 0 ? Math.round(n) : null;
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
src,
|
|
18
|
+
alt: e.getAttribute("alt") ?? "",
|
|
19
|
+
width: dim(e.getAttribute("width")),
|
|
20
|
+
height: dim(e.getAttribute("height"))
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function pastedLinkAttrs(el) {
|
|
24
|
+
const href = (el.getAttribute("href") ?? "").trim();
|
|
25
|
+
return /^(https?:|mailto:|#)/i.test(href) ? { href } : false;
|
|
26
|
+
}
|
|
3
27
|
var schema = new Schema({
|
|
4
28
|
nodes: {
|
|
5
29
|
doc: {
|
|
@@ -35,6 +59,11 @@ var schema = new Schema({
|
|
|
35
59
|
// an <h1>–<h6> in toDOM so the a11y mirror is semantic), or null for a
|
|
36
60
|
// body paragraph.
|
|
37
61
|
heading: { default: null },
|
|
62
|
+
// Named Word paragraph style with no outline level: 'Title' |
|
|
63
|
+
// 'Subtitle', or null. Mutually exclusive with `heading` — the
|
|
64
|
+
// setParagraphStyle command is the only writer and keeps the
|
|
65
|
+
// invariant (styleId set ⇒ heading null).
|
|
66
|
+
styleId: { default: null },
|
|
38
67
|
// w:tabs — [{ pos, val: 'left'|'right'|'center'|'decimal', leader? }]
|
|
39
68
|
// in px from the paragraph's content left edge, or null. Importer-set.
|
|
40
69
|
tabs: { default: null },
|
|
@@ -43,15 +72,23 @@ var schema = new Schema({
|
|
|
43
72
|
// w:pageBreakBefore — start this paragraph on a new page.
|
|
44
73
|
pageBreakBefore: { default: false }
|
|
45
74
|
},
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
parseDOM: [
|
|
75
|
+
// HTML paste path: recover heading level from h1–h6 and alignment from
|
|
76
|
+
// inline style. Other attrs (list/indent/tabs/spacing) stay importer-only
|
|
77
|
+
// — pasted HTML rarely carries them faithfully.
|
|
78
|
+
parseDOM: [
|
|
79
|
+
{ tag: "p", getAttrs: (el) => pastedParagraphAttrs(el, null) },
|
|
80
|
+
...[1, 2, 3, 4, 5, 6].map((level) => ({
|
|
81
|
+
tag: `h${level}`,
|
|
82
|
+
getAttrs: (el) => pastedParagraphAttrs(el, level)
|
|
83
|
+
}))
|
|
84
|
+
],
|
|
50
85
|
toDOM(node) {
|
|
51
86
|
const attrs = node.attrs;
|
|
52
87
|
const style = paragraphStyle(attrs);
|
|
53
88
|
const tag = attrs.heading ? `h${attrs.heading}` : "p";
|
|
54
|
-
|
|
89
|
+
const dom = style ? { style } : {};
|
|
90
|
+
if (attrs.styleId) dom["data-style"] = attrs.styleId;
|
|
91
|
+
return [tag, dom, 0];
|
|
55
92
|
}
|
|
56
93
|
},
|
|
57
94
|
text: { group: "inline" },
|
|
@@ -91,9 +128,13 @@ var schema = new Schema({
|
|
|
91
128
|
// Paint-only: the layout box stays axis-aligned.
|
|
92
129
|
rotation: { default: 0 }
|
|
93
130
|
},
|
|
131
|
+
parseDOM: [{ tag: "img[src]", getAttrs: pastedImageAttrs }],
|
|
94
132
|
toDOM(node) {
|
|
95
133
|
const a = node.attrs;
|
|
96
|
-
const attrs = {
|
|
134
|
+
const attrs = {
|
|
135
|
+
src: a["src"],
|
|
136
|
+
alt: a["alt"]
|
|
137
|
+
};
|
|
97
138
|
if (a["width"] != null) attrs["width"] = String(a["width"]);
|
|
98
139
|
if (a["height"] != null) attrs["height"] = String(a["height"]);
|
|
99
140
|
return ["img", attrs];
|
|
@@ -130,7 +171,11 @@ var schema = new Schema({
|
|
|
130
171
|
align: { default: null }
|
|
131
172
|
},
|
|
132
173
|
parseDOM: [{ tag: "table" }],
|
|
133
|
-
toDOM: (node) => [
|
|
174
|
+
toDOM: (node) => [
|
|
175
|
+
"table",
|
|
176
|
+
node.attrs["borders"] ? { "data-borders": "1" } : {},
|
|
177
|
+
["tbody", 0]
|
|
178
|
+
]
|
|
134
179
|
},
|
|
135
180
|
table_row: {
|
|
136
181
|
content: "table_cell+",
|
|
@@ -166,9 +211,12 @@ var schema = new Schema({
|
|
|
166
211
|
parseDOM: [{ tag: "td" }, { tag: "th" }],
|
|
167
212
|
toDOM(node) {
|
|
168
213
|
const attrs = {};
|
|
169
|
-
if (node.attrs["colspan"] !== 1)
|
|
170
|
-
|
|
171
|
-
if (node.attrs["
|
|
214
|
+
if (node.attrs["colspan"] !== 1)
|
|
215
|
+
attrs["colspan"] = String(node.attrs["colspan"]);
|
|
216
|
+
if (node.attrs["rowspan"] !== 1)
|
|
217
|
+
attrs["rowspan"] = String(node.attrs["rowspan"]);
|
|
218
|
+
if (node.attrs["background"])
|
|
219
|
+
attrs["style"] = `background-color: ${node.attrs["background"]}`;
|
|
172
220
|
return ["td", attrs, 0];
|
|
173
221
|
}
|
|
174
222
|
}
|
|
@@ -197,9 +245,15 @@ var schema = new Schema({
|
|
|
197
245
|
// w:color — hex "#RRGGBB"
|
|
198
246
|
textColor: {
|
|
199
247
|
attrs: { color: {} },
|
|
200
|
-
parseDOM: [
|
|
248
|
+
parseDOM: [
|
|
249
|
+
{ style: "color", getAttrs: (value) => ({ color: value }) }
|
|
250
|
+
],
|
|
201
251
|
toDOM(mark) {
|
|
202
|
-
return [
|
|
252
|
+
return [
|
|
253
|
+
"span",
|
|
254
|
+
{ style: `color: ${mark.attrs["color"]}` },
|
|
255
|
+
0
|
|
256
|
+
];
|
|
203
257
|
}
|
|
204
258
|
},
|
|
205
259
|
// w:sz — size in points
|
|
@@ -215,7 +269,11 @@ var schema = new Schema({
|
|
|
215
269
|
}
|
|
216
270
|
],
|
|
217
271
|
toDOM(mark) {
|
|
218
|
-
return [
|
|
272
|
+
return [
|
|
273
|
+
"span",
|
|
274
|
+
{ style: `font-size: ${mark.attrs["size"]}pt` },
|
|
275
|
+
0
|
|
276
|
+
];
|
|
219
277
|
}
|
|
220
278
|
},
|
|
221
279
|
// w:vertAlign — superscript / subscript
|
|
@@ -232,26 +290,51 @@ var schema = new Schema({
|
|
|
232
290
|
highlight: {
|
|
233
291
|
attrs: { color: {} },
|
|
234
292
|
parseDOM: [
|
|
235
|
-
{
|
|
293
|
+
{
|
|
294
|
+
style: "background-color",
|
|
295
|
+
getAttrs: (value) => ({ color: value })
|
|
296
|
+
}
|
|
236
297
|
],
|
|
237
298
|
toDOM(mark) {
|
|
238
|
-
return [
|
|
299
|
+
return [
|
|
300
|
+
"span",
|
|
301
|
+
{ style: `background-color: ${mark.attrs["color"]}` },
|
|
302
|
+
0
|
|
303
|
+
];
|
|
239
304
|
}
|
|
240
305
|
},
|
|
241
306
|
// w:rFonts — font family
|
|
242
307
|
fontFamily: {
|
|
243
308
|
attrs: { family: {} },
|
|
244
|
-
parseDOM: [
|
|
309
|
+
parseDOM: [
|
|
310
|
+
{
|
|
311
|
+
style: "font-family",
|
|
312
|
+
getAttrs: (value) => ({ family: value })
|
|
313
|
+
}
|
|
314
|
+
],
|
|
245
315
|
toDOM(mark) {
|
|
246
|
-
return [
|
|
316
|
+
return [
|
|
317
|
+
"span",
|
|
318
|
+
{ style: `font-family: ${mark.attrs["family"]}` },
|
|
319
|
+
0
|
|
320
|
+
];
|
|
247
321
|
}
|
|
248
322
|
},
|
|
249
323
|
// w:hyperlink — external URL or "#anchor"
|
|
250
324
|
link: {
|
|
251
325
|
attrs: { href: {} },
|
|
252
326
|
inclusive: false,
|
|
327
|
+
parseDOM: [{ tag: "a[href]", getAttrs: pastedLinkAttrs }],
|
|
253
328
|
toDOM(mark) {
|
|
254
|
-
return [
|
|
329
|
+
return [
|
|
330
|
+
"a",
|
|
331
|
+
{
|
|
332
|
+
href: mark.attrs["href"],
|
|
333
|
+
rel: "noopener",
|
|
334
|
+
target: "_blank"
|
|
335
|
+
},
|
|
336
|
+
0
|
|
337
|
+
];
|
|
255
338
|
}
|
|
256
339
|
},
|
|
257
340
|
// w:footnoteReference — the carrier text is the superscript number; `num`
|
|
@@ -265,12 +348,20 @@ var schema = new Schema({
|
|
|
265
348
|
// `el` is an HTMLElement at runtime; this package has no DOM lib, so
|
|
266
349
|
// narrow structurally rather than naming the type.
|
|
267
350
|
getAttrs: (el) => ({
|
|
268
|
-
num: Number(
|
|
351
|
+
num: Number(
|
|
352
|
+
el.getAttribute(
|
|
353
|
+
"data-footnote"
|
|
354
|
+
)
|
|
355
|
+
) || 0
|
|
269
356
|
})
|
|
270
357
|
}
|
|
271
358
|
],
|
|
272
359
|
toDOM(mark) {
|
|
273
|
-
return [
|
|
360
|
+
return [
|
|
361
|
+
"sup",
|
|
362
|
+
{ "data-footnote": String(mark.attrs["num"]) },
|
|
363
|
+
0
|
|
364
|
+
];
|
|
274
365
|
}
|
|
275
366
|
}
|
|
276
367
|
// The `comment` mark (w:commentRangeStart/End) is contributed by the comment
|
|
@@ -283,7 +374,12 @@ var schema = new Schema({
|
|
|
283
374
|
var commentSchema = new Schema({
|
|
284
375
|
nodes: {
|
|
285
376
|
doc: { content: "block+" },
|
|
286
|
-
paragraph: {
|
|
377
|
+
paragraph: {
|
|
378
|
+
group: "block",
|
|
379
|
+
content: "inline*",
|
|
380
|
+
parseDOM: [{ tag: "p" }],
|
|
381
|
+
toDOM: () => ["p", 0]
|
|
382
|
+
},
|
|
287
383
|
text: { group: "inline" },
|
|
288
384
|
// @mention: an inline atom carrying the mentioned user's id + display name.
|
|
289
385
|
// `leafText` lets textContent include "@Name" (search / plain-text preview).
|
|
@@ -304,7 +400,10 @@ var commentSchema = new Schema({
|
|
|
304
400
|
tag: "span.mention",
|
|
305
401
|
getAttrs: (el) => {
|
|
306
402
|
const e = el;
|
|
307
|
-
return {
|
|
403
|
+
return {
|
|
404
|
+
id: e.getAttribute("data-id"),
|
|
405
|
+
label: (e.textContent ?? "").replace(/^@/, "")
|
|
406
|
+
};
|
|
308
407
|
}
|
|
309
408
|
}
|
|
310
409
|
]
|
|
@@ -326,7 +425,8 @@ function paragraphStyle(attrs) {
|
|
|
326
425
|
if (sp) {
|
|
327
426
|
if (sp.before) parts.push(`margin-top: ${sp.before}px`);
|
|
328
427
|
if (sp.after) parts.push(`margin-bottom: ${sp.after}px`);
|
|
329
|
-
if (sp.line && sp.lineRule === "auto")
|
|
428
|
+
if (sp.line && sp.lineRule === "auto")
|
|
429
|
+
parts.push(`line-height: ${sp.line}`);
|
|
330
430
|
else if (sp.line) parts.push(`line-height: ${sp.line}px`);
|
|
331
431
|
}
|
|
332
432
|
return parts.join("; ");
|
package/dist/lib/model.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export interface ParagraphAttrs {
|
|
|
42
42
|
indent: Indent | null;
|
|
43
43
|
spacing?: Spacing | null;
|
|
44
44
|
heading?: number | null;
|
|
45
|
+
styleId?: 'Title' | 'Subtitle' | null;
|
|
45
46
|
}
|
|
46
47
|
/** Value of a list paragraph's `list` attribute. The marker string ("1.",
|
|
47
48
|
* "2.a", "•") is NOT stored — it's recomputed at layout time from the doc's
|
package/dist/lib/model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/lib/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/lib/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AA0C3C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,2PA8VjB,CAAC;AAEH,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG,OAAO,MAAM,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,aAAa,yDA0CxB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC;AAEjD,qDAAqD;AACrD,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAE5D;+EAC+E;AAC/E,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,2EAA2E;AAC3E,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAAC;CACvC;AA0BD;;;4EAG4E;AAC5E,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|