@shadow-garden/bapbong-model 0.9.0 → 0.10.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 +61 -6
- package/dist/index.js +61 -6
- package/dist/lib/model.d.ts +1 -1
- package/dist/lib/model.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -102,12 +102,15 @@ function pastedImageAttrs(el) {
|
|
|
102
102
|
src,
|
|
103
103
|
alt: e.getAttribute("alt") ?? "",
|
|
104
104
|
width: dim(e.getAttribute("width")),
|
|
105
|
-
height: dim(e.getAttribute("height"))
|
|
105
|
+
height: dim(e.getAttribute("height")),
|
|
106
|
+
crop: dataJson(el, "data-crop"),
|
|
107
|
+
outline: dataJson(el, "data-outline")
|
|
106
108
|
};
|
|
107
109
|
}
|
|
108
110
|
function pastedLinkAttrs(el) {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
+
const e = el;
|
|
112
|
+
const href = (e.getAttribute("href") ?? "").trim();
|
|
113
|
+
return /^(https?:|mailto:|#)/i.test(href) ? { href, targetFrame: e.getAttribute("data-target-frame") } : false;
|
|
111
114
|
}
|
|
112
115
|
function pastedCellAttrs(el) {
|
|
113
116
|
const e = el;
|
|
@@ -124,6 +127,7 @@ function pastedCellAttrs(el) {
|
|
|
124
127
|
background: bg ? bg[1].trim() : null,
|
|
125
128
|
vAlign: e.getAttribute("data-valign"),
|
|
126
129
|
borders: dataJson(el, "data-borders"),
|
|
130
|
+
diagonals: dataJson(el, "data-diagonals"),
|
|
127
131
|
padding: dataJson(el, "data-padding"),
|
|
128
132
|
carry: dataJson(el, "data-carry")
|
|
129
133
|
};
|
|
@@ -195,6 +199,11 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
195
199
|
field: { default: null },
|
|
196
200
|
// w:pageBreakBefore — start this paragraph on a new page.
|
|
197
201
|
pageBreakBefore: { default: false },
|
|
202
|
+
// w:contextualSpacing — "ignore spacing above and below when using
|
|
203
|
+
// identical styles". Present ⇒ the flag is on; the two booleans say
|
|
204
|
+
// which side actually borders a paragraph of the SAME style, which is
|
|
205
|
+
// resolved at import (only there is both sides of a boundary visible).
|
|
206
|
+
contextualSpacing: { default: null },
|
|
198
207
|
// w:keepNext — stay on the same page as the next block's first line.
|
|
199
208
|
keepNext: { default: false },
|
|
200
209
|
// w:keepLines — never split this paragraph across pages.
|
|
@@ -205,6 +214,10 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
205
214
|
// w:pBdr — { top?, bottom?, left?, right? } of BorderSide, or null.
|
|
206
215
|
// Importer-set; painted as a box around the paragraph's lines.
|
|
207
216
|
borders: { default: null },
|
|
217
|
+
// w:shd at the paragraph layer, resolved to a fill "#RRGGBB" (or
|
|
218
|
+
// null). Painted behind the paragraph's lines, in the same box the
|
|
219
|
+
// borders use.
|
|
220
|
+
shading: { default: null },
|
|
208
221
|
// Carry-through fidelity (docx round-trip): OOXML paragraph
|
|
209
222
|
// properties the model does NOT represent, preserved verbatim so a
|
|
210
223
|
// customer's save never drops them. { pPr?: string, markRPr?: string }
|
|
@@ -230,6 +243,8 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
230
243
|
if (attrs.styleId) dom["data-style"] = attrs.styleId;
|
|
231
244
|
if (node.attrs["borders"])
|
|
232
245
|
dom["data-borders"] = JSON.stringify(node.attrs["borders"]);
|
|
246
|
+
if (node.attrs["shading"])
|
|
247
|
+
dom["data-shading"] = String(node.attrs["shading"]);
|
|
233
248
|
if (node.attrs["carry"])
|
|
234
249
|
dom["data-carry"] = JSON.stringify(node.attrs["carry"]);
|
|
235
250
|
return [tag, dom, 0];
|
|
@@ -271,7 +286,13 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
271
286
|
textbox: { default: null },
|
|
272
287
|
// Clockwise rotation in degrees around the box center (a:xfrm@rot).
|
|
273
288
|
// Paint-only: the layout box stays axis-aligned.
|
|
274
|
-
rotation: { default: 0 }
|
|
289
|
+
rotation: { default: 0 },
|
|
290
|
+
// a:srcRect — { l, t, r, b } ratios of the BITMAP, inward from each
|
|
291
|
+
// edge, or null for the whole image. Negative values outset. The box
|
|
292
|
+
// keeps its size; the selected region scales to fill it.
|
|
293
|
+
crop: { default: null },
|
|
294
|
+
// a:ln on pic:spPr — Word's picture border, as a BorderSide, or null.
|
|
295
|
+
outline: { default: null }
|
|
275
296
|
},
|
|
276
297
|
parseDOM: [{ tag: "img[src]", getAttrs: pastedImageAttrs }],
|
|
277
298
|
toDOM(node) {
|
|
@@ -282,6 +303,8 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
282
303
|
};
|
|
283
304
|
if (a["width"] != null) attrs["width"] = String(a["width"]);
|
|
284
305
|
if (a["height"] != null) attrs["height"] = String(a["height"]);
|
|
306
|
+
if (a["crop"]) attrs["data-crop"] = JSON.stringify(a["crop"]);
|
|
307
|
+
if (a["outline"]) attrs["data-outline"] = JSON.stringify(a["outline"]);
|
|
285
308
|
return ["img", attrs];
|
|
286
309
|
}
|
|
287
310
|
},
|
|
@@ -395,6 +418,8 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
395
418
|
// w:vAlign — 'center' | 'bottom' (top default)
|
|
396
419
|
borders: { default: null },
|
|
397
420
|
// w:tcBorders per-side visibility override
|
|
421
|
+
// w:tcBorders/w:tl2br + w:br2tl — rules across the cell's corners
|
|
422
|
+
diagonals: { default: null },
|
|
398
423
|
padding: { default: null },
|
|
399
424
|
// w:tcMar per-side margin override (px)
|
|
400
425
|
// Carry-through fidelity: unmodelled w:tcPr children ({ tcPr: string
|
|
@@ -419,6 +444,8 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
419
444
|
attrs["data-valign"] = String(node.attrs["vAlign"]);
|
|
420
445
|
if (node.attrs["borders"])
|
|
421
446
|
attrs["data-borders"] = JSON.stringify(node.attrs["borders"]);
|
|
447
|
+
if (node.attrs["diagonals"])
|
|
448
|
+
attrs["data-diagonals"] = JSON.stringify(node.attrs["diagonals"]);
|
|
422
449
|
if (node.attrs["padding"])
|
|
423
450
|
attrs["data-padding"] = JSON.stringify(node.attrs["padding"]);
|
|
424
451
|
if (node.attrs["carry"])
|
|
@@ -537,6 +564,29 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
537
564
|
0
|
|
538
565
|
]
|
|
539
566
|
},
|
|
567
|
+
// w:kern — the smallest font size (HALF-POINTS) that gets pair kerning.
|
|
568
|
+
// A threshold, not a switch: whether it bites depends on the run's own
|
|
569
|
+
// size, so the declared number is what the model keeps and the layout
|
|
570
|
+
// compares. No DOM representation — CSS font-kerning cannot express a
|
|
571
|
+
// size threshold, so an external paste simply has no opinion.
|
|
572
|
+
kern: {
|
|
573
|
+
attrs: { halfPoints: {} },
|
|
574
|
+
parseDOM: [
|
|
575
|
+
{
|
|
576
|
+
tag: "span[data-kern]",
|
|
577
|
+
getAttrs: (el) => {
|
|
578
|
+
const raw = el.getAttribute("data-kern");
|
|
579
|
+
const n = Number(raw);
|
|
580
|
+
return Number.isFinite(n) ? { halfPoints: n } : false;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
],
|
|
584
|
+
toDOM: (mark) => [
|
|
585
|
+
"span",
|
|
586
|
+
{ "data-kern": String(mark.attrs["halfPoints"]) },
|
|
587
|
+
0
|
|
588
|
+
]
|
|
589
|
+
},
|
|
540
590
|
// w:w — horizontal glyph scale as a PERCENT (100 = normal). Squeezes the
|
|
541
591
|
// glyphs and their advances; independent of letterSpacing, which rides on
|
|
542
592
|
// top at its absolute value.
|
|
@@ -617,7 +667,11 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
617
667
|
},
|
|
618
668
|
// w:hyperlink — external URL or "#anchor"
|
|
619
669
|
link: {
|
|
620
|
-
|
|
670
|
+
// w:hyperlink @w:tgtFrame — the frame the link was meant to open in
|
|
671
|
+
// ("_blank", "_top", or a frame name), from the HTML-frames era. There
|
|
672
|
+
// is no frame here to obey it and nothing acts on it; it is modelled so
|
|
673
|
+
// that saving the file gives the attribute back instead of dropping it.
|
|
674
|
+
attrs: { href: {}, targetFrame: { default: null } },
|
|
621
675
|
inclusive: false,
|
|
622
676
|
parseDOM: [{ tag: "a[href]", getAttrs: pastedLinkAttrs }],
|
|
623
677
|
toDOM(mark) {
|
|
@@ -626,7 +680,8 @@ var schema = new import_prosemirror_model.Schema({
|
|
|
626
680
|
{
|
|
627
681
|
href: mark.attrs["href"],
|
|
628
682
|
rel: "noopener",
|
|
629
|
-
target: "_blank"
|
|
683
|
+
target: "_blank",
|
|
684
|
+
...mark.attrs["targetFrame"] ? { "data-target-frame": String(mark.attrs["targetFrame"]) } : {}
|
|
630
685
|
},
|
|
631
686
|
0
|
|
632
687
|
];
|
package/dist/index.js
CHANGED
|
@@ -70,12 +70,15 @@ function pastedImageAttrs(el) {
|
|
|
70
70
|
src,
|
|
71
71
|
alt: e.getAttribute("alt") ?? "",
|
|
72
72
|
width: dim(e.getAttribute("width")),
|
|
73
|
-
height: dim(e.getAttribute("height"))
|
|
73
|
+
height: dim(e.getAttribute("height")),
|
|
74
|
+
crop: dataJson(el, "data-crop"),
|
|
75
|
+
outline: dataJson(el, "data-outline")
|
|
74
76
|
};
|
|
75
77
|
}
|
|
76
78
|
function pastedLinkAttrs(el) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
+
const e = el;
|
|
80
|
+
const href = (e.getAttribute("href") ?? "").trim();
|
|
81
|
+
return /^(https?:|mailto:|#)/i.test(href) ? { href, targetFrame: e.getAttribute("data-target-frame") } : false;
|
|
79
82
|
}
|
|
80
83
|
function pastedCellAttrs(el) {
|
|
81
84
|
const e = el;
|
|
@@ -92,6 +95,7 @@ function pastedCellAttrs(el) {
|
|
|
92
95
|
background: bg ? bg[1].trim() : null,
|
|
93
96
|
vAlign: e.getAttribute("data-valign"),
|
|
94
97
|
borders: dataJson(el, "data-borders"),
|
|
98
|
+
diagonals: dataJson(el, "data-diagonals"),
|
|
95
99
|
padding: dataJson(el, "data-padding"),
|
|
96
100
|
carry: dataJson(el, "data-carry")
|
|
97
101
|
};
|
|
@@ -163,6 +167,11 @@ var schema = new Schema({
|
|
|
163
167
|
field: { default: null },
|
|
164
168
|
// w:pageBreakBefore — start this paragraph on a new page.
|
|
165
169
|
pageBreakBefore: { default: false },
|
|
170
|
+
// w:contextualSpacing — "ignore spacing above and below when using
|
|
171
|
+
// identical styles". Present ⇒ the flag is on; the two booleans say
|
|
172
|
+
// which side actually borders a paragraph of the SAME style, which is
|
|
173
|
+
// resolved at import (only there is both sides of a boundary visible).
|
|
174
|
+
contextualSpacing: { default: null },
|
|
166
175
|
// w:keepNext — stay on the same page as the next block's first line.
|
|
167
176
|
keepNext: { default: false },
|
|
168
177
|
// w:keepLines — never split this paragraph across pages.
|
|
@@ -173,6 +182,10 @@ var schema = new Schema({
|
|
|
173
182
|
// w:pBdr — { top?, bottom?, left?, right? } of BorderSide, or null.
|
|
174
183
|
// Importer-set; painted as a box around the paragraph's lines.
|
|
175
184
|
borders: { default: null },
|
|
185
|
+
// w:shd at the paragraph layer, resolved to a fill "#RRGGBB" (or
|
|
186
|
+
// null). Painted behind the paragraph's lines, in the same box the
|
|
187
|
+
// borders use.
|
|
188
|
+
shading: { default: null },
|
|
176
189
|
// Carry-through fidelity (docx round-trip): OOXML paragraph
|
|
177
190
|
// properties the model does NOT represent, preserved verbatim so a
|
|
178
191
|
// customer's save never drops them. { pPr?: string, markRPr?: string }
|
|
@@ -198,6 +211,8 @@ var schema = new Schema({
|
|
|
198
211
|
if (attrs.styleId) dom["data-style"] = attrs.styleId;
|
|
199
212
|
if (node.attrs["borders"])
|
|
200
213
|
dom["data-borders"] = JSON.stringify(node.attrs["borders"]);
|
|
214
|
+
if (node.attrs["shading"])
|
|
215
|
+
dom["data-shading"] = String(node.attrs["shading"]);
|
|
201
216
|
if (node.attrs["carry"])
|
|
202
217
|
dom["data-carry"] = JSON.stringify(node.attrs["carry"]);
|
|
203
218
|
return [tag, dom, 0];
|
|
@@ -239,7 +254,13 @@ var schema = new Schema({
|
|
|
239
254
|
textbox: { default: null },
|
|
240
255
|
// Clockwise rotation in degrees around the box center (a:xfrm@rot).
|
|
241
256
|
// Paint-only: the layout box stays axis-aligned.
|
|
242
|
-
rotation: { default: 0 }
|
|
257
|
+
rotation: { default: 0 },
|
|
258
|
+
// a:srcRect — { l, t, r, b } ratios of the BITMAP, inward from each
|
|
259
|
+
// edge, or null for the whole image. Negative values outset. The box
|
|
260
|
+
// keeps its size; the selected region scales to fill it.
|
|
261
|
+
crop: { default: null },
|
|
262
|
+
// a:ln on pic:spPr — Word's picture border, as a BorderSide, or null.
|
|
263
|
+
outline: { default: null }
|
|
243
264
|
},
|
|
244
265
|
parseDOM: [{ tag: "img[src]", getAttrs: pastedImageAttrs }],
|
|
245
266
|
toDOM(node) {
|
|
@@ -250,6 +271,8 @@ var schema = new Schema({
|
|
|
250
271
|
};
|
|
251
272
|
if (a["width"] != null) attrs["width"] = String(a["width"]);
|
|
252
273
|
if (a["height"] != null) attrs["height"] = String(a["height"]);
|
|
274
|
+
if (a["crop"]) attrs["data-crop"] = JSON.stringify(a["crop"]);
|
|
275
|
+
if (a["outline"]) attrs["data-outline"] = JSON.stringify(a["outline"]);
|
|
253
276
|
return ["img", attrs];
|
|
254
277
|
}
|
|
255
278
|
},
|
|
@@ -363,6 +386,8 @@ var schema = new Schema({
|
|
|
363
386
|
// w:vAlign — 'center' | 'bottom' (top default)
|
|
364
387
|
borders: { default: null },
|
|
365
388
|
// w:tcBorders per-side visibility override
|
|
389
|
+
// w:tcBorders/w:tl2br + w:br2tl — rules across the cell's corners
|
|
390
|
+
diagonals: { default: null },
|
|
366
391
|
padding: { default: null },
|
|
367
392
|
// w:tcMar per-side margin override (px)
|
|
368
393
|
// Carry-through fidelity: unmodelled w:tcPr children ({ tcPr: string
|
|
@@ -387,6 +412,8 @@ var schema = new Schema({
|
|
|
387
412
|
attrs["data-valign"] = String(node.attrs["vAlign"]);
|
|
388
413
|
if (node.attrs["borders"])
|
|
389
414
|
attrs["data-borders"] = JSON.stringify(node.attrs["borders"]);
|
|
415
|
+
if (node.attrs["diagonals"])
|
|
416
|
+
attrs["data-diagonals"] = JSON.stringify(node.attrs["diagonals"]);
|
|
390
417
|
if (node.attrs["padding"])
|
|
391
418
|
attrs["data-padding"] = JSON.stringify(node.attrs["padding"]);
|
|
392
419
|
if (node.attrs["carry"])
|
|
@@ -505,6 +532,29 @@ var schema = new Schema({
|
|
|
505
532
|
0
|
|
506
533
|
]
|
|
507
534
|
},
|
|
535
|
+
// w:kern — the smallest font size (HALF-POINTS) that gets pair kerning.
|
|
536
|
+
// A threshold, not a switch: whether it bites depends on the run's own
|
|
537
|
+
// size, so the declared number is what the model keeps and the layout
|
|
538
|
+
// compares. No DOM representation — CSS font-kerning cannot express a
|
|
539
|
+
// size threshold, so an external paste simply has no opinion.
|
|
540
|
+
kern: {
|
|
541
|
+
attrs: { halfPoints: {} },
|
|
542
|
+
parseDOM: [
|
|
543
|
+
{
|
|
544
|
+
tag: "span[data-kern]",
|
|
545
|
+
getAttrs: (el) => {
|
|
546
|
+
const raw = el.getAttribute("data-kern");
|
|
547
|
+
const n = Number(raw);
|
|
548
|
+
return Number.isFinite(n) ? { halfPoints: n } : false;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
],
|
|
552
|
+
toDOM: (mark) => [
|
|
553
|
+
"span",
|
|
554
|
+
{ "data-kern": String(mark.attrs["halfPoints"]) },
|
|
555
|
+
0
|
|
556
|
+
]
|
|
557
|
+
},
|
|
508
558
|
// w:w — horizontal glyph scale as a PERCENT (100 = normal). Squeezes the
|
|
509
559
|
// glyphs and their advances; independent of letterSpacing, which rides on
|
|
510
560
|
// top at its absolute value.
|
|
@@ -585,7 +635,11 @@ var schema = new Schema({
|
|
|
585
635
|
},
|
|
586
636
|
// w:hyperlink — external URL or "#anchor"
|
|
587
637
|
link: {
|
|
588
|
-
|
|
638
|
+
// w:hyperlink @w:tgtFrame — the frame the link was meant to open in
|
|
639
|
+
// ("_blank", "_top", or a frame name), from the HTML-frames era. There
|
|
640
|
+
// is no frame here to obey it and nothing acts on it; it is modelled so
|
|
641
|
+
// that saving the file gives the attribute back instead of dropping it.
|
|
642
|
+
attrs: { href: {}, targetFrame: { default: null } },
|
|
589
643
|
inclusive: false,
|
|
590
644
|
parseDOM: [{ tag: "a[href]", getAttrs: pastedLinkAttrs }],
|
|
591
645
|
toDOM(mark) {
|
|
@@ -594,7 +648,8 @@ var schema = new Schema({
|
|
|
594
648
|
{
|
|
595
649
|
href: mark.attrs["href"],
|
|
596
650
|
rel: "noopener",
|
|
597
|
-
target: "_blank"
|
|
651
|
+
target: "_blank",
|
|
652
|
+
...mark.attrs["targetFrame"] ? { "data-target-frame": String(mark.attrs["targetFrame"]) } : {}
|
|
598
653
|
},
|
|
599
654
|
0
|
|
600
655
|
];
|
package/dist/lib/model.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { Schema } from 'prosemirror-model';
|
|
|
8
8
|
* extend THIS schema so the importer, layout engine, and (canvas) painter all
|
|
9
9
|
* agree on one document model.
|
|
10
10
|
*/
|
|
11
|
-
export declare const schema: Schema<"paragraph" | "doc" | "text" | "hard_break" | "image" | "page_field" | "table" | "table_row" | "table_cell", "strong" | "em" | "underline" | "strike" | "dstrike" | "smallCaps" | "textColor" | "fontSize" | "vertAlign" | "letterSpacing" | "charScale" | "position" | "highlight" | "fontFamily" | "link" | "footnote" | "carryRPr">;
|
|
11
|
+
export declare const schema: Schema<"paragraph" | "doc" | "text" | "hard_break" | "image" | "page_field" | "table" | "table_row" | "table_cell", "strong" | "em" | "underline" | "strike" | "dstrike" | "smallCaps" | "textColor" | "fontSize" | "vertAlign" | "letterSpacing" | "kern" | "charScale" | "position" | "highlight" | "fontFamily" | "link" | "footnote" | "carryRPr">;
|
|
12
12
|
/** Concrete schema type, handy for typing Node/Mark across packages. */
|
|
13
13
|
export type BapbongSchema = typeof schema;
|
|
14
14
|
/**
|
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;AAwF3C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,wVA+mBjB,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"}
|