@haklex/rich-litexml 0.24.0 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -0
- package/dist/browser.mjs +1 -1
- package/dist/node.mjs +1 -1
- package/dist/readers/custom.d.ts.map +1 -1
- package/dist/{src-BHEK3mCO.js → src-1idECb05.js} +34 -0
- package/dist/writers/custom.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# @haklex/rich-litexml
|
|
2
|
+
|
|
3
|
+
Bidirectional Lexical editor state ↔ XML serialization for LLM-friendly document I/O. Converts Lexical `SerializedEditorState` to a compact, token-efficient XML format and back again — enabling AI agents to read and write structured rich text documents with minimal token overhead.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @haklex/rich-litexml
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Peer Dependencies
|
|
12
|
+
|
|
13
|
+
| Package | Version |
|
|
14
|
+
| --------- | --------- |
|
|
15
|
+
| `lexical` | `^0.45.0` |
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Serialize editor state to XML
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { serializeToXml } from '@haklex/rich-litexml';
|
|
23
|
+
|
|
24
|
+
const xml = serializeToXml(serializedEditorState);
|
|
25
|
+
// '<root><p>Hello <strong>world</strong></p><img src="..." /></root>'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Deserialize XML to editor state
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { deserializeFromXml } from '@haklex/rich-litexml';
|
|
32
|
+
|
|
33
|
+
const editorState = deserializeFromXml(xmlString);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Register custom node types
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { LitexmlRegistry } from '@haklex/rich-litexml';
|
|
40
|
+
import { registerBuiltinReaders, registerCustomReaders } from '@haklex/rich-litexml';
|
|
41
|
+
import { registerBuiltinWriters, registerCustomWriters } from '@haklex/rich-litexml';
|
|
42
|
+
|
|
43
|
+
const registry = new LitexmlRegistry();
|
|
44
|
+
registerBuiltinReaders(registry);
|
|
45
|
+
registerBuiltinWriters(registry);
|
|
46
|
+
|
|
47
|
+
// Add custom node readers/writers
|
|
48
|
+
registerCustomReaders(registry, [myReader]);
|
|
49
|
+
registerCustomWriters(registry, [myWriter]);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Exports
|
|
53
|
+
|
|
54
|
+
### Serialization
|
|
55
|
+
|
|
56
|
+
| Export | Description |
|
|
57
|
+
| -------------------------------------- | ------------------------------------------------ |
|
|
58
|
+
| `serializeToXml(state, options?)` | Convert `SerializedEditorState` to XML string |
|
|
59
|
+
| `serializeNodesToXml(nodes, options?)` | Convert an array of serialized nodes to XML |
|
|
60
|
+
| `deserializeFromXml(xml)` | Convert an XML string to `SerializedEditorState` |
|
|
61
|
+
| `deserializeNodesFromXml(xml)` | Convert an XML string to serialized nodes array |
|
|
62
|
+
|
|
63
|
+
### Registry
|
|
64
|
+
|
|
65
|
+
| Export | Description |
|
|
66
|
+
| ------------------------------------------ | ----------------------------------------------------- |
|
|
67
|
+
| `LitexmlRegistry` | Plugin registry class for custom node readers/writers |
|
|
68
|
+
| `createDefaultRegistry()` | Create a registry pre-populated with builtins |
|
|
69
|
+
| `registerBuiltinReaders(registry)` | Register builtin XML → node readers |
|
|
70
|
+
| `registerBuiltinWriters(registry)` | Register builtin node → XML writers |
|
|
71
|
+
| `registerCustomReaders(registry, readers)` | Register custom readers |
|
|
72
|
+
| `registerCustomWriters(registry, writers)` | Register custom writers |
|
|
73
|
+
|
|
74
|
+
### Types
|
|
75
|
+
|
|
76
|
+
| Export | Description |
|
|
77
|
+
| ------------------------------- | ------------------------------------------ |
|
|
78
|
+
| `XmlSerializerOptions` | Options for XML serialization |
|
|
79
|
+
| `LitexmlNodeReader` | Reader interface for XML → node conversion |
|
|
80
|
+
| `LitexmlNodeWriter` | Writer interface for node → XML conversion |
|
|
81
|
+
| `XmlNodeData`, `XmlNodeElement` | XML AST types |
|
|
82
|
+
| `XmlRenderOptions` | Rendering style options for XML output |
|
|
83
|
+
|
|
84
|
+
### Sub-path Exports
|
|
85
|
+
|
|
86
|
+
| Import Path | Description |
|
|
87
|
+
| ---------------------- | ------------------------------------------------ |
|
|
88
|
+
| `@haklex/rich-litexml` | Full exports (browser or Node.js, auto-selected) |
|
|
89
|
+
|
|
90
|
+
The package selects between browser and Node.js entry points automatically: Node.js uses `linkedom` for HTML parsing, while the browser entry uses the native `DOMParser`.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
> **Note:** LiteXML is XML-based, not a custom DSL. The compact tag vocabulary minimizes token count for LLM consumption. For AI agent integration, see `@haklex/rich-agent-core`.
|
|
95
|
+
|
|
96
|
+
## Part of Haklex
|
|
97
|
+
|
|
98
|
+
This package is part of the [Haklex](../../README.md) rich editor ecosystem.
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
MIT
|
package/dist/browser.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as createDefaultRegistry, c as LitexmlRegistry, d as registerParseHTML, i as deserializeNodesFromXml, l as registerCustomReaders, n as serializeToXml, o as registerCustomWriters, r as deserializeFromXml, s as registerBuiltinWriters, t as serializeNodesToXml, u as registerBuiltinReaders } from "./src-
|
|
1
|
+
import { a as createDefaultRegistry, c as LitexmlRegistry, d as registerParseHTML, i as deserializeNodesFromXml, l as registerCustomReaders, n as serializeToXml, o as registerCustomWriters, r as deserializeFromXml, s as registerBuiltinWriters, t as serializeNodesToXml, u as registerBuiltinReaders } from "./src-1idECb05.js";
|
|
2
2
|
//#region src/index-browser.ts
|
|
3
3
|
registerParseHTML((html) => new DOMParser().parseFromString(html, "text/html"));
|
|
4
4
|
//#endregion
|
package/dist/node.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as createDefaultRegistry, c as LitexmlRegistry, d as registerParseHTML, i as deserializeNodesFromXml, l as registerCustomReaders, n as serializeToXml, o as registerCustomWriters, r as deserializeFromXml, s as registerBuiltinWriters, t as serializeNodesToXml, u as registerBuiltinReaders } from "./src-
|
|
1
|
+
import { a as createDefaultRegistry, c as LitexmlRegistry, d as registerParseHTML, i as deserializeNodesFromXml, l as registerCustomReaders, n as serializeToXml, o as registerCustomWriters, r as deserializeFromXml, s as registerBuiltinWriters, t as serializeNodesToXml, u as registerBuiltinReaders } from "./src-1idECb05.js";
|
|
2
2
|
import { parseHTML } from "linkedom";
|
|
3
3
|
//#region src/index-node.ts
|
|
4
4
|
registerParseHTML((html) => parseHTML(html).document);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/readers/custom.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAoDnD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/readers/custom.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAoDnD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CA0erE"}
|
|
@@ -405,6 +405,22 @@ function registerCustomReaders(registry) {
|
|
|
405
405
|
snapshot: extractCdataText(el) || el.getAttribute("snapshot") || el.textContent?.trim() || "",
|
|
406
406
|
version: 1
|
|
407
407
|
}));
|
|
408
|
+
registry.registerReader("dynamic", (el) => {
|
|
409
|
+
let props = {};
|
|
410
|
+
const raw = (extractCdataText(el) ?? el.textContent ?? "").trim();
|
|
411
|
+
if (raw) try {
|
|
412
|
+
const parsed = JSON.parse(raw);
|
|
413
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) props = parsed;
|
|
414
|
+
} catch {}
|
|
415
|
+
return {
|
|
416
|
+
type: "dynamic",
|
|
417
|
+
...extractBlockId(el),
|
|
418
|
+
url: el.getAttribute("url") ?? "",
|
|
419
|
+
props,
|
|
420
|
+
initialHeight: numAttr(el, "initial-height") ?? 320,
|
|
421
|
+
version: 1
|
|
422
|
+
};
|
|
423
|
+
});
|
|
408
424
|
registry.registerReader("grid", (el, ctx) => {
|
|
409
425
|
const cells = [];
|
|
410
426
|
for (const child of el.children) if (child.tagName.toLowerCase() === "cell") {
|
|
@@ -795,6 +811,24 @@ function registerCustomWriters(registry) {
|
|
|
795
811
|
children: [{ cdata: n.snapshot }]
|
|
796
812
|
};
|
|
797
813
|
});
|
|
814
|
+
registry.registerWriter("dynamic", (node) => {
|
|
815
|
+
const n = node;
|
|
816
|
+
const attrs = optAttr({
|
|
817
|
+
...blockId(n),
|
|
818
|
+
"url": n.url,
|
|
819
|
+
"initial-height": n.initialHeight != null ? String(n.initialHeight) : void 0
|
|
820
|
+
});
|
|
821
|
+
if (!n.props || Object.keys(n.props).length === 0) return {
|
|
822
|
+
tag: "dynamic",
|
|
823
|
+
attrs,
|
|
824
|
+
selfClosing: true
|
|
825
|
+
};
|
|
826
|
+
return {
|
|
827
|
+
tag: "dynamic",
|
|
828
|
+
attrs,
|
|
829
|
+
children: [{ cdata: JSON.stringify(n.props) }]
|
|
830
|
+
};
|
|
831
|
+
});
|
|
798
832
|
registry.registerWriter("grid-container", (node, ctx) => {
|
|
799
833
|
const n = node;
|
|
800
834
|
const cells = (n.cells ?? []).map((cellState) => ({
|
|
@@ -1 +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,
|
|
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,CA2VrE"}
|