@graphty/graph-io 0.3.39 → 0.3.40

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.
Files changed (94) hide show
  1. package/dist/chunks/{escape-BpYMQZVa.js → escape-BJRLd3vJ.js} +3 -2
  2. package/dist/chunks/escape-BJRLd3vJ.js.map +1 -0
  3. package/dist/chunks/{exporter-BqKs1Q12.js → exporter-6ocL_9x_.js} +5 -4
  4. package/dist/chunks/exporter-6ocL_9x_.js.map +1 -0
  5. package/dist/chunks/{exporter-DXqCPNrI.js → exporter-BVXnV9-9.js} +42 -29
  6. package/dist/chunks/exporter-BVXnV9-9.js.map +1 -0
  7. package/dist/chunks/{exporter-CNJZF_BN.js → exporter-Bcp-l4Bo.js} +2 -2
  8. package/dist/chunks/{exporter-CNJZF_BN.js.map → exporter-Bcp-l4Bo.js.map} +1 -1
  9. package/dist/chunks/{importer-CqgYq4Ld.js → importer-AjwOJrn2.js} +2 -2
  10. package/dist/chunks/{importer-CqgYq4Ld.js.map → importer-AjwOJrn2.js.map} +1 -1
  11. package/dist/chunks/{importer-BfJ1jnNr.js → importer-BJlGAOht.js} +27 -12
  12. package/dist/chunks/importer-BJlGAOht.js.map +1 -0
  13. package/dist/chunks/{importer-PVXkeoaS.js → importer-BpuS3J8C.js} +8 -8
  14. package/dist/chunks/importer-BpuS3J8C.js.map +1 -0
  15. package/dist/chunks/{importer-CSt-gaYE.js → importer-CPqnIY8m.js} +4 -4
  16. package/dist/chunks/{importer-CSt-gaYE.js.map → importer-CPqnIY8m.js.map} +1 -1
  17. package/dist/chunks/{importer-B7Ir269L.js → importer-DEp_fYjf.js} +28 -10
  18. package/dist/chunks/importer-DEp_fYjf.js.map +1 -0
  19. package/dist/chunks/{importer-DvFznt5-.js → importer-D_srHyj6.js} +111 -61
  20. package/dist/chunks/importer-D_srHyj6.js.map +1 -0
  21. package/dist/chunks/{importer--tQQsY4W.js → importer-DcKB97kW.js} +2 -2
  22. package/dist/chunks/{importer--tQQsY4W.js.map → importer-DcKB97kW.js.map} +1 -1
  23. package/dist/chunks/{json-elements-CXs4z1iL.js → json-elements-DpO6AXIc.js} +5 -3
  24. package/dist/chunks/{json-elements-CXs4z1iL.js.map → json-elements-DpO6AXIc.js.map} +1 -1
  25. package/dist/chunks/{records-C9jd7yLD.js → records-r3SFHz11.js} +136 -95
  26. package/dist/chunks/records-r3SFHz11.js.map +1 -0
  27. package/dist/csv.js +2 -2
  28. package/dist/cx.js +1 -1
  29. package/dist/cx2.js +2 -2
  30. package/dist/cys.js +1 -1
  31. package/dist/dot.js +1 -1
  32. package/dist/gexf.js +5 -3
  33. package/dist/gexf.js.map +1 -1
  34. package/dist/gml.js +1 -1
  35. package/dist/graph-io.js +19 -19
  36. package/dist/graphml.js +1 -1
  37. package/dist/json.js +1 -1
  38. package/dist/neo4j.js +2 -2
  39. package/dist/pajek.js +1 -1
  40. package/dist/src/common/json-elements.d.ts.map +1 -1
  41. package/dist/src/common/json-elements.js +4 -2
  42. package/dist/src/common/json-elements.js.map +1 -1
  43. package/dist/src/common/xml.d.ts.map +1 -1
  44. package/dist/src/common/xml.js +2 -1
  45. package/dist/src/common/xml.js.map +1 -1
  46. package/dist/src/formats/csv/records.d.ts.map +1 -1
  47. package/dist/src/formats/csv/records.js +138 -100
  48. package/dist/src/formats/csv/records.js.map +1 -1
  49. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  50. package/dist/src/formats/cx/importer.js +108 -53
  51. package/dist/src/formats/cx/importer.js.map +1 -1
  52. package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
  53. package/dist/src/formats/cx2/exporter.js +2 -1
  54. package/dist/src/formats/cx2/exporter.js.map +1 -1
  55. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  56. package/dist/src/formats/cx2/importer.js +28 -6
  57. package/dist/src/formats/cx2/importer.js.map +1 -1
  58. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  59. package/dist/src/formats/gexf/exporter.js +4 -2
  60. package/dist/src/formats/gexf/exporter.js.map +1 -1
  61. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  62. package/dist/src/formats/graphml/exporter.js +2 -1
  63. package/dist/src/formats/graphml/exporter.js.map +1 -1
  64. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  65. package/dist/src/formats/graphml/importer.js +3 -2
  66. package/dist/src/formats/graphml/importer.js.map +1 -1
  67. package/dist/src/formats/xgmml/emit.d.ts +6 -0
  68. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  69. package/dist/src/formats/xgmml/emit.js +33 -10
  70. package/dist/src/formats/xgmml/emit.js.map +1 -1
  71. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
  72. package/dist/src/formats/xgmml/exporter.js +54 -22
  73. package/dist/src/formats/xgmml/exporter.js.map +1 -1
  74. package/dist/xgmml.js +2 -2
  75. package/package.json +2 -2
  76. package/src/common/json-elements.ts +4 -2
  77. package/src/common/xml.ts +2 -1
  78. package/src/formats/csv/records.ts +143 -99
  79. package/src/formats/cx/importer.ts +140 -58
  80. package/src/formats/cx2/exporter.ts +2 -1
  81. package/src/formats/cx2/importer.ts +34 -10
  82. package/src/formats/gexf/exporter.ts +4 -2
  83. package/src/formats/graphml/exporter.ts +2 -3
  84. package/src/formats/graphml/importer.ts +3 -2
  85. package/src/formats/xgmml/emit.ts +34 -10
  86. package/src/formats/xgmml/exporter.ts +63 -23
  87. package/dist/chunks/escape-BpYMQZVa.js.map +0 -1
  88. package/dist/chunks/exporter-BqKs1Q12.js.map +0 -1
  89. package/dist/chunks/exporter-DXqCPNrI.js.map +0 -1
  90. package/dist/chunks/importer-B7Ir269L.js.map +0 -1
  91. package/dist/chunks/importer-BfJ1jnNr.js.map +0 -1
  92. package/dist/chunks/importer-DvFznt5-.js.map +0 -1
  93. package/dist/chunks/importer-PVXkeoaS.js.map +0 -1
  94. package/dist/chunks/records-C9jd7yLD.js.map +0 -1
