@haklex/rich-litexml 0.41.0 → 0.42.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/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-D18H2iDy.js";
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-DY5NNS6M.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-D18H2iDy.js";
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-DY5NNS6M.js";
2
2
  import { parseHTML } from "linkedom";
3
3
  //#region src/index-node.ts
4
4
  registerParseHTML((html) => parseHTML(html).document);
@@ -1134,8 +1134,11 @@ var FORMAT_TAG_TO_BIT = {
1134
1134
  };
1135
1135
  /** Wrap text content with nested format tags based on bitmask. */
1136
1136
  function wrapWithFormatTags(text, format) {
1137
- if (format === 0) return [text];
1138
- let content = [text];
1137
+ return wrapContentWithFormatTags([text], format);
1138
+ }
1139
+ /** Wrap already-serialized inline content with nested format tags based on bitmask. */
1140
+ function wrapContentWithFormatTags(content, format) {
1141
+ if (format === 0) return content;
1139
1142
  for (let idx = FORMAT_BIT_TO_TAG.length - 1; idx >= 0; idx--) {
1140
1143
  const [bit, tag] = FORMAT_BIT_TO_TAG[idx];
1141
1144
  if (format & bit) content = [{
@@ -1488,10 +1491,58 @@ function serializeNodesToXml(nodes, registry, options = {}) {
1488
1491
  const ctx = createWriterContext(registry);
1489
1492
  return renderXml(nodes.flatMap((node) => ctx.serializeNode(node)), 0, options);
1490
1493
  }
1494
+ function isTextRun(node) {
1495
+ return node.type === "text";
1496
+ }
1497
+ function serializeTextRun(run) {
1498
+ if (run.length === 1) return wrapWithFormatTags(run[0].text, run[0].format);
1499
+ const common = run.reduce((acc, node) => acc & node.format, -1);
1500
+ if (common !== 0) return wrapContentWithFormatTags(serializeTextRun(run.map((node) => ({
1501
+ ...node,
1502
+ format: node.format & ~common
1503
+ }))), common);
1504
+ const groups = [];
1505
+ let current;
1506
+ let previous;
1507
+ for (const node of run) {
1508
+ if (current && previous && (previous.format & node.format) !== 0) current.push(node);
1509
+ else {
1510
+ current = [node];
1511
+ groups.push(current);
1512
+ }
1513
+ previous = node;
1514
+ }
1515
+ if (groups.length === 1) return run.flatMap((node) => wrapWithFormatTags(node.text, node.format));
1516
+ return groups.flatMap((group) => serializeTextRun(group));
1517
+ }
1518
+ function serializeSiblings(nodes, ctx) {
1519
+ const out = [];
1520
+ let run = [];
1521
+ const flush = () => {
1522
+ if (run.length > 0) out.push(...serializeTextRun(run));
1523
+ run = [];
1524
+ };
1525
+ for (const node of nodes) {
1526
+ if (isTextRun(node)) {
1527
+ const n = node;
1528
+ run.push({
1529
+ text: n.text ?? "",
1530
+ format: n.format ?? 0
1531
+ });
1532
+ continue;
1533
+ }
1534
+ flush();
1535
+ const result = ctx.serializeNode(node);
1536
+ if (Array.isArray(result)) out.push(...result);
1537
+ else out.push(result);
1538
+ }
1539
+ flush();
1540
+ return out;
1541
+ }
1491
1542
  function createWriterContext(registry) {
1492
1543
  const ctx = {
1493
1544
  serializeChildren(children) {
1494
- return children.flatMap((child) => ctx.serializeNode(child));
1545
+ return serializeSiblings(children, ctx);
1495
1546
  },
1496
1547
  serializeNode(node) {
1497
1548
  const n = node;
@@ -1508,7 +1559,7 @@ function createWriterContext(registry) {
1508
1559
  return serializeFallback(node);
1509
1560
  },
1510
1561
  serializeNestedState(state) {
1511
- return (state.root.children ?? []).flatMap((child) => ctx.serializeNode(child));
1562
+ return serializeSiblings(state.root.children ?? [], ctx);
1512
1563
  }
1513
1564
  };
1514
1565
  return ctx;
@@ -14,6 +14,8 @@ export declare const FORMAT_BITS: {
14
14
  export declare const FORMAT_TAG_TO_BIT: Record<string, number>;
15
15
  /** Wrap text content with nested format tags based on bitmask. */
16
16
  export declare function wrapWithFormatTags(text: string, format: number): XmlContent[];
17
+ /** Wrap already-serialized inline content with nested format tags based on bitmask. */
18
+ export declare function wrapContentWithFormatTags(content: XmlContent[], format: number): XmlContent[];
17
19
  /** Check if a tag name is a known text format tag. */
18
20
  export declare function isFormatTag(tagName: string): boolean;
19
21
  /** Get the format bit for a tag name. Returns 0 if not a format tag. */
@@ -1 +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"}
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,CAE7E;AAED,uFAAuF;AACvF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAW7F;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haklex/rich-litexml",
3
- "version": "0.41.0",
3
+ "version": "0.42.0",
4
4
  "description": "Bidirectional Lexical SerializedNode <-> XML conversion with plugin registry",
5
5
  "repository": {
6
6
  "type": "git",