@graphty/graph-io 0.3.38 → 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.
- package/dist/chunks/{choose-CsO24U-5.js → choose-CS3fvGT1.js} +2 -2
- package/dist/chunks/{choose-CsO24U-5.js.map → choose-CS3fvGT1.js.map} +1 -1
- package/dist/chunks/{constants-BPRiVyBu.js → constants-DqKZT6cH.js} +2 -2
- package/dist/chunks/{constants-BPRiVyBu.js.map → constants-DqKZT6cH.js.map} +1 -1
- package/dist/chunks/{escape-BRcyzD77.js → escape-BJRLd3vJ.js} +4 -3
- package/dist/chunks/escape-BJRLd3vJ.js.map +1 -0
- package/dist/chunks/{export-CTUlibzr.js → export-B-aVCwyG.js} +103 -92
- package/dist/chunks/export-B-aVCwyG.js.map +1 -0
- package/dist/chunks/{exporter-Bf5tZA0X.js → exporter-6ocL_9x_.js} +6 -5
- package/dist/chunks/exporter-6ocL_9x_.js.map +1 -0
- package/dist/chunks/{exporter-Bn4jdYfd.js → exporter-BVXnV9-9.js} +43 -30
- package/dist/chunks/exporter-BVXnV9-9.js.map +1 -0
- package/dist/chunks/{exporter-D-qQuRcG.js → exporter-Bcp-l4Bo.js} +6 -6
- package/dist/chunks/exporter-Bcp-l4Bo.js.map +1 -0
- package/dist/chunks/{exporter-F0vT919P.js → exporter-SFYkDzD0.js} +5 -4
- package/dist/chunks/exporter-SFYkDzD0.js.map +1 -0
- package/dist/chunks/{importer-Bgb9sgZZ.js → importer-AjwOJrn2.js} +6 -8
- package/dist/chunks/importer-AjwOJrn2.js.map +1 -0
- package/dist/chunks/{importer-BuzbaFFY.js → importer-BJlGAOht.js} +28 -13
- package/dist/chunks/importer-BJlGAOht.js.map +1 -0
- package/dist/chunks/{importer-DqMtyYLX.js → importer-BpuS3J8C.js} +12 -14
- package/dist/chunks/importer-BpuS3J8C.js.map +1 -0
- package/dist/chunks/{importer-CEuUmyPe.js → importer-CPqnIY8m.js} +6 -6
- package/dist/chunks/{importer-CEuUmyPe.js.map → importer-CPqnIY8m.js.map} +1 -1
- package/dist/chunks/{importer-yWUPR_nU.js → importer-DEp_fYjf.js} +30 -12
- package/dist/chunks/importer-DEp_fYjf.js.map +1 -0
- package/dist/chunks/{importer-CNMQnHDd.js → importer-D_srHyj6.js} +112 -62
- package/dist/chunks/importer-D_srHyj6.js.map +1 -0
- package/dist/chunks/{importer-oIUx9u_g.js → importer-DcKB97kW.js} +40 -18
- package/dist/chunks/importer-DcKB97kW.js.map +1 -0
- package/dist/chunks/{json-elements-AkglPS3m.js → json-elements-DpO6AXIc.js} +7 -5
- package/dist/chunks/{json-elements-AkglPS3m.js.map → json-elements-DpO6AXIc.js.map} +1 -1
- package/dist/chunks/{ontology-export-DDoG3egY.js → ontology-export-50L9DOV4.js} +2 -2
- package/dist/chunks/{ontology-export-DDoG3egY.js.map → ontology-export-50L9DOV4.js.map} +1 -1
- package/dist/chunks/{records-ChmWZGuz.js → records-r3SFHz11.js} +137 -96
- package/dist/chunks/records-r3SFHz11.js.map +1 -0
- package/dist/chunks/{text-Btw3sBe_.js → text-Bjfa1xYL.js} +2 -2
- package/dist/chunks/{text-Btw3sBe_.js.map → text-Bjfa1xYL.js.map} +1 -1
- package/dist/csv.js +4 -4
- package/dist/cx.js +1 -1
- package/dist/cx2.js +2 -2
- package/dist/cys.js +1 -1
- package/dist/dot.js +1 -1
- package/dist/gexf.js +6 -4
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +8 -6
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +26 -26
- package/dist/graphml.js +2 -2
- package/dist/json.js +1 -1
- package/dist/neo4j.js +3 -3
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/src/common/direction.js +1 -1
- package/dist/src/common/direction.js.map +1 -1
- package/dist/src/common/export.d.ts.map +1 -1
- package/dist/src/common/export.js +136 -71
- package/dist/src/common/export.js.map +1 -1
- package/dist/src/common/input.js +1 -1
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/json-elements.d.ts.map +1 -1
- package/dist/src/common/json-elements.js +4 -2
- package/dist/src/common/json-elements.js.map +1 -1
- package/dist/src/common/xml.d.ts.map +1 -1
- package/dist/src/common/xml.js +2 -1
- package/dist/src/common/xml.js.map +1 -1
- package/dist/src/formats/csv/records.d.ts.map +1 -1
- package/dist/src/formats/csv/records.js +138 -100
- package/dist/src/formats/csv/records.js.map +1 -1
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +108 -53
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
- package/dist/src/formats/cx2/exporter.js +2 -1
- package/dist/src/formats/cx2/exporter.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +28 -6
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/dot/importer.d.ts +6 -0
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +11 -6
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/names.d.ts +5 -0
- package/dist/src/formats/dot/names.d.ts.map +1 -1
- package/dist/src/formats/dot/names.js +5 -0
- package/dist/src/formats/dot/names.js.map +1 -1
- package/dist/src/formats/dot/tokenizer.js +9 -9
- package/dist/src/formats/dot/tokenizer.js.map +1 -1
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +4 -2
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts +6 -0
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +6 -3
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
- package/dist/src/formats/graphml/exporter.js +2 -1
- package/dist/src/formats/graphml/exporter.js.map +1 -1
- package/dist/src/formats/graphml/importer.d.ts.map +1 -1
- package/dist/src/formats/graphml/importer.js +5 -6
- package/dist/src/formats/graphml/importer.js.map +1 -1
- package/dist/src/formats/obo/importer.d.ts.map +1 -1
- package/dist/src/formats/obo/importer.js +2 -1
- package/dist/src/formats/obo/importer.js.map +1 -1
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +4 -5
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts +6 -0
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +33 -10
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
- package/dist/src/formats/xgmml/exporter.js +54 -22
- package/dist/src/formats/xgmml/exporter.js.map +1 -1
- package/dist/src/sniff.js +1 -1
- package/dist/src/sniff.js.map +1 -1
- package/dist/xgmml.js +2 -2
- package/package.json +2 -2
- package/src/common/direction.ts +1 -1
- package/src/common/export.ts +190 -97
- package/src/common/input.ts +1 -1
- package/src/common/json-elements.ts +4 -2
- package/src/common/xml.ts +2 -1
- package/src/formats/csv/records.ts +143 -99
- package/src/formats/cx/importer.ts +140 -58
- package/src/formats/cx2/exporter.ts +2 -1
- package/src/formats/cx2/importer.ts +34 -10
- package/src/formats/dot/importer.ts +35 -4
- package/src/formats/dot/names.ts +6 -0
- package/src/formats/dot/tokenizer.ts +9 -9
- package/src/formats/gexf/exporter.ts +4 -2
- package/src/formats/gml/importer.ts +14 -3
- package/src/formats/graphml/exporter.ts +2 -3
- package/src/formats/graphml/importer.ts +5 -6
- package/src/formats/obo/importer.ts +2 -1
- package/src/formats/pajek/exporter.ts +6 -4
- package/src/formats/xgmml/emit.ts +34 -10
- package/src/formats/xgmml/exporter.ts +63 -23
- package/src/sniff.ts +1 -1
- package/dist/chunks/escape-BRcyzD77.js.map +0 -1
- package/dist/chunks/export-CTUlibzr.js.map +0 -1
- package/dist/chunks/exporter-Bf5tZA0X.js.map +0 -1
- package/dist/chunks/exporter-Bn4jdYfd.js.map +0 -1
- package/dist/chunks/exporter-D-qQuRcG.js.map +0 -1
- package/dist/chunks/exporter-F0vT919P.js.map +0 -1
- package/dist/chunks/importer-Bgb9sgZZ.js.map +0 -1
- package/dist/chunks/importer-BuzbaFFY.js.map +0 -1
- package/dist/chunks/importer-CNMQnHDd.js.map +0 -1
- package/dist/chunks/importer-DqMtyYLX.js.map +0 -1
- package/dist/chunks/importer-oIUx9u_g.js.map +0 -1
- package/dist/chunks/importer-yWUPR_nU.js.map +0 -1
- package/dist/chunks/records-ChmWZGuz.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-Btw3sBe_.js","sources":["../../src/common/text.ts"],"sourcesContent":["/**\n * The fixed lexical grammar of design section 5.1 for untyped text sources (CSV cells, GML\n * values, DOT strings, Pajek tokens), reproduced from the core's reference implementation so the\n * two agree (invariant I15). Text importers parse each cell with parseTextCell() and push the JS\n * value; the sink's per-column inference then widens `bool -> i32 -> f64 -> string` and never per\n * cell, so a column that saw `1` and then `\"01\"` becomes string for all rows.\n *\n * - `bool` is exactly `true` / `false` (case-sensitive);\n * - `i32` is `/^-?(0|[1-9][0-9]*)$/` within `[-2^31, 2^31)`; `0` / `1` are i32, never bool;\n * - `f64` is a decimal or exponent literal accepted by `Number()` that is not empty, not\n * whitespace, not `Infinity` / `NaN`, not a hex / octal / binary form, has no leading zeros in\n * its integer part, and whose value is finite (an integer literal outside i32 range is f64);\n * - everything else is `string`.\n */\n\nimport { type ColumnHandle, GraphFormatError, type GraphSink, INVALID_INDEX } from \"@graphty/graph-format\";\n\nimport { PRECISION_CODE } from \"./codes.js\";\nimport { type ImportReportBuilder } from \"./report.js\";\n\nconst I32_TEXT = /^-?(0|[1-9]\\d*)$/;\nconst F64_TEXT = /^[+-]?((0|[1-9]\\d*)(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?$/;\nconst I32_MIN = -2147483648;\nconst I32_MAX = 2147483647;\n\n/**\n * The dtype a text cell parses as under the fixed text grammar.\n * @public\n * @category Plugin helpers\n */\nexport type TextDtype = \"bool\" | \"i32\" | \"f64\" | \"string\";\n\n/**\n * A digit string without its trailing zeros (`\"1200\"` becomes `\"12\"`).\n * @param digits - the digits\n * @returns the digits up to the last one that is not 0\n */\nexport function trimTrailingZeros(digits: string): string {\n let end = digits.length;\n while (end > 0 && digits[end - 1] === \"0\") {\n end--;\n }\n return digits.slice(0, end);\n}\n\n/**\n * Classify one text cell by the fixed grammar.\n * @param text - the cell text, exactly as read (no trimming)\n * @returns bool, i32, f64 or string\n * @category Plugin helpers\n */\nexport function inferTextDtype(text: string): TextDtype {\n if (text === \"true\" || text === \"false\") {\n return \"bool\";\n }\n if (I32_TEXT.test(text)) {\n const n = Number(text);\n if (n >= I32_MIN && n <= I32_MAX) {\n return \"i32\";\n }\n return Number.isFinite(n) ? \"f64\" : \"string\";\n }\n if (F64_TEXT.test(text) && Number.isFinite(Number(text))) {\n return \"f64\";\n }\n return \"string\";\n}\n\n/**\n * Parse one text cell into the JS value its grammar class implies: a boolean for bool, a number for\n * i32 / f64, the text itself for string. The sink infers the column dtype from the value.\n * @param text - the cell text, exactly as read\n * @returns the value\n * @category Plugin helpers\n */\nexport function parseTextCell(text: string): boolean | number | string {\n switch (inferTextDtype(text)) {\n case \"bool\":\n return text === \"true\";\n case \"i32\":\n case \"f64\":\n return Number(text);\n case \"string\":\n return text;\n default:\n return text;\n }\n}\n\n/**\n * Whether a text cell is a number under the f64 grammar (an i32 or f64 literal).\n * @param text - the cell text\n * @returns true when parseTextCell(text) returns a number\n * @category Plugin helpers\n */\nexport function isNumericText(text: string): boolean {\n const dtype = inferTextDtype(text);\n return dtype === \"i32\" || dtype === \"f64\";\n}\n\n/**\n * Whether a numeric cell text is the canonical spelling of its value (`String(value) === text`),\n * so that the sink's own re-formatting of the value would reproduce it.\n * @param text - the cell text\n * @param value - the parsed value\n * @returns true when the lexical form survives a widening to string\n */\nfunction isCanonicalNumberText(text: string, value: number): boolean {\n return String(value) === text;\n}\n\n/**\n * The widening rank of a text dtype in the design section 5.1 order.\n * @param dtype - the text dtype\n * @returns 0 for bool, 1 for i32, 2 for f64, 3 for string\n */\nfunction textDtypeRank(dtype: TextDtype): number {\n switch (dtype) {\n case \"bool\":\n return 0;\n case \"i32\":\n return 1;\n case \"f64\":\n return 2;\n case \"string\":\n return 3;\n default: {\n const name: string = dtype;\n throw new GraphFormatError(\"E_UNSUPPORTED\", `unknown text dtype ${name}`, { dtype: name });\n }\n }\n}\n\n/**\n * Writes the cells of one attribute of a text format whose values carry no type (CSV, DOT, Pajek):\n * you hand it each cell's text and it stores a number, a boolean or text, choosing one type for the\n * whole attribute. A column of `2.0`, `3.5` stays a number column with decimals even though `2.0`\n * alone looks like an integer, and once one cell turns out to be text, earlier cells such as `1e5`\n * are kept as written instead of as `100000`. Create one writer per attribute name and per kind\n * (\"node\" or \"edge\"), and call `write(index, text)` with the node or edge index the sink gave you:\n *\n * ```ts\n * const color = new TextCellWriter(\"color\", \"node\", sink, report);\n * color.write(sink.addNode(\"a\"), \"red\");\n * ```\n *\n * A sink that cannot change a column's type after the fact (one of your own without\n * `widenNodeColumn` / `widenEdgeColumn`) keeps the type the first values implied, with one W_WIDENING_UNSUPPORTED warning\n * per attribute.\n * @public\n * @category Writing a format\n */\nexport class TextCellWriter {\n /** The column name in the sink. */\n readonly name: string;\n\n private readonly domain: \"node\" | \"edge\";\n\n private readonly sink: GraphSink;\n\n private readonly report: ImportReportBuilder;\n\n private handle: ColumnHandle = INVALID_INDEX as ColumnHandle;\n\n /** The widest text dtype seen (the column's dtype under the 5.1 grammar). */\n private textDtype: TextDtype | null = null;\n\n /** The widest dtype the pushed values imply (what the sink inferred on its own). */\n private valueDtype: TextDtype | null = null;\n\n private readonly keptRows: number[] = [];\n\n private readonly keptTexts: string[] = [];\n\n /**\n * Create a writer. The attribute is added to the sink on the first write.\n * @param name - the attribute name\n * @param domain - \"node\" for a node attribute, \"edge\" for an edge attribute\n * @param sink - the sink the importer fills\n * @param report - the import report, for warnings about the values\n */\n constructor(name: string, domain: \"node\" | \"edge\", sink: GraphSink, report: ImportReportBuilder) {\n this.name = name;\n this.domain = domain;\n this.sink = sink;\n this.report = report;\n }\n\n /**\n * The sink's handle of the attribute's column, for reading it back.\n * @returns the handle, or INVALID_INDEX before the first write\n */\n get column(): ColumnHandle {\n return this.handle;\n }\n\n /**\n * Write one cell.\n * @param row - the node or edge index, as the sink's addNode() or addEdge() returned it\n * @param text - the cell text, exactly as read from the file\n */\n write(row: number, text: string): void {\n const kind = inferTextDtype(text);\n const value = parseTextCell(text);\n if (\n typeof value === \"number\" &&\n !Number.isSafeInteger(value) &&\n I32_TEXT.test(text) &&\n BigInt(text) !== BigInt(value)\n ) {\n // an integer beyond 2^53 is stored as the nearest double; say so once per column\n this.report.warnOnce(\n \"precision\",\n PRECISION_CODE,\n `${this.domain} column \"${this.name}\": integers beyond 2^53 are stored as the nearest double (first: ${text})`,\n { element: this.name },\n `${PRECISION_CODE}:${this.domain}:${this.name}`,\n );\n }\n const wasString = this.textDtype === \"string\";\n const textDtype =\n this.textDtype === null || textDtypeRank(kind) > textDtypeRank(this.textDtype) ? kind : this.textDtype;\n // a string column keeps every cell's lexical form; a numeric text is never re-spelled. The\n // sink may refuse the value (a declared column of another dtype): the state advances only\n // once the cell is written, so a refused cell leaves the writer as it was.\n this.set(row, textDtype === \"string\" ? text : value);\n this.textDtype = textDtype;\n const valueKind = kindOfValue(value);\n if (this.valueDtype === null || textDtypeRank(valueKind) > textDtypeRank(this.valueDtype)) {\n this.valueDtype = valueKind;\n }\n if (this.textDtype === \"string\") {\n if (!wasString && this.keptRows.length > 0) {\n // the sink just widened the column to string from the values; restore the texts\n // whose lexical form the values did not carry\n for (let i = 0; i < this.keptRows.length; i++) {\n this.set(this.keptRows[i], this.keptTexts[i]);\n }\n this.keptRows.length = 0;\n this.keptTexts.length = 0;\n }\n return;\n }\n if (typeof value === \"number\" && !isCanonicalNumberText(text, value)) {\n this.keptRows.push(row);\n this.keptTexts.push(text);\n }\n if (this.textDtype === \"f64\" && this.valueDtype !== \"f64\") {\n this.widen(\"f64\");\n }\n }\n\n /**\n * Write a value (the parsed scalar, or a text into a widened column).\n * @param row - the row\n * @param value - the value\n */\n private set(row: number, value: unknown): void {\n if (this.handle === INVALID_INDEX) {\n if (this.domain === \"node\") {\n this.sink.setNodeValue(this.name, row, value);\n this.handle = this.sink.nodeColumn(this.name);\n } else {\n this.sink.setEdgeValue(this.name, row, value);\n this.handle = this.sink.edgeColumn(this.name);\n }\n return;\n }\n if (this.domain === \"node\") {\n this.sink.setNodeValue(this.handle, row, value);\n } else {\n this.sink.setEdgeValue(this.handle, row, value);\n }\n }\n\n /**\n * Widen the column to the dtype the text grammar implies, through the sink's optional call.\n * @param dtype - the dtype\n */\n private widen(dtype: \"f64\"): void {\n const { sink } = this;\n const supported =\n this.domain === \"node\" ? sink.widenNodeColumn !== undefined : sink.widenEdgeColumn !== undefined;\n if (!supported) {\n this.report.warnOnce(\n \"coercion\",\n WIDENING_UNSUPPORTED_CODE,\n `column \"${this.name}\" holds ${dtype} text but the sink cannot widen an inferred column; it keeps the value-inferred dtype`,\n { element: this.name },\n );\n this.valueDtype = dtype;\n return;\n }\n try {\n if (this.domain === \"node\") {\n sink.widenNodeColumn?.(this.handle, dtype);\n } else {\n sink.widenEdgeColumn?.(this.handle, dtype);\n }\n this.valueDtype = dtype;\n } catch (err) {\n if (!(err instanceof GraphFormatError) || err.code !== \"E_COLUMN_TYPE\") {\n throw err;\n }\n // a caller's declared column of the name: its dtype stands\n this.valueDtype = dtype;\n }\n }\n}\n\n/**\n * Your graph builder cannot change an attribute's type after its first value, so a text column keeps the type of its\n * first values.\n * @category Issue and loss codes\n */\nexport const WIDENING_UNSUPPORTED_CODE = \"W_WIDENING_UNSUPPORTED\";\n\n/**\n * The text dtype a parsed cell value implies on its own (what the sink's inference sees). It must\n * be graph-format's inference rule exactly: -0 is an integer there, so a column holding only\n * `-0.0` is inferred i32 and must be widened to f64, or the sign is lost.\n * @param value - the parsed value\n * @returns the dtype\n */\nfunction kindOfValue(value: boolean | number | string): TextDtype {\n if (typeof value === \"boolean\") {\n return \"bool\";\n }\n if (typeof value === \"string\") {\n return \"string\";\n }\n return Number.isInteger(value) && value >= -2147483648 && value <= 2147483647 ? \"i32\" : \"f64\";\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"text-Bjfa1xYL.js","sources":["../../src/common/text.ts"],"sourcesContent":["/**\n * The fixed lexical grammar of design section 5.1 for untyped text sources (CSV cells, GML\n * values, DOT strings, Pajek tokens), reproduced from the core's reference implementation so the\n * two agree (invariant I15). Text importers parse each cell with parseTextCell() and push the JS\n * value; the sink's per-column inference then widens `bool -> i32 -> f64 -> string` and never per\n * cell, so a column that saw `1` and then `\"01\"` becomes string for all rows.\n *\n * - `bool` is exactly `true` / `false` (case-sensitive);\n * - `i32` is `/^-?(0|[1-9][0-9]*)$/` within `[-2^31, 2^31)`; `0` / `1` are i32, never bool;\n * - `f64` is a decimal or exponent literal accepted by `Number()` that is not empty, not\n * whitespace, not `Infinity` / `NaN`, not a hex / octal / binary form, has no leading zeros in\n * its integer part, and whose value is finite (an integer literal outside i32 range is f64);\n * - everything else is `string`.\n */\n\nimport { type ColumnHandle, GraphFormatError, type GraphSink, INVALID_INDEX } from \"@graphty/graph-format\";\n\nimport { PRECISION_CODE } from \"./codes.js\";\nimport { type ImportReportBuilder } from \"./report.js\";\n\nconst I32_TEXT = /^-?(0|[1-9]\\d*)$/;\nconst F64_TEXT = /^[+-]?((0|[1-9]\\d*)(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?$/;\nconst I32_MIN = -2147483648;\nconst I32_MAX = 2147483647;\n\n/**\n * The dtype a text cell parses as under the fixed text grammar.\n * @public\n * @category Plugin helpers\n */\nexport type TextDtype = \"bool\" | \"i32\" | \"f64\" | \"string\";\n\n/**\n * A digit string without its trailing zeros (`\"1200\"` becomes `\"12\"`).\n * @param digits - the digits\n * @returns the digits up to the last one that is not 0\n */\nexport function trimTrailingZeros(digits: string): string {\n let end = digits.length;\n while (end > 0 && digits[end - 1] === \"0\") {\n end--;\n }\n return digits.slice(0, end);\n}\n\n/**\n * Classify one text cell by the fixed grammar.\n * @param text - the cell text, exactly as read (no trimming)\n * @returns bool, i32, f64 or string\n * @category Plugin helpers\n */\nexport function inferTextDtype(text: string): TextDtype {\n if (text === \"true\" || text === \"false\") {\n return \"bool\";\n }\n if (I32_TEXT.test(text)) {\n const n = Number(text);\n if (n >= I32_MIN && n <= I32_MAX) {\n return \"i32\";\n }\n return Number.isFinite(n) ? \"f64\" : \"string\";\n }\n if (F64_TEXT.test(text) && Number.isFinite(Number(text))) {\n return \"f64\";\n }\n return \"string\";\n}\n\n/**\n * Parse one text cell into the JS value its grammar class implies: a boolean for bool, a number for\n * i32 / f64, the text itself for string. The sink infers the column dtype from the value.\n * @param text - the cell text, exactly as read\n * @returns the value\n * @category Plugin helpers\n */\nexport function parseTextCell(text: string): boolean | number | string {\n switch (inferTextDtype(text)) {\n case \"bool\":\n return text === \"true\";\n case \"i32\":\n case \"f64\":\n return Number(text);\n case \"string\":\n return text;\n default:\n return text;\n }\n}\n\n/**\n * Whether a text cell is a number under the f64 grammar (an i32 or f64 literal).\n * @param text - the cell text\n * @returns true when parseTextCell(text) returns a number\n * @category Plugin helpers\n */\nexport function isNumericText(text: string): boolean {\n const dtype = inferTextDtype(text);\n return dtype === \"i32\" || dtype === \"f64\";\n}\n\n/**\n * Whether a numeric cell text is the canonical spelling of its value (`String(value) === text`),\n * so that the sink's own re-formatting of the value would reproduce it.\n * @param text - the cell text\n * @param value - the parsed value\n * @returns true when the lexical form survives a widening to string\n */\nfunction isCanonicalNumberText(text: string, value: number): boolean {\n return String(value) === text;\n}\n\n/**\n * The widening rank of a text dtype in the design section 5.1 order.\n * @param dtype - the text dtype\n * @returns 0 for bool, 1 for i32, 2 for f64, 3 for string\n */\nfunction textDtypeRank(dtype: TextDtype): number {\n switch (dtype) {\n case \"bool\":\n return 0;\n case \"i32\":\n return 1;\n case \"f64\":\n return 2;\n case \"string\":\n return 3;\n default: {\n const name: string = dtype;\n throw new GraphFormatError(\"E_UNSUPPORTED\", `unknown text dtype ${name}`, { dtype: name });\n }\n }\n}\n\n/**\n * Writes the cells of one attribute of a text format whose values carry no type (CSV, DOT, Pajek):\n * you hand it each cell's text and it stores a number, a boolean or text, choosing one type for the\n * whole attribute. A column of `2.0`, `3.5` stays a number column with decimals even though `2.0`\n * alone looks like an integer, and once one cell turns out to be text, earlier cells such as `1e5`\n * are kept as written instead of as `100000`. Create one writer per attribute name and per kind\n * (\"node\" or \"edge\"), and call `write(index, text)` with the node or edge index the sink gave you:\n *\n * ```ts\n * const color = new TextCellWriter(\"color\", \"node\", sink, report);\n * color.write(sink.addNode(\"a\"), \"red\");\n * ```\n *\n * A sink that cannot change a column's type after the fact (one of your own without\n * `widenNodeColumn` / `widenEdgeColumn`) keeps the type the first values implied, with one W_WIDENING_UNSUPPORTED warning\n * per attribute.\n * @public\n * @category Writing a format\n */\nexport class TextCellWriter {\n /** The column name in the sink. */\n readonly name: string;\n\n private readonly domain: \"node\" | \"edge\";\n\n private readonly sink: GraphSink;\n\n private readonly report: ImportReportBuilder;\n\n private handle: ColumnHandle = INVALID_INDEX as ColumnHandle;\n\n /** The widest text dtype seen (the column's dtype under the 5.1 grammar). */\n private textDtype: TextDtype | null = null;\n\n /** The widest dtype the pushed values imply (what the sink inferred on its own). */\n private valueDtype: TextDtype | null = null;\n\n private readonly keptRows: number[] = [];\n\n private readonly keptTexts: string[] = [];\n\n /**\n * Create a writer. The attribute is added to the sink on the first write.\n * @param name - the attribute name\n * @param domain - \"node\" for a node attribute, \"edge\" for an edge attribute\n * @param sink - the sink the importer fills\n * @param report - the import report, for warnings about the values\n */\n constructor(name: string, domain: \"node\" | \"edge\", sink: GraphSink, report: ImportReportBuilder) {\n this.name = name;\n this.domain = domain;\n this.sink = sink;\n this.report = report;\n }\n\n /**\n * The sink's handle of the attribute's column, for reading it back.\n * @returns the handle, or INVALID_INDEX before the first write\n */\n get column(): ColumnHandle {\n return this.handle;\n }\n\n /**\n * Write one cell.\n * @param row - the node or edge index, as the sink's addNode() or addEdge() returned it\n * @param text - the cell text, exactly as read from the file\n */\n write(row: number, text: string): void {\n const kind = inferTextDtype(text);\n const value = parseTextCell(text);\n if (\n typeof value === \"number\" &&\n !Number.isSafeInteger(value) &&\n I32_TEXT.test(text) &&\n BigInt(text) !== BigInt(value)\n ) {\n // an integer beyond 2^53 is stored as the nearest double; say so once per column\n this.report.warnOnce(\n \"precision\",\n PRECISION_CODE,\n `${this.domain} column \"${this.name}\": integers beyond 2^53 are stored as the nearest double (first: ${text})`,\n { element: this.name },\n `${PRECISION_CODE}:${this.domain}:${this.name}`,\n );\n }\n const wasString = this.textDtype === \"string\";\n const textDtype =\n this.textDtype === null || textDtypeRank(kind) > textDtypeRank(this.textDtype) ? kind : this.textDtype;\n // a string column keeps every cell's lexical form; a numeric text is never re-spelled. The\n // sink may refuse the value (a declared column of another dtype): the state advances only\n // once the cell is written, so a refused cell leaves the writer as it was.\n this.set(row, textDtype === \"string\" ? text : value);\n this.textDtype = textDtype;\n const valueKind = kindOfValue(value);\n if (this.valueDtype === null || textDtypeRank(valueKind) > textDtypeRank(this.valueDtype)) {\n this.valueDtype = valueKind;\n }\n if (this.textDtype === \"string\") {\n if (!wasString && this.keptRows.length > 0) {\n // the sink just widened the column to string from the values; restore the texts\n // whose lexical form the values did not carry\n for (let i = 0; i < this.keptRows.length; i++) {\n this.set(this.keptRows[i], this.keptTexts[i]);\n }\n this.keptRows.length = 0;\n this.keptTexts.length = 0;\n }\n return;\n }\n if (typeof value === \"number\" && !isCanonicalNumberText(text, value)) {\n this.keptRows.push(row);\n this.keptTexts.push(text);\n }\n if (this.textDtype === \"f64\" && this.valueDtype !== \"f64\") {\n this.widen(\"f64\");\n }\n }\n\n /**\n * Write a value (the parsed scalar, or a text into a widened column).\n * @param row - the row\n * @param value - the value\n */\n private set(row: number, value: unknown): void {\n if (this.handle === INVALID_INDEX) {\n if (this.domain === \"node\") {\n this.sink.setNodeValue(this.name, row, value);\n this.handle = this.sink.nodeColumn(this.name);\n } else {\n this.sink.setEdgeValue(this.name, row, value);\n this.handle = this.sink.edgeColumn(this.name);\n }\n return;\n }\n if (this.domain === \"node\") {\n this.sink.setNodeValue(this.handle, row, value);\n } else {\n this.sink.setEdgeValue(this.handle, row, value);\n }\n }\n\n /**\n * Widen the column to the dtype the text grammar implies, through the sink's optional call.\n * @param dtype - the dtype\n */\n private widen(dtype: \"f64\"): void {\n const { sink } = this;\n const supported =\n this.domain === \"node\" ? sink.widenNodeColumn !== undefined : sink.widenEdgeColumn !== undefined;\n if (!supported) {\n this.report.warnOnce(\n \"coercion\",\n WIDENING_UNSUPPORTED_CODE,\n `column \"${this.name}\" holds ${dtype} text but the sink cannot widen an inferred column; it keeps the value-inferred dtype`,\n { element: this.name },\n );\n this.valueDtype = dtype;\n return;\n }\n try {\n if (this.domain === \"node\") {\n sink.widenNodeColumn?.(this.handle, dtype);\n } else {\n sink.widenEdgeColumn?.(this.handle, dtype);\n }\n this.valueDtype = dtype;\n } catch (err) {\n if (!(err instanceof GraphFormatError) || err.code !== \"E_COLUMN_TYPE\") {\n throw err;\n }\n // a caller's declared column of the name: its dtype stands\n this.valueDtype = dtype;\n }\n }\n}\n\n/**\n * Your graph builder cannot change an attribute's type after its first value, so a text column keeps the type of its\n * first values.\n * @category Issue and loss codes\n */\nexport const WIDENING_UNSUPPORTED_CODE = \"W_WIDENING_UNSUPPORTED\";\n\n/**\n * The text dtype a parsed cell value implies on its own (what the sink's inference sees). It must\n * be graph-format's inference rule exactly: -0 is an integer there, so a column holding only\n * `-0.0` is inferred i32 and must be widened to f64, or the sign is lost.\n * @param value - the parsed value\n * @returns the dtype\n */\nfunction kindOfValue(value: boolean | number | string): TextDtype {\n if (typeof value === \"boolean\") {\n return \"bool\";\n }\n if (typeof value === \"string\") {\n return \"string\";\n }\n return Number.isInteger(value) && value >= -2147483648 && value <= 2147483647 ? \"i32\" : \"f64\";\n}\n"],"names":[],"mappings":"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"}
|
package/dist/csv.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { b as plural, bU as DICT_SAMPLE_ROWS, ac as DictHeuristic, R as ROLE_TAKEN_CODE$1, I as ID_MERGED_CODE$1, m as DUPLICATE_EDGE_ID_CODE$1, n as DUPLICATE_NODE_CODE$1, t as MISSING_ID_CODE$1, s as MISSING_ENDPOINT_CODE$1, E as EMPTY_INPUT_CODE$1, al as resolveImportOptions, a8 as ImportReportBuilder, ao as reportSinkOptions, an as reportUnusedOptions, aq as DirectionResolver, ar as IdCoercer, am as throwIfAborted, O as OPTION_IGNORED_CODE, aK as parseWeightText, a0 as uniqueColumnName, ay as RENAMED_CODE, a1 as declareResolved, c as capabilities, L as LOSS, a as checkCapabilities, r as resolveExportOptions, p as pairFolding, bD as countMixedEdges, $ as agree, e as explicitWeights, b_ as otherFormatDialect, bS as joinListText, aG as formatInteger, aF as formatDecimal, aH as canonicalId, M as MIXED_DIRECTION_CODE, D as DIRECTION_FORCED_CODE, d as DIRECTION_REFUSED_CODE, S as SINK_OPTION_CODE, C as COLUMN_RENAMED_CODE, w as UNKNOWN_ENCODING_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, P as PRECISION_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE } from "./chunks/export-
|
|
2
|
-
import { i as inferTextDtype, T as TextCellWriter, p as parseTextCell, W as WIDENING_UNSUPPORTED_CODE } from "./chunks/text-
|
|
1
|
+
import { b as plural, bU as DICT_SAMPLE_ROWS, ac as DictHeuristic, R as ROLE_TAKEN_CODE$1, I as ID_MERGED_CODE$1, m as DUPLICATE_EDGE_ID_CODE$1, n as DUPLICATE_NODE_CODE$1, t as MISSING_ID_CODE$1, s as MISSING_ENDPOINT_CODE$1, E as EMPTY_INPUT_CODE$1, al as resolveImportOptions, a8 as ImportReportBuilder, ao as reportSinkOptions, an as reportUnusedOptions, aq as DirectionResolver, ar as IdCoercer, am as throwIfAborted, O as OPTION_IGNORED_CODE, aK as parseWeightText, a0 as uniqueColumnName, ay as RENAMED_CODE, a1 as declareResolved, c as capabilities, L as LOSS, a as checkCapabilities, r as resolveExportOptions, p as pairFolding, bD as countMixedEdges, $ as agree, e as explicitWeights, b_ as otherFormatDialect, bS as joinListText, aG as formatInteger, aF as formatDecimal, aH as canonicalId, M as MIXED_DIRECTION_CODE, D as DIRECTION_FORCED_CODE, d as DIRECTION_REFUSED_CODE, S as SINK_OPTION_CODE, C as COLUMN_RENAMED_CODE, w as UNKNOWN_ENCODING_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, P as PRECISION_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE } from "./chunks/export-B-aVCwyG.js";
|
|
2
|
+
import { i as inferTextDtype, T as TextCellWriter, p as parseTextCell, W as WIDENING_UNSUPPORTED_CODE } from "./chunks/text-Bjfa1xYL.js";
|
|
3
3
|
import { GraphFormatError, INVALID_INDEX } from "@graphty/graph-format";
|
|
4
|
-
import { s as stripLeadingComments, a as sniffNewline, b as sniffDelimiter, D as DELIMITER_CANDIDATES, c as checkRecordSyntax, C as CsvRecordReader, d as splitRecords, B as BAD_QUOTE_CODE, U as UNCLOSED_QUOTE_CODE } from "./chunks/records-
|
|
5
|
-
import { o as quoteCsvCell } from "./chunks/escape-
|
|
4
|
+
import { s as stripLeadingComments, a as sniffNewline, b as sniffDelimiter, D as DELIMITER_CANDIDATES, c as checkRecordSyntax, C as CsvRecordReader, d as splitRecords, B as BAD_QUOTE_CODE, U as UNCLOSED_QUOTE_CODE } from "./chunks/records-r3SFHz11.js";
|
|
5
|
+
import { o as quoteCsvCell } from "./chunks/escape-BJRLd3vJ.js";
|
|
6
6
|
import { j as joinText, e as encodeChunks } from "./chunks/writer-DxjgHwSe.js";
|
|
7
7
|
const SOURCE_NAMES = Object.freeze([
|
|
8
8
|
"source",
|
package/dist/cx.js
CHANGED
package/dist/cx2.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C, a, c } from "./chunks/exporter-
|
|
2
|
-
import { C as C2, c as c2 } from "./chunks/importer-
|
|
1
|
+
import { C, a, c } from "./chunks/exporter-6ocL_9x_.js";
|
|
2
|
+
import { C as C2, c as c2 } from "./chunks/importer-BJlGAOht.js";
|
|
3
3
|
export {
|
|
4
4
|
C as CX2_CAPABILITIES,
|
|
5
5
|
C2 as CX2_ISSUE,
|
package/dist/cys.js
CHANGED
package/dist/dot.js
CHANGED
package/dist/gexf.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { bF as TIME_TEXT_ROLE, bG as TIME_TEXT_SUFFIX, al as resolveImportOptions, a8 as ImportReportBuilder, ao as reportSinkOptions, an as reportUnusedOptions, a4 as textChunks, E as EMPTY_INPUT_CODE, X as XML_SYNTAX_CODE, am as throwIfAborted, ar as IdCoercer, aq as DirectionResolver, f as STRAY_TEXT_CODE, N as NO_GRAPH_CODE, h as UNKNOWN_XML_ATTRIBUTE_CODE, l as MULTIPLE_GRAPHS_CODE, j as COUNT_MISMATCH_CODE, k as COUNT_HINT_CODE, o as DUPLICATE_ATTRIBUTE_CODE, aJ as isWeightField, bH as declareAttribute, a1 as declareResolved, t as MISSING_ID_CODE, n as DUPLICATE_NODE_CODE, q as UNKNOWN_PARENT_CODE, ai as PARENT_CYCLE_CODE, s as MISSING_ENDPOINT_CODE, m as DUPLICATE_EDGE_ID_CODE, aK as parseWeightText, bI as overflowsToInfinity, P as PRECISION_CODE, bJ as parseDeclaredTemporal, br as declareCompanion, bK as parseDeclaredValue, bL as losesPrecision, bM as parseTimeText, a3 as BAD_VALUE_CODE, bN as splitListText, g as UNKNOWN_ELEMENT_CODE, I as ID_MERGED_CODE, bO as timeTextCompanion, bP as parseDecimalText, c as capabilities, L as LOSS, aE as sanitizeIds, p as pairFolding, e as explicitWeights, r as resolveExportOptions, a as checkCapabilities, bQ as formatTimeValue, aa as formatF32, ab as formatF64, bR as mapDeclaredType, bS as joinListText, bT as formatTemporal, aG as formatInteger, b as plural, $ as agree, bx as isCanonicalIntegerText, M as MIXED_DIRECTION_CODE, D as DIRECTION_FORCED_CODE, d as DIRECTION_REFUSED_CODE, S as SINK_OPTION_CODE, O as OPTION_IGNORED_CODE, R as ROLE_TAKEN_CODE, C as COLUMN_RENAMED_CODE, aZ as BAD_OPTIONS_CODE, B as BAD_DEFAULT_CODE, U as UNKNOWN_ATTR_TYPE_CODE, v as ENCODING_CONFLICT_CODE, w as UNKNOWN_ENCODING_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, A as COLUMN_TYPE_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE } from "./chunks/export-
|
|
1
|
+
import { bF as TIME_TEXT_ROLE, bG as TIME_TEXT_SUFFIX, al as resolveImportOptions, a8 as ImportReportBuilder, ao as reportSinkOptions, an as reportUnusedOptions, a4 as textChunks, E as EMPTY_INPUT_CODE, X as XML_SYNTAX_CODE, am as throwIfAborted, ar as IdCoercer, aq as DirectionResolver, f as STRAY_TEXT_CODE, N as NO_GRAPH_CODE, h as UNKNOWN_XML_ATTRIBUTE_CODE, l as MULTIPLE_GRAPHS_CODE, j as COUNT_MISMATCH_CODE, k as COUNT_HINT_CODE, o as DUPLICATE_ATTRIBUTE_CODE, aJ as isWeightField, bH as declareAttribute, a1 as declareResolved, t as MISSING_ID_CODE, n as DUPLICATE_NODE_CODE, q as UNKNOWN_PARENT_CODE, ai as PARENT_CYCLE_CODE, s as MISSING_ENDPOINT_CODE, m as DUPLICATE_EDGE_ID_CODE, aK as parseWeightText, bI as overflowsToInfinity, P as PRECISION_CODE, bJ as parseDeclaredTemporal, br as declareCompanion, bK as parseDeclaredValue, bL as losesPrecision, bM as parseTimeText, a3 as BAD_VALUE_CODE, bN as splitListText, g as UNKNOWN_ELEMENT_CODE, I as ID_MERGED_CODE, bO as timeTextCompanion, bP as parseDecimalText, c as capabilities, L as LOSS, aE as sanitizeIds, p as pairFolding, e as explicitWeights, r as resolveExportOptions, a as checkCapabilities, bQ as formatTimeValue, aa as formatF32, ab as formatF64, bR as mapDeclaredType, bS as joinListText, bT as formatTemporal, aG as formatInteger, b as plural, $ as agree, bx as isCanonicalIntegerText, M as MIXED_DIRECTION_CODE, D as DIRECTION_FORCED_CODE, d as DIRECTION_REFUSED_CODE, S as SINK_OPTION_CODE, O as OPTION_IGNORED_CODE, R as ROLE_TAKEN_CODE, C as COLUMN_RENAMED_CODE, aZ as BAD_OPTIONS_CODE, B as BAD_DEFAULT_CODE, U as UNKNOWN_ATTR_TYPE_CODE, v as ENCODING_CONFLICT_CODE, w as UNKNOWN_ENCODING_CODE, x as ENCODING_FALLBACK_CODE, y as INVALID_ENCODING_CODE, z as INVALID_UTF8_CODE, A as COLUMN_TYPE_CODE, F as ELEMENT_ISSUE, G as INPUT_ISSUE } from "./chunks/export-B-aVCwyG.js";
|
|
2
2
|
import { GraphFormatError, INVALID_INDEX, MAX_COUNT } from "@graphty/graph-format";
|
|
3
|
-
import { t as tokenizeXml, f as xmlDeclaredEncoding, g as XmlEmptyInputError, X as XmlSyntaxError, s as sniffXmlText, l as localName, j as isWhitespace, x as xmlIllegalTextNotes, a as escapeXmlText, e as escapeXmlAttribute } from "./chunks/escape-
|
|
3
|
+
import { t as tokenizeXml, f as xmlDeclaredEncoding, g as XmlEmptyInputError, X as XmlSyntaxError, s as sniffXmlText, l as localName, j as isWhitespace, x as xmlIllegalTextNotes, a as escapeXmlText, e as escapeXmlAttribute } from "./chunks/escape-BJRLd3vJ.js";
|
|
4
4
|
import { j as joinText, e as encodeChunks } from "./chunks/writer-DxjgHwSe.js";
|
|
5
5
|
const GEXF_FORMAT = "gexf";
|
|
6
6
|
const GEXF_NAMESPACES = {
|
|
@@ -3355,7 +3355,8 @@ function lifetimeAttrs(roles, row, plan) {
|
|
|
3355
3355
|
return;
|
|
3356
3356
|
}
|
|
3357
3357
|
const text = timeText(column, roles.companions.get(column.meta.name) ?? null, row, timeFormat);
|
|
3358
|
-
|
|
3358
|
+
const attribute = open ? `${name}open` : name;
|
|
3359
|
+
out += ` ${attribute}="${escapeXmlAttribute(text)}"`;
|
|
3359
3360
|
};
|
|
3360
3361
|
if (roles.timestamp?.isSet(row)) {
|
|
3361
3362
|
if (version === "1.3" && plan.timeRepresentation === "timestamp") {
|
|
@@ -3370,7 +3371,8 @@ function lifetimeAttrs(roles, row, plan) {
|
|
|
3370
3371
|
}
|
|
3371
3372
|
if (version === "1.3" && roles.timestamps?.isSet(row)) {
|
|
3372
3373
|
const items = listItems(roles.timestamps, row).map((t) => formatTimeValue(t, timeFormat));
|
|
3373
|
-
|
|
3374
|
+
const stamps = `<[${items.join(", ")}]>`;
|
|
3375
|
+
out += ` timestamps="${escapeXmlAttribute(stamps)}"`;
|
|
3374
3376
|
}
|
|
3375
3377
|
return out;
|
|
3376
3378
|
}
|