@graphty/graph-io 0.3.39 → 0.3.41
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-CS3fvGT1.js → choose-CwFQamH9.js} +2 -2
- package/dist/chunks/{choose-CS3fvGT1.js.map → choose-CwFQamH9.js.map} +1 -1
- package/dist/chunks/{constants-DqKZT6cH.js → constants-Cf4Nn6tw.js} +2 -2
- package/dist/chunks/{constants-DqKZT6cH.js.map → constants-Cf4Nn6tw.js.map} +1 -1
- package/dist/chunks/{escape-BpYMQZVa.js → escape-DBb8zuNE.js} +4 -3
- package/dist/chunks/escape-DBb8zuNE.js.map +1 -0
- package/dist/chunks/{export-B-aVCwyG.js → export-DD3Lvw-F.js} +173 -116
- package/dist/chunks/export-DD3Lvw-F.js.map +1 -0
- package/dist/chunks/{exporter-CNJZF_BN.js → exporter-BqtmlxNr.js} +545 -459
- package/dist/chunks/exporter-BqtmlxNr.js.map +1 -0
- package/dist/chunks/{exporter-BqKs1Q12.js → exporter-CS35R6Fg.js} +6 -5
- package/dist/chunks/exporter-CS35R6Fg.js.map +1 -0
- package/dist/chunks/{exporter-DXqCPNrI.js → exporter-D8r1N2dU.js} +67 -42
- package/dist/chunks/exporter-D8r1N2dU.js.map +1 -0
- package/dist/chunks/{exporter-SFYkDzD0.js → exporter-NMplSnYn.js} +23 -20
- package/dist/chunks/{exporter-SFYkDzD0.js.map → exporter-NMplSnYn.js.map} +1 -1
- package/dist/chunks/{importer-CSt-gaYE.js → importer-BKC7AmCA.js} +42 -29
- package/dist/chunks/importer-BKC7AmCA.js.map +1 -0
- package/dist/chunks/{importer-DvFznt5-.js → importer-BdWHmlmG.js} +112 -62
- package/dist/chunks/importer-BdWHmlmG.js.map +1 -0
- package/dist/chunks/{importer-CqgYq4Ld.js → importer-BfbzWk6k.js} +202 -181
- package/dist/chunks/importer-BfbzWk6k.js.map +1 -0
- package/dist/chunks/{importer-PVXkeoaS.js → importer-BmaZcskq.js} +79 -66
- package/dist/chunks/importer-BmaZcskq.js.map +1 -0
- package/dist/chunks/{importer-B7Ir269L.js → importer-DviEsHy4.js} +118 -72
- package/dist/chunks/importer-DviEsHy4.js.map +1 -0
- package/dist/chunks/{importer--tQQsY4W.js → importer-S-abxJHn.js} +5 -5
- package/dist/chunks/{importer--tQQsY4W.js.map → importer-S-abxJHn.js.map} +1 -1
- package/dist/chunks/{importer-BfJ1jnNr.js → importer-r29cWnEf.js} +28 -13
- package/dist/chunks/importer-r29cWnEf.js.map +1 -0
- package/dist/chunks/{json-elements-CXs4z1iL.js → json-elements-DdF-etPT.js} +7 -5
- package/dist/chunks/{json-elements-CXs4z1iL.js.map → json-elements-DdF-etPT.js.map} +1 -1
- package/dist/chunks/{ontology-export-50L9DOV4.js → ontology-export-BC0zyPhj.js} +2 -2
- package/dist/chunks/{ontology-export-50L9DOV4.js.map → ontology-export-BC0zyPhj.js.map} +1 -1
- package/dist/chunks/{records-C9jd7yLD.js → records-Uc3LkABx.js} +150 -106
- package/dist/chunks/records-Uc3LkABx.js.map +1 -0
- package/dist/chunks/{text-Bjfa1xYL.js → text-Bh9SaAob.js} +20 -11
- package/dist/chunks/text-Bh9SaAob.js.map +1 -0
- package/dist/csv.js +67 -49
- package/dist/csv.js.map +1 -1
- 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 +199 -99
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +170 -149
- 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 +103 -65
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/src/common/attributes.d.ts.map +1 -1
- package/dist/src/common/attributes.js +34 -9
- package/dist/src/common/attributes.js.map +1 -1
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +180 -102
- 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/text.d.ts +7 -0
- package/dist/src/common/text.d.ts.map +1 -1
- package/dist/src/common/text.js +15 -7
- package/dist/src/common/text.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/common/zip.d.ts.map +1 -1
- package/dist/src/common/zip.js +36 -19
- package/dist/src/common/zip.js.map +1 -1
- package/dist/src/formats/csv/exporter.d.ts.map +1 -1
- package/dist/src/formats/csv/exporter.js +77 -25
- package/dist/src/formats/csv/exporter.js.map +1 -1
- package/dist/src/formats/csv/importer.d.ts.map +1 -1
- package/dist/src/formats/csv/importer.js +16 -6
- package/dist/src/formats/csv/importer.js.map +1 -1
- package/dist/src/formats/csv/records.d.ts.map +1 -1
- package/dist/src/formats/csv/records.js +156 -110
- 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/cys/tables.d.ts.map +1 -1
- package/dist/src/formats/cys/tables.js +11 -8
- package/dist/src/formats/cys/tables.js.map +1 -1
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +69 -39
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +138 -50
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gml/exporter.d.ts.map +1 -1
- package/dist/src/formats/gml/exporter.js +51 -35
- package/dist/src/formats/gml/exporter.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +103 -58
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/syntax.d.ts.map +1 -1
- package/dist/src/formats/gml/syntax.js +17 -8
- package/dist/src/formats/gml/syntax.js.map +1 -1
- package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
- package/dist/src/formats/graphml/exporter.js +36 -25
- 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 +20 -15
- package/dist/src/formats/graphml/importer.js.map +1 -1
- package/dist/src/formats/graphml/tree.js +23 -14
- package/dist/src/formats/graphml/tree.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +22 -10
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/exporter.d.ts.map +1 -1
- package/dist/src/formats/json/exporter.js +38 -21
- package/dist/src/formats/json/exporter.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +536 -343
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/obographs.js +29 -17
- package/dist/src/formats/json/obographs.js.map +1 -1
- package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
- package/dist/src/formats/neo4j/exporter.js +73 -43
- package/dist/src/formats/neo4j/exporter.js.map +1 -1
- package/dist/src/formats/neo4j/header.d.ts.map +1 -1
- package/dist/src/formats/neo4j/header.js +37 -16
- package/dist/src/formats/neo4j/header.js.map +1 -1
- package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
- package/dist/src/formats/neo4j/importer.js +21 -11
- package/dist/src/formats/neo4j/importer.js.map +1 -1
- package/dist/src/formats/obo/exporter.d.ts.map +1 -1
- package/dist/src/formats/obo/exporter.js +18 -7
- package/dist/src/formats/obo/exporter.js.map +1 -1
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +142 -73
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +26 -15
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +85 -58
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts +13 -0
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +112 -50
- 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 +92 -34
- package/dist/src/formats/xgmml/exporter.js.map +1 -1
- package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
- package/dist/src/formats/xgmml/importer.js +38 -18
- package/dist/src/formats/xgmml/importer.js.map +1 -1
- package/dist/src/sniff.js +109 -57
- package/dist/src/sniff.js.map +1 -1
- package/dist/xgmml.js +2 -2
- package/package.json +2 -2
- package/src/common/attributes.ts +59 -19
- package/src/common/input.ts +216 -102
- package/src/common/json-elements.ts +4 -2
- package/src/common/text.ts +24 -15
- package/src/common/xml.ts +2 -1
- package/src/common/zip.ts +47 -18
- package/src/formats/csv/exporter.ts +103 -39
- package/src/formats/csv/importer.ts +17 -6
- package/src/formats/csv/records.ts +162 -109
- 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/cys/tables.ts +11 -10
- package/src/formats/gexf/exporter.ts +71 -38
- package/src/formats/gexf/importer.ts +173 -63
- package/src/formats/gml/exporter.ts +78 -82
- package/src/formats/gml/importer.ts +119 -68
- package/src/formats/gml/syntax.ts +18 -8
- package/src/formats/graphml/exporter.ts +46 -27
- package/src/formats/graphml/importer.ts +21 -13
- package/src/formats/graphml/tree.ts +22 -12
- package/src/formats/graphml/yfiles.ts +23 -10
- package/src/formats/json/exporter.ts +40 -21
- package/src/formats/json/importer.ts +701 -385
- package/src/formats/json/obographs.ts +35 -15
- package/src/formats/neo4j/exporter.ts +79 -41
- package/src/formats/neo4j/header.ts +50 -16
- package/src/formats/neo4j/importer.ts +21 -10
- package/src/formats/obo/exporter.ts +34 -17
- package/src/formats/pajek/exporter.ts +180 -117
- package/src/formats/pajek/importer.ts +27 -15
- package/src/formats/pajek/syntax.ts +99 -58
- package/src/formats/xgmml/emit.ts +122 -50
- package/src/formats/xgmml/exporter.ts +103 -35
- package/src/formats/xgmml/importer.ts +45 -23
- package/src/sniff.ts +115 -59
- package/dist/chunks/escape-BpYMQZVa.js.map +0 -1
- package/dist/chunks/export-B-aVCwyG.js.map +0 -1
- package/dist/chunks/exporter-BqKs1Q12.js.map +0 -1
- package/dist/chunks/exporter-CNJZF_BN.js.map +0 -1
- package/dist/chunks/exporter-DXqCPNrI.js.map +0 -1
- package/dist/chunks/importer-B7Ir269L.js.map +0 -1
- package/dist/chunks/importer-BfJ1jnNr.js.map +0 -1
- package/dist/chunks/importer-CSt-gaYE.js.map +0 -1
- package/dist/chunks/importer-CqgYq4Ld.js.map +0 -1
- package/dist/chunks/importer-DvFznt5-.js.map +0 -1
- package/dist/chunks/importer-PVXkeoaS.js.map +0 -1
- package/dist/chunks/records-C9jd7yLD.js.map +0 -1
- package/dist/chunks/text-Bjfa1xYL.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { INVALID_INDEX, GraphFormatError } from "@graphty/graph-format";
|
|
2
|
-
import { P as PRECISION_CODE } from "./export-
|
|
2
|
+
import { P as PRECISION_CODE } from "./export-DD3Lvw-F.js";
|
|
3
3
|
const I32_TEXT = /^-?(0|[1-9]\d*)$/;
|
|
4
4
|
const F64_TEXT = /^[+-]?((0|[1-9]\d*)(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
|
|
5
5
|
const I32_MIN = -2147483648;
|
|
@@ -97,15 +97,7 @@ class TextCellWriter {
|
|
|
97
97
|
write(row, text) {
|
|
98
98
|
const kind = inferTextDtype(text);
|
|
99
99
|
const value = parseTextCell(text);
|
|
100
|
-
|
|
101
|
-
this.report.warnOnce(
|
|
102
|
-
"precision",
|
|
103
|
-
PRECISION_CODE,
|
|
104
|
-
`${this.domain} column "${this.name}": integers beyond 2^53 are stored as the nearest double (first: ${text})`,
|
|
105
|
-
{ element: this.name },
|
|
106
|
-
`${PRECISION_CODE}:${this.domain}:${this.name}`
|
|
107
|
-
);
|
|
108
|
-
}
|
|
100
|
+
this.warnIfImprecise(text, value);
|
|
109
101
|
const wasString = this.textDtype === "string";
|
|
110
102
|
const textDtype = this.textDtype === null || textDtypeRank(kind) > textDtypeRank(this.textDtype) ? kind : this.textDtype;
|
|
111
103
|
this.set(row, textDtype === "string" ? text : value);
|
|
@@ -132,6 +124,23 @@ class TextCellWriter {
|
|
|
132
124
|
this.widen("f64");
|
|
133
125
|
}
|
|
134
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Warn, once per column, when the cell is an integer beyond 2^53 that is stored as the nearest
|
|
129
|
+
* double.
|
|
130
|
+
* @param text - the cell text
|
|
131
|
+
* @param value - the parsed value
|
|
132
|
+
*/
|
|
133
|
+
warnIfImprecise(text, value) {
|
|
134
|
+
if (typeof value === "number" && !Number.isSafeInteger(value) && I32_TEXT.test(text) && BigInt(text) !== BigInt(value)) {
|
|
135
|
+
this.report.warnOnce(
|
|
136
|
+
"precision",
|
|
137
|
+
PRECISION_CODE,
|
|
138
|
+
`${this.domain} column "${this.name}": integers beyond 2^53 are stored as the nearest double (first: ${text})`,
|
|
139
|
+
{ element: this.name },
|
|
140
|
+
`${PRECISION_CODE}:${this.domain}:${this.name}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
135
144
|
/**
|
|
136
145
|
* Write a value (the parsed scalar, or a text into a widened column).
|
|
137
146
|
* @param row - the row
|
|
@@ -204,4 +213,4 @@ export {
|
|
|
204
213
|
parseTextCell as p,
|
|
205
214
|
trimTrailingZeros as t
|
|
206
215
|
};
|
|
207
|
-
//# sourceMappingURL=text-
|
|
216
|
+
//# sourceMappingURL=text-Bh9SaAob.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-Bh9SaAob.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 this.warnIfImprecise(text, value);\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 * Warn, once per column, when the cell is an integer beyond 2^53 that is stored as the nearest\n * double.\n * @param text - the cell text\n * @param value - the parsed value\n */\n private warnIfImprecise(text: string, value: unknown): void {\n if (\n typeof value === \"number\" &&\n !Number.isSafeInteger(value) &&\n I32_TEXT.test(text) &&\n BigInt(text) !== BigInt(value)\n ) {\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 }\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-DD3Lvw-F.js";
|
|
2
|
+
import { i as inferTextDtype, T as TextCellWriter, p as parseTextCell, W as WIDENING_UNSUPPORTED_CODE } from "./chunks/text-Bh9SaAob.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-Uc3LkABx.js";
|
|
5
|
+
import { o as quoteCsvCell } from "./chunks/escape-DBb8zuNE.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",
|
|
@@ -433,6 +433,15 @@ function isBlank(text) {
|
|
|
433
433
|
function isUnset(text, quoted) {
|
|
434
434
|
return quoted !== true && isBlank(text);
|
|
435
435
|
}
|
|
436
|
+
function setNeighborCells(row, quoted) {
|
|
437
|
+
let neighbors = 0;
|
|
438
|
+
for (let k = 1; k < row.length; k++) {
|
|
439
|
+
if (!isUnset(row[k], quoted[k])) {
|
|
440
|
+
neighbors++;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return neighbors;
|
|
444
|
+
}
|
|
436
445
|
const ABORT_CHECK_INTERVAL = 64;
|
|
437
446
|
function uniqueNames(names, report, line) {
|
|
438
447
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -1199,12 +1208,7 @@ class TableReader {
|
|
|
1199
1208
|
const { where } = this;
|
|
1200
1209
|
where.line = line;
|
|
1201
1210
|
where.element = null;
|
|
1202
|
-
|
|
1203
|
-
for (let k = 1; k < row.length; k++) {
|
|
1204
|
-
if (!isUnset(row[k], quoted[k])) {
|
|
1205
|
-
neighbors++;
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1211
|
+
const neighbors = setNeighborCells(row, quoted);
|
|
1208
1212
|
if (isUnset(row[0], quoted[0])) {
|
|
1209
1213
|
report.error("missing-value", MISSING_ID_CODE, `blank node cell`, { line });
|
|
1210
1214
|
counts.skippedNodes++;
|
|
@@ -1926,19 +1930,23 @@ function nodeTableNote(names, table, notes) {
|
|
|
1926
1930
|
);
|
|
1927
1931
|
}
|
|
1928
1932
|
}
|
|
1933
|
+
function idTextCollisions(ids) {
|
|
1934
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1935
|
+
let collisions = 0;
|
|
1936
|
+
for (let i = 0; i < ids.size; i++) {
|
|
1937
|
+
const text = String(ids.idOf(i));
|
|
1938
|
+
if (seen.has(text)) {
|
|
1939
|
+
collisions++;
|
|
1940
|
+
} else {
|
|
1941
|
+
seen.add(text);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
return collisions;
|
|
1945
|
+
}
|
|
1929
1946
|
function idNotes(snapshot, values, note) {
|
|
1930
1947
|
const { ids } = snapshot;
|
|
1931
1948
|
if (ids.kind === "mixed") {
|
|
1932
|
-
const
|
|
1933
|
-
let collisions = 0;
|
|
1934
|
-
for (let i = 0; i < ids.size; i++) {
|
|
1935
|
-
const text = String(ids.idOf(i));
|
|
1936
|
-
if (seen.has(text)) {
|
|
1937
|
-
collisions++;
|
|
1938
|
-
} else {
|
|
1939
|
-
seen.add(text);
|
|
1940
|
-
}
|
|
1941
|
-
}
|
|
1949
|
+
const collisions = idTextCollisions(ids);
|
|
1942
1950
|
if (collisions > 0) {
|
|
1943
1951
|
note(
|
|
1944
1952
|
CSV_LOSS.ID_TEXT_COLLISION,
|
|
@@ -2152,39 +2160,44 @@ function attributeColumns(table, domain, reserved, idColumn, labelColumn, note)
|
|
|
2152
2160
|
if (role !== null && SKIPPED_ROLES.has(role)) {
|
|
2153
2161
|
continue;
|
|
2154
2162
|
}
|
|
2155
|
-
const low = lower(name);
|
|
2156
2163
|
const set = column.length - column.nullCount;
|
|
2157
|
-
|
|
2158
|
-
if (reserved.has(low) || isIdName || idColumn !== null && lower(idColumn.meta.name) === low) {
|
|
2159
|
-
note?.(
|
|
2160
|
-
CSV_LOSS.RESERVED_NAME,
|
|
2161
|
-
`${domain} column "${name}" is not written: the name is reserved for the ${isIdName ? "edge id" : low} column`,
|
|
2162
|
-
name,
|
|
2163
|
-
set
|
|
2164
|
-
);
|
|
2164
|
+
if (isReservedName(name, domain, reserved, idColumn, set, note)) {
|
|
2165
2165
|
continue;
|
|
2166
2166
|
}
|
|
2167
|
-
if (findColumn([name], LABEL_NAMES) >= 0) {
|
|
2168
|
-
|
|
2169
|
-
note?.(
|
|
2170
|
-
CSV_LOSS.RESERVED_NAME,
|
|
2171
|
-
`${domain} column "${name}" is not written: the name is reserved for the label column`,
|
|
2172
|
-
name,
|
|
2173
|
-
set
|
|
2174
|
-
);
|
|
2175
|
-
continue;
|
|
2176
|
-
}
|
|
2177
|
-
note?.(
|
|
2178
|
-
CSV_LOSS.ROLE_ASSUMED,
|
|
2179
|
-
`${domain} column "${name}" reads back with the label role (string)`,
|
|
2180
|
-
name,
|
|
2181
|
-
set
|
|
2182
|
-
);
|
|
2167
|
+
if (findColumn([name], LABEL_NAMES) >= 0 && !labelNameWritten(name, domain, labelColumn, set, note)) {
|
|
2168
|
+
continue;
|
|
2183
2169
|
}
|
|
2184
2170
|
out.push({ column, header: name });
|
|
2185
2171
|
}
|
|
2186
2172
|
return out;
|
|
2187
2173
|
}
|
|
2174
|
+
function isReservedName(name, domain, reserved, idColumn, set, note) {
|
|
2175
|
+
const low = lower(name);
|
|
2176
|
+
const isIdName = domain === "edge" ? findColumn([name], EDGE_ID_NAMES) >= 0 : false;
|
|
2177
|
+
if (reserved.has(low) || isIdName || idColumn !== null && lower(idColumn.meta.name) === low) {
|
|
2178
|
+
note?.(
|
|
2179
|
+
CSV_LOSS.RESERVED_NAME,
|
|
2180
|
+
`${domain} column "${name}" is not written: the name is reserved for the ${isIdName ? "edge id" : low} column`,
|
|
2181
|
+
name,
|
|
2182
|
+
set
|
|
2183
|
+
);
|
|
2184
|
+
return true;
|
|
2185
|
+
}
|
|
2186
|
+
return false;
|
|
2187
|
+
}
|
|
2188
|
+
function labelNameWritten(name, domain, labelColumn, set, note) {
|
|
2189
|
+
if (labelColumn !== null) {
|
|
2190
|
+
note?.(
|
|
2191
|
+
CSV_LOSS.RESERVED_NAME,
|
|
2192
|
+
`${domain} column "${name}" is not written: the name is reserved for the label column`,
|
|
2193
|
+
name,
|
|
2194
|
+
set
|
|
2195
|
+
);
|
|
2196
|
+
return false;
|
|
2197
|
+
}
|
|
2198
|
+
note?.(CSV_LOSS.ROLE_ASSUMED, `${domain} column "${name}" reads back with the label role (string)`, name, set);
|
|
2199
|
+
return true;
|
|
2200
|
+
}
|
|
2188
2201
|
function checkRoleColumn(column, role, names, domain, rows, note) {
|
|
2189
2202
|
if (column === null) {
|
|
2190
2203
|
return;
|
|
@@ -2303,6 +2316,14 @@ function neighbourCell(id, weight) {
|
|
|
2303
2316
|
}
|
|
2304
2317
|
return id.includes(":") ? `${id}:` : id;
|
|
2305
2318
|
}
|
|
2319
|
+
function sourceRunEnd(src, edgeRows, r) {
|
|
2320
|
+
const source = src[edgeRows[r]];
|
|
2321
|
+
let end = r;
|
|
2322
|
+
while (end < edgeRows.length && src[edgeRows[end]] === source) {
|
|
2323
|
+
end++;
|
|
2324
|
+
}
|
|
2325
|
+
return end;
|
|
2326
|
+
}
|
|
2306
2327
|
function* adjacencyLines(snapshot, plan) {
|
|
2307
2328
|
const { delimiter, newline } = plan.csv;
|
|
2308
2329
|
const forced = (text) => `"${text.replaceAll('"', '""')}"`;
|
|
@@ -2329,10 +2350,7 @@ function* adjacencyLines(snapshot, plan) {
|
|
|
2329
2350
|
let r = 0;
|
|
2330
2351
|
while (r < edgeRows.length) {
|
|
2331
2352
|
const source = list.src[edgeRows[r]];
|
|
2332
|
-
|
|
2333
|
-
while (end < edgeRows.length && list.src[edgeRows[end]] === source) {
|
|
2334
|
-
end++;
|
|
2335
|
-
}
|
|
2353
|
+
const end = sourceRunEnd(list.src, edgeRows, r);
|
|
2336
2354
|
const fresh = [];
|
|
2337
2355
|
let highest = -1;
|
|
2338
2356
|
let inOrder = true;
|