@graphty/graph-io 0.3.28 → 0.3.30
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-DrXtu_96.js → choose-BfOLq6OX.js} +2 -2
- package/dist/chunks/{choose-DrXtu_96.js.map → choose-BfOLq6OX.js.map} +1 -1
- package/dist/chunks/{constants-ikG85dT8.js → constants-M8Qsjz1C.js} +2 -2
- package/dist/chunks/{constants-ikG85dT8.js.map → constants-M8Qsjz1C.js.map} +1 -1
- package/dist/chunks/{escape-D1HPTUrP.js → escape-UMMpQZqs.js} +2 -2
- package/dist/chunks/{escape-D1HPTUrP.js.map → escape-UMMpQZqs.js.map} +1 -1
- package/dist/chunks/{export-CHd4tQE2.js → export-Dq4U8Ubq.js} +165 -148
- package/dist/chunks/{export-CHd4tQE2.js.map → export-Dq4U8Ubq.js.map} +1 -1
- package/dist/chunks/{exporter-DhtW6FxK.js → exporter-BUosqV0K.js} +34 -34
- package/dist/chunks/exporter-BUosqV0K.js.map +1 -0
- package/dist/chunks/{exporter-D23CKNqF.js → exporter-Bd_VZ9ph.js} +9 -10
- package/dist/chunks/exporter-Bd_VZ9ph.js.map +1 -0
- package/dist/chunks/{exporter-DfWTgrti.js → exporter-COgVm-ff.js} +8 -7
- package/dist/chunks/{exporter-DfWTgrti.js.map → exporter-COgVm-ff.js.map} +1 -1
- package/dist/chunks/{exporter-Cl021ZIE.js → exporter-DEk_XLLs.js} +4 -4
- package/dist/chunks/{exporter-Cl021ZIE.js.map → exporter-DEk_XLLs.js.map} +1 -1
- package/dist/chunks/{importer-BZB7iP9r.js → importer-AQ3KpNHz.js} +11 -20
- package/dist/chunks/importer-AQ3KpNHz.js.map +1 -0
- package/dist/chunks/{importer-BVRE--Un.js → importer-BsZa2Phx.js} +5 -5
- package/dist/chunks/importer-BsZa2Phx.js.map +1 -0
- package/dist/chunks/{importer-DpEW5zeG.js → importer-CV8au8gH.js} +4 -4
- package/dist/chunks/{importer-DpEW5zeG.js.map → importer-CV8au8gH.js.map} +1 -1
- package/dist/chunks/{importer-BSALvkui.js → importer-Cj4-lXlv.js} +10 -9
- package/dist/chunks/importer-Cj4-lXlv.js.map +1 -0
- package/dist/chunks/{importer-B2W_58pz.js → importer-DQsgmhxc.js} +5 -5
- package/dist/chunks/{importer-B2W_58pz.js.map → importer-DQsgmhxc.js.map} +1 -1
- package/dist/chunks/{importer-CIAzt-wo.js → importer-Dkn79TjB.js} +6 -6
- package/dist/chunks/importer-Dkn79TjB.js.map +1 -0
- package/dist/chunks/{importer-z_FL4VMb.js → importer-DwSZvMDq.js} +10 -19
- package/dist/chunks/importer-DwSZvMDq.js.map +1 -0
- package/dist/chunks/{json-elements-BAmNBZok.js → json-elements-CreeKoaH.js} +12 -16
- package/dist/chunks/{json-elements-BAmNBZok.js.map → json-elements-CreeKoaH.js.map} +1 -1
- package/dist/chunks/{ontology-export-Bab4eUA8.js → ontology-export-C5Xd3W-7.js} +2 -2
- package/dist/chunks/{ontology-export-Bab4eUA8.js.map → ontology-export-C5Xd3W-7.js.map} +1 -1
- package/dist/chunks/{records-CdlvL4RO.js → records-BwaH_2ll.js} +2 -2
- package/dist/chunks/{records-CdlvL4RO.js.map → records-BwaH_2ll.js.map} +1 -1
- package/dist/chunks/{text-DzXjAiTl.js → text-4HHe6YH3.js} +2 -2
- package/dist/chunks/{text-DzXjAiTl.js.map → text-4HHe6YH3.js.map} +1 -1
- package/dist/csv.js +22 -15
- 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 +9 -8
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +3 -3
- package/dist/graph-io.js +69 -69
- 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/export.d.ts +6 -0
- package/dist/src/common/export.d.ts.map +1 -1
- package/dist/src/common/export.js +62 -28
- package/dist/src/common/export.js.map +1 -1
- package/dist/src/common/format.d.ts +0 -8
- package/dist/src/common/format.d.ts.map +1 -1
- package/dist/src/common/format.js +0 -10
- package/dist/src/common/format.js.map +1 -1
- package/dist/src/common/json-elements.d.ts +1 -9
- package/dist/src/common/json-elements.d.ts.map +1 -1
- package/dist/src/common/json-elements.js +2 -12
- package/dist/src/common/json-elements.js.map +1 -1
- package/dist/src/formats/csv/exporter.d.ts.map +1 -1
- package/dist/src/formats/csv/exporter.js +18 -7
- package/dist/src/formats/csv/exporter.js.map +1 -1
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +3 -3
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +3 -3
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/cys/exporter.d.ts.map +1 -1
- package/dist/src/formats/cys/exporter.js +4 -3
- package/dist/src/formats/cys/exporter.js.map +1 -1
- package/dist/src/formats/dot/exporter.js +1 -1
- package/dist/src/formats/dot/importer.d.ts +2 -2
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +7 -11
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/gexf/exporter.d.ts +2 -2
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +7 -5
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/schema.js +1 -1
- package/dist/src/formats/json/exporter.js +1 -1
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +4 -6
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/obo/syntax.d.ts +4 -0
- package/dist/src/formats/obo/syntax.d.ts.map +1 -1
- package/dist/src/formats/obo/syntax.js +35 -31
- package/dist/src/formats/obo/syntax.js.map +1 -1
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +5 -4
- 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 +3 -7
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/syntax.d.ts +1 -1
- package/dist/src/formats/pajek/syntax.js +1 -1
- package/dist/src/formats/xgmml/constants.d.ts +1 -1
- package/dist/src/formats/xgmml/constants.js +1 -1
- package/dist/src/formats/xgmml/emit.js +1 -1
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
- package/dist/src/formats/xgmml/exporter.js +4 -3
- package/dist/src/formats/xgmml/exporter.js.map +1 -1
- package/dist/src/types.d.ts +6 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/xgmml.js +2 -2
- package/package.json +1 -1
- package/src/common/export.ts +105 -62
- package/src/common/format.ts +0 -11
- package/src/common/json-elements.ts +2 -13
- package/src/formats/csv/exporter.ts +19 -15
- package/src/formats/cx/importer.ts +2 -3
- package/src/formats/cx2/importer.ts +2 -3
- package/src/formats/cys/exporter.ts +4 -3
- package/src/formats/dot/exporter.ts +1 -1
- package/src/formats/dot/importer.ts +7 -17
- package/src/formats/gexf/exporter.ts +7 -5
- package/src/formats/gexf/schema.ts +1 -1
- package/src/formats/json/exporter.ts +1 -1
- package/src/formats/json/importer.ts +4 -7
- package/src/formats/obo/syntax.ts +35 -31
- package/src/formats/pajek/exporter.ts +5 -4
- package/src/formats/pajek/importer.ts +3 -13
- package/src/formats/pajek/syntax.ts +1 -1
- package/src/formats/xgmml/constants.ts +1 -1
- package/src/formats/xgmml/emit.ts +1 -1
- package/src/formats/xgmml/exporter.ts +4 -3
- package/src/types.ts +6 -0
- package/dist/chunks/exporter-D23CKNqF.js.map +0 -1
- package/dist/chunks/exporter-DhtW6FxK.js.map +0 -1
- package/dist/chunks/importer-BSALvkui.js.map +0 -1
- package/dist/chunks/importer-BVRE--Un.js.map +0 -1
- package/dist/chunks/importer-BZB7iP9r.js.map +0 -1
- package/dist/chunks/importer-CIAzt-wo.js.map +0 -1
- package/dist/chunks/importer-z_FL4VMb.js.map +0 -1
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Every function works on the RAW text (escapes still in place) and unescapes only the pieces it
|
|
8
8
|
* hands back, so an escaped quote, colon, comma, brace or `!` never ends a construct.
|
|
9
|
+
*
|
|
10
|
+
* The scanners read characters with charAt(), never `text[i]`: the importer's linear-time tests
|
|
11
|
+
* count the characters the import reads through the string methods, and an index read is
|
|
12
|
+
* invisible to them, so a quadratic scan written with it would pass unnoticed.
|
|
9
13
|
*/
|
|
10
14
|
|
|
11
15
|
/** The OBO escapes with a meaning of their own; any other `\x` is `x` (the guides). */
|
|
@@ -29,14 +33,14 @@ export function unescapeObo(text: string): string {
|
|
|
29
33
|
}
|
|
30
34
|
let out = "";
|
|
31
35
|
for (let i = 0; i < text.length; i++) {
|
|
32
|
-
const ch = text
|
|
36
|
+
const ch = text.charAt(i);
|
|
33
37
|
if (ch !== "\\") {
|
|
34
38
|
out += ch;
|
|
35
39
|
continue;
|
|
36
40
|
}
|
|
37
41
|
i++;
|
|
38
42
|
if (i < text.length) {
|
|
39
|
-
const next = text
|
|
43
|
+
const next = text.charAt(i);
|
|
40
44
|
out += ESCAPES[next] ?? next;
|
|
41
45
|
}
|
|
42
46
|
}
|
|
@@ -51,7 +55,7 @@ export function unescapeObo(text: string): string {
|
|
|
51
55
|
*/
|
|
52
56
|
function isEscaped(text: string, index: number): boolean {
|
|
53
57
|
let run = 0;
|
|
54
|
-
for (let i = index - 1; i >= 0 && text
|
|
58
|
+
for (let i = index - 1; i >= 0 && text.charAt(i) === "\\"; i--) {
|
|
55
59
|
run++;
|
|
56
60
|
}
|
|
57
61
|
return run % 2 === 1;
|
|
@@ -71,8 +75,8 @@ export function splitFormFeeds(line: string): string[] {
|
|
|
71
75
|
const pieces: string[] = [];
|
|
72
76
|
let quoted = false;
|
|
73
77
|
let start = 0;
|
|
74
|
-
for (let i = 0; i < line.length; i += line
|
|
75
|
-
const ch = line
|
|
78
|
+
for (let i = 0; i < line.length; i += line.charAt(i) === "\\" ? 2 : 1) {
|
|
79
|
+
const ch = line.charAt(i);
|
|
76
80
|
if (ch === '"') {
|
|
77
81
|
quoted = !quoted;
|
|
78
82
|
} else if (ch === "\f" && !quoted) {
|
|
@@ -110,11 +114,11 @@ interface TagValue {
|
|
|
110
114
|
*/
|
|
111
115
|
export function splitTagValue(line: string): TagValue | null {
|
|
112
116
|
for (let i = 0; i < line.length; i++) {
|
|
113
|
-
if (line
|
|
117
|
+
if (line.charAt(i) === "\\") {
|
|
114
118
|
i++;
|
|
115
119
|
continue;
|
|
116
120
|
}
|
|
117
|
-
if (line
|
|
121
|
+
if (line.charAt(i) === ":") {
|
|
118
122
|
return { tag: unescapeObo(line.slice(0, i).trim()), rest: line.slice(i + 1).trimStart() };
|
|
119
123
|
}
|
|
120
124
|
}
|
|
@@ -134,12 +138,12 @@ export function splitTagValue(line: string): TagValue | null {
|
|
|
134
138
|
export function stripComment(rest: string): string {
|
|
135
139
|
let quoted = false;
|
|
136
140
|
for (let i = 0; i < rest.length; i++) {
|
|
137
|
-
const ch = rest
|
|
141
|
+
const ch = rest.charAt(i);
|
|
138
142
|
if (ch === "\\") {
|
|
139
143
|
i++;
|
|
140
144
|
continue;
|
|
141
145
|
}
|
|
142
|
-
const atStart = i === 0 || rest
|
|
146
|
+
const atStart = i === 0 || rest.charAt(i - 1) === " " || rest.charAt(i - 1) === "\t";
|
|
143
147
|
if (ch === '"' && (quoted || atStart)) {
|
|
144
148
|
quoted = !quoted;
|
|
145
149
|
} else if (ch === "!" && !quoted && atStart) {
|
|
@@ -183,7 +187,7 @@ export function splitQualifiers(value: string): QualifiedValue {
|
|
|
183
187
|
const parsed: Qualifiers[] = [];
|
|
184
188
|
let end = value.length;
|
|
185
189
|
let badBlock: string | null = null;
|
|
186
|
-
while (end > 0 && value
|
|
190
|
+
while (end > 0 && value.charAt(end - 1) === "}" && !isEscaped(value, end - 1)) {
|
|
187
191
|
const open = blocks.get(end - 1) ?? -1;
|
|
188
192
|
const block = open < 0 ? null : parseQualifiers(value.slice(open + 1, end - 1));
|
|
189
193
|
if (block === null) {
|
|
@@ -192,7 +196,7 @@ export function splitQualifiers(value: string): QualifiedValue {
|
|
|
192
196
|
}
|
|
193
197
|
parsed.push(block);
|
|
194
198
|
end = open;
|
|
195
|
-
while (end > 0 && /\s/.test(value
|
|
199
|
+
while (end > 0 && /\s/.test(value.charAt(end - 1))) {
|
|
196
200
|
end--;
|
|
197
201
|
}
|
|
198
202
|
}
|
|
@@ -217,7 +221,7 @@ function braceBlocks(value: string): Map<number, number> {
|
|
|
217
221
|
let quoted = false;
|
|
218
222
|
let open = -1;
|
|
219
223
|
for (let i = 0; i < value.length; i++) {
|
|
220
|
-
const ch = value
|
|
224
|
+
const ch = value.charAt(i);
|
|
221
225
|
if (ch === "\\") {
|
|
222
226
|
i++;
|
|
223
227
|
continue;
|
|
@@ -244,8 +248,8 @@ function braceBlocks(value: string): Map<number, number> {
|
|
|
244
248
|
export function unclosedBlock(value: string): number {
|
|
245
249
|
let quoted = false;
|
|
246
250
|
let open = -1;
|
|
247
|
-
for (let i = 0; i < value.length; i += value
|
|
248
|
-
const ch = value
|
|
251
|
+
for (let i = 0; i < value.length; i += value.charAt(i) === "\\" ? 2 : 1) {
|
|
252
|
+
const ch = value.charAt(i);
|
|
249
253
|
if (ch === "\\") {
|
|
250
254
|
continue;
|
|
251
255
|
}
|
|
@@ -297,7 +301,7 @@ export function parseQualifiers(inner: string): Qualifiers | null {
|
|
|
297
301
|
const n = inner.length;
|
|
298
302
|
let any = false;
|
|
299
303
|
while (i < n) {
|
|
300
|
-
while (i < n && (inner
|
|
304
|
+
while (i < n && (inner.charAt(i) === " " || inner.charAt(i) === "\t" || inner.charAt(i) === ",")) {
|
|
301
305
|
i++;
|
|
302
306
|
}
|
|
303
307
|
if (i >= n) {
|
|
@@ -312,11 +316,11 @@ export function parseQualifiers(inner: string): Qualifiers | null {
|
|
|
312
316
|
return null;
|
|
313
317
|
}
|
|
314
318
|
i = eq + 1;
|
|
315
|
-
while (i < n && (inner
|
|
319
|
+
while (i < n && (inner.charAt(i) === " " || inner.charAt(i) === "\t")) {
|
|
316
320
|
i++;
|
|
317
321
|
}
|
|
318
322
|
let value: string;
|
|
319
|
-
if (inner
|
|
323
|
+
if (inner.charAt(i) === '"') {
|
|
320
324
|
const end = closingQuote(inner, i + 1);
|
|
321
325
|
if (end < 0) {
|
|
322
326
|
return null;
|
|
@@ -325,8 +329,8 @@ export function parseQualifiers(inner: string): Qualifiers | null {
|
|
|
325
329
|
i = end + 1;
|
|
326
330
|
} else {
|
|
327
331
|
let end = i;
|
|
328
|
-
while (end < n && inner
|
|
329
|
-
end += inner
|
|
332
|
+
while (end < n && inner.charAt(end) !== ",") {
|
|
333
|
+
end += inner.charAt(end) === "\\" ? 2 : 1;
|
|
330
334
|
}
|
|
331
335
|
value = unescapeObo(inner.slice(i, end).trim());
|
|
332
336
|
i = end;
|
|
@@ -345,9 +349,9 @@ export function parseQualifiers(inner: string): Qualifiers | null {
|
|
|
345
349
|
*/
|
|
346
350
|
function closingQuote(text: string, from: number): number {
|
|
347
351
|
for (let i = from; i < text.length; i++) {
|
|
348
|
-
if (text
|
|
352
|
+
if (text.charAt(i) === "\\") {
|
|
349
353
|
i++;
|
|
350
|
-
} else if (text
|
|
354
|
+
} else if (text.charAt(i) === '"') {
|
|
351
355
|
return i;
|
|
352
356
|
}
|
|
353
357
|
}
|
|
@@ -379,7 +383,7 @@ export function tokenize(value: string): Token[] {
|
|
|
379
383
|
const n = value.length;
|
|
380
384
|
let i = 0;
|
|
381
385
|
while (i < n) {
|
|
382
|
-
const ch = value
|
|
386
|
+
const ch = value.charAt(i);
|
|
383
387
|
if (ch === " " || ch === "\t") {
|
|
384
388
|
i++;
|
|
385
389
|
continue;
|
|
@@ -390,8 +394,8 @@ export function tokenize(value: string): Token[] {
|
|
|
390
394
|
// a 1.4 language tag glued to the closing quote ("chat"@fr) is kept with the text, as an
|
|
391
395
|
// unquoted chat@fr is (research-obo.md 4.1: no language is split out)
|
|
392
396
|
let after = stop + 1;
|
|
393
|
-
if (end >= 0 && value
|
|
394
|
-
while (after < n && value
|
|
397
|
+
if (end >= 0 && value.charAt(after) === "@") {
|
|
398
|
+
while (after < n && value.charAt(after) !== " " && value.charAt(after) !== "\t") {
|
|
395
399
|
after++;
|
|
396
400
|
}
|
|
397
401
|
}
|
|
@@ -412,8 +416,8 @@ export function tokenize(value: string): Token[] {
|
|
|
412
416
|
continue;
|
|
413
417
|
}
|
|
414
418
|
let end = i;
|
|
415
|
-
while (end < n && value
|
|
416
|
-
end += value
|
|
419
|
+
while (end < n && value.charAt(end) !== " " && value.charAt(end) !== "\t") {
|
|
420
|
+
end += value.charAt(end) === "\\" ? 2 : 1;
|
|
417
421
|
}
|
|
418
422
|
tokens.push({ kind: "word", text: unescapeObo(value.slice(i, Math.min(end, n))), unterminated: false });
|
|
419
423
|
i = end;
|
|
@@ -430,7 +434,7 @@ export function tokenize(value: string): Token[] {
|
|
|
430
434
|
function closingBracket(text: string, from: number): number {
|
|
431
435
|
let quoted = false;
|
|
432
436
|
for (let i = from; i < text.length; i++) {
|
|
433
|
-
const ch = text
|
|
437
|
+
const ch = text.charAt(i);
|
|
434
438
|
if (ch === "\\") {
|
|
435
439
|
i++;
|
|
436
440
|
} else if (ch === '"') {
|
|
@@ -468,9 +472,9 @@ export function parseXref(raw: string): Xref | null {
|
|
|
468
472
|
const { value, qualifiers } = splitQualifiers(raw.trim());
|
|
469
473
|
let quote = -1;
|
|
470
474
|
for (let i = 0; i < value.length; i++) {
|
|
471
|
-
if (value
|
|
475
|
+
if (value.charAt(i) === "\\") {
|
|
472
476
|
i++;
|
|
473
|
-
} else if (value
|
|
477
|
+
} else if (value.charAt(i) === '"') {
|
|
474
478
|
quote = i;
|
|
475
479
|
break;
|
|
476
480
|
}
|
|
@@ -508,7 +512,7 @@ export function parseXrefList(inner: string): Xref[] {
|
|
|
508
512
|
}
|
|
509
513
|
};
|
|
510
514
|
for (let i = 0; i < inner.length; i++) {
|
|
511
|
-
const ch = inner
|
|
515
|
+
const ch = inner.charAt(i);
|
|
512
516
|
if (ch === "\\") {
|
|
513
517
|
i++;
|
|
514
518
|
} else if (ch === '"') {
|
|
@@ -538,7 +542,7 @@ export function hasStrayBrace(value: string): boolean {
|
|
|
538
542
|
let quoted = false;
|
|
539
543
|
let listed = false;
|
|
540
544
|
for (let i = 0; i < value.length; i++) {
|
|
541
|
-
const ch = value
|
|
545
|
+
const ch = value.charAt(i);
|
|
542
546
|
if (ch === "\\") {
|
|
543
547
|
i++;
|
|
544
548
|
} else if (ch === '"') {
|
|
@@ -17,7 +17,7 @@ import { type Column, GraphFormatError, type GraphSnapshot } from "@graphty/grap
|
|
|
17
17
|
import { pairFolding } from "../../common/direction.js";
|
|
18
18
|
import { isPajekLabel, quotePajekLabel } from "../../common/escape.js";
|
|
19
19
|
import { capabilities, checkCapabilities, LOSS, type SanitizedIds, sanitizeIds } from "../../common/export.js";
|
|
20
|
-
import { formatDecimal, formatF32, formatInteger, idText } from "../../common/format.js";
|
|
20
|
+
import { formatDecimal, formatF32, formatInteger, formatNumber, idText } from "../../common/format.js";
|
|
21
21
|
import { canonicalId } from "../../common/ids.js";
|
|
22
22
|
import { resolveExportOptions } from "../../common/options.js";
|
|
23
23
|
import { agree, plural } from "../../common/plural.js";
|
|
@@ -586,10 +586,11 @@ function coordinatesText(column: Column, i: number, writeZ: boolean): string | n
|
|
|
586
586
|
}
|
|
587
587
|
const dtype = column.dtype as "f32" | "f64" | "i32" | "u32" | "u8";
|
|
588
588
|
const vector = column.value(i) as ArrayLike<number>;
|
|
589
|
-
|
|
590
|
-
const
|
|
589
|
+
// the importer reads coordinates by position, so the shortest text of each is enough
|
|
590
|
+
const x = formatNumber(vector[0], dtype);
|
|
591
|
+
const y = formatNumber(vector[1], dtype);
|
|
591
592
|
if (column.meta.components === 3 && writeZ) {
|
|
592
|
-
return `${x} ${y} ${
|
|
593
|
+
return `${x} ${y} ${formatNumber(vector[2], dtype)}`;
|
|
593
594
|
}
|
|
594
595
|
return `${x} ${y}`;
|
|
595
596
|
}
|
|
@@ -46,7 +46,6 @@ import {
|
|
|
46
46
|
UNKNOWN_ENCODING_CODE,
|
|
47
47
|
} from "../../common/codes.js";
|
|
48
48
|
import { DirectionResolver, type EdgeKind } from "../../common/direction.js";
|
|
49
|
-
import { survivesF32 } from "../../common/format.js";
|
|
50
49
|
import { coerceIdText, ID_MERGED_CODE, IdCoercer } from "../../common/ids.js";
|
|
51
50
|
import { LineReader, throwIfAborted } from "../../common/input.js";
|
|
52
51
|
import {
|
|
@@ -292,14 +291,14 @@ function spellsDecl(): ColumnDecl {
|
|
|
292
291
|
}
|
|
293
292
|
|
|
294
293
|
/**
|
|
295
|
-
* The position column declaration (design section 5.2:
|
|
294
|
+
* The position column declaration (design section 5.2: f64 x 3, role position, units "file").
|
|
296
295
|
* @param sourceDims - 2 or 3, the coordinate count of the first vertex line with coordinates
|
|
297
296
|
* @returns a fresh declaration
|
|
298
297
|
*/
|
|
299
298
|
function positionDecl(sourceDims: number): ColumnDecl {
|
|
300
299
|
return {
|
|
301
300
|
name: POSITION_COLUMN,
|
|
302
|
-
dtype: "
|
|
301
|
+
dtype: "f64",
|
|
303
302
|
components: 3,
|
|
304
303
|
nullable: true,
|
|
305
304
|
role: "position",
|
|
@@ -1183,7 +1182,7 @@ class PajekParser {
|
|
|
1183
1182
|
}
|
|
1184
1183
|
|
|
1185
1184
|
/**
|
|
1186
|
-
* Write a vertex's coordinates into the position column (
|
|
1185
|
+
* Write a vertex's coordinates into the position column (f64 x 3), declared on first use.
|
|
1187
1186
|
* @param index - the node index
|
|
1188
1187
|
* @param dims - 2 or 3, the coordinates the line gave
|
|
1189
1188
|
* @param point - x, y, z (0 when absent)
|
|
@@ -1202,15 +1201,6 @@ class PajekParser {
|
|
|
1202
1201
|
{ line, element: String(k) },
|
|
1203
1202
|
);
|
|
1204
1203
|
}
|
|
1205
|
-
if (!point.every(survivesF32)) {
|
|
1206
|
-
this.report.warnOnce(
|
|
1207
|
-
"precision",
|
|
1208
|
-
PAJEK_ISSUE.PRECISION,
|
|
1209
|
-
`vertex ${k} has a coordinate the f32 position column rounds (warned once)`,
|
|
1210
|
-
{ line, element: String(k) },
|
|
1211
|
-
`${PAJEK_ISSUE.PRECISION}:position`,
|
|
1212
|
-
);
|
|
1213
|
-
}
|
|
1214
1204
|
this.sink.setNodeValue(this.positionHandle, index, point);
|
|
1215
1205
|
}
|
|
1216
1206
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
export const LABEL_COLUMN = "label";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* The node column holding the vertex coordinates (role position,
|
|
18
|
+
* The node column holding the vertex coordinates (role position, f64 x 3, units "file").
|
|
19
19
|
* @category Plugin helpers
|
|
20
20
|
*/
|
|
21
21
|
export const POSITION_COLUMN = "position";
|
|
@@ -108,7 +108,7 @@ export const LABEL_COLUMN = "label";
|
|
|
108
108
|
export const EDGE_ID_COLUMN = "id";
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
|
-
* The node position (
|
|
111
|
+
* The node position (f64 x3, role position, y up).
|
|
112
112
|
* @category Plugin helpers
|
|
113
113
|
*/
|
|
114
114
|
export const POSITION_COLUMN = "position";
|
|
@@ -538,7 +538,7 @@ function planExport(snapshot: GraphSnapshot, options: ResolvedExportOptions, esc
|
|
|
538
538
|
const notes = checkCapabilities(snapshot, CAPABILITIES, options, {
|
|
539
539
|
roles: SLOT_ROLES,
|
|
540
540
|
roleNames: ROLE_NAMES,
|
|
541
|
-
positionDtype: "
|
|
541
|
+
positionDtype: "f64",
|
|
542
542
|
}).filter((n) => n.code !== LOSS.JSON);
|
|
543
543
|
const note: NoteFn = (code, message, column = null, count = null): void => {
|
|
544
544
|
notes.push(Object.freeze({ code, message, column, count }));
|
|
@@ -986,10 +986,11 @@ function coordsOf(plan: Plan, zColumn: Column | null, node: number): [string, st
|
|
|
986
986
|
const xyz = cellOf(plan.position, node);
|
|
987
987
|
if (xyz !== null) {
|
|
988
988
|
const [x, y, z] = Array.from(xyz as ArrayLike<number>);
|
|
989
|
+
const fmt = plan.position?.dtype === "f32" ? formatF32 : formatF64;
|
|
989
990
|
if (Number.isFinite(x) && Number.isFinite(y)) {
|
|
990
|
-
out.push(["x",
|
|
991
|
+
out.push(["x", fmt(x)], ["y", fmt(y === 0 ? 0 : -y)]);
|
|
991
992
|
if (zColumn === null && z !== undefined && z !== 0 && Number.isFinite(z)) {
|
|
992
|
-
out.push(["z",
|
|
993
|
+
out.push(["z", fmt(z)]);
|
|
993
994
|
}
|
|
994
995
|
}
|
|
995
996
|
}
|
package/src/types.ts
CHANGED
|
@@ -368,6 +368,12 @@ export interface LossNote {
|
|
|
368
368
|
readonly column: string | null;
|
|
369
369
|
/** How many nodes, edges or values are affected, or null when not counted. */
|
|
370
370
|
readonly count: number | null;
|
|
371
|
+
/**
|
|
372
|
+
* Every column the note is about, when it is about several and `column` is null: the graph
|
|
373
|
+
* attributes a format has no place for, or the node columns a CSV edge table leaves for the node
|
|
374
|
+
* table. Absent on a note about one column or none.
|
|
375
|
+
*/
|
|
376
|
+
readonly columns?: readonly string[];
|
|
371
377
|
}
|
|
372
378
|
|
|
373
379
|
/**
|