@haklex/rich-litexml 0.0.94

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.
@@ -0,0 +1,3 @@
1
+ import { LitexmlRegistry } from './registry';
2
+ export declare function createDefaultRegistry(): LitexmlRegistry;
3
+ //# sourceMappingURL=default-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-registry.d.ts","sourceRoot":"","sources":["../src/default-registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI7C,wBAAgB,qBAAqB,IAAI,eAAe,CAOvD"}
@@ -0,0 +1,5 @@
1
+ import { SerializedEditorState, SerializedLexicalNode } from 'lexical';
2
+ import { LitexmlRegistry } from './registry';
3
+ export declare function deserializeFromXml(xml: string, registry: LitexmlRegistry): SerializedEditorState;
4
+ export declare function deserializeNodesFromXml(xml: string, registry: LitexmlRegistry): SerializedLexicalNode[];
5
+ //# sourceMappingURL=deserializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deserializer.d.ts","sourceRoot":"","sources":["../src/deserializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAG5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAUlD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,qBAAqB,CAkBhG;AAED,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,eAAe,GACxB,qBAAqB,EAAE,CAKzB"}
@@ -0,0 +1,12 @@
1
+ export { createDefaultRegistry } from './default-registry';
2
+ export { deserializeFromXml, deserializeNodesFromXml } from './deserializer';
3
+ export { registerBuiltinReaders } from './readers/builtin';
4
+ export { registerCustomReaders } from './readers/custom';
5
+ export { LitexmlRegistry } from './registry';
6
+ export type { XmlSerializerOptions } from './serializer';
7
+ export { serializeNodesToXml, serializeToXml } from './serializer';
8
+ export type { ReaderContext, WriterContext, XmlContent, XmlElement, XmlReaderFn, XmlWriterFn, } from './types';
9
+ export { registerBuiltinWriters } from './writers/builtin';
10
+ export { registerCustomWriters } from './writers/custom';
11
+ export type { XmlRenderOptions } from './xml-utils';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnE,YAAY,EACV,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,WAAW,EACX,WAAW,GACZ,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.mjs ADDED
@@ -0,0 +1,1096 @@
1
+ import { parseHTML } from "linkedom";
2
+ function extractBlockId$1(el) {
3
+ const id = el.getAttribute("id");
4
+ return id ? { $: { blockId: id } } : {};
5
+ }
6
+ const ELEMENT_DEFAULTS = {
7
+ direction: "ltr",
8
+ format: "",
9
+ indent: 0,
10
+ textFormat: 0,
11
+ textStyle: "",
12
+ version: 1
13
+ };
14
+ function registerBuiltinReaders(registry) {
15
+ registry.registerReader(
16
+ "p",
17
+ (el, ctx) => ({
18
+ type: "paragraph",
19
+ ...extractBlockId$1(el),
20
+ children: ctx.parseChildren(el),
21
+ ...ELEMENT_DEFAULTS
22
+ })
23
+ );
24
+ for (let level = 1; level <= 6; level++) {
25
+ registry.registerReader(
26
+ `h${level}`,
27
+ (el, ctx) => ({
28
+ type: "heading",
29
+ tag: `h${level}`,
30
+ ...extractBlockId$1(el),
31
+ children: ctx.parseChildren(el),
32
+ ...ELEMENT_DEFAULTS
33
+ })
34
+ );
35
+ }
36
+ registry.registerReader(
37
+ "blockquote",
38
+ (el, ctx) => ({
39
+ type: "quote",
40
+ ...extractBlockId$1(el),
41
+ children: ctx.parseChildren(el),
42
+ ...ELEMENT_DEFAULTS
43
+ })
44
+ );
45
+ registry.registerReader(
46
+ "hr",
47
+ (el) => ({
48
+ type: "horizontalrule",
49
+ ...extractBlockId$1(el),
50
+ version: 1
51
+ })
52
+ );
53
+ registry.registerReader("ul", (el, ctx) => {
54
+ const isCheck = el.getAttribute("type") === "check";
55
+ return {
56
+ type: "list",
57
+ listType: isCheck ? "check" : "bullet",
58
+ tag: "ul",
59
+ start: 1,
60
+ ...extractBlockId$1(el),
61
+ children: ctx.parseChildren(el),
62
+ direction: "ltr",
63
+ format: "",
64
+ indent: 0,
65
+ version: 1
66
+ };
67
+ });
68
+ registry.registerReader(
69
+ "ol",
70
+ (el, ctx) => ({
71
+ type: "list",
72
+ listType: "number",
73
+ tag: "ol",
74
+ start: Number(el.getAttribute("start") ?? 1),
75
+ ...extractBlockId$1(el),
76
+ children: ctx.parseChildren(el),
77
+ direction: "ltr",
78
+ format: "",
79
+ indent: 0,
80
+ version: 1
81
+ })
82
+ );
83
+ registry.registerReader("li", (el, ctx) => {
84
+ const checked = el.getAttribute("checked");
85
+ return {
86
+ type: "listitem",
87
+ ...extractBlockId$1(el),
88
+ ...checked !== null ? { checked: checked === "true" } : {},
89
+ children: ctx.parseChildren(el),
90
+ ...ELEMENT_DEFAULTS,
91
+ value: 1
92
+ };
93
+ });
94
+ registry.registerReader(
95
+ "a",
96
+ (el, ctx) => ({
97
+ type: "link",
98
+ url: el.getAttribute("href") ?? "",
99
+ target: el.getAttribute("target") ?? null,
100
+ title: el.getAttribute("title") ?? null,
101
+ rel: null,
102
+ children: ctx.parseChildren(el),
103
+ direction: "ltr",
104
+ format: "",
105
+ indent: 0,
106
+ version: 1
107
+ })
108
+ );
109
+ registry.registerReader(
110
+ "table",
111
+ (el, ctx) => ({
112
+ type: "table",
113
+ ...extractBlockId$1(el),
114
+ children: ctx.parseChildren(el),
115
+ direction: "ltr",
116
+ format: "",
117
+ indent: 0,
118
+ version: 1
119
+ })
120
+ );
121
+ registry.registerReader(
122
+ "tr",
123
+ (el, ctx) => ({
124
+ type: "tablerow",
125
+ children: ctx.parseChildren(el),
126
+ direction: "ltr",
127
+ format: "",
128
+ indent: 0,
129
+ version: 1
130
+ })
131
+ );
132
+ registry.registerReader(
133
+ "th",
134
+ (el, ctx) => ({
135
+ type: "tablecell",
136
+ headerState: 1,
137
+ children: ctx.parseChildren(el),
138
+ direction: "ltr",
139
+ format: "",
140
+ indent: 0,
141
+ version: 1
142
+ })
143
+ );
144
+ registry.registerReader(
145
+ "td",
146
+ (el, ctx) => ({
147
+ type: "tablecell",
148
+ headerState: 0,
149
+ children: ctx.parseChildren(el),
150
+ direction: "ltr",
151
+ format: "",
152
+ indent: 0,
153
+ version: 1
154
+ })
155
+ );
156
+ }
157
+ function extractBlockId(el) {
158
+ const id = el.getAttribute("id");
159
+ return id ? { $: { blockId: id } } : {};
160
+ }
161
+ function numAttr(el, name) {
162
+ const v = el.getAttribute(name);
163
+ return v !== null ? Number(v) : void 0;
164
+ }
165
+ function registerCustomReaders(registry) {
166
+ registry.registerReader("img", (el) => {
167
+ if (el.parentElement?.tagName.toLowerCase() === "gallery") return false;
168
+ return {
169
+ type: "image",
170
+ ...extractBlockId(el),
171
+ src: el.getAttribute("src") ?? "",
172
+ altText: el.getAttribute("alt") ?? "",
173
+ width: numAttr(el, "width"),
174
+ height: numAttr(el, "height"),
175
+ caption: el.getAttribute("caption") ?? void 0,
176
+ thumbhash: el.getAttribute("thumbhash") ?? void 0,
177
+ accent: el.getAttribute("accent") ?? void 0,
178
+ version: 1
179
+ };
180
+ });
181
+ registry.registerReader(
182
+ "video",
183
+ (el) => ({
184
+ type: "video",
185
+ ...extractBlockId(el),
186
+ src: el.getAttribute("src") ?? "",
187
+ poster: el.getAttribute("poster") ?? void 0,
188
+ width: numAttr(el, "width"),
189
+ height: numAttr(el, "height"),
190
+ version: 1
191
+ })
192
+ );
193
+ registry.registerReader(
194
+ "linkcard",
195
+ (el) => ({
196
+ type: "link-card",
197
+ ...extractBlockId(el),
198
+ url: el.getAttribute("url") ?? "",
199
+ source: el.getAttribute("source") ?? void 0,
200
+ title: el.getAttribute("title") ?? void 0,
201
+ description: el.getAttribute("description") ?? void 0,
202
+ favicon: el.getAttribute("favicon") ?? void 0,
203
+ image: el.getAttribute("image") ?? void 0,
204
+ version: 1
205
+ })
206
+ );
207
+ registry.registerReader(
208
+ "embed",
209
+ (el) => ({
210
+ type: "embed",
211
+ ...extractBlockId(el),
212
+ url: el.getAttribute("url") ?? "",
213
+ source: el.getAttribute("source") ?? null,
214
+ version: 1
215
+ })
216
+ );
217
+ registry.registerReader(
218
+ "codeblock",
219
+ (el) => ({
220
+ type: "code-block",
221
+ ...extractBlockId(el),
222
+ code: el.textContent ?? "",
223
+ language: el.getAttribute("lang") ?? "",
224
+ version: 1
225
+ })
226
+ );
227
+ registry.registerReader(
228
+ "mermaid",
229
+ (el) => ({
230
+ type: "mermaid",
231
+ ...extractBlockId(el),
232
+ diagram: el.textContent ?? "",
233
+ version: 1
234
+ })
235
+ );
236
+ registry.registerReader("math", (el) => {
237
+ const display = el.getAttribute("display");
238
+ if (display === "block") {
239
+ return {
240
+ type: "katex-block",
241
+ ...extractBlockId(el),
242
+ equation: el.textContent ?? "",
243
+ version: 1
244
+ };
245
+ }
246
+ return {
247
+ type: "katex-inline",
248
+ equation: el.textContent ?? "",
249
+ version: 1
250
+ };
251
+ });
252
+ registry.registerReader("alert", (el, ctx) => {
253
+ const children = ctx.parseChildren(el);
254
+ const content = {
255
+ root: {
256
+ type: "root",
257
+ children,
258
+ direction: "ltr",
259
+ format: "",
260
+ indent: 0,
261
+ version: 1
262
+ }
263
+ };
264
+ return {
265
+ type: "alert-quote",
266
+ ...extractBlockId(el),
267
+ alertType: el.getAttribute("type") ?? "note",
268
+ content,
269
+ version: 1
270
+ };
271
+ });
272
+ registry.registerReader("banner", (el, ctx) => {
273
+ const children = ctx.parseChildren(el);
274
+ const content = {
275
+ root: {
276
+ type: "root",
277
+ children,
278
+ direction: "ltr",
279
+ format: "",
280
+ indent: 0,
281
+ version: 1
282
+ }
283
+ };
284
+ return {
285
+ type: "banner",
286
+ ...extractBlockId(el),
287
+ bannerType: el.getAttribute("type") ?? "note",
288
+ content,
289
+ version: 1
290
+ };
291
+ });
292
+ registry.registerReader("nesteddoc", (el, ctx) => {
293
+ const children = ctx.parseChildren(el);
294
+ const content = {
295
+ root: {
296
+ type: "root",
297
+ children,
298
+ direction: "ltr",
299
+ format: "",
300
+ indent: 0,
301
+ version: 1
302
+ }
303
+ };
304
+ return {
305
+ type: "nested-doc",
306
+ ...extractBlockId(el),
307
+ content,
308
+ version: 1
309
+ };
310
+ });
311
+ registry.registerReader(
312
+ "details",
313
+ (el, ctx) => ({
314
+ type: "details",
315
+ ...extractBlockId(el),
316
+ summary: el.getAttribute("summary") ?? "",
317
+ open: el.getAttribute("open") === "true",
318
+ children: ctx.parseChildren(el),
319
+ direction: "ltr",
320
+ format: "",
321
+ indent: 0,
322
+ version: 1
323
+ })
324
+ );
325
+ registry.registerReader(
326
+ "spoiler",
327
+ (el, ctx) => ({
328
+ type: "spoiler",
329
+ children: ctx.parseChildren(el),
330
+ direction: "ltr",
331
+ format: "",
332
+ indent: 0,
333
+ textFormat: 0,
334
+ textStyle: "",
335
+ version: 1
336
+ })
337
+ );
338
+ registry.registerReader(
339
+ "ruby",
340
+ (el, ctx) => ({
341
+ type: "ruby",
342
+ reading: el.getAttribute("rt") ?? "",
343
+ children: ctx.parseChildren(el),
344
+ direction: "ltr",
345
+ format: "",
346
+ indent: 0,
347
+ textFormat: 0,
348
+ textStyle: "",
349
+ version: 1
350
+ })
351
+ );
352
+ registry.registerReader(
353
+ "mention",
354
+ (el) => ({
355
+ type: "mention",
356
+ platform: el.getAttribute("platform") ?? "",
357
+ handle: el.getAttribute("handle") ?? "",
358
+ displayName: el.textContent || void 0,
359
+ version: 1
360
+ })
361
+ );
362
+ registry.registerReader(
363
+ "tag",
364
+ (el) => ({
365
+ type: "tag",
366
+ text: el.textContent ?? "",
367
+ format: 0,
368
+ detail: 0,
369
+ mode: "normal",
370
+ style: "",
371
+ version: 1
372
+ })
373
+ );
374
+ registry.registerReader(
375
+ "comment",
376
+ (el) => ({
377
+ type: "comment",
378
+ text: el.textContent ?? "",
379
+ format: 0,
380
+ detail: 0,
381
+ mode: "normal",
382
+ style: "",
383
+ version: 1
384
+ })
385
+ );
386
+ registry.registerReader(
387
+ "footnote",
388
+ (el) => ({
389
+ type: "footnote",
390
+ identifier: el.getAttribute("ref") ?? "",
391
+ version: 1
392
+ })
393
+ );
394
+ registry.registerReader("footnotesection", (el) => {
395
+ const definitions = {};
396
+ for (const child of el.children) {
397
+ if (child.tagName.toLowerCase() === "def") {
398
+ const ref = child.getAttribute("ref") ?? "";
399
+ definitions[ref] = child.textContent ?? "";
400
+ }
401
+ }
402
+ return {
403
+ type: "footnote-section",
404
+ ...extractBlockId(el),
405
+ definitions,
406
+ version: 1
407
+ };
408
+ });
409
+ registry.registerReader("gallery", (el) => {
410
+ const images = [];
411
+ for (const child of el.children) {
412
+ if (child.tagName.toLowerCase() === "img") {
413
+ images.push({
414
+ src: child.getAttribute("src") ?? "",
415
+ alt: child.getAttribute("alt") ?? void 0
416
+ });
417
+ }
418
+ }
419
+ return {
420
+ type: "gallery",
421
+ ...extractBlockId(el),
422
+ images,
423
+ layout: el.getAttribute("layout") ?? "grid",
424
+ version: 1
425
+ };
426
+ });
427
+ registry.registerReader("codesnippet", (el) => {
428
+ const files = [];
429
+ for (const child of el.children) {
430
+ if (child.tagName.toLowerCase() === "file") {
431
+ files.push({
432
+ filename: child.getAttribute("name") ?? "",
433
+ code: child.textContent ?? "",
434
+ language: child.getAttribute("lang") ?? ""
435
+ });
436
+ }
437
+ }
438
+ return {
439
+ type: "code-snippet",
440
+ ...extractBlockId(el),
441
+ files,
442
+ version: 1
443
+ };
444
+ });
445
+ }
446
+ class LitexmlRegistry {
447
+ constructor() {
448
+ this.writers = /* @__PURE__ */ new Map();
449
+ this.readers = /* @__PURE__ */ new Map();
450
+ }
451
+ registerWriter(nodeType, writer) {
452
+ this.writers.set(nodeType, writer);
453
+ }
454
+ registerReader(tagName, reader) {
455
+ this.readers.set(tagName.toLowerCase(), reader);
456
+ }
457
+ getWriter(nodeType) {
458
+ return this.writers.get(nodeType);
459
+ }
460
+ getReader(tagName) {
461
+ return this.readers.get(tagName.toLowerCase());
462
+ }
463
+ }
464
+ function blockId$1(node) {
465
+ return node.$?.blockId ? { id: node.$.blockId } : {};
466
+ }
467
+ function registerBuiltinWriters(registry) {
468
+ registry.registerWriter("paragraph", (node, ctx) => {
469
+ const n = node;
470
+ return {
471
+ tag: "p",
472
+ attrs: blockId$1(n),
473
+ children: ctx.serializeChildren(n.children ?? [])
474
+ };
475
+ });
476
+ registry.registerWriter("heading", (node, ctx) => {
477
+ const n = node;
478
+ const tag = n.tag ?? "h1";
479
+ return {
480
+ tag,
481
+ attrs: blockId$1(n),
482
+ children: ctx.serializeChildren(n.children ?? [])
483
+ };
484
+ });
485
+ registry.registerWriter("quote", (node, ctx) => {
486
+ const n = node;
487
+ return {
488
+ tag: "blockquote",
489
+ attrs: blockId$1(n),
490
+ children: ctx.serializeChildren(n.children ?? [])
491
+ };
492
+ });
493
+ registry.registerWriter("horizontalrule", (node) => {
494
+ const n = node;
495
+ return { tag: "hr", attrs: blockId$1(n), selfClosing: true };
496
+ });
497
+ registry.registerWriter("list", (node, ctx) => {
498
+ const n = node;
499
+ const tag = n.listType === "number" ? "ol" : "ul";
500
+ const attrs = { ...blockId$1(n) };
501
+ if (n.listType === "check") attrs.type = "check";
502
+ return {
503
+ tag,
504
+ attrs,
505
+ children: ctx.serializeChildren(n.children ?? [])
506
+ };
507
+ });
508
+ registry.registerWriter("listitem", (node, ctx) => {
509
+ const n = node;
510
+ const attrs = { ...blockId$1(n) };
511
+ if (n.checked !== void 0) attrs.checked = String(n.checked);
512
+ return {
513
+ tag: "li",
514
+ attrs,
515
+ children: ctx.serializeChildren(n.children ?? [])
516
+ };
517
+ });
518
+ registry.registerWriter("link", (node, ctx) => {
519
+ const n = node;
520
+ const attrs = { href: n.url ?? "" };
521
+ if (n.target) attrs.target = n.target;
522
+ if (n.title) attrs.title = n.title;
523
+ return {
524
+ tag: "a",
525
+ attrs,
526
+ children: ctx.serializeChildren(n.children ?? [])
527
+ };
528
+ });
529
+ registry.registerWriter("autolink", (node, ctx) => {
530
+ const n = node;
531
+ return {
532
+ tag: "a",
533
+ attrs: { href: n.url ?? "" },
534
+ children: ctx.serializeChildren(n.children ?? [])
535
+ };
536
+ });
537
+ registry.registerWriter("table", (node, ctx) => {
538
+ const n = node;
539
+ return {
540
+ tag: "table",
541
+ attrs: blockId$1(n),
542
+ children: ctx.serializeChildren(n.children ?? [])
543
+ };
544
+ });
545
+ registry.registerWriter("tablerow", (node, ctx) => {
546
+ const n = node;
547
+ return {
548
+ tag: "tr",
549
+ children: ctx.serializeChildren(n.children ?? [])
550
+ };
551
+ });
552
+ registry.registerWriter("tablecell", (node, ctx) => {
553
+ const n = node;
554
+ const tag = n.headerState === 1 ? "th" : "td";
555
+ return {
556
+ tag,
557
+ children: ctx.serializeChildren(n.children ?? [])
558
+ };
559
+ });
560
+ }
561
+ function blockId(node) {
562
+ return node.$?.blockId ? { id: node.$.blockId } : {};
563
+ }
564
+ function optAttr(attrs) {
565
+ const result = {};
566
+ for (const [k, v] of Object.entries(attrs)) {
567
+ if (v !== void 0 && v !== null && v !== "") result[k] = String(v);
568
+ }
569
+ return result;
570
+ }
571
+ function registerCustomWriters(registry) {
572
+ registry.registerWriter("image", (node) => {
573
+ const n = node;
574
+ return {
575
+ tag: "img",
576
+ attrs: optAttr({
577
+ ...blockId(n),
578
+ src: n.src,
579
+ alt: n.altText,
580
+ width: n.width != null ? String(n.width) : void 0,
581
+ height: n.height != null ? String(n.height) : void 0,
582
+ caption: n.caption,
583
+ thumbhash: n.thumbhash,
584
+ accent: n.accent
585
+ }),
586
+ selfClosing: true
587
+ };
588
+ });
589
+ registry.registerWriter("video", (node) => {
590
+ const n = node;
591
+ return {
592
+ tag: "video",
593
+ attrs: optAttr({ ...blockId(n), src: n.src, poster: n.poster }),
594
+ selfClosing: true
595
+ };
596
+ });
597
+ registry.registerWriter("link-card", (node) => {
598
+ const n = node;
599
+ return {
600
+ tag: "linkcard",
601
+ attrs: optAttr({
602
+ ...blockId(n),
603
+ url: n.url,
604
+ source: n.source,
605
+ title: n.title,
606
+ description: n.description,
607
+ favicon: n.favicon,
608
+ image: n.image
609
+ }),
610
+ selfClosing: true
611
+ };
612
+ });
613
+ registry.registerWriter("embed", (node) => {
614
+ const n = node;
615
+ return {
616
+ tag: "embed",
617
+ attrs: optAttr({ ...blockId(n), url: n.url, source: n.source }),
618
+ selfClosing: true
619
+ };
620
+ });
621
+ registry.registerWriter("code-block", (node) => {
622
+ const n = node;
623
+ return {
624
+ tag: "codeblock",
625
+ attrs: optAttr({ ...blockId(n), lang: n.language }),
626
+ children: [n.code ?? ""]
627
+ };
628
+ });
629
+ registry.registerWriter("mermaid", (node) => {
630
+ const n = node;
631
+ return {
632
+ tag: "mermaid",
633
+ attrs: blockId(n),
634
+ children: [n.diagram ?? ""]
635
+ };
636
+ });
637
+ registry.registerWriter("katex-block", (node) => {
638
+ const n = node;
639
+ return {
640
+ tag: "math",
641
+ attrs: { ...blockId(n), display: "block" },
642
+ children: [n.equation ?? ""]
643
+ };
644
+ });
645
+ registry.registerWriter("katex-inline", (node) => {
646
+ const n = node;
647
+ return {
648
+ tag: "math",
649
+ children: [n.equation ?? ""]
650
+ };
651
+ });
652
+ registry.registerWriter("alert-quote", (node, ctx) => {
653
+ const n = node;
654
+ return {
655
+ tag: "alert",
656
+ attrs: optAttr({ ...blockId(n), type: n.alertType }),
657
+ children: ctx.serializeNestedState(n.content)
658
+ };
659
+ });
660
+ registry.registerWriter("banner", (node, ctx) => {
661
+ const n = node;
662
+ return {
663
+ tag: "banner",
664
+ attrs: optAttr({ ...blockId(n), type: n.bannerType }),
665
+ children: ctx.serializeNestedState(n.content)
666
+ };
667
+ });
668
+ registry.registerWriter("nested-doc", (node, ctx) => {
669
+ const n = node;
670
+ return {
671
+ tag: "nesteddoc",
672
+ attrs: blockId(n),
673
+ children: ctx.serializeNestedState(n.content ?? n.contentState)
674
+ };
675
+ });
676
+ registry.registerWriter("details", (node, ctx) => {
677
+ const n = node;
678
+ return {
679
+ tag: "details",
680
+ attrs: optAttr({
681
+ ...blockId(n),
682
+ summary: n.summary,
683
+ open: n.open != null ? String(n.open) : void 0
684
+ }),
685
+ children: ctx.serializeChildren(n.children ?? [])
686
+ };
687
+ });
688
+ registry.registerWriter("spoiler", (node, ctx) => {
689
+ const n = node;
690
+ return {
691
+ tag: "spoiler",
692
+ children: ctx.serializeChildren(n.children ?? [])
693
+ };
694
+ });
695
+ registry.registerWriter("ruby", (node, ctx) => {
696
+ const n = node;
697
+ return {
698
+ tag: "ruby",
699
+ attrs: optAttr({ rt: n.reading }),
700
+ children: ctx.serializeChildren(n.children ?? [])
701
+ };
702
+ });
703
+ registry.registerWriter("mention", (node) => {
704
+ const n = node;
705
+ return {
706
+ tag: "mention",
707
+ attrs: optAttr({ platform: n.platform, handle: n.handle }),
708
+ children: [n.displayName ?? n.handle ?? ""]
709
+ };
710
+ });
711
+ registry.registerWriter("tag", (node) => {
712
+ const n = node;
713
+ return { tag: "tag", children: [n.text ?? ""] };
714
+ });
715
+ registry.registerWriter("comment", (node) => {
716
+ const n = node;
717
+ return { tag: "comment", children: [n.text ?? ""] };
718
+ });
719
+ registry.registerWriter("footnote", (node) => {
720
+ const n = node;
721
+ return { tag: "footnote", attrs: { ref: n.identifier ?? "" }, selfClosing: true };
722
+ });
723
+ registry.registerWriter("footnote-section", (node) => {
724
+ const n = node;
725
+ const defs = n.definitions ?? {};
726
+ const children = Object.entries(defs).map(([ref, text]) => ({
727
+ tag: "def",
728
+ attrs: { ref },
729
+ children: [text]
730
+ }));
731
+ return { tag: "footnotesection", attrs: blockId(n), children };
732
+ });
733
+ registry.registerWriter("gallery", (node) => {
734
+ const n = node;
735
+ const images = (n.images ?? []).map((img) => ({
736
+ tag: "img",
737
+ attrs: optAttr({ src: img.src, alt: img.alt }),
738
+ selfClosing: true
739
+ }));
740
+ return {
741
+ tag: "gallery",
742
+ attrs: optAttr({ ...blockId(n), layout: n.layout }),
743
+ children: images
744
+ };
745
+ });
746
+ registry.registerWriter("code-snippet", (node) => {
747
+ const n = node;
748
+ const files = (n.files ?? []).map((f) => ({
749
+ tag: "file",
750
+ attrs: optAttr({ name: f.filename, lang: f.language }),
751
+ children: [f.code ?? ""]
752
+ }));
753
+ return { tag: "codesnippet", attrs: blockId(n), children: files };
754
+ });
755
+ }
756
+ function createDefaultRegistry() {
757
+ const registry = new LitexmlRegistry();
758
+ registerBuiltinWriters(registry);
759
+ registerBuiltinReaders(registry);
760
+ registerCustomWriters(registry);
761
+ registerCustomReaders(registry);
762
+ return registry;
763
+ }
764
+ const FORMAT_BIT_TO_TAG = [
765
+ [1, "b"],
766
+ [2, "i"],
767
+ [4, "s"],
768
+ [8, "u"],
769
+ [16, "code"],
770
+ [32, "sub"],
771
+ [64, "sup"],
772
+ [128, "mark"]
773
+ ];
774
+ const FORMAT_TAG_TO_BIT = {
775
+ b: 1,
776
+ strong: 1,
777
+ i: 2,
778
+ em: 2,
779
+ s: 4,
780
+ del: 4,
781
+ strike: 4,
782
+ u: 8,
783
+ code: 16,
784
+ sub: 32,
785
+ sup: 64,
786
+ mark: 128
787
+ };
788
+ function wrapWithFormatTags(text, format) {
789
+ if (format === 0) return [text];
790
+ let content = [text];
791
+ for (let idx = FORMAT_BIT_TO_TAG.length - 1; idx >= 0; idx--) {
792
+ const [bit, tag] = FORMAT_BIT_TO_TAG[idx];
793
+ if (format & bit) {
794
+ content = [{ tag, children: content }];
795
+ }
796
+ }
797
+ return content;
798
+ }
799
+ function isFormatTag(tagName) {
800
+ return tagName.toLowerCase() in FORMAT_TAG_TO_BIT;
801
+ }
802
+ function getFormatBit(tagName) {
803
+ return FORMAT_TAG_TO_BIT[tagName.toLowerCase()] ?? 0;
804
+ }
805
+ function parseXml(xml) {
806
+ const { document } = parseHTML(`<!DOCTYPE html><html><body>${xml}</body></html>`);
807
+ return document;
808
+ }
809
+ function deserializeFromXml(xml, registry) {
810
+ const doc = parseXml(xml);
811
+ const docEl = doc.querySelector("doc") ?? doc.body;
812
+ const ctx = createReaderContext(registry);
813
+ const children = ctx.parseChildren(docEl);
814
+ return {
815
+ root: {
816
+ type: "root",
817
+ children,
818
+ direction: "ltr",
819
+ format: "",
820
+ indent: 0,
821
+ version: 1
822
+ }
823
+ };
824
+ }
825
+ function deserializeNodesFromXml(xml, registry) {
826
+ const doc = parseXml(`<fragment>${xml}</fragment>`);
827
+ const fragment = doc.querySelector("fragment") ?? doc.body;
828
+ const ctx = createReaderContext(registry);
829
+ return ctx.parseChildren(fragment);
830
+ }
831
+ const BLOCK_TAGS = /* @__PURE__ */ new Set([
832
+ "doc",
833
+ "fragment",
834
+ "root",
835
+ "ul",
836
+ "ol",
837
+ "table",
838
+ "tr",
839
+ "alert",
840
+ "banner",
841
+ "details",
842
+ "nesteddoc",
843
+ "gallery",
844
+ "codesnippet",
845
+ "footnotesection"
846
+ ]);
847
+ function isBlockContainer(element) {
848
+ return BLOCK_TAGS.has(element.tagName.toLowerCase());
849
+ }
850
+ function createReaderContext(registry) {
851
+ const ctx = {
852
+ parseChildren(element) {
853
+ const blockLevel = isBlockContainer(element);
854
+ const nodes = [];
855
+ for (const child of element.childNodes) {
856
+ if (child.nodeType === 3) {
857
+ const text = child.textContent ?? "";
858
+ if (blockLevel && text.trim() === "") continue;
859
+ if (text === "") continue;
860
+ nodes.push(makeTextNode(text, 0));
861
+ } else if (child.nodeType === 1) {
862
+ const el = child;
863
+ const parsed = parseElement(el, registry, ctx, 0);
864
+ if (parsed) {
865
+ if (Array.isArray(parsed)) nodes.push(...parsed);
866
+ else nodes.push(parsed);
867
+ }
868
+ }
869
+ }
870
+ return nodes;
871
+ },
872
+ parseNestedState(xml) {
873
+ return deserializeFromXml(xml, registry);
874
+ }
875
+ };
876
+ return ctx;
877
+ }
878
+ function parseElement(element, registry, ctx, inheritedFormat) {
879
+ const tag = element.tagName.toLowerCase();
880
+ if (isFormatTag(tag)) {
881
+ const format = inheritedFormat | getFormatBit(tag);
882
+ return parseInlineChildren(element, registry, ctx, format);
883
+ }
884
+ if (tag === "br") {
885
+ return { type: "linebreak", version: 1 };
886
+ }
887
+ if (tag === "node") {
888
+ return parseFallbackNode(element);
889
+ }
890
+ const reader = registry.getReader(tag);
891
+ if (reader) {
892
+ const result = reader(element, ctx);
893
+ if (result !== false) return result;
894
+ }
895
+ return ctx.parseChildren(element);
896
+ }
897
+ function parseInlineChildren(element, registry, ctx, format) {
898
+ const nodes = [];
899
+ for (const child of element.childNodes) {
900
+ if (child.nodeType === 3) {
901
+ const text = child.textContent ?? "";
902
+ if (text === "") continue;
903
+ nodes.push(makeTextNode(text, format));
904
+ } else if (child.nodeType === 1) {
905
+ const el = child;
906
+ const parsed = parseElement(el, registry, ctx, format);
907
+ if (parsed) {
908
+ if (Array.isArray(parsed)) nodes.push(...parsed);
909
+ else nodes.push(parsed);
910
+ }
911
+ }
912
+ }
913
+ return nodes;
914
+ }
915
+ function parseFallbackNode(element) {
916
+ const type = element.getAttribute("type") ?? "unknown";
917
+ const id = element.getAttribute("id");
918
+ const dataStr = element.getAttribute("data");
919
+ const data = dataStr ? JSON.parse(dataStr) : {};
920
+ return {
921
+ type,
922
+ ...id ? { $: { blockId: id } } : {},
923
+ ...data,
924
+ version: 1
925
+ };
926
+ }
927
+ function makeTextNode(text, format) {
928
+ return {
929
+ type: "text",
930
+ text,
931
+ format,
932
+ detail: 0,
933
+ mode: "normal",
934
+ style: "",
935
+ version: 1
936
+ };
937
+ }
938
+ const ESCAPE_MAP = {
939
+ "&": "&amp;",
940
+ "<": "&lt;",
941
+ ">": "&gt;",
942
+ '"': "&quot;",
943
+ "'": "&apos;"
944
+ };
945
+ function escapeXml(text) {
946
+ return text.replaceAll(/["&'<>]/g, (ch) => ESCAPE_MAP[ch]);
947
+ }
948
+ function buildAttrs(attrs) {
949
+ const parts = Object.entries(attrs).filter(([, v]) => v !== void 0 && v !== "").map(([k, v]) => ` ${k}="${escapeXml(v)}"`);
950
+ return parts.join("");
951
+ }
952
+ function renderXml(content, indent = 0, options = {}) {
953
+ const lines = [];
954
+ for (const item of content) {
955
+ if (typeof item === "string") {
956
+ lines.push(escapeXml(item));
957
+ } else {
958
+ lines.push(renderElement(item, indent, options));
959
+ }
960
+ }
961
+ return lines.join("");
962
+ }
963
+ function renderElement(el, indent, options) {
964
+ const attrs = el.attrs ? buildAttrs(el.attrs) : "";
965
+ const compact = options.compact === true;
966
+ if (el.selfClosing) {
967
+ return compact ? `<${el.tag}${attrs} />` : `${pad(indent)}<${el.tag}${attrs} />
968
+ `;
969
+ }
970
+ if (!el.children || el.children.length === 0) {
971
+ return compact ? `<${el.tag}${attrs} />` : `${pad(indent)}<${el.tag}${attrs} />
972
+ `;
973
+ }
974
+ const allInline = el.children.every((c) => typeof c === "string" || isInlineElement(c));
975
+ if (allInline) {
976
+ const inner2 = el.children.map((c) => typeof c === "string" ? escapeXml(c) : renderInline(c)).join("");
977
+ return compact ? `<${el.tag}${attrs}>${inner2}</${el.tag}>` : `${pad(indent)}<${el.tag}${attrs}>${inner2}</${el.tag}>
978
+ `;
979
+ }
980
+ if (compact) {
981
+ const inner2 = el.children.map((c) => typeof c === "string" ? escapeXml(c) : renderElement(c, indent + 1, options)).join("");
982
+ return `<${el.tag}${attrs}>${inner2}</${el.tag}>`;
983
+ }
984
+ const inner = el.children.map((c) => {
985
+ if (typeof c === "string") return `${pad(indent + 1)}${escapeXml(c)}
986
+ `;
987
+ return renderElement(c, indent + 1, options);
988
+ }).join("");
989
+ return `${pad(indent)}<${el.tag}${attrs}>
990
+ ${inner}${pad(indent)}</${el.tag}>
991
+ `;
992
+ }
993
+ function renderInline(el) {
994
+ const attrs = el.attrs ? buildAttrs(el.attrs) : "";
995
+ if (el.selfClosing || !el.children || el.children.length === 0) {
996
+ return `<${el.tag}${attrs} />`;
997
+ }
998
+ const inner = el.children.map((c) => typeof c === "string" ? escapeXml(c) : renderInline(c)).join("");
999
+ return `<${el.tag}${attrs}>${inner}</${el.tag}>`;
1000
+ }
1001
+ function isInlineElement(el) {
1002
+ const inlineTags = /* @__PURE__ */ new Set([
1003
+ "b",
1004
+ "i",
1005
+ "u",
1006
+ "s",
1007
+ "code",
1008
+ "sub",
1009
+ "sup",
1010
+ "mark",
1011
+ "strong",
1012
+ "em",
1013
+ "del",
1014
+ "a",
1015
+ "mention",
1016
+ "tag",
1017
+ "spoiler",
1018
+ "ruby",
1019
+ "math",
1020
+ "footnote",
1021
+ "comment"
1022
+ ]);
1023
+ return inlineTags.has(el.tag);
1024
+ }
1025
+ function pad(indent) {
1026
+ return " ".repeat(indent);
1027
+ }
1028
+ function serializeToXml(state, registry, options = {}) {
1029
+ const root = state.root;
1030
+ const children = root.children ?? [];
1031
+ const ctx = createWriterContext(registry);
1032
+ const content = children.flatMap((child) => ctx.serializeNode(child));
1033
+ if (options.compact) {
1034
+ return `<doc>${renderXml(content, 0, options)}</doc>`;
1035
+ }
1036
+ return `<doc>
1037
+ ${renderXml(content, 1, options)}</doc>
1038
+ `;
1039
+ }
1040
+ function serializeNodesToXml(nodes, registry, options = {}) {
1041
+ const ctx = createWriterContext(registry);
1042
+ const content = nodes.flatMap((node) => ctx.serializeNode(node));
1043
+ return renderXml(content, 0, options);
1044
+ }
1045
+ function createWriterContext(registry) {
1046
+ const ctx = {
1047
+ serializeChildren(children) {
1048
+ return children.flatMap((child) => ctx.serializeNode(child));
1049
+ },
1050
+ serializeNode(node) {
1051
+ const n = node;
1052
+ if (n.type === "text") {
1053
+ return wrapWithFormatTags(n.text ?? "", n.format ?? 0);
1054
+ }
1055
+ if (n.type === "linebreak") {
1056
+ return { tag: "br", selfClosing: true };
1057
+ }
1058
+ const writer = registry.getWriter(n.type);
1059
+ if (writer) {
1060
+ const result = writer(node, ctx);
1061
+ if (result !== false) return result;
1062
+ }
1063
+ return serializeFallback(node);
1064
+ },
1065
+ serializeNestedState(state) {
1066
+ const root = state.root;
1067
+ const children = root.children ?? [];
1068
+ return children.flatMap((child) => ctx.serializeNode(child));
1069
+ }
1070
+ };
1071
+ return ctx;
1072
+ }
1073
+ function serializeFallback(node) {
1074
+ const n = node;
1075
+ const blockId2 = n.$?.blockId;
1076
+ const { type, $: _meta, version: _v, ...rest } = n;
1077
+ const attrs = { type };
1078
+ if (blockId2) attrs.id = blockId2;
1079
+ const dataKeys = Object.keys(rest);
1080
+ if (dataKeys.length > 0) {
1081
+ attrs.data = JSON.stringify(rest);
1082
+ }
1083
+ return { tag: "node", attrs, selfClosing: true };
1084
+ }
1085
+ export {
1086
+ LitexmlRegistry,
1087
+ createDefaultRegistry,
1088
+ deserializeFromXml,
1089
+ deserializeNodesFromXml,
1090
+ registerBuiltinReaders,
1091
+ registerBuiltinWriters,
1092
+ registerCustomReaders,
1093
+ registerCustomWriters,
1094
+ serializeNodesToXml,
1095
+ serializeToXml
1096
+ };
@@ -0,0 +1,3 @@
1
+ import { LitexmlRegistry } from '../registry';
2
+ export declare function registerBuiltinReaders(registry: LitexmlRegistry): void;
3
+ //# sourceMappingURL=builtin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin.d.ts","sourceRoot":"","sources":["../../src/readers/builtin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgBnD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CA+KtE"}
@@ -0,0 +1,3 @@
1
+ import { LitexmlRegistry } from '../registry';
2
+ export declare function registerCustomReaders(registry: LitexmlRegistry): void;
3
+ //# sourceMappingURL=custom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/readers/custom.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAYnD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAmUrE"}
@@ -0,0 +1,10 @@
1
+ import { XmlReaderFn, XmlWriterFn } from './types';
2
+ export declare class LitexmlRegistry {
3
+ private writers;
4
+ private readers;
5
+ registerWriter(nodeType: string, writer: XmlWriterFn): void;
6
+ registerReader(tagName: string, reader: XmlReaderFn): void;
7
+ getWriter(nodeType: string): XmlWriterFn | undefined;
8
+ getReader(tagName: string): XmlReaderFn | undefined;
9
+ }
10
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAExD,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,OAAO,CAAkC;IAEjD,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI;IAI3D,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI;IAI1D,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAIpD,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;CAGpD"}
@@ -0,0 +1,7 @@
1
+ import { SerializedEditorState, SerializedLexicalNode } from 'lexical';
2
+ import { LitexmlRegistry } from './registry';
3
+ import { XmlRenderOptions } from './xml-utils';
4
+ export type XmlSerializerOptions = XmlRenderOptions;
5
+ export declare function serializeToXml(state: SerializedEditorState, registry: LitexmlRegistry, options?: XmlSerializerOptions): string;
6
+ export declare function serializeNodesToXml(nodes: SerializedLexicalNode[], registry: LitexmlRegistry, options?: XmlSerializerOptions): string;
7
+ //# sourceMappingURL=serializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAEpD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,qBAAqB,EAC5B,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE,oBAAyB,GACjC,MAAM,CAYR;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,qBAAqB,EAAE,EAC9B,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE,oBAAyB,GACjC,MAAM,CAIR"}
@@ -0,0 +1,21 @@
1
+ import { XmlContent } from './types';
2
+ /** Lexical text format bitmask values */
3
+ export declare const FORMAT_BITS: {
4
+ readonly bold: 1;
5
+ readonly italic: 2;
6
+ readonly strikethrough: 4;
7
+ readonly underline: 8;
8
+ readonly code: 16;
9
+ readonly subscript: 32;
10
+ readonly superscript: 64;
11
+ readonly highlight: 128;
12
+ };
13
+ /** Reverse map: XML tag name → bit value (includes aliases) */
14
+ export declare const FORMAT_TAG_TO_BIT: Record<string, number>;
15
+ /** Wrap text content with nested format tags based on bitmask. */
16
+ export declare function wrapWithFormatTags(text: string, format: number): XmlContent[];
17
+ /** Check if a tag name is a known text format tag. */
18
+ export declare function isFormatTag(tagName: string): boolean;
19
+ /** Get the format bit for a tag name. Returns 0 if not a format tag. */
20
+ export declare function getFormatBit(tagName: string): number;
21
+ //# sourceMappingURL=text-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-format.d.ts","sourceRoot":"","sources":["../src/text-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,SAAS,CAAC;AAEtD,yCAAyC;AACzC,eAAO,MAAM,WAAW;;;;;;;;;CASd,CAAC;AAcX,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAapD,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAa7E;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,37 @@
1
+ import { SerializedEditorState, SerializedLexicalNode } from 'lexical';
2
+ /** Structured XML element for serializer output */
3
+ export interface XmlElement {
4
+ attrs?: Record<string, string>;
5
+ children?: XmlContent[];
6
+ selfClosing?: boolean;
7
+ tag: string;
8
+ }
9
+ /** XML content: either a structured element or raw text (will be escaped) */
10
+ export type XmlContent = XmlElement | string;
11
+ /** Context provided to writer functions */
12
+ export interface WriterContext {
13
+ /** Serialize an array of child nodes into XML content */
14
+ serializeChildren: (children: SerializedLexicalNode[]) => XmlContent[];
15
+ /** Serialize a nested SerializedEditorState's root children into XmlContent[] (for container nodes like alert-quote, banner) */
16
+ serializeNestedState: (state: SerializedEditorState) => XmlContent[];
17
+ /** Serialize a single node into XML content */
18
+ serializeNode: (node: SerializedLexicalNode) => XmlContent | XmlContent[];
19
+ }
20
+ /** Context provided to reader functions */
21
+ export interface ReaderContext {
22
+ /** Parse all child elements of a DOM element into serialized nodes */
23
+ parseChildren: (element: Element) => SerializedLexicalNode[];
24
+ /** Parse a nested XML string into SerializedEditorState (for container nodes) */
25
+ parseNestedState: (xml: string) => SerializedEditorState;
26
+ }
27
+ /**
28
+ * Writer: converts a SerializedLexicalNode to XML representation.
29
+ * Return `false` to indicate this writer does not handle the node.
30
+ */
31
+ export type XmlWriterFn = (node: SerializedLexicalNode, ctx: WriterContext) => XmlContent | XmlContent[] | false;
32
+ /**
33
+ * Reader: converts a DOM Element to SerializedLexicalNode(s).
34
+ * Return `false` to indicate this reader does not handle the element.
35
+ */
36
+ export type XmlReaderFn = (element: Element, ctx: ReaderContext) => SerializedLexicalNode | SerializedLexicalNode[] | false;
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAE5E,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,6EAA6E;AAC7E,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAE7C,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,QAAQ,EAAE,qBAAqB,EAAE,KAAK,UAAU,EAAE,CAAC;IACvE,gIAAgI;IAChI,oBAAoB,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,UAAU,EAAE,CAAC;IACrE,+CAA+C;IAC/C,aAAa,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,UAAU,GAAG,UAAU,EAAE,CAAC;CAC3E;AAED,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,aAAa,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,qBAAqB,EAAE,CAAC;IAC7D,iFAAiF;IACjF,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,qBAAqB,CAAC;CAC1D;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,CACxB,IAAI,EAAE,qBAAqB,EAC3B,GAAG,EAAE,aAAa,KACf,UAAU,GAAG,UAAU,EAAE,GAAG,KAAK,CAAC;AAEvC;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,CACxB,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,aAAa,KACf,qBAAqB,GAAG,qBAAqB,EAAE,GAAG,KAAK,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { LitexmlRegistry } from '../registry';
2
+ export declare function registerBuiltinWriters(registry: LitexmlRegistry): void;
3
+ //# sourceMappingURL=builtin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin.d.ts","sourceRoot":"","sources":["../../src/writers/builtin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAMnD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAkHtE"}
@@ -0,0 +1,3 @@
1
+ import { LitexmlRegistry } from '../registry';
2
+ export declare function registerCustomWriters(registry: LitexmlRegistry): void;
3
+ //# sourceMappingURL=custom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/writers/custom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAenD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAyNrE"}
@@ -0,0 +1,9 @@
1
+ import { XmlContent } from './types';
2
+ export interface XmlRenderOptions {
3
+ compact?: boolean;
4
+ }
5
+ export declare function escapeXml(text: string): string;
6
+ export declare function buildAttrs(attrs: Record<string, string>): string;
7
+ /** Render XmlContent tree to XML string. */
8
+ export declare function renderXml(content: XmlContent[], indent?: number, options?: XmlRenderOptions): string;
9
+ //# sourceMappingURL=xml-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml-utils.d.ts","sourceRoot":"","sources":["../src/xml-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,SAAS,CAAC;AAEtD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAUD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAKhE;AAED,4CAA4C;AAC5C,wBAAgB,SAAS,CACvB,OAAO,EAAE,UAAU,EAAE,EACrB,MAAM,GAAE,MAAU,EAClB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAUR"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@haklex/rich-litexml",
3
+ "version": "0.0.94",
4
+ "description": "Bidirectional Lexical SerializedNode <-> XML conversion with plugin registry",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/Innei/haklex.git",
8
+ "directory": "packages/rich-litexml"
9
+ },
10
+ "license": "MIT",
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/index.mjs",
15
+ "types": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "main": "./dist/index.mjs",
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "dependencies": {
23
+ "lexical": "^0.42.0",
24
+ "linkedom": "^0.18.9"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^5.9.3",
28
+ "vite": "^7.3.1",
29
+ "vite-plugin-dts": "^4.5.4"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "scripts": {
35
+ "build": "vite build",
36
+ "dev:build": "vite build --watch"
37
+ },
38
+ "types": "./dist/index.d.ts"
39
+ }