@@ -188,7 +188,8 @@ function decodeEntities(raw, line, repairs) {
188
188
  const hex = name.startsWith("#x") || name.startsWith("#X");
189
189
  const digits = name.slice(hex ? 2 : 1);
190
190
  const ok = hex ? /^0*[\da-fA-F]{1,6}$/.test(digits) : /^0*\d{1,7}$/.test(digits);
191
- const cp = ok ? Number.parseInt(digits, hex ? 16 : 10) : -1;
191
+ const radix = hex ? 16 : 10;
192
+ const cp = ok ? Number.parseInt(digits, radix) : -1;
192
193
  const low = cp >= 55296 && cp <= 56319 ? lowSurrogateAfter(raw, semi + 1, repairs) : null;
193
194
  if (low !== null) {
194
195
  repairs?.surrogatePair?.(lineAt(raw, amp, line));
@@ -1309,4 +1310,4 @@ export {
1309
1310
  tokenizeXml as t,
1310
1311
  xmlIllegalTextNotes as x
1311
1312
  };
1312
- //# sourceMappingURL=escape-BpYMQZVa.js.map
1313
+ //# sourceMappingURL=escape-BJRLd3vJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape-BJRLd3vJ.js","sources":["../../src/common/xml.ts","../../src/common/escape.ts"],"sourcesContent":["/**\n * The streaming XML tokenizer shared by the GEXF and GraphML importers (design sections 8.2 and\n * 8.4): SAX-style start / end / text events over the text chunks of the common reader, so both\n * importers run in one pass with bounded memory and every issue carries a line number.\n *\n * Cost model: every character of the input is scanned once. A token that spans many chunks (a\n * long attribute value, comment, CDATA section or name) resumes where the previous chunk left off\n * instead of re-reading the token from its `<`, and line numbers are counted from a cached next\n * line-break position, so a document without line breaks costs the same as one with them.\n *\n * What it handles: the XML declaration and processing instructions (skipped), comments (skipped;\n * a `--` inside one, which XML 1.0 forbids, is accepted: a comment carries no data and banner\n * comments such as `<!-- ----- -->` are common in hand-written files),\n * CDATA sections (text), a DOCTYPE with an internal subset (skipped; entity declarations are not\n * expanded, so an unknown entity reference is a syntax error), the five predefined entities and\n * numeric character references (decimal and hexadecimal) in text and attribute values, attribute\n * value whitespace normalization, end-of-line normalization (CR LF and lone CR become LF), and\n * well-formedness: matching end tags, one root element, no text outside it, no duplicate\n * attributes, no unterminated markup at the end of the input. Namespaces are not resolved; element\n * and attribute names are reported as written (with their prefix).\n *\n * Why not fast-xml-parser: its XMLParser accepts mismatched and unclosed tags without error, does\n * not decode numeric character references unless the deprecated `htmlEntities` option is set, and\n * its validator (`XMLValidator`, the `parse(xml, true)` overload) and `XMLBuilder` are deprecated in\n * 5.x, which the root lint's `no-deprecated` rule forbids using; so the malformed corpus could not\n * be rejected and attribute values written by the common `escapeXmlAttribute` (`&#10;`) could not\n * be read back.\n */\n\nimport { type Column, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { type LossNote } from \"../types.js\";\nimport { XML_ILLEGAL_CHAR_CODE } from \"./codes.js\";\nimport { isNameChar } from \"./export.js\";\nimport { agree, plural } from \"./plural.js\";\n\n/**\n * The events of the tokenizer; every callback is synchronous.\n * @category Plugin helpers\n */\nexport interface XmlHandler {\n /**\n * An element starts (a self-closing element produces start then end).\n * @param name - the element name as written, prefix included\n * @param attrs - the attributes, entities decoded, in document order\n * @param line - the 1-based line of the `<`\n * @param ns - the namespace URI the element's prefix (or the default namespace) is bound to:\n * \"\" when the element is in no namespace, null when its prefix is undeclared or the name is not\n * namespace-well-formed (a leading or trailing colon, two colons)\n */\n start(name: string, attrs: ReadonlyMap<string, string>, line: number, ns: string | null): void;\n /**\n * An element ends.\n * @param name - the element name\n * @param line - the 1-based line of the end tag (or of the self-closing start tag)\n */\n end(name: string, line: number): void;\n /**\n * Character data between two tags (entities decoded, CDATA included), one call per run;\n * whitespace-only runs are delivered too.\n * @param text - the text\n * @param line - the 1-based line where the run starts\n */\n text(text: string, line: number): void;\n /**\n * A DOCTYPE declaration (optional; its internal subset is never expanded).\n * @param text - the declaration as written, from `<!DOCTYPE` to its `>`\n * @param line - the 1-based line of the `<`\n */\n doctype?(text: string, line: number): void;\n}\n\n/**\n * A well-formedness or syntax error, with the line it was found on.\n * @category Plugin helpers\n */\nexport class XmlSyntaxError extends Error {\n /** The 1-based line. */\n readonly line: number;\n\n /**\n * Create the error.\n * @param message - a plain-ASCII message\n * @param line - the 1-based line\n */\n constructor(message: string, line: number) {\n super(message);\n this.name = \"XmlSyntaxError\";\n this.line = line;\n }\n}\n\n/**\n * The input holds no markup at all (empty, whitespace only, a byte order mark only): an importer\n * reports it as E_EMPTY_INPUT rather than as a syntax error.\n * @category Plugin helpers\n */\nexport class XmlEmptyInputError extends XmlSyntaxError {\n /**\n * Create the error.\n * @param line - the 1-based line where the input ended\n */\n constructor(line: number) {\n super(\"the input is empty: no root element\", line);\n this.name = \"XmlEmptyInputError\";\n }\n}\n\n/**\n * Opt-in repairs of two defects the Cytoscape XGMML writer is known to produce. Each is off unless its callback is given; GEXF and GraphML never\n * pass them, so their documents stay strictly well-formed. The callback is told the line of each\n * repair, so the importer can warn per occurrence.\n * @category Plugin helpers\n */\nexport interface XmlRepairs {\n /**\n * Read an `&` that is not followed by a `;` within the next 7 characters as `&amp;` (Cytoscape's\n * `cytoscape.xgmml.repair.bare.ampersands` lookahead); an `&name;` that does end in time is\n * still decoded, and still fatal when the entity is unknown. A complete numeric character\n * reference is decoded whatever its length (`&#128512;`), where Cytoscape's byte lookahead\n * would turn it into text.\n */\n readonly bareAmpersand?: ((line: number) => void) | undefined;\n /**\n * Join a high-surrogate character reference immediately followed by a low-surrogate one\n * (`&#xd83d;&#xde00;`, which XML 1.0 forbids but Cytoscape writes for astral characters) into\n * the one character they encode; a lone surrogate stays fatal.\n */\n readonly surrogatePair?: ((line: number) => void) | undefined;\n}\n\n/** How far Cytoscape's bare-ampersand repair looks for the `;` that ends an entity reference. */\nconst BARE_AMPERSAND_LOOKAHEAD = 7;\n\n/** A numeric character reference at the start of a text: `&#123;` or `&#x1F;`. */\nconst CHAR_REFERENCE = /^&#(?:[xX]([0-9a-fA-F]{1,6})|(\\d{1,7}));/;\n\n/** A numeric character reference at the end of a text. */\nconst TRAILING_CHAR_REFERENCE = /&#(?:[xX]([0-9a-fA-F]{1,6})|(\\d{1,7}));$/;\n\nconst NAMED_ENTITIES: Readonly<Record<string, string>> = {\n lt: \"<\",\n gt: \">\",\n amp: \"&\",\n quot: '\"',\n apos: \"'\",\n};\n\nconst LT = 60;\nconst GT = 62;\nconst SLASH = 47;\nconst EQUALS = 61;\nconst QUOTE = 34;\nconst APOS = 39;\nconst OPEN_BRACKET = 91;\nconst CLOSE_BRACKET = 93;\nconst BANG = 33;\nconst DASH = 45;\nconst QUESTION = 63;\n\n/** The longest entity reference held back at a chunk boundary (`&#x10FFFF;` is 10 characters). */\nconst MAX_ENTITY_LENGTH = 16;\n\n/** Markup shorter than this (`<![CDATA[` is 9 characters) cannot be classified yet. */\nconst MIN_DECIDABLE_MARKUP = 9;\n\n/**\n * Whether a char code is XML whitespace (space, tab, LF, CR).\n * @param c - the char code\n * @returns true for whitespace\n */\nfunction isSpace(c: number): boolean {\n return c === 32 || c === 9 || c === 10 || c === 13;\n}\n\n/**\n * Whether a code point may start an XML Name: a NameChar that is not a digit, `-`, `.`, U+00B7,\n * a combining character (U+0300..U+036F) or U+203F / U+2040.\n * @param cp - the code point\n * @returns true for a NameStartChar\n */\nfunction isNameStart(cp: number): boolean {\n if (!isNameChar(cp)) {\n return false;\n }\n if ((cp >= 0x30 && cp <= 0x39) || cp === 0x2d || cp === 0x2e || cp === 0xb7) {\n return false;\n }\n return !(cp >= 0x300 && cp <= 0x36f) && cp !== 0x203f && cp !== 0x2040;\n}\n\n/** ASCII code -> whether it is a NameStartChar / NameChar, for the fast path of readName(). */\nconst ASCII_NAME_START = new Uint8Array(128);\nconst ASCII_NAME_CHAR = new Uint8Array(128);\nfor (let c = 0; c < 128; c++) {\n ASCII_NAME_START[c] = isNameStart(c) ? 1 : 0;\n ASCII_NAME_CHAR[c] = isNameChar(c) ? 1 : 0;\n}\n\n/**\n * Characters XML 1.0 forbids in a document (the Char production): C0 controls other than tab, LF\n * and CR, U+FFFE / U+FFFF, and lone surrogates (the `u` flag makes the surrogate class match only\n * an unpaired one). Built from char codes so no control character appears in the source.\n */\nconst ILLEGAL_CHAR = new RegExp(\n `[${String.fromCharCode(0)}-${String.fromCharCode(8)}${String.fromCharCode(11)}${String.fromCharCode(12)}` +\n `${String.fromCharCode(14)}-${String.fromCharCode(31)}\\\\uFFFE\\\\uFFFF\\\\uD800-\\\\uDFFF]`,\n \"u\",\n);\n\n/**\n * Whether a text holds a character XML 1.0 forbids (see ILLEGAL_CHAR); such a character cannot be\n * written even as a character reference, so a conforming parser rejects the whole document.\n * @param text - the text\n * @returns true when the text cannot appear in an XML 1.0 document\n * @category Plugin helpers\n */\nexport function hasIllegalXmlChar(text: string): boolean {\n return ILLEGAL_CHAR.test(text);\n}\n\n/**\n * Where the first character XML 1.0 forbids is in a text.\n * @param text - the text\n * @returns its index, or -1\n */\nfunction illegalCharIndex(text: string): number {\n const match = ILLEGAL_CHAR.exec(text);\n return match === null ? -1 : match.index;\n}\n\n/**\n * The loss notes of the texts a snapshot holds that no XML 1.0 document can carry (see\n * hasIllegalXmlChar): one E_XML_ILLEGAL_CHAR note per column (node, edge and graph string / dict /\n * list-of-text columns) and one for the ids, each counting the affected rows; export() throws on\n * the first such text. Shared by the GEXF and GraphML exporters' check().\n * @param snapshot - the snapshot\n * @returns the notes, empty when every text is writable\n * @category Plugin helpers\n */\nexport function xmlIllegalTextNotes(snapshot: GraphSnapshot): LossNote[] {\n const notes: LossNote[] = [];\n let ids = 0;\n for (let i = 0; i < snapshot.nodeCount; i++) {\n const id = snapshot.ids.idOf(i);\n if (typeof id === \"string\" && hasIllegalXmlChar(id)) {\n ids++;\n }\n }\n if (ids > 0) {\n notes.push(\n Object.freeze({\n code: XML_ILLEGAL_CHAR_CODE,\n message: `${ids} node id${plural(ids)} ${agree(ids, \"holds\", \"hold\")} a character XML 1.0 cannot carry; the save fails`,\n column: null,\n count: ids,\n }),\n );\n }\n for (const [domain, table] of [\n [\"node\", snapshot.nodes],\n [\"edge\", snapshot.edges],\n [\"graph\", snapshot.graph],\n ] as const) {\n for (const column of table) {\n const bad = countIllegalRows(column);\n if (bad > 0) {\n notes.push(\n Object.freeze({\n code: XML_ILLEGAL_CHAR_CODE,\n message: `${domain} column \"${column.meta.name}\": ${bad} value${plural(bad)} ${agree(bad, \"holds\", \"hold\")} a character XML 1.0 cannot carry; the save fails`,\n column: column.meta.name,\n count: bad,\n }),\n );\n }\n }\n }\n return notes;\n}\n\n/**\n * How many set rows of a text column hold an XML-illegal character.\n * @param column - the column\n * @returns the count; 0 for a non-text column\n */\nfunction countIllegalRows(column: Column): number {\n let bad = 0;\n if (column.dtype === \"string\" || column.dtype === \"dict\") {\n for (let r = 0; r < column.length; r++) {\n if (column.isSet(r) && hasIllegalXmlChar(column.value(r) as string)) {\n bad++;\n }\n }\n } else if (column.dtype === \"list\" && (column.meta.itemDtype === \"string\" || column.meta.itemDtype === \"dict\")) {\n for (let r = 0; r < column.length; r++) {\n if (\n column.isSet(r) &&\n column.sliceOf(r).some((item) => typeof item === \"string\" && hasIllegalXmlChar(item))\n ) {\n bad++;\n }\n }\n }\n return bad;\n}\n\n/**\n * The encoding pseudo-attribute of an XML declaration at the very start of a document (one\n * anywhere else is a syntax error of the tokenizer).\n */\nconst XML_DECLARED_ENCODING = /^<\\?xml\\s[^>]*?\\bencoding\\s*=\\s*[\"']([A-Za-z][A-Za-z0-9._-]*)[\"']/;\n\n/**\n * The encoding an XML document declares in its prolog (`<?xml version=\"1.0\" encoding=\"...\"?>`),\n * for the shared byte decoder (common/input.ts).\n * @param head - the start of the document, decoded as windows-1252\n * @returns the declared label, or null when there is no declaration or it names no encoding\n * @category Plugin helpers\n */\nexport function xmlDeclaredEncoding(head: string): string | null {\n const match = XML_DECLARED_ENCODING.exec(head);\n return match === null ? null : match[1];\n}\n\n/**\n * The head of a document as text for an XML format's sniff(): UTF-16 when a byte order mark (or\n * BOM-less UTF-16 `<?`, XML 1.0 Appendix F) says so, else UTF-8, never failing.\n * @param head - the first bytes\n * @returns the text, a leading byte order mark removed\n * @category Plugin helpers\n */\nexport function sniffXmlText(head: Uint8Array): string {\n let label = \"utf-8\";\n if ((head[0] === 0xff && head[1] === 0xfe) || (head[0] === 0x3c && head[1] === 0x00 && head[2] === 0x3f)) {\n label = \"utf-16le\";\n } else if ((head[0] === 0xfe && head[1] === 0xff) || (head[0] === 0x00 && head[1] === 0x3c && head[3] === 0x3f)) {\n label = \"utf-16be\";\n }\n return new TextDecoder(label, { fatal: false }).decode(head);\n}\n\n/**\n * Whether a text is an XML Name.\n * @param text - the text\n * @returns true for a well-formed name\n * @category Plugin helpers\n */\nexport function isXmlName(text: string): boolean {\n if (text.length === 0) {\n return false;\n }\n let first = true;\n for (const ch of text) {\n const cp = ch.codePointAt(0);\n if (cp === undefined || (first ? !isNameStart(cp) : !isNameChar(cp))) {\n return false;\n }\n first = false;\n }\n return true;\n}\n\n/**\n * Whether a code point is a legal XML 1.0 character.\n * @param cp - the code point\n * @returns true when a character reference may produce it\n */\nfunction isXmlChar(cp: number): boolean {\n return (\n cp === 0x9 ||\n cp === 0xa ||\n cp === 0xd ||\n (cp >= 0x20 && cp <= 0xd7ff) ||\n (cp >= 0xe000 && cp <= 0xfffd) ||\n (cp >= 0x10000 && cp <= 0x10ffff)\n );\n}\n\n/**\n * Decode the predefined entities and character references of a text.\n * @param raw - the text as written\n * @param line - the line, for errors\n * @param repairs - the opt-in repairs (XGMML only); none by default\n * @returns the decoded text\n * @category Plugin helpers\n */\nexport function decodeEntities(raw: string, line: number, repairs?: XmlRepairs): string {\n let amp = raw.indexOf(\"&\");\n if (amp < 0) {\n return raw;\n }\n let out = \"\";\n let start = 0;\n while (amp >= 0) {\n out += raw.slice(start, amp);\n const semi = raw.indexOf(\";\", amp + 1);\n if (\n repairs?.bareAmpersand !== undefined &&\n (semi < 0 || semi - amp > BARE_AMPERSAND_LOOKAHEAD) &&\n // a well-formed character reference longer than the lookahead (&#128512;) is not bare\n !CHAR_REFERENCE.test(raw.slice(amp, amp + 12))\n ) {\n repairs.bareAmpersand(lineAt(raw, amp, line));\n out += \"&\";\n start = amp + 1;\n amp = raw.indexOf(\"&\", start);\n continue;\n }\n if (semi < 0) {\n throw new XmlSyntaxError(\"unterminated entity reference\", lineAt(raw, amp, line));\n }\n const name = raw.slice(amp + 1, semi);\n if (name.startsWith(\"#\")) {\n const hex = name.startsWith(\"#x\") || name.startsWith(\"#X\");\n const digits = name.slice(hex ? 2 : 1);\n // XML 1.0 puts no limit on leading zeros (&#x0000000041; is \"A\")\n const ok = hex ? /^0*[\\da-fA-F]{1,6}$/.test(digits) : /^0*\\d{1,7}$/.test(digits);\n const radix = hex ? 16 : 10;\n const cp = ok ? Number.parseInt(digits, radix) : -1;\n const low = cp >= 0xd800 && cp <= 0xdbff ? lowSurrogateAfter(raw, semi + 1, repairs) : null;\n if (low !== null) {\n repairs?.surrogatePair?.(lineAt(raw, amp, line));\n out += String.fromCharCode(cp, low.unit);\n start = low.end;\n amp = raw.indexOf(\"&\", start);\n continue;\n }\n if (cp < 0 || !isXmlChar(cp)) {\n throw new XmlSyntaxError(`invalid character reference &${name};`, lineAt(raw, amp, line));\n }\n out += String.fromCodePoint(cp);\n } else {\n const value = NAMED_ENTITIES[name];\n if (value === undefined) {\n throw new XmlSyntaxError(`unknown entity &${name};`, lineAt(raw, amp, line));\n }\n out += value;\n }\n start = semi + 1;\n amp = raw.indexOf(\"&\", start);\n }\n return out + raw.slice(start);\n}\n\n/**\n * The line of a position inside a text that starts on a known line.\n * @param raw - the text\n * @param at - the position\n * @param line - the line the text starts on\n * @returns the line of the position\n */\nfunction lineAt(raw: string, at: number, line: number): number {\n let n = line;\n for (let i = raw.indexOf(\"\\n\"); i >= 0 && i < at; i = raw.indexOf(\"\\n\", i + 1)) {\n n++;\n }\n return n;\n}\n\n/**\n * The low-surrogate character reference that may follow a high-surrogate one, when the\n * surrogate-pair repair is on.\n * @param raw - the text\n * @param at - where the next reference would start\n * @param repairs - the repairs in force\n * @returns the low surrogate code unit and the index after its reference, or null\n */\nfunction lowSurrogateAfter(\n raw: string,\n at: number,\n repairs: XmlRepairs | undefined,\n): { readonly unit: number; readonly end: number } | null {\n if (repairs?.surrogatePair === undefined || raw.charCodeAt(at) !== 38) {\n return null;\n }\n const match = CHAR_REFERENCE.exec(raw.slice(at, at + 12));\n if (match === null) {\n return null;\n }\n const unit = match[1] === undefined ? Number.parseInt(match[2], 10) : Number.parseInt(match[1], 16);\n return unit >= 0xdc00 && unit <= 0xdfff ? { unit, end: at + match[0].length } : null;\n}\n\n/**\n * Whether a text is whitespace only.\n * @param text - the text\n * @returns true when every character is XML whitespace (also for an empty text)\n * @category Plugin helpers\n */\nexport function isWhitespace(text: string): boolean {\n for (let i = 0; i < text.length; i++) {\n if (!isSpace(text.charCodeAt(i))) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * The local part of a possibly prefixed XML name.\n * @param name - the name as written\n * @returns the text after the last colon, or the name itself\n * @category Plugin helpers\n */\nexport function localName(name: string): string {\n const colon = name.lastIndexOf(\":\");\n return colon < 0 ? name : name.slice(colon + 1);\n}\n\n/**\n * Tokenize XML text arriving in chunks and deliver events to a handler. Throws XmlSyntaxError on\n * malformed input; any error the handler throws propagates unchanged.\n * @param chunks - the text (already UTF-8 decoded, BOM removed)\n * @param handler - the event sink\n * @param repairs - the opt-in repairs (XGMML only); none by default\n * @category Plugin helpers\n */\nexport async function tokenizeXml(\n chunks: AsyncIterable<string>,\n handler: XmlHandler,\n repairs?: XmlRepairs,\n): Promise<void> {\n const tokenizer = new XmlTokenizer(handler, repairs);\n // XML 1.0 section 2.8: nothing may precede the XML declaration, not even whitespace (template\n // output often adds a line break, and the declared encoding would then go unread)\n let skipped = 0;\n let lines = 1;\n let leading = true;\n try {\n for await (const chunk of chunks) {\n if (leading) {\n const start = chunk.search(/\\S/);\n const blank = start < 0 ? chunk : chunk.slice(0, start);\n skipped += blank.length;\n lines += blank.split(\"\\n\").length - 1;\n if (start >= 0) {\n leading = false;\n if (skipped > 0 && /^<\\?xml\\s/.test(chunk.slice(start, start + 6))) {\n throw new XmlSyntaxError(\n \"the XML declaration must be at the very start of the document; whitespace precedes it\",\n lines,\n );\n }\n }\n }\n tokenizer.push(chunk);\n }\n tokenizer.finish();\n } catch (err) {\n if (err instanceof XmlSyntaxError && tokenizer.declaresXml11 && !err.message.includes(\"XML 1.1\")) {\n throw new XmlSyntaxError(\n `${err.message}; the document declares XML 1.1, which graph-io does not read (it reads XML 1.0)`,\n err.line,\n );\n }\n throw err;\n }\n}\n\n/** The result of parsing one start tag out of the buffer. */\ninterface StartTag {\n /** The element name. */\n readonly name: string;\n /** The attributes. */\n readonly attrs: Map<string, string>;\n /** Whether the tag ends with `/>`. */\n readonly selfClosing: boolean;\n /** Whether an attribute name starts with `xmlns` (a namespace declaration may be among them). */\n readonly declaresNamespace: boolean;\n /** The buffer index one past the `>`. */\n readonly end: number;\n}\n\n/** The kinds of markup whose end may lie in a later chunk. */\ntype PendingKind = \"decl\" | \"comment\" | \"cdata\" | \"pi\" | \"endtag\" | \"doctype\" | \"starttag\";\n\n/** The terminator of each fixed-terminator markup kind. */\nconst TERMINATORS: Readonly<Partial<Record<PendingKind, string>>> = {\n comment: \"-->\",\n cdata: \"]]>\",\n pi: \"?>\",\n endtag: \">\",\n};\n\n/**\n * An incomplete piece of markup at the end of the input so far: its text pieces (never joined\n * until the end is found, so a token spanning many chunks costs its length once) and the state\n * the terminator scan is in. `tail` holds the last characters of the pieces a fixed terminator\n * could straddle; `quote` is the open quote character (0 outside a value) of a start tag or a\n * DOCTYPE; `depth`, `comment`, `pi` and `run` track a DOCTYPE's internal subset.\n */\ninterface Pending {\n kind: PendingKind;\n readonly pieces: string[];\n tail: string;\n quote: number;\n depth: number;\n comment: boolean;\n pi: boolean;\n run: number;\n}\n\n/** One `xmlns` / `xmlns:prefix` declaration in scope. */\ninterface NamespaceBinding {\n /** The prefix; \"\" for the default namespace. */\n readonly prefix: string;\n /** The namespace URI; \"\" undeclares the default namespace. */\n readonly uri: string;\n /** The element depth that declared it (the stack length before the element was pushed). */\n readonly depth: number;\n}\n\n/** The namespace the `xml` prefix is bound to by definition. */\nconst XML_NAMESPACE = \"http://www.w3.org/XML/1998/namespace\";\n\n/** The markup declarations a truncated `<!...` at the end of the input may have been cut from. */\nconst DECLARATION_OPENERS: readonly string[] = [\"<!--\", \"<![CDATA[\", \"<!DOCTYPE\"];\n\n/**\n * The tokenizer state: the unconsumed tail of the input, the current line, the open element\n * stack and the text run being accumulated. `push()` chunks, then `finish()`.\n * @category Plugin helpers\n */\nexport class XmlTokenizer {\n private readonly handler: XmlHandler;\n\n /** Unconsumed input that is not part of a pending token: at most a held-back entity or the last chunk. */\n private buffer = \"\";\n\n /** The markup whose end has not arrived yet, or null. */\n private pending: Pending | null = null;\n\n /** The line number at the start of `buffer` (or of the pending markup). */\n private line = 1;\n\n /**\n * The index of the next line break in `buffer` at or after the last counted position: -2\n * when not yet searched for the current buffer, -1 when the buffer holds no further break.\n */\n private nextBreak = -2;\n\n /** A CR held back from the end of the previous chunk (it may be the first half of CR LF). */\n private pendingCr = false;\n\n /** Whether the input has ended (an incomplete token is then an error, not a wait). */\n private final = false;\n\n /** The text run being accumulated (entities decoded), and the line it started on. */\n private text = \"\";\n\n private textLine = 1;\n\n private readonly stack: string[] = [];\n\n private rootSeen = false;\n\n private rootClosed = false;\n\n /** Whether any markup was consumed (an input with none is empty, not malformed). */\n private markupSeen = false;\n\n /** Whether nothing has been consumed yet: the XML declaration may only appear here. */\n private atStart = true;\n\n /** Whether a DOCTYPE declaration was read (one is allowed, in the prolog). */\n private doctypeSeen = false;\n\n /** The version of the XML declaration, or null. */\n private version: string | null = null;\n\n /** The last two characters of the character data since the last markup, for the `]]>` check. */\n private textTail = \"\";\n\n /** A high surrogate held back from the end of the previous chunk (its low half may start the next). */\n private pendingHigh = \"\";\n\n /** The namespace declarations in scope, innermost last. */\n private readonly bindings: NamespaceBinding[] = [];\n\n private readonly repairs: XmlRepairs | undefined;\n\n /**\n * Create a tokenizer.\n * @param handler - the event sink\n * @param repairs - the opt-in repairs (XGMML only); none by default\n */\n constructor(handler: XmlHandler, repairs?: XmlRepairs) {\n this.handler = handler;\n this.repairs = repairs;\n }\n\n /**\n * Whether the document's XML declaration says version 1.1 (read by the XML 1.0 rules all the\n * same; the syntax error of a 1.1-only construct then says why).\n * @returns true after a `<?xml version=\"1.1\"?>` declaration\n */\n get declaresXml11(): boolean {\n return this.version === \"1.1\";\n }\n\n /**\n * Feed one chunk and emit every complete token in it.\n * @param chunk - the text\n */\n push(chunk: string): void {\n let text = chunk;\n if (this.pendingHigh.length > 0) {\n text = this.pendingHigh + text;\n this.pendingHigh = \"\";\n }\n const last = text.charCodeAt(text.length - 1); // NOSONAR(S7758): reads UTF-16 code units on purpose\n if (last >= 0xd800 && last <= 0xdbff) {\n // a text chunk may end between the two halves of an astral character\n this.pendingHigh = text.slice(-1);\n text = text.slice(0, -1);\n }\n if (this.pendingCr) {\n text = `\\r${text}`;\n this.pendingCr = false;\n }\n if (text.endsWith(\"\\r\")) {\n this.pendingCr = true;\n text = text.slice(0, -1);\n }\n if (text.includes(\"\\r\")) {\n text = text.replaceAll(/\\r\\n?/g, \"\\n\");\n }\n this.feed(text);\n }\n\n /** Signal the end of the input: flush the last text run and check well-formedness. */\n finish(): void {\n this.final = true;\n const held = this.pendingHigh;\n this.pendingHigh = \"\";\n if (this.pendingCr) {\n this.pendingCr = false;\n this.feed(`\\n${held}`);\n } else {\n this.feed(held);\n }\n if (this.pending !== null || this.buffer.length > 0) {\n throw new XmlSyntaxError(\"unexpected end of input inside markup\", this.line);\n }\n this.flushText();\n if (this.stack.length > 0) {\n throw new XmlSyntaxError(`unclosed element <${this.stack[this.stack.length - 1]}>`, this.line);\n }\n if (!this.rootSeen) {\n if (!this.markupSeen) {\n throw new XmlEmptyInputError(this.line);\n }\n throw new XmlSyntaxError(\"no root element\", this.line);\n }\n }\n\n /**\n * Append normalized text: continue a pending token's terminator scan over the new text alone,\n * and once the token is complete (or when none is pending) scan the buffer for tokens.\n * @param text - the text, line breaks normalized\n */\n private feed(text: string): void {\n const { pending } = this;\n if (pending === null) {\n this.buffer = this.buffer.length === 0 ? text : this.buffer + text;\n this.nextBreak = -2;\n this.scan();\n return;\n }\n if (pending.kind === \"decl\") {\n // fewer than MIN_DECIDABLE_MARKUP characters of markup: the kind is decided once enough arrived\n this.pending = null;\n this.buffer = pending.pieces.join(\"\") + text;\n this.nextBreak = -2;\n this.scan();\n return;\n }\n const end = this.scanPending(pending, text);\n if (end < 0) {\n if (text.length > 0) {\n pending.pieces.push(text);\n }\n if (this.final) {\n throw new XmlSyntaxError(\"unexpected end of input inside markup\", this.line);\n }\n return;\n }\n this.pending = null;\n pending.pieces.push(text.slice(0, end));\n this.buffer = pending.pieces.join(\"\") + text.slice(end);\n this.nextBreak = -2;\n this.scan();\n }\n\n /**\n * Continue the terminator scan of a pending token over new text.\n * @param pending - the pending token\n * @param text - the new text\n * @returns the index in `text` one past the token's end, or -1 when it does not end there\n */\n private scanPending(pending: Pending, text: string): number {\n switch (pending.kind) {\n case \"starttag\":\n return this.scanStartTag(pending, text, 0);\n case \"doctype\":\n return this.scanDoctype(pending, text, 0);\n case \"decl\":\n return -1;\n default: {\n const terminator = TERMINATORS[pending.kind] ?? \">\";\n const probe = pending.tail + text;\n const at = probe.indexOf(terminator);\n if (at < 0) {\n pending.tail = probe.slice(Math.max(0, probe.length - (terminator.length - 1)));\n return -1;\n }\n return at + terminator.length - pending.tail.length;\n }\n }\n }\n\n /**\n * Scan text for the `>` that ends a start tag, skipping quoted attribute values (the quote\n * state survives between calls).\n * @param pending - the pending token\n * @param text - the text\n * @param from - where to start\n * @returns the index one past the `>`, or -1\n */\n private scanStartTag(pending: Pending, text: string, from: number): number {\n let { quote } = pending;\n const n = text.length;\n let i = from;\n while (i < n) {\n if (quote !== 0) {\n // inside an attribute value: jump to its closing quote\n const close = text.indexOf(String.fromCharCode(quote), i);\n if (close < 0) {\n break;\n }\n quote = 0;\n i = close + 1;\n continue;\n }\n const c = text.charCodeAt(i);\n if (c === QUOTE || c === APOS) {\n quote = c;\n } else if (c === GT) {\n pending.quote = 0;\n return i + 1;\n }\n i++;\n }\n pending.quote = quote;\n return -1;\n }\n\n /**\n * Scan text for the `>` that ends a DOCTYPE declaration, skipping a bracketed internal subset,\n * quoted literals and comments inside the subset. A character state machine, so the state\n * (`depth`, `quote`, `comment`, and `run`, the progress through a `<!--` or the dashes before\n * a `-->`) survives between calls and nothing is re-read.\n * @param pending - the pending token\n * @param text - the text\n * @param from - where to start\n * @returns the index one past the `>`, or -1\n */\n private scanDoctype(pending: Pending, text: string, from: number): number {\n let { quote, depth, comment, pi, run } = pending;\n for (let i = from; i < text.length; i++) {\n const c = text.charCodeAt(i);\n if (pi) {\n // a processing instruction in the subset ends at `?>`; quotes inside it are text\n if (c === GT && run === 1) {\n pi = false;\n run = 0;\n } else {\n run = c === QUESTION ? 1 : 0;\n }\n continue;\n }\n if (comment) {\n if (c === DASH) {\n run++;\n } else if (c === GT && run >= 2) {\n comment = false;\n run = 0;\n } else {\n run = 0;\n }\n continue;\n }\n if (quote !== 0) {\n if (c === quote) {\n quote = 0;\n }\n continue;\n }\n if (depth > 0) {\n if (run === 1 && c === BANG) {\n run = 2;\n continue;\n }\n if (run === 2 && c === DASH) {\n run = 3;\n continue;\n }\n if (run === 3 && c === DASH) {\n comment = true;\n run = 0;\n continue;\n }\n if (run === 1 && c === QUESTION) {\n pi = true;\n run = 0;\n continue;\n }\n run = 0;\n if (c === LT) {\n run = 1;\n continue;\n }\n }\n if (c === QUOTE || c === APOS) {\n quote = c;\n } else if (c === OPEN_BRACKET) {\n depth++;\n } else if (c === CLOSE_BRACKET) {\n depth--;\n } else if (c === GT && depth <= 0) {\n pending.quote = 0;\n pending.depth = 0;\n pending.comment = false;\n pending.pi = false;\n pending.run = 0;\n return i + 1;\n }\n }\n pending.quote = quote;\n pending.depth = depth;\n pending.comment = comment;\n pending.pi = pi;\n pending.run = run;\n return -1;\n }\n\n /**\n * Consume every complete token at the front of the buffer; an incomplete token at its end\n * becomes the pending token (its text moved out of the buffer), a possibly split entity\n * reference is held back in the buffer.\n */\n private scan(): void {\n const { buffer } = this;\n const { length } = buffer;\n let pos = 0;\n let incomplete = false;\n for (;;) {\n const lt = buffer.indexOf(\"<\", pos);\n if (lt < 0) {\n let end = length;\n if (!this.final) {\n // an entity reference may be split across chunks: hold back from its \"&\"\n const amp = buffer.lastIndexOf(\"&\");\n if (\n amp >= pos &&\n !buffer.includes(\";\", amp) &&\n // ponytail: a zero-padded reference longer than MAX_ENTITY_LENGTH is held back\n // whole, so an absurdly long run of zeros is re-scanned once per chunk\n (amp >= length - MAX_ENTITY_LENGTH || /^&#[xX]?0[\\da-fA-F]*$/.test(buffer.slice(amp)))\n ) {\n end = amp;\n }\n if (this.repairs?.surrogatePair !== undefined) {\n end = this.holdHighSurrogate(pos, end);\n }\n }\n this.takeText(pos, end);\n pos = end;\n break;\n }\n if (lt > pos) {\n this.takeText(pos, lt);\n pos = lt;\n }\n const next = this.consumeMarkup(pos);\n if (next < 0) {\n incomplete = true;\n break;\n }\n pos = next;\n }\n if (incomplete) {\n this.pending = this.startPending(buffer, pos);\n this.buffer = \"\";\n } else {\n this.buffer = pos === 0 ? buffer : buffer.slice(pos);\n }\n this.nextBreak = -2;\n }\n\n /**\n * Turn the incomplete markup at `pos` into a pending token, running the terminator scan over\n * the part already in the buffer so later chunks are scanned alone.\n * @param buffer - the buffer\n * @param pos - the index of the `<`\n * @returns the pending token\n */\n private startPending(buffer: string, pos: number): Pending {\n const piece = pos === 0 ? buffer : buffer.slice(pos);\n const pending: Pending = {\n kind: \"starttag\",\n pieces: [piece],\n tail: \"\",\n quote: 0,\n depth: 0,\n comment: false,\n pi: false,\n run: 0,\n };\n if (piece.length < MIN_DECIDABLE_MARKUP) {\n // too short to tell a comment from a start tag: wait for more before choosing a scan\n pending.kind = \"decl\";\n return pending;\n }\n if (piece.startsWith(\"<!--\")) {\n pending.kind = \"comment\";\n } else if (piece.startsWith(\"<![CDATA[\")) {\n pending.kind = \"cdata\";\n } else if (piece.startsWith(\"<!DOCTYPE\")) {\n pending.kind = \"doctype\";\n } else if (piece.startsWith(\"<!\")) {\n pending.kind = \"decl\";\n return pending;\n } else if (piece.startsWith(\"<?\")) {\n pending.kind = \"pi\";\n } else if (piece.startsWith(\"</\")) {\n pending.kind = \"endtag\";\n }\n // the part in the buffer holds no terminator (consumeMarkup said so); record the scan state\n switch (pending.kind) {\n case \"starttag\":\n this.scanStartTag(pending, piece, 1);\n break;\n case \"doctype\":\n this.scanDoctype(pending, piece, 9);\n break;\n default: {\n const terminator = TERMINATORS[pending.kind] ?? \">\";\n pending.tail = piece.slice(Math.max(0, piece.length - (terminator.length - 1)));\n break;\n }\n }\n return pending;\n }\n\n /**\n * Consume the markup starting at `pos` (a `<`).\n * @param pos - the index of the `<`\n * @returns the index after the markup, or -1 when the buffer ends before the markup does\n */\n private consumeMarkup(pos: number): number {\n const end = this.markupEnd(pos);\n if (end >= 0) {\n this.markupSeen = true;\n this.atStart = false;\n // markup ends a run of character data: a `]]>` cannot straddle it\n this.textTail = \"\";\n }\n return end;\n }\n\n /**\n * Read the markup starting at `pos` (a `<`) and deliver what it means.\n * @param pos - the index of the `<`\n * @returns the index after the markup, or -1 when the buffer ends before the markup does\n */\n private markupEnd(pos: number): number {\n const { buffer } = this;\n if (buffer.startsWith(\"<!\", pos)) {\n return this.declarationEnd(pos);\n }\n if (buffer.startsWith(\"<?\", pos)) {\n const end = buffer.indexOf(\"?>\", pos + 2);\n if (end < 0) {\n return -1;\n }\n this.processingInstruction(pos, end);\n this.advanceLine(pos, end + 2);\n return end + 2;\n }\n if (buffer.startsWith(\"</\", pos)) {\n const end = buffer.indexOf(\">\", pos + 2);\n if (end < 0) {\n return -1;\n }\n // whitespace may follow the name, never precede it\n const name = buffer.slice(pos + 2, end).trimEnd();\n if (!isXmlName(name)) {\n throw new XmlSyntaxError(`malformed end tag </${name}>`, this.line);\n }\n this.flushText();\n this.endElement(name);\n this.advanceLine(pos, end + 1);\n return end + 1;\n }\n const tag = this.parseStartTag(pos);\n if (tag === null) {\n return -1;\n }\n this.flushText();\n this.startElement(tag.name, tag.attrs, tag.declaresNamespace);\n if (tag.selfClosing) {\n this.endElement(tag.name);\n }\n this.advanceLine(pos, tag.end);\n return tag.end;\n }\n\n /**\n * Read the CDATA section at `pos` into the text.\n * @param pos - the index of the `<`\n * @returns the index after the section, or -1 when the buffer ends before the section does\n */\n private cdataEnd(pos: number): number {\n const end = this.buffer.indexOf(\"]]>\", pos + 9);\n if (end < 0) {\n return -1;\n }\n if (this.text.length === 0) {\n this.textLine = this.line;\n }\n const cdata = this.buffer.slice(pos + 9, end);\n const bad = illegalCharIndex(cdata);\n if (bad >= 0) {\n throw new XmlSyntaxError(\n \"a character XML 1.0 forbids appears in a CDATA section\",\n this.lineIn(pos, pos + 9 + bad),\n );\n }\n this.text += cdata;\n this.advanceLine(pos, end + 3);\n return end + 3;\n }\n\n /**\n * Read the `<!...>` markup at `pos`: a comment, a CDATA section or the DOCTYPE.\n * @param pos - the index of the `<`\n * @returns the index after the markup, or -1 when the buffer ends before the markup does\n */\n private declarationEnd(pos: number): number {\n const { buffer } = this;\n if (buffer.length - pos < MIN_DECIDABLE_MARKUP) {\n // \"<![CDATA[\" is 9 characters; wait until the kind of declaration is decidable, and at\n // the end of the input read the start of one cut short as a truncation\n const head = buffer.slice(pos);\n if (!this.final || DECLARATION_OPENERS.some((opener) => opener.startsWith(head))) {\n return -1;\n }\n }\n if (buffer.startsWith(\"<!--\", pos)) {\n const end = buffer.indexOf(\"-->\", pos + 4);\n if (end < 0) {\n return -1;\n }\n // a \"--\" inside, which XML 1.0 forbids, is accepted: the comment carries no data\n this.advanceLine(pos, end + 3);\n return end + 3;\n }\n if (buffer.startsWith(\"<![CDATA[\", pos)) {\n return this.cdataEnd(pos);\n }\n if (!buffer.startsWith(\"<!DOCTYPE\", pos)) {\n if (buffer.slice(pos + 2, pos + 9).toUpperCase() === \"DOCTYPE\") {\n throw new XmlSyntaxError(\n `<!${buffer.slice(pos + 2, pos + 9)}> is not XML (it must be written <!DOCTYPE>); the input looks like an HTML document`,\n this.line,\n );\n }\n throw new XmlSyntaxError(\"unexpected markup declaration\", this.line);\n }\n if (this.rootSeen || this.doctypeSeen) {\n throw new XmlSyntaxError(\"a DOCTYPE declaration is allowed once, before the root element\", this.line);\n }\n const state: Pending = {\n kind: \"doctype\",\n pieces: [],\n tail: \"\",\n quote: 0,\n depth: 0,\n comment: false,\n pi: false,\n run: 0,\n };\n const end = this.scanDoctype(state, buffer, pos + 9);\n if (end < 0) {\n return -1;\n }\n this.doctypeSeen = true;\n this.handler.doctype?.(buffer.slice(pos, end), this.line);\n this.advanceLine(pos, end);\n return end;\n }\n\n /**\n * Check a processing instruction `<?target ...?>` (skipped otherwise): its target must be a\n * name, and the reserved target `xml` is the XML declaration, allowed only at the very start\n * of the document with a 1.x version.\n * @param pos - the index of the `<`\n * @param end - the index of the `?>`\n */\n private processingInstruction(pos: number, end: number): void {\n const body = this.buffer.slice(pos + 2, end);\n const target = /^[^\\s]*/.exec(body)?.[0] ?? \"\";\n if (!isXmlName(target)) {\n throw new XmlSyntaxError(`a processing instruction needs a target name, not \"${target}\"`, this.line);\n }\n if (target.toLowerCase() !== \"xml\") {\n return;\n }\n if (target !== \"xml\") {\n throw new XmlSyntaxError(\n `<?${target} is not an XML declaration (which is written <?xml in lower case); the target is reserved`,\n this.line,\n );\n }\n if (!this.atStart || pos !== 0) {\n throw new XmlSyntaxError(\n \"an XML declaration (<?xml ...?>) may appear only at the very start of the document; the target xml is reserved\",\n this.line,\n );\n }\n const version = /\\bversion\\s*=\\s*([\"'])([^\"']*)\\1/.exec(body)?.[2];\n if (version === undefined) {\n throw new XmlSyntaxError(\"the XML declaration has no version\", this.line);\n }\n if (!/^1\\.\\d+$/.test(version)) {\n throw new XmlSyntaxError(`XML version ${version} is not supported (only 1.x)`, this.line);\n }\n this.version = version;\n }\n\n /**\n * The line of a buffer position after `start`, the position the current line count refers to.\n * Used on the error path only.\n * @param start - a position on line `this.line`\n * @param at - the position\n * @returns its line\n */\n private lineIn(start: number, at: number): number {\n return lineAt(this.buffer.slice(start, at), at - start, this.line);\n }\n\n /**\n * Decode the entities of a text, naming XML 1.1 when a character reference XML 1.0 forbids\n * appears in a document that declares version 1.1.\n * @param raw - the text as written\n * @param line - the line the text starts on\n * @returns the decoded text\n */\n private decode(raw: string, line: number): string {\n try {\n return decodeEntities(raw, line, this.repairs);\n } catch (err) {\n if (err instanceof XmlSyntaxError && this.version !== null && this.version !== \"1.0\") {\n throw new XmlSyntaxError(\n `${err.message} (the document declares XML ${this.version}, whose character rules are not supported; it is read as XML 1.0)`,\n err.line,\n );\n }\n throw err;\n }\n }\n\n /**\n * Parse a start tag at `pos`.\n * @param pos - the index of the `<`\n * @returns the tag, or null when the buffer ends inside it\n */\n private parseStartTag(pos: number): StartTag | null {\n const { buffer } = this;\n const { length } = buffer;\n let i = pos + 1;\n const nameEnd = this.readName(i);\n if (nameEnd < 0) {\n return null;\n }\n if (nameEnd === i) {\n throw new XmlSyntaxError(\"expected an element name after <\", this.line);\n }\n const name = buffer.slice(i, nameEnd);\n i = nameEnd;\n const attrs = new Map<string, string>();\n let declaresNamespace = false;\n for (;;) {\n const before = i;\n while (i < length && isSpace(buffer.charCodeAt(i))) {\n i++;\n }\n if (i >= length) {\n return null;\n }\n const c = buffer.charCodeAt(i);\n if (c === GT) {\n return { name, attrs, selfClosing: false, declaresNamespace, end: i + 1 };\n }\n if (c === SLASH) {\n if (i + 1 >= length) {\n return null;\n }\n if (buffer.charCodeAt(i + 1) !== GT) {\n throw new XmlSyntaxError(`unexpected \"/\" in <${name}>`, this.lineIn(pos, i));\n }\n return { name, attrs, selfClosing: true, declaresNamespace, end: i + 2 };\n }\n if (i === before) {\n // the name, or the previous value's closing quote, runs into the next attribute\n throw new XmlSyntaxError(\n `the attributes of <${name}> must be separated by whitespace`,\n this.lineIn(pos, i),\n );\n }\n const attrEnd = this.readName(i);\n if (attrEnd < 0) {\n return null;\n }\n if (attrEnd === i) {\n throw new XmlSyntaxError(`malformed attribute in <${name}>`, this.lineIn(pos, i));\n }\n const attrName = buffer.slice(i, attrEnd);\n i = attrEnd;\n while (i < length && isSpace(buffer.charCodeAt(i))) {\n i++;\n }\n if (i >= length) {\n return null;\n }\n if (buffer.charCodeAt(i) !== EQUALS) {\n throw new XmlSyntaxError(`attribute ${attrName} of <${name}> has no value`, this.lineIn(pos, i));\n }\n i++;\n while (i < length && isSpace(buffer.charCodeAt(i))) {\n i++;\n }\n if (i >= length) {\n return null;\n }\n const quote = buffer.charCodeAt(i);\n if (quote !== QUOTE && quote !== APOS) {\n throw new XmlSyntaxError(`attribute ${attrName} of <${name}> is not quoted`, this.lineIn(pos, i));\n }\n const close = buffer.indexOf(quote === QUOTE ? '\"' : \"'\", i + 1);\n if (close < 0) {\n return null;\n }\n const line = this.lineIn(pos, i);\n if (attrs.has(attrName)) {\n throw new XmlSyntaxError(`duplicate attribute ${attrName} in <${name}>`, line);\n }\n const raw = buffer.slice(i + 1, close);\n if (hasIllegalXmlChar(raw)) {\n throw new XmlSyntaxError(\n `a character XML 1.0 forbids appears in attribute ${attrName} of <${name}>`,\n line,\n );\n }\n if (raw.includes(\"<\")) {\n throw new XmlSyntaxError(`a \"<\" in the value of attribute ${attrName} of <${name}> (write &lt;)`, line);\n }\n if (attrName.startsWith(\"xmlns\")) {\n declaresNamespace = true;\n }\n attrs.set(attrName, this.decode(normalizeAttributeValue(raw), line));\n i = close + 1;\n }\n }\n\n /**\n * The end of the XML Name starting at `i` (an ASCII table for the common case, the code point\n * classes beyond it).\n * @param i - the start index\n * @returns the index after the name; `i` when no name starts there; -1 when the name may\n * continue past the end of the buffer\n */\n private readName(i: number): number {\n const { buffer } = this;\n const { length } = buffer;\n let j = i;\n while (j < length) {\n const c = buffer.charCodeAt(j);\n if (c < 0x80) {\n if ((j === i ? ASCII_NAME_START[c] : ASCII_NAME_CHAR[c]) === 0) {\n break;\n }\n j++;\n continue;\n }\n const cp = buffer.codePointAt(j);\n if (cp === undefined || (j === i ? !isNameStart(cp) : !isNameChar(cp))) {\n break;\n }\n j += cp > 0xffff ? 2 : 1;\n }\n return j >= length && !this.final ? -1 : j;\n }\n\n /**\n * Under the surrogate-pair repair, hold back a high-surrogate character reference that ends\n * the text taken so far, so it is decoded together with the low one the next chunk may start with.\n * @param pos - the start of the text\n * @param end - the end of the text that would be taken\n * @returns the end to take up to\n */\n private holdHighSurrogate(pos: number, end: number): number {\n const tail = this.buffer.slice(Math.max(pos, end - 12), end);\n const match = TRAILING_CHAR_REFERENCE.exec(tail);\n if (match === null) {\n return end;\n }\n const unit = match[1] === undefined ? Number.parseInt(match[2], 10) : Number.parseInt(match[1], 16);\n return unit >= 0xd800 && unit <= 0xdbff ? end - match[0].length : end;\n }\n\n /**\n * Move text from the buffer into the current run.\n * @param start - the start index\n * @param end - the end index (exclusive)\n */\n private takeText(start: number, end: number): void {\n if (end <= start) {\n return;\n }\n if (this.text.length === 0) {\n this.textLine = this.line;\n }\n const raw = this.buffer.slice(start, end);\n const bad = illegalCharIndex(raw);\n if (bad >= 0) {\n throw new XmlSyntaxError(\n \"a character XML 1.0 forbids appears in character data\",\n lineAt(raw, bad, this.line),\n );\n }\n if (raw.includes(\">\")) {\n const probe = this.textTail + raw;\n const close = probe.indexOf(\"]]>\");\n if (close >= 0) {\n throw new XmlSyntaxError(\n '\"]]>\" is not allowed in character data (write ]]&gt;)',\n lineAt(raw, Math.max(0, close - this.textTail.length), this.line),\n );\n }\n }\n this.textTail = raw.length >= 2 ? raw.slice(-2) : (this.textTail + raw).slice(-2);\n this.atStart = false;\n this.text += this.decode(raw, this.line);\n this.advanceLine(start, end);\n }\n\n /**\n * Count the newlines of a consumed range. Ranges are consumed in order, so the next line break\n * is searched for once per buffer and re-searched only after it was passed; a buffer without\n * a further break is searched once and remembered as such.\n * @param start - the start index\n * @param end - the end index (exclusive)\n */\n private advanceLine(start: number, end: number): void {\n let i = this.nextBreak;\n if (i === -1) {\n return;\n }\n if (i === -2 || i < start) {\n i = this.buffer.indexOf(\"\\n\", start);\n }\n while (i >= 0 && i < end) {\n this.line++;\n i = this.buffer.indexOf(\"\\n\", i + 1);\n }\n this.nextBreak = i;\n }\n\n /** Deliver the accumulated text run, if any. */\n private flushText(): void {\n if (this.text.length === 0) {\n return;\n }\n const { text } = this;\n this.text = \"\";\n if (this.stack.length === 0) {\n if (!isWhitespace(text)) {\n throw new XmlSyntaxError(\"text outside the root element\", this.textLine);\n }\n return;\n }\n this.handler.text(text, this.textLine);\n }\n\n /**\n * Open an element.\n * @param name - the element name\n * @param attrs - its attributes\n * @param declaresNamespace - whether an attribute name starts with `xmlns`\n */\n private startElement(name: string, attrs: Map<string, string>, declaresNamespace: boolean): void {\n if (this.stack.length === 0) {\n if (this.rootClosed) {\n throw new XmlSyntaxError(`a second root element <${name}> follows the document element`, this.line);\n }\n this.rootSeen = true;\n }\n if (declaresNamespace) {\n for (const [key, uri] of attrs) {\n if (key === \"xmlns\") {\n this.bindings.push({ prefix: \"\", uri, depth: this.stack.length });\n } else if (key.startsWith(\"xmlns:\")) {\n this.bindings.push({ prefix: key.slice(6), uri, depth: this.stack.length });\n }\n }\n }\n this.stack.push(name);\n this.handler.start(name, attrs, this.line, this.namespaceOf(name));\n }\n\n /**\n * The namespace an element name is in (Namespaces in XML 1.0 section 6).\n * @param name - the element name as written\n * @returns the URI; \"\" for no namespace; null for an undeclared prefix or a name that is not\n * namespace-well-formed\n */\n private namespaceOf(name: string): string | null {\n const colon = name.indexOf(\":\");\n if (colon >= 0 && (colon === 0 || colon === name.length - 1 || name.includes(\":\", colon + 1))) {\n return null;\n }\n const prefix = colon < 0 ? \"\" : name.slice(0, colon);\n for (let i = this.bindings.length - 1; i >= 0; i--) {\n if (this.bindings[i].prefix === prefix) {\n return this.bindings[i].uri;\n }\n }\n if (prefix === \"xml\") {\n return XML_NAMESPACE;\n }\n return prefix === \"\" ? \"\" : null;\n }\n\n /**\n * Close an element, checking that it matches the innermost open one.\n * @param name - the element name\n */\n private endElement(name: string): void {\n const open = this.stack.at(-1) ?? null;\n if (open === null) {\n throw new XmlSyntaxError(`unexpected end tag </${name}>`, this.line);\n }\n if (open !== name) {\n throw new XmlSyntaxError(`end tag </${name}> does not match <${open}>`, this.line);\n }\n this.stack.pop();\n while ((this.bindings.at(-1)?.depth ?? -1) >= this.stack.length) {\n this.bindings.pop();\n }\n if (this.stack.length === 0) {\n this.rootClosed = true;\n }\n this.handler.end(name, this.line);\n }\n}\n\n/**\n * Attribute value normalization (XML 1.0 section 3.3.3): a literal tab or line break becomes a\n * space; a character reference to one is kept, which is why this runs before entity decoding.\n * @param raw - the value between the quotes\n * @returns the normalized value\n */\nfunction normalizeAttributeValue(raw: string): string {\n return raw.includes(\"\\n\") || raw.includes(\"\\t\") ? raw.replaceAll(/[\\n\\t]/g, \" \") : raw;\n}\n","/**\n * Id, label and value escaping for the text formats (design section 8.5), one function per\n * syntax, with the inverse where the importer needs it: XML attribute and element text (GEXF,\n * GraphML), GML quoted strings (`\"` and `&` and non-ASCII as `&#NN;` character entities, the\n * NetworkX convention), DOT ids (bare when the grammar allows, quoted with `\\\"` otherwise), RFC\n * 4180 CSV cells and Pajek labels.\n */\n\nimport { GraphFormatError } from \"@graphty/graph-format\";\n\nimport { hasIllegalXmlChar } from \"./xml.js\";\n\nconst XML_TEXT_SPECIAL = /[&<>\\r]/g;\nconst XML_ATTR_SPECIAL = /[&<>\"\\t\\n\\r]/g;\nconst XML_REPLACEMENTS: Readonly<Record<string, string>> = {\n \"&\": \"&amp;\",\n \"<\": \"&lt;\",\n \">\": \"&gt;\",\n '\"': \"&quot;\",\n \"\\t\": \"&#9;\",\n \"\\n\": \"&#10;\",\n \"\\r\": \"&#13;\",\n};\n\n/**\n * Escape text for an XML element body: `&`, `<`, `>` and a carriage return (which XML\n * end-of-line handling would turn into a line feed on every read) as character references. A\n * character XML 1.0 forbids (a C0 control other than tab / LF / CR, U+FFFE, U+FFFF, a lone\n * surrogate) has no XML spelling at all and is E_COLUMN_TYPE; the exporters' check() counts them.\n * @param text - the text\n * @returns the escaped text\n * @category Plugin helpers\n */\nexport function escapeXmlText(text: string): string {\n if (hasIllegalXmlChar(text)) {\n throw illegalXml(text);\n }\n return text.replaceAll(XML_TEXT_SPECIAL, (c) => XML_REPLACEMENTS[c]);\n}\n\n/**\n * Escape text for a double-quoted XML attribute value: `&`, `<`, `>`, `\"` and the whitespace\n * characters attribute normalization would fold; a character XML 1.0 forbids is E_COLUMN_TYPE.\n * @param text - the text\n * @returns the escaped text\n * @category Plugin helpers\n */\nexport function escapeXmlAttribute(text: string): string {\n if (hasIllegalXmlChar(text)) {\n throw illegalXml(text);\n }\n return text.replaceAll(XML_ATTR_SPECIAL, (c) => XML_REPLACEMENTS[c]);\n}\n\n/**\n * The error of a text no XML 1.0 document can carry.\n * @param text - the text\n * @returns the error\n */\nfunction illegalXml(text: string): GraphFormatError {\n return new GraphFormatError(\"E_COLUMN_TYPE\", \"the text holds a character XML 1.0 cannot carry\", {\n reason: \"xml illegal char\",\n length: text.length,\n });\n}\n\nconst GML_SPECIAL = /[\"&]|[^ -~]/gu;\n\n/**\n * Quote a GML string value: double quotes around the text with `\"`, `&` and every character\n * outside printable ASCII written as `&#NN;` (NetworkX's writer convention, which its reader and\n * Gephi's decode).\n * A lone surrogate cannot be written and is E_COLUMN_TYPE.\n * @param text - the text\n * @returns the quoted GML string\n * @category Plugin helpers\n */\nexport function quoteGmlString(text: string): string {\n const escaped = text.replaceAll(GML_SPECIAL, (c) => {\n const code = c.codePointAt(0);\n if (code === undefined) {\n return c;\n }\n if (code >= 0xd800 && code <= 0xdfff) {\n throw new GraphFormatError(\"E_COLUMN_TYPE\", \"a lone surrogate cannot be written as a GML string\", {\n reason: \"lone surrogate\",\n });\n }\n return `&#${code};`;\n });\n return `\"${escaped}\"`;\n}\n\nconst GML_ENTITY = /&(#\\d+|#x[0-9a-fA-F]+|[A-Za-z][A-Za-z0-9]*);/g;\n\n/** The XML entities and the ISO-8859-1 HTML entities (U+00A0..U+00FF), which GML uses for characters above 127. */\nconst GML_NAMED: ReadonlyMap<string, string> = (() => {\n const table = new Map<string, string>([\n [\"amp\", \"&\"],\n [\"quot\", '\"'],\n [\"lt\", \"<\"],\n [\"gt\", \">\"],\n [\"apos\", \"'\"],\n ]);\n const latin1 = (\n \"nbsp iexcl cent pound curren yen brvbar sect uml copy ordf laquo not shy reg macr deg plusmn sup2 \" +\n \"sup3 acute micro para middot cedil sup1 ordm raquo frac14 frac12 frac34 iquest Agrave Aacute Acirc \" +\n \"Atilde Auml Aring AElig Ccedil Egrave Eacute Ecirc Euml Igrave Iacute Icirc Iuml ETH Ntilde Ograve \" +\n \"Oacute Ocirc Otilde Ouml times Oslash Ugrave Uacute Ucirc Uuml Yacute THORN szlig agrave aacute \" +\n \"acirc atilde auml aring aelig ccedil egrave eacute ecirc euml igrave iacute icirc iuml eth ntilde \" +\n \"ograve oacute ocirc otilde ouml divide oslash ugrave uacute ucirc uuml yacute thorn yuml\"\n ).split(\" \");\n latin1.forEach((name, i) => {\n table.set(name, String.fromCharCode(0xa0 + i));\n });\n return table;\n})();\n\n/**\n * Decode the character entities of a GML string body (the inverse of quoteGmlString on the text\n * between the quotes): numeric references, the XML entities and the ISO-8859-1 HTML entities. An\n * unknown named entity, or a numeric reference beyond U+10FFFF, is left as written and handed to\n * `onUnknown`.\n * @param body - the text between the quotes\n * @param onUnknown - called with each entity left as written (`&name;`, `&#99999999;`), when given\n * @returns the decoded text\n * @category Plugin helpers\n */\nexport function decodeGmlString(body: string, onUnknown?: (entity: string) => void): string {\n return body.replaceAll(GML_ENTITY, (whole, entity: string) => {\n if (entity.startsWith(\"#\")) {\n const code = entity.startsWith(\"#x\") ? Number.parseInt(entity.slice(2), 16) : Number(entity.slice(1));\n if (code <= 0x10ffff) {\n return String.fromCodePoint(code);\n }\n // beyond Unicode: no character to decode to, kept as written like an unknown name\n onUnknown?.(whole);\n return whole;\n }\n const known = GML_NAMED.get(entity);\n if (known === undefined) {\n onUnknown?.(whole);\n return whole;\n }\n return known;\n });\n}\n\nconst DOT_NUMERAL = /^-?(\\.\\d+|\\d+(\\.\\d*)?)$/;\nconst DOT_KEYWORDS: ReadonlySet<string> = new Set([\"node\", \"edge\", \"graph\", \"digraph\", \"subgraph\", \"strict\"]);\n\n/**\n * Whether a text is a DOT ID that needs no quotes: an alphanumeric identifier not starting with\n * a digit, or a numeral, and not a keyword (case-insensitive).\n * @param text - the text\n * @returns true when the text can be written bare\n * @category Plugin helpers\n */\nexport function isBareDotId(text: string): boolean {\n if (DOT_KEYWORDS.has(text.toLowerCase())) {\n return false;\n }\n return isDotIdentifier(text) || DOT_NUMERAL.test(text);\n}\n\n/**\n * Whether a text is a DOT identifier: a letter, underscore or any character of code 128 and\n * above, followed by letters, digits, underscores or such characters.\n * @param text - the text\n * @returns true for a bare identifier\n */\nfunction isDotIdentifier(text: string): boolean {\n if (text.length === 0) {\n return false;\n }\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i);\n const letter = (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c === 95 || c >= 128;\n const digit = c >= 48 && c <= 57;\n if (!letter && (i === 0 || !digit)) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Whether a text can be written as a DOT ID at all. Graphviz's scanner consumes a backslash pair\n * `\\\\` as one unit, `\\\"` as an escaped quote and a backslash before a line break as a line\n * continuation (both removed), left to right, so a backslash that precedes a double quote or a\n * line break, or ends the text, cannot be written: the written `\\\\\"` reads as a pair and a closing\n * quote, a backslash before a line break vanishes with the break, and a trailing backslash escapes\n * the closing quote. Every other text is writable; quoteDotId() writes it.\n * @param text - the id, name or value text\n * @returns true when quoteDotId(text) reads back as `text`\n * @category Plugin helpers\n */\nexport function isWritableDotText(text: string): boolean {\n return !text.endsWith(\"\\\\\") && !text.includes(String.raw`\\\"`) && !/\\\\[\\r\\n]/.test(text);\n}\n\n/**\n * Write a DOT ID: bare when the grammar allows, otherwise double-quoted with `\"` escaped as `\\\"`.\n * In DOT quoted strings the dyad `\\\"` is the only escape; every other character, a backslash and\n * a raw line break included, is kept as written, so nothing else is rewritten. A text ending in a\n * backslash has no DOT spelling (isWritableDotText); the caller refuses it before writing.\n * @param text - the id or label text\n * @returns the DOT ID\n * @category Plugin helpers\n */\nexport function quoteDotId(text: string): string {\n if (isBareDotId(text)) {\n return text;\n }\n const escaped = text.replaceAll('\"', String.raw`\\\"`);\n return `\"${escaped}\"`;\n}\n\n/**\n * Write a set CSV cell per RFC 4180: quoted, with the quote character doubled, when the text\n * contains the delimiter, the quote character, a CR or LF, or leading / trailing whitespace; bare\n * otherwise. The empty string is written as an empty quoted cell (`\"\"`), so the importers can tell a\n * set empty string (and an empty-string node id) from an unset cell, which every exporter writes as\n * nothing between the delimiters.\n * @param text - the cell text of a set cell\n * @param delimiter - the field delimiter (default \",\")\n * @param quote - the quote character (default `\"`)\n * @returns the cell as written\n * @category Plugin helpers\n */\nexport function quoteCsvCell(text: string, delimiter = \",\", quote = '\"'): string {\n if (text.length === 0) {\n return quote + quote;\n }\n if (\n !text.includes(delimiter) &&\n !text.includes(quote) &&\n !text.includes(\"\\n\") &&\n !text.includes(\"\\r\") &&\n text === text.trim()\n ) {\n return text;\n }\n return `${quote}${text.split(quote).join(quote + quote)}${quote}`;\n}\n\n/**\n * Whether a text can be a Pajek label: Pajek has no escape mechanism inside its double-quoted\n * labels, so a text containing a double quote, a CR or an LF cannot be written.\n * @param text - the label text\n * @returns true when quotePajekLabel() can write it\n * @category Plugin helpers\n */\nexport function isPajekLabel(text: string): boolean {\n return !text.includes('\"') && !text.includes(\"\\n\") && !text.includes(\"\\r\");\n}\n\n/**\n * Write a Pajek label: bare when it is a single run of non-space, non-quote characters that does\n * not start with `[` (a bare `[` opens a time set, which the reader groups up to its `]`),\n * otherwise double-quoted. E_UNSUPPORTED (reason \"pajek label\") for a text isPajekLabel() rejects;\n * the exporter's check() counts those.\n * @param text - the label text\n * @returns the label as written\n * @category Plugin helpers\n */\nexport function quotePajekLabel(text: string): string {\n if (!isPajekLabel(text)) {\n throw new GraphFormatError(\"E_UNSUPPORTED\", \"a Pajek label cannot contain a double quote or a line break\", {\n reason: \"pajek label\",\n value: text,\n });\n }\n // a bare `%` token starts a comment for the importer, so such a text is quoted too\n if (text.length > 0 && !/[\\s\"]/.test(text) && !text.startsWith(\"[\") && !text.startsWith(\"%\")) {\n return text;\n }\n return `\"${text}\"`;\n}\n"],"names":["end"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { GraphFormatError } from "@graphty/graph-format";
2
- import { a as CX2_FORMAT, s as stringify, d as directionNotes, p as planNodeIds, O as ORIGINAL_ID_ATTRIBUTE, b as planEdgeIds, e as cx2Type, f as aspectBlock, g as declaredType, B as BYPASS_NAMESPACE, n as nonFinitePositions } from "./importer-BfJ1jnNr.js";
2
+ import { a as CX2_FORMAT, s as stringify, d as directionNotes, p as planNodeIds, O as ORIGINAL_ID_ATTRIBUTE, b as planEdgeIds, e as cx2Type, f as aspectBlock, g as declaredType, B as BYPASS_NAMESPACE, n as nonFinitePositions } from "./importer-BJlGAOht.js";
3
3
  import { c as capabilities, L as LOSS, r as resolveExportOptions, p as pairFolding, e as explicitWeights, a as checkCapabilities, b as plural } from "./export-B-aVCwyG.js";
4
- import { i as isRecord, P as POSITION_COLUMN } from "./json-elements-CXs4z1iL.js";
4
+ import { i as isRecord, P as POSITION_COLUMN } from "./json-elements-DpO6AXIc.js";
5
5
  import { j as joinText, e as encodeChunks } from "./writer-DxjgHwSe.js";
6
6
  const CX2_LOSS = Object.freeze({
7
7
  /**
@@ -160,9 +160,10 @@ function capabilityNotes(snapshot, common, notes, note) {
160
160
  continue;
161
161
  }
162
162
  if (gen.code === LOSS.JSON) {
163
+ const what = gen.column === null ? "a column" : `column "${gen.column}"`;
163
164
  note(
164
165
  CX2_LOSS.JSON_AS_STRING,
165
- `${gen.column === null ? "a column" : `column "${gen.column}"`} holds nested values; written as a string attribute holding their JSON text`,
166
+ `${what} holds nested values; written as a string attribute holding their JSON text`,
166
167
  gen.column,
167
168
  gen.count
168
169
  );
@@ -565,4 +566,4 @@ export {
565
566
  CX2_LOSS as a,
566
567
  cx2Exporter as c
567
568
  };
568
- //# sourceMappingURL=exporter-BqKs1Q12.js.map
569
+ //# sourceMappingURL=exporter-6ocL_9x_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporter-6ocL_9x_.js","sources":["../../src/formats/cx2/exporter.ts"],"sourcesContent":["/**\n * The CX2 exporter (design/graph-io/cytoscape-and-obo/design.md section 1.3; graphty issue #307):\n * writes a snapshot as one CX2 document -- the descriptor, the pre-metadata, one\n * `attributeDeclarations` block (aliases from `origin.id`, defaults from `meta.default`),\n * `networkAttributes`, `nodes` (x / y from the position with y flipped back to screen coordinates,\n * `z` from the `z` column), `edges`, the `cx2.bypass` columns as `nodeBypasses` / `edgeBypasses`,\n * the opaque aspects a CX2 import kept (which returns its own style rules) and `status`.\n *\n * What CX2 cannot hold is announced by check() before anything is written: every edge is\n * directed (W_CX2_UNDIRECTED_AS_DIRECTED, W_MUTUAL_EXPANDED), node ids are integers (E_ID_CHARSET\n * unless `sanitizeIds: \"mangle\"`, which keeps the original in the `graphty:originalId` attribute\n * the importer restores), nested values are written as JSON text (W_CX2_JSON_AS_STRING), NaN and\n * the infinities as null (W_CX2_NONFINITE_AS_NULL), and the generic notes of checkCapabilities().\n */\n\nimport { type Column, GraphFormatError, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport {\n aspectBlock,\n declaredType,\n directionNotes,\n nonFinitePositions,\n planEdgeIds,\n planNodeIds,\n stringify,\n type WrittenIds,\n} from \"../../common/cx-export.js\";\nimport { type PairFolding, pairFolding } from \"../../common/direction.js\";\nimport { capabilities, checkCapabilities, LOSS } from \"../../common/export.js\";\nimport { isRecord, POSITION_COLUMN } from \"../../common/json-elements.js\";\nimport { type ResolvedExportOptions, resolveExportOptions } from \"../../common/options.js\";\nimport { plural } from \"../../common/plural.js\";\nimport { type ExplicitWeights, explicitWeights } from \"../../common/weights.js\";\nimport { encodeChunks, joinText } from \"../../common/writer.js\";\nimport { type CommonExportOptions, type ExportCapabilities, type GraphExporter, type LossNote } from \"../../types.js\";\nimport { BYPASS_NAMESPACE, CX2_FORMAT, cx2Type, ORIGINAL_ID_ATTRIBUTE } from \"./importer.js\";\n\n/**\n * The options of the CX2 exporter: the common export options; it has none of its own.\n * @category Built-in formats\n */\nexport type Cx2ExportOptions = CommonExportOptions;\n\n/**\n * The loss notes the CX2 exporter's check() returns, by name. A key is the\n * code without its severity and format prefixes.\n * @category Built-in formats\n */\nexport const CX2_LOSS = Object.freeze({\n /**\n * Every edge is written as directed, so an undirected graph, or the undirected edges of a mixed graph, read back\n * as directed.\n */\n UNDIRECTED_AS_DIRECTED: \"W_CX2_UNDIRECTED_AS_DIRECTED\",\n /** A nested (json) column is written as a string attribute holding its JSON text. */\n JSON_AS_STRING: \"W_CX2_JSON_AS_STRING\",\n /** NaN and the infinities cannot be written; they are written as null and read back unset. */\n NONFINITE_AS_NULL: \"W_CX2_NONFINITE_AS_NULL\",\n /** A mutual pair is written as two directed edges without its mark. */\n MUTUAL_EXPANDED: LOSS.MUTUAL_EXPANDED,\n /**\n * An attribute without the weight role is named like the key weights are written under; it reads back as the edge\n * weight, or is not written when the graph has weights of its own.\n */\n WEIGHT_KEY_CLASH: LOSS.WEIGHT_KEY_CLASH,\n /** A parent / parents column: CX2 has no containment. */\n HIERARCHY_DROPPED: LOSS.HIERARCHY,\n /** A start / end / timestamp column: CX2 has no time. */\n TEMPORAL_DROPPED: LOSS.TEMPORAL,\n /** An attribute with a role the format has no place for is written as a plain attribute; the role is lost. */\n ROLE_DROPPED: LOSS.ROLE,\n /**\n * An attribute type CX2 stores as another (a 32-bit float as double, an unsigned integer as long, a dictionary as\n * string); it reads back with that type.\n */\n DTYPE_UNSUPPORTED: LOSS.DTYPE,\n /**\n * Node ids the format cannot write, under `sanitizeIds: \"error\"`; the save fails with E_INVALID_ID. Pass\n * `sanitizeIds: \"mangle\"` to rewrite them.\n */\n ID_CHARSET: LOSS.ID_CHARSET,\n /** Node ids that are not integers under sanitizeIds \"mangle\": renumbered, originals kept. */\n ID_MANGLED: LOSS.ID_MANGLED,\n /** Edges without a usable id get generated integer ids. */\n EDGE_IDS_GENERATED: LOSS.EDGE_IDS_GENERATED,\n});\n\n/**\n * What CX2 keeps: directed multigraphs with self-loops, integer node ids,\n * required integer edge ids, declared string / double / integer / boolean columns and lists of\n * them, declared defaults, network attributes and the position role. f32, u32, u8 and dict columns\n * are written as the nearest declared type and read back as it.\n * @category Built-in formats\n */\nexport const CX2_CAPABILITIES: ExportCapabilities = capabilities({\n mixedDirection: false,\n multiEdges: true,\n selfLoops: true,\n edgeIds: \"required\",\n idCharset: \"integer\",\n dtypes: [\"string\", \"f64\", \"i32\", \"bool\"],\n components: false,\n lists: true,\n json: false,\n defaults: true,\n options: false,\n hierarchy: false,\n temporal: \"none\",\n graphAttributes: true,\n positions: true,\n viz: false,\n});\n\n/** The roles CX2 has a slot for, and the column names its importer gives them. */\nconst SLOT_ROLES: ReadonlySet<string> = new Set([\"label\", \"position\", \"id\"]);\nconst ROLE_NAMES: Readonly<Record<string, string>> = Object.freeze({\n label: \"name\",\n position: POSITION_COLUMN,\n});\n\n/** Roles whose columns are never written as attributes. */\nconst SKIPPED_ROLES: ReadonlySet<string> = new Set([\n \"directed\",\n \"pair\",\n \"mutual\",\n \"weight\",\n \"timeText\",\n \"originalId\",\n \"parent\",\n \"parents\",\n \"start\",\n \"end\",\n \"timestamp\",\n \"timestamps\",\n \"spells\",\n \"open\",\n \"spellsOpen\",\n \"position\",\n \"color\",\n \"size\",\n \"shape\",\n \"thickness\",\n]);\n\n/** The aspects the exporter writes itself; an opaque aspect of the same name is not written again. */\nconst CORE_ASPECTS: ReadonlySet<string> = new Set([\n \"nodes\",\n \"edges\",\n \"attributeDeclarations\",\n \"networkAttributes\",\n \"nodeBypasses\",\n \"edgeBypasses\",\n \"metaData\",\n \"status\",\n]);\n\n/** The weight attribute name. */\nconst WEIGHT_ATTRIBUTE = \"weight\";\n\n/** One attribute column as it will be written. */\ninterface AttributePlan {\n readonly column: Column;\n /** The full attribute name. */\n readonly name: string;\n /** The key used in v (the alias, or the name). */\n readonly key: string;\n /** The declared type text. */\n readonly d: string;\n /** Whether values are written as their JSON text (a json column). */\n readonly jsonText: boolean;\n}\n\n/** Everything export() and check() need, computed once. */\ninterface Plan {\n readonly notes: LossNote[];\n readonly fatal: GraphFormatError | null;\n readonly ids: WrittenIds | null;\n readonly folding: PairFolding;\n readonly weights: ExplicitWeights;\n readonly nodeAttrs: readonly AttributePlan[];\n readonly edgeAttrs: readonly AttributePlan[];\n readonly graphAttrs: readonly AttributePlan[];\n readonly nodeBypasses: readonly Column[];\n readonly edgeBypasses: readonly Column[];\n readonly position: Column | null;\n readonly positionZ: boolean;\n readonly z: Column | null;\n readonly edgeIds: readonly number[];\n readonly originalIds: boolean;\n}\n\n/**\n * Whether a column is a bypass column of a CX2 import.\n * @param column - the column\n * @returns true for the cx2.bypass namespace\n */\nfunction isBypass(column: Column): boolean {\n return column.meta.origin?.namespace === BYPASS_NAMESPACE;\n}\n\n/**\n * Whether a column is the z (stacking order) column.\n * @param column - the column\n * @returns true for the column marked by a Cytoscape-family importer\n */\nfunction isZ(column: Column): boolean {\n return column.meta.extra.cytoscape === \"z\";\n}\n\n/**\n * Count the non-finite numbers of a column.\n * @param column - the column\n * @returns how many set cells (or list items) are NaN or infinite\n */\nfunction nonFiniteCount(column: Column): number {\n const { dtype, itemDtype } = column.meta;\n const numeric =\n dtype === \"f32\" || dtype === \"f64\" || (dtype === \"list\" && (itemDtype === \"f32\" || itemDtype === \"f64\"));\n if (!numeric) {\n return 0;\n }\n let count = 0;\n for (let i = 0; i < column.length; i++) {\n if (!column.isSet(i)) {\n continue;\n }\n const value = column.value(i);\n if (dtype === \"list\") {\n if ((value as readonly number[]).some((v) => !Number.isFinite(v))) {\n count++;\n }\n } else if (!Number.isFinite(value)) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Plan the attribute columns of one table.\n * @param table - the table\n * @param skip - columns not written as attributes\n * @param rename - the written name of a column, when it differs (the label as `name`)\n * @param reserved - keys already used in v\n * @returns the plans\n */\nfunction planAttributes(\n table: Iterable<Column>,\n skip: (column: Column) => boolean,\n rename: (column: Column) => string,\n reserved: ReadonlySet<string> = new Set(),\n): AttributePlan[] {\n const plans: AttributePlan[] = [];\n const used = new Set<string>(reserved);\n const candidates = [...table].filter((c) => !skip(c));\n for (const column of candidates) {\n used.add(rename(column));\n }\n for (const column of candidates) {\n const name = rename(column);\n const { origin } = column.meta;\n let key = name;\n const alias = origin?.format === CX2_FORMAT && typeof origin.id === \"string\" ? origin.id : null;\n if (alias !== null && alias.length > 0 && alias !== name && !used.has(alias)) {\n key = alias;\n used.add(alias);\n }\n plans.push({ column, name, key, d: declaredType(column), jsonText: column.meta.dtype === \"json\" });\n }\n return plans;\n}\n\n/** A note-recording callback. */\ntype Note = (code: string, message: string, column?: string | null, count?: number | null) => void;\n\n/**\n * The generic notes of checkCapabilities(), adapted to CX2: bypass columns hold any JSON value,\n * ids are counted by planNodeIds(), nested values are written as JSON text, and only the node\n * label is written into the \"n\" slot (an edge label keeps its own name but loses its role).\n * @param snapshot - the snapshot\n * @param common - the resolved common options\n * @param notes - the notes so far, appended to\n * @param note - the recorder\n * @returns the fatal condition, or null\n */\nfunction capabilityNotes(\n snapshot: GraphSnapshot,\n common: ResolvedExportOptions,\n notes: LossNote[],\n note: Note,\n): GraphFormatError | null {\n let fatal: GraphFormatError | null = null;\n // bypass columns are written as bypasses, which hold any JSON value\n const bypassNames = new Set(\n [...snapshot.nodes, ...snapshot.edges].filter((c) => isBypass(c) || isZ(c)).map((c) => c.meta.name),\n );\n for (const gen of checkCapabilities(snapshot, CX2_CAPABILITIES, common, {\n roles: SLOT_ROLES,\n roleNames: ROLE_NAMES,\n // only the node label is written into the \"n\" slot; an edge label keeps its own name\n edgeRoleNames: {},\n })) {\n if (!keepGenericNote(gen, bypassNames)) {\n continue;\n }\n if (gen.code === LOSS.JSON) {\n const what = gen.column === null ? \"a column\" : `column \"${gen.column}\"`;\n note(\n CX2_LOSS.JSON_AS_STRING,\n `${what} holds nested values; written as a string attribute holding their JSON text`,\n gen.column,\n gen.count,\n );\n continue;\n }\n if (gen.code === LOSS.MIXED_DIRECTION_ERROR && fatal === null) {\n fatal = new GraphFormatError(\"E_DIRECTED\", gen.message, { reason: \"mixed direction\" });\n }\n notes.push(gen);\n }\n const edgeLabel = snapshot.edges.byRole(\"label\");\n if (edgeLabel !== null) {\n note(\n LOSS.ROLE,\n `edge column \"${edgeLabel.meta.name}\" (label) is written as a plain attribute; CX2 edges have no label slot and the role is lost`,\n edgeLabel.meta.name,\n edgeLabel.length - edgeLabel.nullCount,\n );\n }\n return fatal;\n}\n\n/**\n * Whether a generic note applies to CX2 as it stands.\n * @param gen - the generic note\n * @param bypassNames - the names of the columns written as bypasses\n * @returns false for a note CX2 drops or replaces\n */\nfunction keepGenericNote(gen: LossNote, bypassNames: ReadonlySet<string>): boolean {\n if (gen.column !== null && bypassNames.has(gen.column) && (gen.code === LOSS.JSON || gen.code === LOSS.DTYPE)) {\n return false;\n }\n // ids are counted by planNodeIds(): CX2 also keeps integer ids beyond 2^53, which the generic rule refuses\n return gen.code !== LOSS.ID_CHARSET && gen.code !== LOSS.ID_MANGLED;\n}\n\n/**\n * Note the NaN and infinite values written as null: attribute cells, explicit weights, positions.\n * @param snapshot - the snapshot\n * @param attrs - every planned attribute\n * @param weights - the explicit weights\n * @param position - the position column, or null\n * @param note - the recorder\n */\nfunction nonFiniteNote(\n snapshot: GraphSnapshot,\n attrs: readonly AttributePlan[],\n weights: ExplicitWeights,\n position: Column | null,\n note: Note,\n): void {\n let nonfinite = 0;\n for (const p of attrs) {\n nonfinite += nonFiniteCount(p.column);\n }\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (weights.isExplicit(e) && !Number.isFinite(weights.value(e))) {\n nonfinite++;\n }\n }\n if (position !== null) {\n nonfinite += nonFinitePositions(position);\n }\n if (nonfinite > 0) {\n note(\n CX2_LOSS.NONFINITE_AS_NULL,\n `${nonfinite} NaN or infinite value${plural(nonfinite)} cannot be written in CX2; written as null, they read back unset`,\n null,\n nonfinite,\n );\n }\n}\n\n/**\n * Plan the edge attributes, noting a plain `weight` column that clashes with the weight key.\n * @param snapshot - the snapshot\n * @param weights - the explicit weights\n * @param note - the recorder\n * @returns the edge attribute plans\n */\nfunction planEdgeAttributes(snapshot: GraphSnapshot, weights: ExplicitWeights, note: Note): AttributePlan[] {\n const plainWeight = snapshot.edges.get(WEIGHT_ATTRIBUTE);\n if (plainWeight !== null && plainWeight.meta.role === null) {\n note(\n LOSS.WEIGHT_KEY_CLASH,\n weights.weighted\n ? `edge column \"${WEIGHT_ATTRIBUTE}\" is not written: the explicit weights are written under that name`\n : `edge column \"${WEIGHT_ATTRIBUTE}\" reads back as the edge weight`,\n WEIGHT_ATTRIBUTE,\n null,\n );\n }\n return planAttributes(\n snapshot.edges,\n (c) =>\n (c.meta.role !== null && (SKIPPED_ROLES.has(c.meta.role) || c.meta.role === \"id\")) ||\n isBypass(c) ||\n (weights.weighted && c === plainWeight),\n (c) => c.meta.name,\n weights.weighted ? new Set([WEIGHT_ATTRIBUTE]) : new Set(),\n );\n}\n\n/**\n * Plan an export: the notes, the fatal condition and what is written.\n * @param snapshot - the snapshot\n * @param common - the resolved common options\n * @returns the plan\n */\nfunction plan(snapshot: GraphSnapshot, common: ResolvedExportOptions): Plan {\n const notes: LossNote[] = [];\n const note: Note = (code, message, column = null, count = null) => {\n notes.push(Object.freeze({ code, message, column, count }));\n };\n let fatal = capabilityNotes(snapshot, common, notes, note);\n\n const folding = pairFolding(snapshot);\n directionNotes(snapshot, folding, common, CX2_LOSS.UNDIRECTED_AS_DIRECTED, note);\n\n const planned = planNodeIds(snapshot, common, \"CX2\", ORIGINAL_ID_ATTRIBUTE, note);\n const ids = planned instanceof GraphFormatError ? null : planned;\n if (planned instanceof GraphFormatError) {\n fatal ??= planned;\n }\n\n const weights = explicitWeights(snapshot);\n const label = snapshot.nodes.byRole(\"label\");\n const nodeAttrs = planAttributes(\n snapshot.nodes,\n (c) => (c.meta.role !== null && SKIPPED_ROLES.has(c.meta.role)) || isBypass(c) || isZ(c),\n (c) => (c === label && !snapshot.nodes.has(\"name\") ? \"name\" : c.meta.name),\n ids !== null && ids.changed > 0 ? new Set([ORIGINAL_ID_ATTRIBUTE]) : new Set(),\n );\n const edgeAttrs = planEdgeAttributes(snapshot, weights, note);\n const graphAttrs = planAttributes(\n snapshot.graph,\n () => false,\n (c) => c.meta.name,\n ).map((p) => ({ ...p, key: p.name }));\n\n const position = snapshot.nodes.byRole(\"position\");\n nonFiniteNote(snapshot, [...nodeAttrs, ...edgeAttrs, ...graphAttrs], weights, position, note);\n\n const edgeIds = planEdgeIds(snapshot, note, ids);\n const z = [...snapshot.nodes].find(isZ) ?? null;\n const positionZ = position !== null && z === null && position.meta.extra.sourceDims === 3;\n return {\n notes,\n fatal,\n ids,\n folding,\n weights,\n nodeAttrs,\n edgeAttrs,\n graphAttrs,\n nodeBypasses: [...snapshot.nodes].filter(isBypass),\n edgeBypasses: [...snapshot.edges].filter(isBypass),\n position,\n positionZ,\n z,\n edgeIds,\n originalIds: ids !== null && ids.changed > 0,\n };\n}\n\n// ============================================================ writing\n\n/**\n * The value written for one cell.\n * @param p - the attribute plan\n * @param row - the row\n * @returns the value, or undefined for an unset cell\n */\nfunction cellValue(p: AttributePlan, row: number): unknown {\n const { column } = p;\n if (!column.isSet(row)) {\n return undefined;\n }\n const value = column.value(row);\n if (p.jsonText) {\n return JSON.stringify(value);\n }\n if (column.meta.dtype === \"list\" || column.meta.components > 1) {\n const items = Array.from(value as ArrayLike<unknown>);\n if (p.d === \"string\") {\n return JSON.stringify(items);\n }\n return items.some((v) => typeof v === \"number\" && !Number.isFinite(v)) ? null : items;\n }\n if (typeof value === \"number\" && !Number.isFinite(value)) {\n return null;\n }\n return value;\n}\n\n/**\n * The declarations of one table.\n * @param plans - the attribute plans\n * @param defaults - whether defaults and aliases may be written (not for network attributes)\n * @returns the declaration object\n */\nfunction declarations(plans: readonly AttributePlan[], defaults: boolean): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const p of plans) {\n const decl: Record<string, unknown> = { d: p.d };\n if (defaults && p.key !== p.name) {\n decl.a = p.key;\n }\n const fallback = p.column.meta.default;\n if (defaults && fallback !== undefined && fallback !== null) {\n if (defaultFits(cx2Type(p.d), fallback)) {\n decl.v = fallback;\n }\n }\n out[p.name] = decl;\n }\n return out;\n}\n\n/**\n * Whether a declared default can be written as the value of a declared type.\n * @param type - the type\n * @param fallback - the default\n * @returns true when it matches\n */\nfunction defaultFits(type: ReturnType<typeof cx2Type>, fallback: unknown): boolean {\n if (type === null) {\n return false;\n }\n if (type.list) {\n return Array.isArray(fallback);\n }\n switch (type.scalar) {\n case \"string\":\n return typeof fallback === \"string\";\n case \"boolean\":\n return typeof fallback === \"boolean\";\n default:\n return typeof fallback === \"number\" && Number.isFinite(fallback);\n }\n}\n\n/**\n * The v object of one element.\n * @param plans - the attribute plans\n * @param row - the row\n * @returns the object, or null when empty\n */\nfunction attributesOf(plans: readonly AttributePlan[], row: number): Record<string, unknown> | null {\n let out: Record<string, unknown> | null = null;\n for (const p of plans) {\n const value = cellValue(p, row);\n if (value !== undefined) {\n out ??= {};\n out[p.key] = value;\n }\n }\n return out;\n}\n\n/**\n * Write the document as text parts.\n * @param snapshot - the snapshot\n * @param p - the plan\n * @yields the document's text\n * @returns nothing\n */\nfunction* write(snapshot: GraphSnapshot, p: Plan): Generator<string, void, undefined> {\n if (p.fatal !== null) {\n throw p.fatal;\n }\n const { ids } = p;\n if (ids === null) {\n throw new GraphFormatError(\"E_INVALID_ID\", \"node ids cannot be written as CX2 integers\", { reason: \"charset\" });\n }\n const { src, dst } = snapshot.edgeList();\n const edges: number[] = [];\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (!p.folding.folded(e)) {\n edges.push(e);\n }\n }\n\n const nodeDecls = declarations(p.nodeAttrs, true);\n if (p.originalIds) {\n nodeDecls[ORIGINAL_ID_ATTRIBUTE] = { d: \"string\" };\n }\n const edgeDecls = declarations(p.edgeAttrs, true);\n if (p.weights.weighted) {\n edgeDecls[WEIGHT_ATTRIBUTE] = { d: \"double\" };\n }\n const networkDecls = declarations(p.graphAttrs, false);\n const network: Record<string, unknown> = {};\n for (const a of p.graphAttrs) {\n const value = cellValue(a, 0);\n if (value !== undefined) {\n network[a.name] = value;\n }\n }\n const { meta } = snapshot;\n for (const [key, value] of [\n [\"name\", meta.name],\n [\"description\", meta.description],\n ] as const) {\n if (value !== null && !(key in network) && !(key in networkDecls)) {\n network[key] = value;\n networkDecls[key] = { d: \"string\" };\n }\n }\n const kept = isRecord(meta.extra.cx2) ? meta.extra.cx2 : {};\n const otherDecls = isRecord(kept.declarations) ? kept.declarations : {};\n const opaque = meta.sourceFormat === CX2_FORMAT && isRecord(kept.opaque) ? kept.opaque : {};\n const declarationsElement: Record<string, unknown> = { ...otherDecls };\n for (const [key, table] of [\n [\"networkAttributes\", networkDecls],\n [\"nodes\", nodeDecls],\n [\"edges\", edgeDecls],\n ] as const) {\n if (Object.keys(table).length > 0) {\n declarationsElement[key] = table;\n }\n }\n const nodeBypassRows = bypassRows(p.nodeBypasses, snapshot.nodeCount);\n const edgeBypassRows = bypassRows(p.edgeBypasses, snapshot.edgeCount).filter((e) => !p.folding.folded(e));\n const opaqueAspects = Object.entries(opaque).filter(\n (entry): entry is [string, unknown[]] => !CORE_ASPECTS.has(entry[0]) && Array.isArray(entry[1]),\n );\n\n const counts: [string, number][] = [];\n const hasDeclarations = Object.keys(declarationsElement).length > 0;\n if (hasDeclarations) {\n counts.push([\"attributeDeclarations\", 1]);\n }\n if (Object.keys(network).length > 0) {\n counts.push([\"networkAttributes\", 1]);\n }\n counts.push([\"nodes\", snapshot.nodeCount], [\"edges\", edges.length]);\n if (nodeBypassRows.length > 0) {\n counts.push([\"nodeBypasses\", nodeBypassRows.length]);\n }\n if (edgeBypassRows.length > 0) {\n counts.push([\"edgeBypasses\", edgeBypassRows.length]);\n }\n for (const [name, elements] of opaqueAspects) {\n counts.push([name, elements.length]);\n }\n\n yield '[{\"CXVersion\":\"2.0\",\"hasFragments\":false},\\n';\n yield `{\"metaData\":${stringify(counts.map(([name, elementCount]) => ({ name, elementCount })))}},\\n`;\n if (hasDeclarations) {\n yield `{\"attributeDeclarations\":[${stringify(declarationsElement)}]},\\n`;\n }\n if (Object.keys(network).length > 0) {\n yield `{\"networkAttributes\":[${stringify(network)}]},\\n`;\n }\n yield* block(\"nodes\", snapshot.nodeCount, (i) => stringify(nodeElement(p, ids, i)));\n yield* block(\"edges\", edges.length, (k) => {\n const e = edges[k];\n const element: Record<string, unknown> = {\n id: p.edgeIds[e],\n s: ids.idAt(src[e]),\n t: ids.idAt(dst[e]),\n };\n let v = attributesOf(p.edgeAttrs, e);\n if (p.weights.isExplicit(e)) {\n const w = p.weights.value(e);\n v ??= {};\n v[WEIGHT_ATTRIBUTE] = Number.isFinite(w) ? w : null;\n }\n if (v !== null) {\n element.v = v;\n }\n return stringify(element);\n });\n if (nodeBypassRows.length > 0) {\n yield* block(\"nodeBypasses\", nodeBypassRows.length, (k) => {\n const i = nodeBypassRows[k];\n return stringify({ id: ids.idAt(i), v: bypassValues(p.nodeBypasses, i) });\n });\n }\n if (edgeBypassRows.length > 0) {\n yield* block(\"edgeBypasses\", edgeBypassRows.length, (k) => {\n const e = edgeBypassRows[k];\n return stringify({ id: p.edgeIds[e], v: bypassValues(p.edgeBypasses, e) });\n });\n }\n for (const [name, elements] of opaqueAspects) {\n yield* block(name, elements.length, (k) => stringify(elements[k]));\n }\n yield '{\"status\":[{\"error\":\"\",\"success\":true}]}]\\n';\n}\n\n/**\n * The text of one aspect block, element by element.\n * @param aspect - the aspect name\n * @param count - its element count\n * @param element - the JSON text of element k\n * @returns the block's text parts\n */\nfunction block(aspect: string, count: number, element: (k: number) => string): Generator<string, void, undefined> {\n return aspectBlock(\n aspect,\n (function* elements(): Generator<string, void, undefined> {\n for (let k = 0; k < count; k++) {\n yield element(k);\n }\n })(),\n );\n}\n\n/**\n * The element of node i.\n * @param p - the plan\n * @param ids - the written ids\n * @param i - the node index\n * @returns the element\n */\nfunction nodeElement(p: Plan, ids: WrittenIds, i: number): Record<string, unknown> {\n const element: Record<string, unknown> = { id: ids.idAt(i) };\n if (p.position?.isSet(i) === true) {\n const point = p.position.value(i) as ArrayLike<number>;\n if (Number.isFinite(point[0]) && Number.isFinite(point[1])) {\n element.x = point[0];\n element.y = point[1] === 0 ? 0 : -point[1];\n if (p.positionZ && Number.isFinite(point[2])) {\n element.z = point[2];\n }\n }\n }\n if (p.z?.isSet(i) === true) {\n const z = p.z.value(i);\n if (typeof z === \"number\" && Number.isFinite(z)) {\n element.z = z;\n }\n }\n let v = attributesOf(p.nodeAttrs, i);\n if (p.originalIds && ids.isChanged(i)) {\n v ??= {};\n v[ORIGINAL_ID_ATTRIBUTE] = String(ids.originalAt(i));\n }\n if (v !== null) {\n element.v = v;\n }\n return element;\n}\n\n/**\n * The rows with at least one bypass value.\n * @param columns - the bypass columns\n * @param rows - the row count\n * @returns the rows, ascending\n */\nfunction bypassRows(columns: readonly Column[], rows: number): number[] {\n const out: number[] = [];\n if (columns.length === 0) {\n return out;\n }\n for (let i = 0; i < rows; i++) {\n if (columns.some((c) => c.isSet(i))) {\n out.push(i);\n }\n }\n return out;\n}\n\n/**\n * The bypass values of one row.\n * @param columns - the bypass columns\n * @param row - the row\n * @returns property -> value\n */\nfunction bypassValues(columns: readonly Column[], row: number): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const column of columns) {\n if (column.isSet(row)) {\n // the visual property's own name: a column renamed for a clash with an attribute keeps it in origin.id\n const property = column.meta.origin?.id;\n out[typeof property === \"string\" && property.length > 0 ? property : column.meta.name] = column.value(row);\n }\n }\n return out;\n}\n\n/**\n * The CX2 exporter plugin.\n * @category Built-in formats\n */\nexport const cx2Exporter: GraphExporter<Cx2ExportOptions> = Object.freeze({\n format: CX2_FORMAT,\n options: Object.freeze([]),\n capabilities: CX2_CAPABILITIES,\n\n /**\n * Pre-flight: what export() would lose, without writing anything.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the notes, empty when the export is exact\n */\n check(snapshot: GraphSnapshot, options?: Cx2ExportOptions): readonly LossNote[] {\n return Object.freeze([...plan(snapshot, resolveExportOptions(options)).notes]);\n },\n\n /**\n * Write the document as UTF-8 chunks.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the chunks\n */\n export(snapshot: GraphSnapshot, options?: Cx2ExportOptions): AsyncIterable<Uint8Array> {\n return encodeChunks(write(snapshot, plan(snapshot, resolveExportOptions(options))));\n },\n\n /**\n * Write the document as one string.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the document\n */\n exportToString(snapshot: GraphSnapshot, options?: Cx2ExportOptions): Promise<string> {\n return joinText(write(snapshot, plan(snapshot, resolveExportOptions(options))));\n },\n});\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { GraphFormatError } from "@graphty/graph-format";
2
2
  import { c as childrenCsr } from "./children-CL3Cy0ez.js";
3
3
  import { r as resolveExportOptions, c as capabilities, a as checkCapabilities, L as LOSS, p as pairFolding, b as plural, $ as agree, e as explicitWeights, a9 as idText, aa as formatF32, ab as formatF64, ac as DictHeuristic } from "./export-B-aVCwyG.js";
4
- import { e as escapeXmlAttribute, x as xmlIllegalTextNotes, a as escapeXmlText } from "./escape-BpYMQZVa.js";
4
+ import { e as escapeXmlAttribute, x as xmlIllegalTextNotes, a as escapeXmlText } from "./escape-BJRLd3vJ.js";
5
5
  import { j as joinText, e as encodeChunks } from "./writer-DxjgHwSe.js";
6
- import { F as FORMAT, M as META_KEY, b as XLINK_NAMESPACE, C as CY_NAMESPACE, c as XGMML_NAMESPACE, a as XGMML_LOSS, Z as Z_COLUMN, L as LABEL_COLUMN, I as INTERACTION_COLUMN, d as aliasesOf, G as GRAPHICS_COLUMN, S as SUBGRAPH_COLUMN, N as NESTED_NETWORK_COLUMN, e as NETWORK_POINTER_COLUMN, f as NETWORKS_COLUMN, E as EDGE_ID_COLUMN, P as POSITION_COLUMN, g as PARENT_COLUMN, h as PARENTS_COLUMN, i as XGMML_ORIGIN_NAMESPACE, j as CYTOSCAPE_ORIGIN_NAMESPACE } from "./importer-B7Ir269L.js";
6
+ import { F as FORMAT, M as META_KEY, b as XLINK_NAMESPACE, C as CY_NAMESPACE, c as XGMML_NAMESPACE, a as XGMML_LOSS, Z as Z_COLUMN, L as LABEL_COLUMN, I as INTERACTION_COLUMN, d as aliasesOf, G as GRAPHICS_COLUMN, S as SUBGRAPH_COLUMN, N as NESTED_NETWORK_COLUMN, e as NETWORK_POINTER_COLUMN, f as NETWORKS_COLUMN, E as EDGE_ID_COLUMN, P as POSITION_COLUMN, g as PARENT_COLUMN, h as PARENTS_COLUMN, i as XGMML_ORIGIN_NAMESPACE, j as CYTOSCAPE_ORIGIN_NAMESPACE } from "./importer-DEp_fYjf.js";
7
7
  const LITERAL_ESCAPES = String.raw`\n or \t`;
8
8
  const CAPABILITIES = capabilities({
9
9
  mixedDirection: true,
@@ -496,6 +496,12 @@ function countNumericIds(snapshot) {
496
496
  }
497
497
  return n;
498
498
  }
499
+ function optionalAttribute(name, value) {
500
+ return value === null ? "" : ` ${name}="${value}"`;
501
+ }
502
+ function attributeList(entries) {
503
+ return entries.map(([k, v]) => ` ${k}="${escapeXmlAttribute(String(v))}"`).join("");
504
+ }
499
505
  function valueText(value, dtype, escapes) {
500
506
  let text;
501
507
  if (typeof value === "boolean") {
@@ -543,10 +549,10 @@ function* attsOf(writes, row, first, plan, indent) {
543
549
  continue;
544
550
  }
545
551
  const name = `${indent}<att name="${escapeXmlAttribute(w.name)}"`;
546
- const types = `${w.type === null ? "" : ` type="${w.type}"`}${w.cyType === null ? "" : ` cy:type="${w.cyType}"`}`;
552
+ const types = optionalAttribute("type", w.type) + optionalAttribute("cy:type", w.cyType);
547
553
  const extra = `${column.meta.extra.hidden === true ? ' cy:hidden="1"' : ""}${column.meta.extra.equation === true ? ' cy:equation="1"' : ""}`;
548
554
  if (!isSet) {
549
- yield `${name}${types}${w.elementType === null ? "" : ` cy:elementType="${w.elementType}"`}${extra}/>
555
+ yield `${name}${types}${optionalAttribute("cy:elementType", w.elementType)}${extra}/>
550
556
  `;
551
557
  continue;
552
558
  }
@@ -584,7 +590,7 @@ function* graphicsOf(record, coords, indent) {
584
590
  if (attrs.length === 0 && nested.length === 0) {
585
591
  return;
586
592
  }
587
- const head = `${indent}<graphics${attrs.map(([k, v]) => ` ${k}="${escapeXmlAttribute(v)}"`).join("")}`;
593
+ const head = `${indent}<graphics${attributeList(attrs)}`;
588
594
  if (nested.length === 0) {
589
595
  yield `${head}/>
590
596
  `;
@@ -598,7 +604,7 @@ function* graphicsOf(record, coords, indent) {
598
604
  `;
599
605
  for (const point of value) {
600
606
  const entries = typeof point === "object" && point !== null ? Object.entries(point) : [];
601
- yield `${indent} <point${entries.map(([k, v]) => ` ${k}="${escapeXmlAttribute(String(v))}"`).join("")}/>
607
+ yield `${indent} <point${attributeList(entries)}/>
602
608
  `;
603
609
  }
604
610
  yield `${indent} </Line>
@@ -623,7 +629,7 @@ function* jsonAtt(name, value, indent) {
623
629
  } else if (typeof value === "object" && value !== null) {
624
630
  const entries = Object.entries(value);
625
631
  if (name !== null && entries.every(([, v]) => typeof v === "string") && entries.length <= 3 && entries.every(([k]) => /^[a-z]$/.test(k))) {
626
- yield `${indent}<att${nameAttr}${entries.map(([k, v]) => ` ${k}="${escapeXmlAttribute(v)}"`).join("")}/>
632
+ yield `${indent}<att${nameAttr}${attributeList(entries)}/>
627
633
  `;
628
634
  return;
629
635
  }
@@ -667,10 +673,31 @@ function coordsOf(plan, zColumn, node) {
667
673
  }
668
674
  return out;
669
675
  }
676
+ function* groupAttOf(snapshot, sub, children, inner) {
677
+ yield `${inner}<att name="__isGroup" value="1" type="boolean" cy:type="Boolean" cy:hidden="1"/>
678
+ `;
679
+ const id = typeof sub.id === "string" ? ` id="${escapeXmlAttribute(sub.id)}"` : "";
680
+ const lbl = typeof sub.label === "string" ? ` label="${escapeXmlAttribute(sub.label)}"` : "";
681
+ yield `${inner}<att>
682
+ ${inner} <graph${id}${lbl}>
683
+ `;
684
+ const atts = typeof sub.atts === "object" && sub.atts !== null ? Object.entries(sub.atts) : [];
685
+ for (const [key, value] of atts) {
686
+ yield* jsonAtt(key, value, `${inner} `);
687
+ }
688
+ for (const child of children) {
689
+ yield `${inner} <node xlink:href="#${escapeXmlAttribute(idText(snapshot.ids.idOf(child)))}"/>
690
+ `;
691
+ }
692
+ yield `${inner} </graph>
693
+ ${inner}</att>
694
+ `;
695
+ }
670
696
  function* nodeOf(snapshot, plan, node, indent) {
671
697
  const labelCol = slot(plan.nodes, "label");
672
698
  const label = cellOf(labelCol, node);
673
- yield `${indent}<node id="${escapeXmlAttribute(idText(snapshot.ids.idOf(node)))}"${label === null ? "" : ` label="${escapeXmlAttribute(scalarText(label))}"`}${xmlAttributesOf(plan.nodes, node)}>
699
+ const labelAttr = label === null ? "" : ` label="${escapeXmlAttribute(scalarText(label))}"`;
700
+ yield `${indent}<node id="${escapeXmlAttribute(idText(snapshot.ids.idOf(node)))}"${labelAttr}${xmlAttributesOf(plan.nodes, node)}>
674
701
  `;
675
702
  const inner = `${indent} `;
676
703
  yield* attsOf(plan.nodes, node, node === 0, plan, inner);
@@ -679,25 +706,7 @@ function* nodeOf(snapshot, plan, node, indent) {
679
706
  const pointer = cellOf(slot(plan.nodes, "pointer"), node);
680
707
  const subgraph = cellOf(slot(plan.nodes, "subgraph"), node);
681
708
  if (children.length > 0 || subgraph !== null) {
682
- const sub = subgraph ?? {};
683
- yield `${inner}<att name="__isGroup" value="1" type="boolean" cy:type="Boolean" cy:hidden="1"/>
684
- `;
685
- const id = typeof sub.id === "string" ? ` id="${escapeXmlAttribute(sub.id)}"` : "";
686
- const lbl = typeof sub.label === "string" ? ` label="${escapeXmlAttribute(sub.label)}"` : "";
687
- yield `${inner}<att>
688
- ${inner} <graph${id}${lbl}>
689
- `;
690
- const atts = typeof sub.atts === "object" && sub.atts !== null ? Object.entries(sub.atts) : [];
691
- for (const [key, value] of atts) {
692
- yield* jsonAtt(key, value, `${inner} `);
693
- }
694
- for (const child of children) {
695
- yield `${inner} <node xlink:href="#${escapeXmlAttribute(idText(snapshot.ids.idOf(child)))}"/>
696
- `;
697
- }
698
- yield `${inner} </graph>
699
- ${inner}</att>
700
- `;
709
+ yield* groupAttOf(snapshot, subgraph ?? {}, children, inner);
701
710
  } else if (typeof nested === "string") {
702
711
  yield `${inner}<att>
703
712
  ${inner} <graph label="${escapeXmlAttribute(nested)}"/>
@@ -797,7 +806,11 @@ function* edgesOf(snapshot, plan) {
797
806
  const id = cellOf(plan.edgeId, e);
798
807
  const label = cellOf(labelCol, e);
799
808
  const weight = weights.text(e);
800
- yield ` <edge${id === null ? "" : ` id="${escapeXmlAttribute(scalarText(id))}"`}${label === null ? "" : ` label="${escapeXmlAttribute(scalarText(label))}"`} source="${escapeXmlAttribute(idText(snapshot.ids.idOf(u)))}" target="${escapeXmlAttribute(idText(snapshot.ids.idOf(v)))}" cy:directed="${directed ? "1" : "0"}"${weight === null ? "" : ` weight="${weight}"`}${xmlAttributesOf(plan.edges, e)}>
809
+ const idAttr = id === null ? "" : ` id="${escapeXmlAttribute(scalarText(id))}"`;
810
+ const labelAttr = label === null ? "" : ` label="${escapeXmlAttribute(scalarText(label))}"`;
811
+ const source = escapeXmlAttribute(idText(snapshot.ids.idOf(u)));
812
+ const target = escapeXmlAttribute(idText(snapshot.ids.idOf(v)));
813
+ yield ` <edge${idAttr}${labelAttr} source="${source}" target="${target}" cy:directed="${directed ? "1" : "0"}"${optionalAttribute("weight", weight)}${xmlAttributesOf(plan.edges, e)}>
801
814
  `;
802
815
  yield* attsOf(plan.edges, e, first, plan, " ");
803
816
  yield* graphicsOf(cellOf(graphicsCol, e), [], " ");
@@ -834,4 +847,4 @@ const xgmmlExporter = Object.freeze({
834
847
  export {
835
848
  xgmmlExporter as x
836
849
  };
837
- //# sourceMappingURL=exporter-DXqCPNrI.js.map
850
+ //# sourceMappingURL=exporter-BVXnV9-9.js.map