@graphty/graph-io 0.3.42 → 0.3.44
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/approximations-3Q4TsdTh.js +40 -0
- package/dist/chunks/approximations-3Q4TsdTh.js.map +1 -0
- package/dist/chunks/block-JQiwViEt.js +2777 -0
- package/dist/chunks/block-JQiwViEt.js.map +1 -0
- package/dist/chunks/{choose-DvpbdRuz.js → choose-BemygfH8.js} +3 -2
- package/dist/chunks/{choose-DvpbdRuz.js.map → choose-BemygfH8.js.map} +1 -1
- package/dist/chunks/{constants-fT3E8JYY.js → constants-BFUR_CtU.js} +6 -2
- package/dist/chunks/constants-BFUR_CtU.js.map +1 -0
- package/dist/chunks/convert-BcQ8_jMo.js +59 -0
- package/dist/chunks/convert-BcQ8_jMo.js.map +1 -0
- package/dist/chunks/emit-DCwFLts5.js +3456 -0
- package/dist/chunks/emit-DCwFLts5.js.map +1 -0
- package/dist/chunks/{escape-B62ZGM_a.js → escape-B1rMftd9.js} +43 -20
- package/dist/chunks/escape-B1rMftd9.js.map +1 -0
- package/dist/chunks/{export-rKLeGQMo.js → export-D7IGzTG4.js} +196 -792
- package/dist/chunks/export-D7IGzTG4.js.map +1 -0
- package/dist/chunks/{exporter-BWwEuOPT.js → exporter-BtnqYuuj.js} +22 -12
- package/dist/chunks/exporter-BtnqYuuj.js.map +1 -0
- package/dist/chunks/{exporter-yLxKBvLE.js → exporter-ChPyhBOv.js} +4 -3
- package/dist/chunks/{exporter-yLxKBvLE.js.map → exporter-ChPyhBOv.js.map} +1 -1
- package/dist/chunks/{exporter-8hLNemFk.js → exporter-KEPxYUXD.js} +133 -74
- package/dist/chunks/exporter-KEPxYUXD.js.map +1 -0
- package/dist/chunks/{exporter-CpRyHZ3H.js → exporter-quPUCBiC.js} +1807 -288
- package/dist/chunks/exporter-quPUCBiC.js.map +1 -0
- package/dist/chunks/format-GDmO6m6Q.js +676 -0
- package/dist/chunks/format-GDmO6m6Q.js.map +1 -0
- package/dist/chunks/generic-BL06jrJf.js +1347 -0
- package/dist/chunks/generic-BL06jrJf.js.map +1 -0
- package/dist/chunks/{importer-WrGRZb0N.js → importer-B7r2owVf.js} +449 -102
- package/dist/chunks/importer-B7r2owVf.js.map +1 -0
- package/dist/chunks/{importer-Ht7LNg8L.js → importer-BFmOP96W.js} +116 -296
- package/dist/chunks/importer-BFmOP96W.js.map +1 -0
- package/dist/chunks/{importer-BbNb7eNg.js → importer-C2nzGhdV.js} +1390 -129
- package/dist/chunks/importer-C2nzGhdV.js.map +1 -0
- package/dist/chunks/{importer-Dz7tI8Sa.js → importer-CbX2_rNF.js} +617 -115
- package/dist/chunks/importer-CbX2_rNF.js.map +1 -0
- package/dist/chunks/{importer-D794XUTe.js → importer-CdzeN6X4.js} +31 -8
- package/dist/chunks/importer-CdzeN6X4.js.map +1 -0
- package/dist/chunks/{importer-xZ-3suY1.js → importer-ChKNC_GN.js} +791 -135
- package/dist/chunks/importer-ChKNC_GN.js.map +1 -0
- package/dist/chunks/{importer-C98dpSH4.js → importer-dwoYpSqb.js} +141 -82
- package/dist/chunks/importer-dwoYpSqb.js.map +1 -0
- package/dist/chunks/index-B9fdNpTA.js +4310 -0
- package/dist/chunks/index-B9fdNpTA.js.map +1 -0
- package/dist/chunks/{json-elements-DKSqpNW1.js → json-elements-C4FwgnH5.js} +123 -32
- package/dist/chunks/json-elements-C4FwgnH5.js.map +1 -0
- package/dist/chunks/lexicon-B-knUi-l.js +508 -0
- package/dist/chunks/lexicon-B-knUi-l.js.map +1 -0
- package/dist/chunks/{ontology-export-CtRXjg_i.js → ontology-export-BSpbY5FL.js} +3 -2
- package/dist/chunks/{ontology-export-CtRXjg_i.js.map → ontology-export-BSpbY5FL.js.map} +1 -1
- package/dist/chunks/{records-Cu4bxYOm.js → records-Nwz_rbNt.js} +2 -2
- package/dist/chunks/{records-Cu4bxYOm.js.map → records-Nwz_rbNt.js.map} +1 -1
- package/dist/chunks/styles-Brt9JMfs.js +690 -0
- package/dist/chunks/styles-Brt9JMfs.js.map +1 -0
- package/dist/chunks/styles-_N-C8S-U.js +2102 -0
- package/dist/chunks/styles-_N-C8S-U.js.map +1 -0
- package/dist/chunks/styles-yed-DAfcIkf7.js +842 -0
- package/dist/chunks/styles-yed-DAfcIkf7.js.map +1 -0
- package/dist/chunks/{text-DHOJXnED.js → text-CgzMqHQb.js} +2 -2
- package/dist/chunks/{text-DHOJXnED.js.map → text-CgzMqHQb.js.map} +1 -1
- package/dist/chunks/units-XMZFIFe1.js +19 -0
- package/dist/chunks/units-XMZFIFe1.js.map +1 -0
- package/dist/csv.js +5 -4
- 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 +5 -2
- package/dist/dot.js.map +1 -1
- package/dist/gexf.js +295 -414
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +8 -3031
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +354 -240
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +4 -2
- package/dist/graphml.js.map +1 -1
- package/dist/json.js +1 -1
- package/dist/neo4j.js +4 -3
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +1 -1
- package/dist/pajek.js +4 -2
- package/dist/positions.d.ts +1 -0
- package/dist/positions.js +427 -0
- package/dist/positions.js.map +1 -0
- package/dist/src/common/codes.d.ts +6 -0
- package/dist/src/common/codes.d.ts.map +1 -1
- package/dist/src/common/codes.js +6 -0
- package/dist/src/common/codes.js.map +1 -1
- package/dist/src/common/escape.d.ts.map +1 -1
- package/dist/src/common/escape.js +4 -2
- package/dist/src/common/escape.js.map +1 -1
- package/dist/src/common/export.d.ts +10 -0
- package/dist/src/common/export.d.ts.map +1 -1
- package/dist/src/common/export.js +123 -100
- package/dist/src/common/export.js.map +1 -1
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +8 -1
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/json-elements.d.ts +12 -9
- package/dist/src/common/json-elements.d.ts.map +1 -1
- package/dist/src/common/json-elements.js +160 -37
- package/dist/src/common/json-elements.js.map +1 -1
- package/dist/src/common/notes.d.ts +42 -0
- package/dist/src/common/notes.d.ts.map +1 -0
- package/dist/src/common/notes.js +72 -0
- package/dist/src/common/notes.js.map +1 -0
- package/dist/src/common/report.d.ts +18 -0
- package/dist/src/common/report.d.ts.map +1 -1
- package/dist/src/common/report.js +36 -1
- package/dist/src/common/report.js.map +1 -1
- package/dist/src/common/units.d.ts +24 -0
- package/dist/src/common/units.d.ts.map +1 -0
- package/dist/src/common/units.js +26 -0
- package/dist/src/common/units.js.map +1 -0
- package/dist/src/common/xml.d.ts +18 -0
- package/dist/src/common/xml.d.ts.map +1 -1
- package/dist/src/common/xml.js +42 -5
- package/dist/src/common/xml.js.map +1 -1
- package/dist/src/formats/cx/exporter.d.ts +6 -0
- package/dist/src/formats/cx/exporter.d.ts.map +1 -1
- package/dist/src/formats/cx/exporter.js +71 -8
- package/dist/src/formats/cx/exporter.js.map +1 -1
- package/dist/src/formats/cx/importer.d.ts +5 -2
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +102 -72
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx/styles.d.ts +102 -0
- package/dist/src/formats/cx/styles.d.ts.map +1 -0
- package/dist/src/formats/cx/styles.js +225 -0
- package/dist/src/formats/cx/styles.js.map +1 -0
- package/dist/src/formats/cx2/exporter.d.ts +5 -0
- package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
- package/dist/src/formats/cx2/exporter.js +181 -71
- package/dist/src/formats/cx2/exporter.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts +4 -1
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +19 -1
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/cx2/styles.d.ts +18 -0
- package/dist/src/formats/cx2/styles.d.ts.map +1 -0
- package/dist/src/formats/cx2/styles.js +24 -0
- package/dist/src/formats/cx2/styles.js.map +1 -0
- package/dist/src/formats/cys/constants.d.ts +2 -0
- package/dist/src/formats/cys/constants.d.ts.map +1 -1
- package/dist/src/formats/cys/constants.js +2 -0
- package/dist/src/formats/cys/constants.js.map +1 -1
- package/dist/src/formats/cys/exporter.d.ts +6 -2
- package/dist/src/formats/cys/exporter.d.ts.map +1 -1
- package/dist/src/formats/cys/exporter.js +215 -53
- package/dist/src/formats/cys/exporter.js.map +1 -1
- package/dist/src/formats/cys/importer.d.ts +2 -1
- package/dist/src/formats/cys/importer.d.ts.map +1 -1
- package/dist/src/formats/cys/importer.js +119 -6
- package/dist/src/formats/cys/importer.js.map +1 -1
- package/dist/src/formats/cys/session.d.ts +2 -0
- package/dist/src/formats/cys/session.d.ts.map +1 -1
- package/dist/src/formats/cys/session.js +5 -0
- package/dist/src/formats/cys/session.js.map +1 -1
- package/dist/src/formats/cys/styles.d.ts +38 -0
- package/dist/src/formats/cys/styles.d.ts.map +1 -0
- package/dist/src/formats/cys/styles.js +213 -0
- package/dist/src/formats/cys/styles.js.map +1 -0
- package/dist/src/formats/cys/tables.d.ts +8 -3
- package/dist/src/formats/cys/tables.d.ts.map +1 -1
- package/dist/src/formats/cys/tables.js +88 -34
- package/dist/src/formats/cys/tables.js.map +1 -1
- package/dist/src/formats/dot/exporter.d.ts +2 -0
- package/dist/src/formats/dot/exporter.d.ts.map +1 -1
- package/dist/src/formats/dot/exporter.js +195 -81
- package/dist/src/formats/dot/exporter.js.map +1 -1
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +100 -20
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/index.d.ts +1 -0
- package/dist/src/formats/dot/index.d.ts.map +1 -1
- package/dist/src/formats/dot/index.js +1 -0
- package/dist/src/formats/dot/index.js.map +1 -1
- package/dist/src/formats/dot/positions.d.ts +14 -0
- package/dist/src/formats/dot/positions.d.ts.map +1 -0
- package/dist/src/formats/dot/positions.js +70 -0
- package/dist/src/formats/dot/positions.js.map +1 -0
- package/dist/src/formats/dot/styles.d.ts +82 -0
- package/dist/src/formats/dot/styles.d.ts.map +1 -0
- package/dist/src/formats/dot/styles.js +1484 -0
- package/dist/src/formats/dot/styles.js.map +1 -0
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +23 -7
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts +8 -1
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +251 -131
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/index.d.ts +8 -0
- package/dist/src/formats/gexf/index.d.ts.map +1 -1
- package/dist/src/formats/gexf/index.js +10 -2
- package/dist/src/formats/gexf/index.js.map +1 -1
- package/dist/src/formats/gexf/schema.d.ts +5 -0
- package/dist/src/formats/gexf/schema.d.ts.map +1 -1
- package/dist/src/formats/gexf/schema.js +5 -0
- package/dist/src/formats/gexf/schema.js.map +1 -1
- package/dist/src/formats/gexf/styles.d.ts +74 -0
- package/dist/src/formats/gexf/styles.d.ts.map +1 -0
- package/dist/src/formats/gexf/styles.js +604 -0
- package/dist/src/formats/gexf/styles.js.map +1 -0
- package/dist/src/formats/gml/exporter.d.ts +1 -5
- package/dist/src/formats/gml/exporter.d.ts.map +1 -1
- package/dist/src/formats/gml/exporter.js +19 -8
- 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 +4 -0
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/index.d.ts +2 -1
- package/dist/src/formats/gml/index.d.ts.map +1 -1
- package/dist/src/formats/gml/index.js +2 -1
- package/dist/src/formats/gml/index.js.map +1 -1
- package/dist/src/formats/gml/positions.d.ts +14 -0
- package/dist/src/formats/gml/positions.d.ts.map +1 -0
- package/dist/src/formats/gml/positions.js +46 -0
- package/dist/src/formats/gml/positions.js.map +1 -0
- package/dist/src/formats/gml/styles.d.ts +59 -0
- package/dist/src/formats/gml/styles.d.ts.map +1 -0
- package/dist/src/formats/gml/styles.js +1056 -0
- package/dist/src/formats/gml/styles.js.map +1 -0
- package/dist/src/formats/gml/syntax.d.ts +11 -0
- package/dist/src/formats/gml/syntax.d.ts.map +1 -1
- package/dist/src/formats/gml/syntax.js +151 -62
- package/dist/src/formats/gml/syntax.js.map +1 -1
- package/dist/src/formats/graphml/constants.d.ts +4 -0
- package/dist/src/formats/graphml/constants.d.ts.map +1 -1
- package/dist/src/formats/graphml/constants.js +5 -1
- package/dist/src/formats/graphml/constants.js.map +1 -1
- package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
- package/dist/src/formats/graphml/exporter.js +133 -65
- package/dist/src/formats/graphml/exporter.js.map +1 -1
- package/dist/src/formats/graphml/importer.d.ts +4 -1
- package/dist/src/formats/graphml/importer.d.ts.map +1 -1
- package/dist/src/formats/graphml/importer.js +100 -44
- package/dist/src/formats/graphml/importer.js.map +1 -1
- package/dist/src/formats/graphml/index.d.ts +1 -0
- package/dist/src/formats/graphml/index.d.ts.map +1 -1
- package/dist/src/formats/graphml/index.js +1 -0
- package/dist/src/formats/graphml/index.js.map +1 -1
- package/dist/src/formats/graphml/styles-plain.d.ts +19 -0
- package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -0
- package/dist/src/formats/graphml/styles-plain.js +187 -0
- package/dist/src/formats/graphml/styles-plain.js.map +1 -0
- package/dist/src/formats/graphml/styles-yed.d.ts +179 -0
- package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -0
- package/dist/src/formats/graphml/styles-yed.js +1086 -0
- package/dist/src/formats/graphml/styles-yed.js.map +1 -0
- package/dist/src/formats/graphml/styles-yfiles3.d.ts +19 -0
- package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -0
- package/dist/src/formats/graphml/styles-yfiles3.js +508 -0
- package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -0
- package/dist/src/formats/graphml/tree.d.ts.map +1 -1
- package/dist/src/formats/graphml/tree.js +34 -19
- package/dist/src/formats/graphml/tree.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts +16 -2
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +83 -12
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/exporter.d.ts +5 -0
- package/dist/src/formats/json/exporter.d.ts.map +1 -1
- package/dist/src/formats/json/exporter.js +68 -25
- package/dist/src/formats/json/exporter.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts +22 -3
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +441 -265
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/positions.d.ts +16 -0
- package/dist/src/formats/json/positions.d.ts.map +1 -0
- package/dist/src/formats/json/positions.js +44 -0
- package/dist/src/formats/json/positions.js.map +1 -0
- package/dist/src/formats/json/styles.d.ts +102 -0
- package/dist/src/formats/json/styles.d.ts.map +1 -0
- package/dist/src/formats/json/styles.js +1753 -0
- package/dist/src/formats/json/styles.js.map +1 -0
- package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
- package/dist/src/formats/neo4j/exporter.js +2 -1
- package/dist/src/formats/neo4j/exporter.js.map +1 -1
- package/dist/src/formats/pajek/exporter.d.ts +2 -0
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +142 -76
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts +4 -0
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +60 -6
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/index.d.ts +2 -0
- package/dist/src/formats/pajek/index.d.ts.map +1 -1
- package/dist/src/formats/pajek/index.js +2 -0
- package/dist/src/formats/pajek/index.js.map +1 -1
- package/dist/src/formats/pajek/styles.d.ts +50 -0
- package/dist/src/formats/pajek/styles.d.ts.map +1 -0
- package/dist/src/formats/pajek/styles.js +569 -0
- package/dist/src/formats/pajek/styles.js.map +1 -0
- package/dist/src/formats/pajek/syntax.d.ts +6 -0
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +6 -0
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
- package/dist/src/formats/xgmml/columns.js +34 -9
- package/dist/src/formats/xgmml/columns.js.map +1 -1
- package/dist/src/formats/xgmml/constants.d.ts +2 -0
- package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
- package/dist/src/formats/xgmml/constants.js +3 -1
- package/dist/src/formats/xgmml/constants.js.map +1 -1
- package/dist/src/formats/xgmml/document.d.ts +12 -8
- package/dist/src/formats/xgmml/document.d.ts.map +1 -1
- package/dist/src/formats/xgmml/document.js +56 -13
- package/dist/src/formats/xgmml/document.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +12 -6
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/exporter.d.ts +3 -1
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
- package/dist/src/formats/xgmml/exporter.js +22 -9
- package/dist/src/formats/xgmml/exporter.js.map +1 -1
- package/dist/src/formats/xgmml/importer.d.ts +2 -1
- package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
- package/dist/src/formats/xgmml/importer.js +31 -24
- package/dist/src/formats/xgmml/importer.js.map +1 -1
- package/dist/src/formats/xgmml/styles.d.ts +104 -0
- package/dist/src/formats/xgmml/styles.d.ts.map +1 -0
- package/dist/src/formats/xgmml/styles.js +310 -0
- package/dist/src/formats/xgmml/styles.js.map +1 -0
- package/dist/src/index.d.ts +9 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -7
- package/dist/src/index.js.map +1 -1
- package/dist/src/positions/codes.d.ts +31 -0
- package/dist/src/positions/codes.d.ts.map +1 -0
- package/dist/src/positions/codes.js +26 -0
- package/dist/src/positions/codes.js.map +1 -0
- package/dist/src/positions/convert.d.ts +58 -0
- package/dist/src/positions/convert.d.ts.map +1 -0
- package/dist/src/positions/convert.js +107 -0
- package/dist/src/positions/convert.js.map +1 -0
- package/dist/src/positions/extract.d.ts +27 -0
- package/dist/src/positions/extract.d.ts.map +1 -0
- package/dist/src/positions/extract.js +526 -0
- package/dist/src/positions/extract.js.map +1 -0
- package/dist/src/positions/index.d.ts +10 -0
- package/dist/src/positions/index.d.ts.map +1 -0
- package/dist/src/positions/index.js +9 -0
- package/dist/src/positions/index.js.map +1 -0
- package/dist/src/positions/types.d.ts +208 -0
- package/dist/src/positions/types.d.ts.map +1 -0
- package/dist/src/positions/types.js +10 -0
- package/dist/src/positions/types.js.map +1 -0
- package/dist/src/registry.d.ts +30 -0
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +130 -9
- package/dist/src/registry.js.map +1 -1
- package/dist/src/styles/annotations.d.ts +132 -0
- package/dist/src/styles/annotations.d.ts.map +1 -0
- package/dist/src/styles/annotations.js +320 -0
- package/dist/src/styles/annotations.js.map +1 -0
- package/dist/src/styles/budget.d.ts +45 -0
- package/dist/src/styles/budget.d.ts.map +1 -0
- package/dist/src/styles/budget.js +58 -0
- package/dist/src/styles/budget.js.map +1 -0
- package/dist/src/styles/canon/bends.d.ts +32 -0
- package/dist/src/styles/canon/bends.d.ts.map +1 -0
- package/dist/src/styles/canon/bends.js +74 -0
- package/dist/src/styles/canon/bends.js.map +1 -0
- package/dist/src/styles/canon/color-tables.d.ts +22 -0
- package/dist/src/styles/canon/color-tables.d.ts.map +1 -0
- package/dist/src/styles/canon/color-tables.js +369 -0
- package/dist/src/styles/canon/color-tables.js.map +1 -0
- package/dist/src/styles/canon/color.d.ts +66 -0
- package/dist/src/styles/canon/color.d.ts.map +1 -0
- package/dist/src/styles/canon/color.js +548 -0
- package/dist/src/styles/canon/color.js.map +1 -0
- package/dist/src/styles/canon/enums.d.ts +25 -0
- package/dist/src/styles/canon/enums.d.ts.map +1 -0
- package/dist/src/styles/canon/enums.js +187 -0
- package/dist/src/styles/canon/enums.js.map +1 -0
- package/dist/src/styles/canon/graphviz.d.ts +48 -0
- package/dist/src/styles/canon/graphviz.d.ts.map +1 -0
- package/dist/src/styles/canon/graphviz.js +160 -0
- package/dist/src/styles/canon/graphviz.js.map +1 -0
- package/dist/src/styles/canon/index.d.ts +13 -0
- package/dist/src/styles/canon/index.d.ts.map +1 -0
- package/dist/src/styles/canon/index.js +13 -0
- package/dist/src/styles/canon/index.js.map +1 -0
- package/dist/src/styles/canon/number.d.ts +59 -0
- package/dist/src/styles/canon/number.d.ts.map +1 -0
- package/dist/src/styles/canon/number.js +142 -0
- package/dist/src/styles/canon/number.js.map +1 -0
- package/dist/src/styles/canon/site.d.ts +51 -0
- package/dist/src/styles/canon/site.d.ts.map +1 -0
- package/dist/src/styles/canon/site.js +63 -0
- package/dist/src/styles/canon/site.js.map +1 -0
- package/dist/src/styles/canon/text.d.ts +61 -0
- package/dist/src/styles/canon/text.d.ts.map +1 -0
- package/dist/src/styles/canon/text.js +199 -0
- package/dist/src/styles/canon/text.js.map +1 -0
- package/dist/src/styles/codes.d.ts +95 -0
- package/dist/src/styles/codes.d.ts.map +1 -0
- package/dist/src/styles/codes.js +97 -0
- package/dist/src/styles/codes.js.map +1 -0
- package/dist/src/styles/cyjs/cascade.d.ts +134 -0
- package/dist/src/styles/cyjs/cascade.d.ts.map +1 -0
- package/dist/src/styles/cyjs/cascade.js +2252 -0
- package/dist/src/styles/cyjs/cascade.js.map +1 -0
- package/dist/src/styles/cyjs/defaults-table.d.ts +25 -0
- package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -0
- package/dist/src/styles/cyjs/defaults-table.js +76 -0
- package/dist/src/styles/cyjs/defaults-table.js.map +1 -0
- package/dist/src/styles/cyjs/emit.d.ts +82 -0
- package/dist/src/styles/cyjs/emit.d.ts.map +1 -0
- package/dist/src/styles/cyjs/emit.js +790 -0
- package/dist/src/styles/cyjs/emit.js.map +1 -0
- package/dist/src/styles/cyjs/index.d.ts +13 -0
- package/dist/src/styles/cyjs/index.d.ts.map +1 -0
- package/dist/src/styles/cyjs/index.js +13 -0
- package/dist/src/styles/cyjs/index.js.map +1 -0
- package/dist/src/styles/cyjs/live.d.ts +46 -0
- package/dist/src/styles/cyjs/live.d.ts.map +1 -0
- package/dist/src/styles/cyjs/live.js +108 -0
- package/dist/src/styles/cyjs/live.js.map +1 -0
- package/dist/src/styles/cyjs/mappers.d.ts +147 -0
- package/dist/src/styles/cyjs/mappers.d.ts.map +1 -0
- package/dist/src/styles/cyjs/mappers.js +744 -0
- package/dist/src/styles/cyjs/mappers.js.map +1 -0
- package/dist/src/styles/cyjs/selector.d.ts +113 -0
- package/dist/src/styles/cyjs/selector.d.ts.map +1 -0
- package/dist/src/styles/cyjs/selector.js +611 -0
- package/dist/src/styles/cyjs/selector.js.map +1 -0
- package/dist/src/styles/cyjs/stylesheet-text.d.ts +37 -0
- package/dist/src/styles/cyjs/stylesheet-text.d.ts.map +1 -0
- package/dist/src/styles/cyjs/stylesheet-text.js +181 -0
- package/dist/src/styles/cyjs/stylesheet-text.js.map +1 -0
- package/dist/src/styles/cytoscape/emit.d.ts +125 -0
- package/dist/src/styles/cytoscape/emit.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/emit.js +1025 -0
- package/dist/src/styles/cytoscape/emit.js.map +1 -0
- package/dist/src/styles/cytoscape/index.d.ts +10 -0
- package/dist/src/styles/cytoscape/index.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/index.js +10 -0
- package/dist/src/styles/cytoscape/index.js.map +1 -0
- package/dist/src/styles/cytoscape/lexicon.d.ts +49 -0
- package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/lexicon.js +603 -0
- package/dist/src/styles/cytoscape/lexicon.js.map +1 -0
- package/dist/src/styles/cytoscape/mappings.d.ts +171 -0
- package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/mappings.js +460 -0
- package/dist/src/styles/cytoscape/mappings.js.map +1 -0
- package/dist/src/styles/cytoscape/resolve.d.ts +137 -0
- package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/resolve.js +381 -0
- package/dist/src/styles/cytoscape/resolve.js.map +1 -0
- package/dist/src/styles/cytoscape/translate.d.ts +50 -0
- package/dist/src/styles/cytoscape/translate.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/translate.js +156 -0
- package/dist/src/styles/cytoscape/translate.js.map +1 -0
- package/dist/src/styles/defaults.d.ts +90 -0
- package/dist/src/styles/defaults.d.ts.map +1 -0
- package/dist/src/styles/defaults.js +414 -0
- package/dist/src/styles/defaults.js.map +1 -0
- package/dist/src/styles/index.d.ts +15 -0
- package/dist/src/styles/index.d.ts.map +1 -0
- package/dist/src/styles/index.js +14 -0
- package/dist/src/styles/index.js.map +1 -0
- package/dist/src/styles/internal.d.ts +17 -0
- package/dist/src/styles/internal.d.ts.map +1 -0
- package/dist/src/styles/internal.js +16 -0
- package/dist/src/styles/internal.js.map +1 -0
- package/dist/src/styles/io/approximations.d.ts +24 -0
- package/dist/src/styles/io/approximations.d.ts.map +1 -0
- package/dist/src/styles/io/approximations.js +51 -0
- package/dist/src/styles/io/approximations.js.map +1 -0
- package/dist/src/styles/io/block.d.ts +166 -0
- package/dist/src/styles/io/block.d.ts.map +1 -0
- package/dist/src/styles/io/block.js +930 -0
- package/dist/src/styles/io/block.js.map +1 -0
- package/dist/src/styles/io/generic.d.ts +88 -0
- package/dist/src/styles/io/generic.d.ts.map +1 -0
- package/dist/src/styles/io/generic.js +516 -0
- package/dist/src/styles/io/generic.js.map +1 -0
- package/dist/src/styles/io/index.d.ts +8 -0
- package/dist/src/styles/io/index.d.ts.map +1 -0
- package/dist/src/styles/io/index.js +7 -0
- package/dist/src/styles/io/index.js.map +1 -0
- package/dist/src/styles/io/writer.d.ts +80 -0
- package/dist/src/styles/io/writer.d.ts.map +1 -0
- package/dist/src/styles/io/writer.js +596 -0
- package/dist/src/styles/io/writer.js.map +1 -0
- package/dist/src/styles/notes.d.ts +47 -0
- package/dist/src/styles/notes.d.ts.map +1 -0
- package/dist/src/styles/notes.js +140 -0
- package/dist/src/styles/notes.js.map +1 -0
- package/dist/src/styles/plan/classes.d.ts +31 -0
- package/dist/src/styles/plan/classes.d.ts.map +1 -0
- package/dist/src/styles/plan/classes.js +139 -0
- package/dist/src/styles/plan/classes.js.map +1 -0
- package/dist/src/styles/plan/continuous.d.ts +32 -0
- package/dist/src/styles/plan/continuous.d.ts.map +1 -0
- package/dist/src/styles/plan/continuous.js +165 -0
- package/dist/src/styles/plan/continuous.js.map +1 -0
- package/dist/src/styles/plan/discrete.d.ts +39 -0
- package/dist/src/styles/plan/discrete.d.ts.map +1 -0
- package/dist/src/styles/plan/discrete.js +127 -0
- package/dist/src/styles/plan/discrete.js.map +1 -0
- package/dist/src/styles/plan/families.d.ts +31 -0
- package/dist/src/styles/plan/families.d.ts.map +1 -0
- package/dist/src/styles/plan/families.js +95 -0
- package/dist/src/styles/plan/families.js.map +1 -0
- package/dist/src/styles/plan/features.d.ts +58 -0
- package/dist/src/styles/plan/features.d.ts.map +1 -0
- package/dist/src/styles/plan/features.js +185 -0
- package/dist/src/styles/plan/features.js.map +1 -0
- package/dist/src/styles/plan/index.d.ts +7 -0
- package/dist/src/styles/plan/index.d.ts.map +1 -0
- package/dist/src/styles/plan/index.js +7 -0
- package/dist/src/styles/plan/index.js.map +1 -0
- package/dist/src/styles/plan/plan.d.ts +71 -0
- package/dist/src/styles/plan/plan.d.ts.map +1 -0
- package/dist/src/styles/plan/plan.js +893 -0
- package/dist/src/styles/plan/plan.js.map +1 -0
- package/dist/src/styles/plan/resolve.d.ts +137 -0
- package/dist/src/styles/plan/resolve.d.ts.map +1 -0
- package/dist/src/styles/plan/resolve.js +587 -0
- package/dist/src/styles/plan/resolve.js.map +1 -0
- package/dist/src/styles/types.d.ts +702 -0
- package/dist/src/styles/types.d.ts.map +1 -0
- package/dist/src/styles/types.js +10 -0
- package/dist/src/styles/types.js.map +1 -0
- package/dist/src/styles/vocabulary.d.ts +41 -0
- package/dist/src/styles/vocabulary.d.ts.map +1 -0
- package/dist/src/styles/vocabulary.js +140 -0
- package/dist/src/styles/vocabulary.js.map +1 -0
- package/dist/src/types.d.ts +64 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/styles.d.ts +1 -0
- package/dist/styles.js +322 -0
- package/dist/styles.js.map +1 -0
- package/dist/xgmml.js +5 -4
- package/dist/xgmml.js.map +1 -1
- package/package.json +13 -2
- package/src/common/codes.ts +7 -0
- package/src/common/escape.ts +5 -2
- package/src/common/export.ts +179 -140
- package/src/common/input.ts +8 -4
- package/src/common/json-elements.ts +169 -38
- package/src/common/notes.ts +94 -0
- package/src/common/report.ts +41 -1
- package/src/common/units.ts +42 -0
- package/src/common/xml.ts +45 -5
- package/src/formats/cx/exporter.ts +95 -11
- package/src/formats/cx/importer.ts +126 -90
- package/src/formats/cx/styles.ts +304 -0
- package/src/formats/cx2/exporter.ts +234 -77
- package/src/formats/cx2/importer.ts +19 -1
- package/src/formats/cx2/styles.ts +29 -0
- package/src/formats/cys/constants.ts +3 -0
- package/src/formats/cys/exporter.ts +246 -60
- package/src/formats/cys/importer.ts +125 -9
- package/src/formats/cys/session.ts +6 -0
- package/src/formats/cys/styles.ts +254 -0
- package/src/formats/cys/tables.ts +117 -48
- package/src/formats/dot/exporter.ts +262 -126
- package/src/formats/dot/importer.ts +111 -20
- package/src/formats/dot/index.ts +1 -0
- package/src/formats/dot/positions.ts +77 -0
- package/src/formats/dot/styles.ts +1741 -0
- package/src/formats/gexf/exporter.ts +30 -13
- package/src/formats/gexf/importer.ts +308 -158
- package/src/formats/gexf/index.ts +10 -0
- package/src/formats/gexf/schema.ts +5 -0
- package/src/formats/gexf/styles.ts +719 -0
- package/src/formats/gml/exporter.ts +33 -14
- package/src/formats/gml/importer.ts +4 -0
- package/src/formats/gml/index.ts +2 -1
- package/src/formats/gml/positions.ts +52 -0
- package/src/formats/gml/styles.ts +1248 -0
- package/src/formats/gml/syntax.ts +173 -62
- package/src/formats/graphml/constants.ts +5 -0
- package/src/formats/graphml/exporter.ts +163 -71
- package/src/formats/graphml/importer.ts +119 -45
- package/src/formats/graphml/index.ts +1 -0
- package/src/formats/graphml/styles-plain.ts +236 -0
- package/src/formats/graphml/styles-yed.ts +1221 -0
- package/src/formats/graphml/styles-yfiles3.ts +573 -0
- package/src/formats/graphml/tree.ts +36 -20
- package/src/formats/graphml/yfiles.ts +89 -13
- package/src/formats/json/exporter.ts +76 -26
- package/src/formats/json/importer.ts +543 -323
- package/src/formats/json/positions.ts +50 -0
- package/src/formats/json/styles.ts +2082 -0
- package/src/formats/neo4j/exporter.ts +2 -1
- package/src/formats/pajek/exporter.ts +195 -106
- package/src/formats/pajek/importer.ts +78 -9
- package/src/formats/pajek/index.ts +2 -0
- package/src/formats/pajek/styles.ts +685 -0
- package/src/formats/pajek/syntax.ts +7 -0
- package/src/formats/xgmml/columns.ts +39 -9
- package/src/formats/xgmml/constants.ts +3 -0
- package/src/formats/xgmml/document.ts +54 -12
- package/src/formats/xgmml/emit.ts +11 -6
- package/src/formats/xgmml/exporter.ts +32 -13
- package/src/formats/xgmml/importer.ts +43 -29
- package/src/formats/xgmml/styles.ts +400 -0
- package/src/index.ts +16 -0
- package/src/positions/codes.ts +32 -0
- package/src/positions/convert.ts +123 -0
- package/src/positions/extract.ts +619 -0
- package/src/positions/index.ts +23 -0
- package/src/positions/types.ts +221 -0
- package/src/registry.ts +179 -8
- package/src/styles/annotations.ts +478 -0
- package/src/styles/budget.ts +60 -0
- package/src/styles/canon/bends.ts +84 -0
- package/src/styles/canon/color-tables.ts +386 -0
- package/src/styles/canon/color.ts +624 -0
- package/src/styles/canon/enums.ts +211 -0
- package/src/styles/canon/graphviz.ts +189 -0
- package/src/styles/canon/index.ts +13 -0
- package/src/styles/canon/number.ts +152 -0
- package/src/styles/canon/site.ts +87 -0
- package/src/styles/canon/text.ts +221 -0
- package/src/styles/codes.ts +104 -0
- package/src/styles/cyjs/cascade.ts +2670 -0
- package/src/styles/cyjs/defaults-table.ts +82 -0
- package/src/styles/cyjs/emit.ts +951 -0
- package/src/styles/cyjs/index.ts +37 -0
- package/src/styles/cyjs/live.ts +147 -0
- package/src/styles/cyjs/mappers.ts +879 -0
- package/src/styles/cyjs/selector.ts +778 -0
- package/src/styles/cyjs/stylesheet-text.ts +214 -0
- package/src/styles/cytoscape/emit.ts +1264 -0
- package/src/styles/cytoscape/index.ts +40 -0
- package/src/styles/cytoscape/lexicon.ts +656 -0
- package/src/styles/cytoscape/mappings.ts +603 -0
- package/src/styles/cytoscape/resolve.ts +521 -0
- package/src/styles/cytoscape/translate.ts +237 -0
- package/src/styles/defaults.ts +504 -0
- package/src/styles/index.ts +57 -0
- package/src/styles/internal.ts +17 -0
- package/src/styles/io/approximations.ts +47 -0
- package/src/styles/io/block.ts +1138 -0
- package/src/styles/io/generic.ts +687 -0
- package/src/styles/io/index.ts +18 -0
- package/src/styles/io/writer.ts +745 -0
- package/src/styles/notes.ts +165 -0
- package/src/styles/plan/classes.ts +166 -0
- package/src/styles/plan/continuous.ts +218 -0
- package/src/styles/plan/discrete.ts +165 -0
- package/src/styles/plan/families.ts +115 -0
- package/src/styles/plan/features.ts +234 -0
- package/src/styles/plan/index.ts +7 -0
- package/src/styles/plan/plan.ts +1129 -0
- package/src/styles/plan/resolve.ts +685 -0
- package/src/styles/types.ts +814 -0
- package/src/styles/vocabulary.ts +172 -0
- package/src/types.ts +76 -1
- package/dist/chunks/constants-fT3E8JYY.js.map +0 -1
- package/dist/chunks/escape-B62ZGM_a.js.map +0 -1
- package/dist/chunks/export-rKLeGQMo.js.map +0 -1
- package/dist/chunks/exporter-8hLNemFk.js.map +0 -1
- package/dist/chunks/exporter-BWwEuOPT.js.map +0 -1
- package/dist/chunks/exporter-CpRyHZ3H.js.map +0 -1
- package/dist/chunks/importer-BbNb7eNg.js.map +0 -1
- package/dist/chunks/importer-C98dpSH4.js.map +0 -1
- package/dist/chunks/importer-D794XUTe.js.map +0 -1
- package/dist/chunks/importer-Dz7tI8Sa.js.map +0 -1
- package/dist/chunks/importer-Ht7LNg8L.js.map +0 -1
- package/dist/chunks/importer-WrGRZb0N.js.map +0 -1
- package/dist/chunks/importer-xZ-3suY1.js.map +0 -1
- package/dist/chunks/json-elements-DKSqpNW1.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-GDmO6m6Q.js","sources":["../../src/common/codes.ts","../../src/common/plural.ts","../../src/types.ts","../../src/common/report.ts","../../src/common/format.ts"],"sourcesContent":["/**\n * The issue and loss codes shared by more than one format: one constant per condition, aliased by every format's\n * `<FMT>_ISSUE` / `<FMT>_LOSS` table, so a consumer can switch on a condition without knowing the\n * format and two importers never spell the same condition differently. A condition specific to one\n * format keeps that format's own `E_<FMT>_` / `W_<FMT>_` code next to its importer or exporter.\n *\n * Naming scheme: `E_` for an issue recorded with severity \"error\" (or a loss note whose export()\n * throws), `W_` for a warning; a table key is the code without the severity prefix and without the\n * format prefix.\n */\n\nimport type { GraphFormatErrorCode } from \"@graphty/graph-format\";\n\n// ============================================================ importer issues\n\n/**\n * The URL could not be fetched (network failure, CORS refusal or a non-2xx status).\n * @category Issue and loss codes\n */\nexport const FETCH_CODE = \"E_FETCH\";\n\n/**\n * The element (node, attribute, key, ...) has no id where the format requires one.\n * @category Issue and loss codes\n */\nexport const MISSING_ID_CODE = \"E_MISSING_ID\";\n\n/**\n * An edge has no source or no target.\n * @category Issue and loss codes\n */\nexport const MISSING_ENDPOINT_CODE = \"E_MISSING_ENDPOINT\";\n\n/**\n * A node id declared twice; the second declaration merges into the first.\n * @category Issue and loss codes\n */\nexport const DUPLICATE_NODE_CODE = \"W_DUPLICATE_NODE\";\n\n/**\n * The file declares no graph at all. The import stops.\n * @category Issue and loss codes\n */\nexport const NO_GRAPH_CODE = \"E_NO_GRAPH\";\n\n/**\n * The file holds several graphs and only the first was read (GraphML and GEXF merge them into one graph instead). It is not added when `graphIndex` or `graphName` chose the graph.\n * `importAllGraphs()` reads every one.\n * @category Issue and loss codes\n */\nexport const MULTIPLE_GRAPHS_CODE = \"W_MULTIPLE_GRAPHS\";\n\n/**\n * The input is empty. The import stops.\n * @category Issue and loss codes\n */\nexport const EMPTY_INPUT_CODE = \"E_EMPTY_INPUT\";\n\n/**\n * The text breaks the format's syntax; the message says where and how. The import stops.\n * @category Issue and loss codes\n */\nexport const SYNTAX_CODE = \"E_SYNTAX\";\n\n/**\n * The XML is not well-formed; the message says where. The import stops.\n * @category Issue and loss codes\n */\nexport const XML_SYNTAX_CODE = \"E_XML_SYNTAX\";\n\n/**\n * Elements are nested deeper than graph-io reads (`MAX_XML_DEPTH`, 100,000 levels); the message says where. The import\n * stops.\n * @category Issue and loss codes\n */\nexport const XML_NESTING_CODE = \"E_XML_NESTING\";\n\n/**\n * An element the format does not define at that place was skipped.\n * @category Issue and loss codes\n */\nexport const UNKNOWN_ELEMENT_CODE = \"W_UNKNOWN_ELEMENT\";\n\n/**\n * Text where the format allows only elements was ignored.\n * @category Issue and loss codes\n */\nexport const STRAY_TEXT_CODE = \"W_STRAY_TEXT\";\n\n/**\n * A `pid` / parent reference names a node the document never declares.\n * @category Issue and loss codes\n */\nexport const UNKNOWN_PARENT_CODE = \"E_UNKNOWN_PARENT\";\n\n/**\n * A hyperedge (an edge with more than two ends) while `hyperedges` is \"error\". The import stops.\n * @category Issue and loss codes\n */\nexport const HYPEREDGE_CODE = \"E_HYPEREDGE\";\n\n/**\n * A declaration's key / attribute id is declared twice.\n * @category Issue and loss codes\n */\nexport const DUPLICATE_KEY_CODE = \"E_DUPLICATE_KEY\";\n\n/**\n * An attribute was renamed `<name>#<suffix>` because another attribute already has its name, for example a repeated\n * column header.\n * @category Issue and loss codes\n */\nexport const COLUMN_RENAMED_CODE = \"W_COLUMN_RENAMED\";\n\n/**\n * A node or edge attribute is not written, because the format has nowhere to put it.\n * @category Issue and loss codes\n */\nexport const COLUMN_DROPPED_CODE = \"W_COLUMN_DROPPED\";\n\n/**\n * You read into a graph builder that already has an id, label or position attribute, so this file's one is kept as a\n * plain attribute.\n * @category Issue and loss codes\n */\nexport const ROLE_TAKEN_CODE = \"W_ROLE_TAKEN\";\n\n/**\n * An integer beyond 2^53 was stored as the nearest 64-bit float; pass `long: \"string\"` to keep every digit.\n * @category Issue and loss codes\n */\nexport const PRECISION_CODE = \"W_PRECISION\";\n\n/**\n * Two different id texts became the same number because `ids` is \"number\" (for example, \"042\" and \"42\"), so their nodes were\n * merged.\n * @category Issue and loss codes\n */\nexport const ID_MERGED_CODE = \"W_ID_MERGED\";\n\n/**\n * You read into your own graph builder, which was created with a different `addMissingNodes`, `duplicateEdges`,\n * `selfLoops` or `weightDtype` than the option you passed; the builder's setting applies.\n * @category Issue and loss codes\n */\nexport const SINK_OPTION_CODE = \"W_SINK_OPTION\";\n\n/**\n * You set an option this format does not use; it had no effect. The message names the option.\n * @category Issue and loss codes\n */\nexport const OPTION_IGNORED_CODE = \"W_OPTION_IGNORED\";\n\n/**\n * The input is not valid UTF-8. The import stops.\n * @category Issue and loss codes\n */\nexport const INVALID_UTF8_CODE = \"E_INVALID_UTF8\";\n\n/**\n * Some bytes are not valid in the encoding that was chosen (by a byte order mark, the file's own declaration or the\n * `encoding` option). The import stops.\n * @category Issue and loss codes\n */\nexport const INVALID_ENCODING_CODE = \"E_INVALID_ENCODING\";\n\n/**\n * Bytes that are not valid UTF-8 (and declare no other encoding) were read as windows-1252.\n * @category Issue and loss codes\n */\nexport const ENCODING_FALLBACK_CODE = \"W_ENCODING_FALLBACK\";\n\n/**\n * The file declares an encoding the platform's TextDecoder does not know; the declaration is ignored.\n * @category Issue and loss codes\n */\nexport const UNKNOWN_ENCODING_CODE = \"W_UNKNOWN_ENCODING\";\n\n/**\n * A byte order mark, the `encoding` option and the encoding the file declares disagree, or the file\n * declares UTF-16 over bytes that are not UTF-16; the message names which one applied (a BOM wins\n * over the option and the declaration, the option over the declaration).\n * @category Issue and loss codes\n */\nexport const ENCODING_CONFLICT_CODE = \"W_ENCODING_CONFLICT\";\n\n/**\n * The text holds a control character, such as a NUL byte or an escape character, which is kept in the id or value it\n * is part of; or it ends with a Ctrl-Z end-of-file marker, which was ignored. Reported once per import.\n * @category Issue and loss codes\n */\nexport const CONTROL_CHARACTER_CODE = \"W_CONTROL_CHARACTER\";\n\n/**\n * The input is a known kind of file that is not a graph: an HTML page, a PDF, compressed or zip data, or an image. The\n * import stops.\n * @category Issue and loss codes\n */\nexport const FOREIGN_FORMAT_CODE = \"E_FOREIGN_FORMAT\";\n\n/**\n * More warnings of one code than a report keeps: the first ones are kept and this one warning (the\n * suppressed code as its element) counts the rest.\n * @category Issue and loss codes\n */\nexport const ISSUES_SUPPRESSED_CODE = \"W_ISSUES_SUPPRESSED\";\n\n/**\n * An XML attribute the format does not define (or does not keep) on that element; it is not kept.\n * @category Issue and loss codes\n */\nexport const UNKNOWN_XML_ATTRIBUTE_CODE = \"W_UNKNOWN_XML_ATTRIBUTE\";\n\n/**\n * You read into a graph builder that already holds edges (or whose direction is locked), and its direction differs\n * from the file's, so the file is read with the builder's direction. A builder without edges takes the file's\n * direction.\n * @category Issue and loss codes\n */\nexport const DIRECTION_REFUSED_CODE = \"W_DIRECTION_REFUSED\";\n\n/**\n * `onMixedDirection` (\"directed\" or \"undirected\") made edges take a direction the file did not give them. It can\n * appear twice in one report: once for the direction the file declares and once for the edges that declared\n * their own.\n * @category Issue and loss codes\n */\nexport const DIRECTION_FORCED_CODE = \"W_DIRECTION_FORCED\";\n\n/**\n * The graph has both directed and undirected edges and `onMixedDirection` is \"error\". An import stops; a save to a\n * format that holds one direction per file fails with E_DIRECTED. Pass \"directed\" or \"undirected\" to read or write it\n * anyway.\n * @category Issue and loss codes\n */\nexport const MIXED_DIRECTION_CODE = \"E_MIXED_DIRECTION\";\n\n/**\n * A node or edge count the file announces is too large to reserve room for; it is ignored and the elements are read as\n * they come.\n * @category Issue and loss codes\n */\nexport const COUNT_HINT_CODE = \"W_COUNT_HINT\";\n\n/**\n * The declared type is not one the format defines; the column is kept as string.\n * @category Issue and loss codes\n */\nexport const UNKNOWN_ATTR_TYPE_CODE = \"W_UNKNOWN_ATTR_TYPE\";\n\n/**\n * The declared default does not parse as the declared type; the column has no default.\n * @category Issue and loss codes\n */\nexport const BAD_DEFAULT_CODE = \"W_BAD_DEFAULT\";\n\n/**\n * A declared option does not parse as the declared type; the options are dropped.\n * @category Issue and loss codes\n */\nexport const BAD_OPTIONS_CODE = \"W_BAD_OPTIONS\";\n\n/**\n * A repeated edge id in a format whose edge ids are unique; the second edge is skipped.\n * @category Issue and loss codes\n */\nexport const DUPLICATE_EDGE_ID_CODE = \"E_DUPLICATE_EDGE_ID\";\n\n/**\n * A value does not parse as its declared type; the cell is left unset.\n * @category Issue and loss codes\n */\nexport const BAD_VALUE_CODE = \"E_BAD_VALUE\";\n\n/**\n * An attribute's type was widened because a later value did not fit: an integer above 2^31 in an integer column, or\n * two declared types for one attribute.\n * @category Issue and loss codes\n */\nexport const WIDENED_CODE = \"W_WIDENED\";\n\n/**\n * A reference that is not a containment link (an attribute's element id, a layout or bypass\n * entry, a subnetwork member, a view's network, an undeclared target) names nothing; reported\n * once per kind with the count.\n * @category Issue and loss codes\n */\nexport const DANGLING_REFERENCE_CODE = \"W_DANGLING_REFERENCE\";\n\n/**\n * The same attribute twice on one element; one value is kept (the later, unless the format's specification says the first).\n * @category Issue and loss codes\n */\nexport const DUPLICATE_ATTRIBUTE_CODE = \"W_DUPLICATE_ATTRIBUTE\";\n\n/**\n * A containment link would close a parent cycle; that one link is dropped.\n * @category Issue and loss codes\n */\nexport const PARENT_CYCLE_CODE = \"E_PARENT_CYCLE\";\n\n/**\n * A formula (Cytoscape's `=ABS($x)`) is kept as its text; it is never evaluated.\n * @category Issue and loss codes\n */\nexport const EQUATION_AS_TEXT_CODE = \"W_EQUATION_AS_TEXT\";\n\n/**\n * The file's style rules (default styles, mappings, visual properties) are not applied to the graph. Reported once per\n * import; the message names what was not applied.\n * @category Issue and loss codes\n */\nexport const STYLES_NOT_IMPORTED_CODE = \"W_STYLES_NOT_IMPORTED\";\n\n/**\n * A CX file is an array of blocks, each an object with one key (`{\"nodes\": [...]}`). A member of that array\n * that is not such a block cannot be read and is skipped; the rest of the file is read.\n * @category Issue and loss codes\n */\nexport const BAD_ASPECT_BLOCK_CODE = \"E_BAD_ASPECT_BLOCK\";\n\n/**\n * A CX array member holding several aspects (`{\"nodes\": [...], \"edges\": [...]}`); each array-valued key is read as its own fragment.\n * @category Issue and loss codes\n */\nexport const MULTI_ASPECT_FRAGMENT_CODE = \"W_MULTI_ASPECT_FRAGMENT\";\n\n/**\n * A CX aspect, an array of elements, written as one object (`{\"nodes\": {\"@id\": 1}}`); read as one element.\n * @category Issue and loss codes\n */\nexport const SINGLE_OBJECT_ASPECT_CODE = \"W_SINGLE_OBJECT_ASPECT\";\n\n/**\n * The document uses the bare tokens NaN, Infinity or -Infinity (Python's json writes them), which\n * strict JSON does not allow; read as the numbers.\n * @category Issue and loss codes\n */\nexport const JSON_NONSTANDARD_NUMBER_CODE = \"W_JSON_NONSTANDARD_NUMBER\";\n\n/**\n * A CX aspect out of its place (after the post-metadata, a status that is not last, a block buffered for what it depends on).\n * @category Issue and loss codes\n */\nexport const ASPECT_ORDER_CODE = \"W_ASPECT_ORDER\";\n\n/**\n * A declared element count disagrees with what was read.\n * @category Issue and loss codes\n */\nexport const COUNT_MISMATCH_CODE = \"W_COUNT_MISMATCH\";\n\n/**\n * The program that wrote the file marked it as failed (CX `status.success: false`), so it is incomplete. The import\n * stops.\n * @category Issue and loss codes\n */\nexport const STATUS_FAILED_CODE = \"E_STATUS_FAILED\";\n\n/**\n * The producer marked the document as successful but attached an error text.\n * @category Issue and loss codes\n */\nexport const STATUS_WARNING_CODE = \"W_STATUS_WARNING\";\n\n/**\n * The input is beyond a size limit (a zip's uncompressed total or ratio, a document longer than\n * one string); the same string as graph-format's E_TOO_LARGE, recorded with category \"unsupported\".\n * @category Issue and loss codes\n */\nexport const TOO_LARGE_CODE = \"E_TOO_LARGE\";\n\n/**\n * A value that does not fit its attribute's type. An import records it for a value that does not parse as the\n * type the file declares for it (\"x\" in an integer attribute): GraphML and GEXF leave that value unset, Neo4j CSV\n * skips the row. A save throws it when an attribute value cannot be written in the format; `checkExport()` returns\n * the `E_` note that names the attribute.\n * @category Issue and loss codes\n */\nexport const COLUMN_TYPE_CODE = \"E_COLUMN_TYPE\";\n\n/**\n * `graphIndex` is past the last graph in the file, or `graphName` matches none of them. The import stops, and\n * the message lists the index and name of each graph the file holds.\n * @category Issue and loss codes\n */\nexport const GRAPH_NOT_FOUND_CODE = \"E_GRAPH_NOT_FOUND\";\n\n/**\n * `graphName` matches more than one graph; the message lists their positions. The import stops.\n * @category Issue and loss codes\n */\nexport const AMBIGUOUS_GRAPH_NAME_CODE = \"E_AMBIGUOUS_GRAPH_NAME\";\n\n/**\n * A second edge between the same two nodes under `duplicateEdges: \"error\"`; the import stops.\n * @category Issue and loss codes\n */\nexport const DUPLICATE_EDGE_CODE = \"E_DUPLICATE_EDGE\" satisfies GraphFormatErrorCode;\n\n/**\n * An edge from a node to itself under `selfLoops: \"error\"`; the import stops.\n * @category Issue and loss codes\n */\nexport const SELF_LOOP_CODE = \"E_SELF_LOOP\" satisfies GraphFormatErrorCode;\n\n/**\n * The `duplicateEdges` option merged parallel edges into one edge per pair, so whatever told them apart (an OBO\n * relation, a label) is lost. Recorded once, with the number merged.\n * @category Issue and loss codes\n */\nexport const EDGES_MERGED_CODE = \"W_EDGES_MERGED\";\n\n/**\n * Self-loops were removed by the `selfLoops: \"drop\"` option. Recorded once by importGraph() with the\n * number removed.\n * @category Issue and loss codes\n */\nexport const SELF_LOOPS_DROPPED_CODE = \"W_SELF_LOOPS_DROPPED\";\n\n/**\n * An option name that no format and no load or save function takes, most often a misspelling (`delimeter`). The\n * option has no effect. A load records it as a warning, and `checkExport()` returns it as a note. Reported only while\n * every registered format lists its options, as the built-in formats do.\n * @category Issue and loss codes\n */\nexport const UNKNOWN_OPTION_CODE = \"W_UNKNOWN_OPTION\";\n\n/**\n * A line the `parseLine` function of a format made with defineLineFormat() could not read (it threw). The line is\n * skipped; the message is the one the function threw with.\n * @category Issue and loss codes\n */\nexport const BAD_LINE_CODE = \"E_BAD_LINE\";\n\n/**\n * The `weightFrom` option names an attribute no edge has a value for, so the graph has no weights. The usual cause\n * is one options object shared between formats: GML and Pajek keep their weights in `value`, not `weight`. Recorded\n * once by importGraph().\n * @category Issue and loss codes\n */\nexport const WEIGHT_NOT_FOUND_CODE = \"W_WEIGHT_NOT_FOUND\";\n\n// ============================================================ exporter loss notes\n\n/**\n * An attribute with a role the format has no place for is written as a plain attribute; the role is lost.\n * @category Issue and loss codes\n */\nexport const ROLE_DROPPED_CODE = \"W_ROLE_DROPPED\";\n\n/**\n * A parents (multi-parent) column in a format with single containment only.\n * @category Issue and loss codes\n */\nexport const PARENTS_DROPPED_CODE = \"W_PARENTS_DROPPED\";\n\n/**\n * A start / end / timestamp column in a format without temporal support.\n * @category Issue and loss codes\n */\nexport const TEMPORAL_DROPPED_CODE = \"W_TEMPORAL_DROPPED\";\n\n/**\n * A mutual pair is written as two directed edges without the mutual mark.\n * @category Issue and loss codes\n */\nexport const MUTUAL_EXPANDED_CODE = \"W_MUTUAL_EXPANDED\";\n\n/**\n * A mutual pair is written as one undirected edge; the pair reads back undirected, the mark is lost.\n * @category Issue and loss codes\n */\nexport const MUTUAL_AS_UNDIRECTED_CODE = \"W_MUTUAL_AS_UNDIRECTED\";\n\n/**\n * Node ids whose written text reads back as the other type under the importer's id rule.\n * @category Issue and loss codes\n */\nexport const ID_TEXT_TYPE_CODE = \"W_ID_TEXT_TYPE\";\n\n/**\n * Two node ids would be written as the same text (the number 5 and the text \"5\"); the save fails with E_INVALID_ID.\n * @category Issue and loss codes\n */\nexport const ID_TEXT_COLLISION_CODE = \"E_ID_TEXT_COLLISION\";\n\n/**\n * A `<column>.text` companion the format cannot carry.\n * @category Issue and loss codes\n */\nexport const TEMPORAL_TEXT_DROPPED_CODE = \"W_TEMPORAL_TEXT_DROPPED\";\n\n/**\n * The graph has edge weights and the file does not keep them: every edge reads back with the default weight 1.\n * @category Issue and loss codes\n */\nexport const WEIGHTS_DROPPED_CODE = \"W_WEIGHTS_DROPPED\";\n\n/**\n * An attribute without the weight role is named like the attribute graph-io reads weights from (for example, `weight`), so it\n * reads back as the edge weight.\n * @category Issue and loss codes\n */\nexport const WEIGHT_KEY_CLASH_CODE = \"W_WEIGHT_KEY_CLASH\";\n\n/**\n * An attribute without a role is written where the format keeps a role (for example, a `name` column as the label), and reads\n * back with that role.\n * @category Issue and loss codes\n */\nexport const ROLE_ASSUMED_CODE = \"W_ROLE_ASSUMED\";\n\n/**\n * An attribute with a role (for example, the label) is written where the format keeps that role, and reads back under the name\n * the format's importer gives it.\n * @category Issue and loss codes\n */\nexport const COLUMN_RENAMED_LOSS_CODE = \"W_COLUMN_NAME_CHANGED\";\n\n/**\n * A declared column whose every row is unset is not written by a format without declarations.\n * @category Issue and loss codes\n */\nexport const EMPTY_COLUMN_DROPPED_CODE = \"W_EMPTY_COLUMN_DROPPED\";\n\n/**\n * A text attribute reads back as a dictionary attribute, or the reverse, because the importer chooses by how often its\n * values repeat. The values are the same.\n * @category Issue and loss codes\n */\nexport const STORAGE_CLASS_CODE = \"W_STORAGE_CLASS_CHANGED\";\n\n/**\n * A number attribute whose values are all whole numbers reads back as integers, because the format does not record the\n * type.\n * @category Issue and loss codes\n */\nexport const INTEGRAL_F64_CODE = \"W_INTEGRAL_F64_AS_I32\";\n\n/**\n * A text value that reads back as a number or a boolean, because the format does not record that it was text (the text\n * \"42\" reads back as the number 42).\n * @category Issue and loss codes\n */\nexport const TEXT_INFERRED_CODE = \"W_TEXT_INFERRED\";\n\n/**\n * A text value holds a character XML 1.0 forbids (most control characters); the save fails with E_COLUMN_TYPE.\n * @category Issue and loss codes\n */\nexport const XML_ILLEGAL_CHAR_CODE = \"E_XML_ILLEGAL_CHAR\";\n\n/**\n * An ontology exporter (OBO, OBO Graphs) writes a node column outside its vocabulary as property values; it reads back inside the `property_value` column.\n * @category Issue and loss codes\n */\nexport const COLUMN_AS_PROPERTY_VALUE_CODE = \"W_COLUMN_AS_PROPERTY_VALUE\";\n\n/**\n * An ontology exporter writes an edge without a relation as `is_a` (or the relation the caller chose).\n * @category Issue and loss codes\n */\nexport const RELATION_ASSUMED_CODE = \"W_RELATION_ASSUMED\";\n\n/**\n * An ontology exporter writes Typedef (property) nodes; they read back as nodes only under the importer's `typedefs: \"nodes\"`.\n * @category Issue and loss codes\n */\nexport const TYPEDEF_NODES_CODE = \"W_TYPEDEF_NODES\";\n\n/**\n * A graph attribute is written into the file's metadata and reads back in `snapshot.meta.extra`, not as a graph\n * attribute.\n * @category Issue and loss codes\n */\nexport const GRAPH_COLUMN_AS_METADATA_CODE = \"W_GRAPH_COLUMN_AS_METADATA\";\n\n/**\n * The file cannot record direction: an undirected graph's edges read back as directed, or the whole graph reads back\n * with the importer's default direction.\n * @category Issue and loss codes\n */\nexport const DIRECTION_DROPPED_CODE = \"W_DIRECTION_DROPPED\";\n\n/**\n * NaN and the infinities cannot be written; they are written as null and read back unset.\n * @category Issue and loss codes\n */\nexport const NONFINITE_AS_NULL_CODE = \"W_NONFINITE_AS_NULL\";\n\n/**\n * The nodes read back in a different order.\n * @category Issue and loss codes\n */\nexport const NODE_ORDER_CODE = \"W_NODE_ORDER\";\n\n/**\n * A text attribute stored as a dictionary, without a declared list of allowed values, reads back with its distinct\n * values as that list.\n * @category Issue and loss codes\n */\nexport const OPTIONS_GAINED_CODE = \"W_OPTIONS_GAINED\";\n\n// ============================================================ the graph builder\n\n/**\n * The issue codes every importer can record when the graph refuses an element, by name; every\n * format's `<FMT>_ISSUE` table includes them. Each one skips that element and counts toward\n * `errorLimit`.\n * @category Issue and loss codes\n */\nexport const ELEMENT_ISSUE = Object.freeze({\n /** A node id of a type the graph cannot hold (an empty id, a non-finite number, an object). The node is skipped. */\n INVALID_ID: \"E_INVALID_ID\",\n /** An edge names a node the file never declares, while `addMissingNodes` is false. The edge is skipped. */\n UNKNOWN_NODE: \"E_UNKNOWN_NODE\",\n /**\n * An edge weight that is not a number (text such as \"2,5\" with a decimal comma, NaN, a boolean). The whole edge is\n * skipped, not only its weight.\n */\n INVALID_WEIGHT: \"E_INVALID_WEIGHT\",\n /** A second edge between the same two nodes, while `duplicateEdges` is \"error\". The edge is skipped. */\n DUPLICATE_EDGE: DUPLICATE_EDGE_CODE,\n /** An edge from a node to itself, while `selfLoops` is \"error\". The edge is skipped. */\n SELF_LOOP: SELF_LOOP_CODE,\n /** An edge id declared twice. The second edge is skipped. */\n DUPLICATE_EDGE_ID: DUPLICATE_EDGE_ID_CODE,\n});\n\n// ============================================================ the input layer\n\n/**\n * The issue codes every importer can record for input it cannot read (empty, too large, invalid\n * bytes, not a graph file), by name; every format's `<FMT>_ISSUE` table includes them.\n * @category Issue and loss codes\n */\nexport const INPUT_ISSUE = Object.freeze({\n /** The input is empty or holds only whitespace. The import stops. */\n EMPTY_INPUT: EMPTY_INPUT_CODE,\n /** The input, or one of its lines, is longer than a JavaScript string can hold. The import stops. */\n TOO_LARGE: TOO_LARGE_CODE,\n /** A byte order mark, the encoding option and the declared encoding disagree. */\n ENCODING_CONFLICT: ENCODING_CONFLICT_CODE,\n /** A control character or a stray U+FEFF in the text, or an ignored trailing Ctrl-Z. */\n CONTROL_CHARACTER: CONTROL_CHARACTER_CODE,\n /** The input is an HTML page, a PDF, compressed or zip data, or an image. The import stops. */\n FOREIGN_FORMAT: FOREIGN_FORMAT_CODE,\n /** Warnings of one code beyond the number a report keeps, counted in one warning. */\n ISSUES_SUPPRESSED: ISSUES_SUPPRESSED_CODE,\n});\n","/**\n * Count agreement for messages, so a report says \"1 node is\" and \"3 nodes are\", never \"1 node(s) are\".\n */\n\n/**\n * The plural ending of a regular noun after a count.\n * @param n - the count\n * @returns \"\" for 1, \"s\" otherwise\n */\nexport function plural(n: number): string {\n return n === 1 ? \"\" : \"s\";\n}\n\n/**\n * The form of a verb that agrees with a count.\n * @param n - the count\n * @param one - the form for 1 (\"is\", \"was\", \"holds\")\n * @param many - the form for any other count (\"are\", \"were\", \"hold\")\n * @returns `one` or `many`\n */\nexport function agree(n: number, one: string, many: string): string {\n return n === 1 ? one : many;\n}\n\n/**\n * A count of nodes and edges, leaving out a zero: \"2 nodes and 1 edge\", \"1 edge\".\n * @param nodes - the node count\n * @param edges - the edge count\n * @returns the text\n */\nexport function elementCount(nodes: number, edges: number): string {\n const parts = [];\n if (nodes > 0 || edges === 0) {\n parts.push(`${nodes} node${plural(nodes)}`);\n }\n if (edges > 0) {\n parts.push(`${edges} edge${plural(edges)}`);\n }\n return parts.join(\" and \");\n}\n\n/**\n * A word with its indefinite article, chosen by its first letter: \"an integer\", \"a double\".\n * @param word - the word\n * @returns \"a word\" or \"an word\"\n */\nexport function withArticle(word: string): string {\n return `${/^[aeiou]/i.test(word) ? \"an\" : \"a\"} ${word}`;\n}\n","/**\n * The io contract types of @graphty/graph-io: what every importer\n * and exporter implements and what every caller of one programs against. They are declared here\n * rather than in the core because ImportInput and CommonImportOptions reference ReadableStream and\n * AbortSignal, which need the DOM lib (or @types/node >= 18); the core's public types reference only\n * ES2020 globals (decision D-IO-TYPES). Every declaration is transcribed verbatim from the design;\n * the behavior behind each option is specified in sections 8.4 (import), 8.5 (export) and 8.6\n * (report and error aggregation).\n */\n\nimport {\n type Dtype,\n type DuplicatePolicy,\n GraphFormatError,\n type GraphSink,\n type GraphSnapshot,\n type IdCoercion,\n} from \"@graphty/graph-format\";\n\nimport type { ImporterPositions, PositionReadContext } from \"./positions/types.js\";\nimport type {\n EdgeStyleProperty,\n GraphStyleProperty,\n ImporterStyles,\n NodeStyleProperty,\n StyleReadContext,\n StyleWriteCapabilities,\n} from \"./styles/types.js\";\n\n/**\n * What an importer reads: whole text, whole bytes, a byte stream (a browser\n * `File.stream()`, a fetch body) or an async iterable of text or byte chunks. Bytes are decoded\n * strictly in the encoding the `encoding` option, a byte order mark or the file's own declaration\n * names, else as UTF-8 (undeclared bytes that are not UTF-8 are read as windows-1252 with a\n * warning), so an invalid sequence is a parse-error and never a silent U+FFFD that could alias two ids.\n * @category Loading\n */\nexport type ImportInput = string | Uint8Array | ReadableStream<Uint8Array> | AsyncIterable<string | Uint8Array>;\n\n/**\n * The options every importer accepts next to its format-specific ones. The\n * builder-policy fields (`addMissingNodes`, `duplicateEdges`, `selfLoops`, `weightDtype`) seed the\n * registry's builder; on a caller's sink they are read back from `sink.options` and every option the\n * sink cannot honor is reported.\n * @category Loading\n */\nexport interface CommonImportOptions {\n /**\n * How id text becomes a node id. \"canonical\": integer text such as \"42\" becomes the number 42\n * and everything else (\"042\", \"4.2\", \"a\") stays text. \"string\": every id stays text. \"number\":\n * every id is read as a number, so \"042\" and \"42\" become one node (with a warning) and text that\n * is not a number is an error. \"keep\": ids keep the type the file gives them. The default is\n * \"keep\" for JSON, OBO, XGMML, CX, CX2 and Cytoscape sessions, and \"canonical\" for the other\n * formats.\n * @defaultValue per format\n */\n ids?: IdCoercion | undefined;\n /**\n * Which value becomes the node id: the file's own id (\"id\"), the node's label (\"label\"), or its\n * position among the nodes, counting from 0 (\"index\"). Use it when a file's ids are meaningless\n * numbers and the labels are the real names. In d3 JSON, \"index\" also reads edges whose ends are\n * node positions. In GML and Pajek it only renames: every node still needs its id key or vertex\n * number, because edges refer to nodes by it, and a GML node without an `id` key is skipped\n * with E_MISSING_ID. CSV reads this option only when there is a node table, and it does not\n * just rename: with \"label\" the node table's label column (`label`, or the `labelColumn`\n * option) gives the ids, so the edge table must name its nodes by those labels.\n * @defaultValue \"id\"\n */\n nodeIdFrom?: \"id\" | \"label\" | \"index\" | undefined;\n /**\n * Whether an edge may name a node the file never declares; that node is then created. When\n * false, such an edge is skipped as an error. The default is false for GEXF, XGMML, CX, CX2 and\n * Cytoscape sessions, whose files must declare every node, and true for the other formats.\n * @defaultValue per format\n */\n addMissingNodes?: boolean | undefined;\n /**\n * What to do with a second edge between the same two nodes: \"keep\" keeps both, \"first\" / \"last\"\n * keep one, \"sum\" / \"min\" / \"max\" keep one with the weights combined, and \"error\" stops the\n * import. Merged edges are reported once as W_EDGES_MERGED.\n * @defaultValue \"keep\"\n */\n duplicateEdges?: DuplicatePolicy | undefined;\n /**\n * What to do with an edge from a node to itself: \"keep\", \"drop\" (reported once as\n * W_SELF_LOOPS_DROPPED with the number removed), or \"error\" to stop the import.\n * @defaultValue \"keep\"\n */\n selfLoops?: \"keep\" | \"drop\" | \"error\" | undefined;\n /**\n * How edge direction is read. \"expand\" (the default) keeps the file's direction, and for a file\n * that has both directed and undirected edges makes a directed graph in which each undirected\n * edge is two edges, marked so an export can write them back as one. \"directed\" / \"undirected\"\n * read every edge of any file that way, including a file whose edges all have the other\n * direction, with a W_DIRECTION_FORCED warning. \"error\" stops the import at the first edge whose\n * direction differs from the file's.\n * @defaultValue \"expand\"\n */\n onMixedDirection?: \"expand\" | \"directed\" | \"undirected\" | \"error\" | undefined;\n /**\n * Whether the graph is directed when the file does not say. The default is undirected for\n * GraphML, GEXF, GML, JSON and XGMML, and directed for CSV, Pajek and Cytoscape sessions. DOT,\n * Neo4j, CX, CX2 and OBO files always settle the direction themselves (DOT by `graph` or\n * `digraph`; the others are always directed), so those formats do not read this option and\n * report it as W_OPTION_IGNORED.\n * @defaultValue per format\n */\n defaultDirected?: boolean | undefined;\n /**\n * The edge attribute read as the edge weight. The default is \"weight\", except \"value\" for GML\n * and Pajek and none for OBO. Pass null to read every attribute as a plain attribute and leave\n * the graph unweighted. A name no edge has leaves the graph unweighted, with a W_WEIGHT_NOT_FOUND\n * warning: one options object with `weightFrom: \"weight\"` shared across formats reads GML and\n * Pajek files, which keep their weights in `value`, without weights. An edge whose weight cell is\n * empty or missing gets the default weight 1, and an export writes no weight for it.\n * @defaultValue per format\n */\n weightFrom?: string | null | undefined;\n /**\n * Whether weights a 32-bit float cannot hold exactly are also kept exactly. \"f64\" keeps them in\n * an edge column that `snapshot.edges.byRole(\"weight\")` finds, so 0.1 and 16777217\n * stay exact. \"f32\" keeps no such column and uses less memory: the 32-bit weight arrays\n * `snapshot.weights` and `snapshot.edgeList().weights`, which every import fills, are then the\n * only weights.\n * @defaultValue \"f64\"\n */\n weightDtype?: \"f32\" | \"f64\" | undefined;\n /**\n * How a column the file declares as a 64-bit integer is stored: \"f64\" (a number, exact up to\n * 2^53) or \"string\" (every digit kept, as text). GML declares no types, so there it applies to a\n * key whose integer values go beyond 2^53.\n * @defaultValue \"f64\"\n */\n long?: \"f64\" | \"string\" | undefined;\n /**\n * Whether to give back the original ids that an export with `sanitizeIds: \"mangle\"` had to\n * rewrite. The export writes them to the file in an attribute whose name each format page\n * gives. When false, the rewritten ids stay the ids and the originals are an ordinary node\n * attribute, named after the format's spelling: `graphty.originalId` in GraphML,\n * `graphty_originalId` in GML and Pajek, `graphty:originalId` in CX, CX2 and Cytoscape sessions,\n * and a `graphty:originalId` entry of the `property_value` attribute in OBO.\n * @defaultValue true\n */\n restoreMangledIds?: boolean | undefined;\n /**\n * What to do with a GraphML or JGF hyperedge (an edge with more than two ends): \"skip\" leaves it\n * out with a warning, \"error\" stops the import, and \"star\" and \"clique\" turn it into ordinary\n * edges. \"clique\" joins every pair of ends. \"star\" works differently per format: GraphML adds a\n * new hub node joined to every end, while JGF makes the hyperedge's first node the hub, so no\n * node is added. A directed JGF hyperedge (`source` and `target` arrays) becomes one edge from\n * every source to every target under both. In JGF every edge made from a hyperedge carries the\n * hyperedge's id, label, relation and metadata; GraphML drops a hyperedge's `<data>` and its\n * `<desc>`, with a warning.\n * @defaultValue \"skip\"\n */\n hyperedges?: \"error\" | \"skip\" | \"star\" | \"clique\" | undefined;\n /**\n * How many errors an import tolerates. Each error skips one node, edge or value and is listed in\n * the report; one error more than this stops the import with an ImportError. Pass 0 to stop at\n * the first error.\n * @defaultValue 100\n */\n errorLimit?: number | undefined;\n /**\n * Cancels the import. When it aborts, the import stops and rejects with the signal's reason\n * (an AbortError, or a TimeoutError from `AbortSignal.timeout()`).\n */\n signal?: AbortSignal | undefined;\n /**\n * Called as the input is read, with the bytes read so far and the total. For a string or a\n * Uint8Array the total is known from the first call. For a stream (which includes loadFromUrl()\n * and loadFromFile()) it is undefined until the last call, which always has\n * `bytesDone === bytesTotal`. Text counts its UTF-8 length.\n */\n onProgress?: ((bytesDone: number, bytesTotal?: number) => void) | undefined;\n /**\n * The character encoding of byte input, as a label such as \"utf-8\", \"windows-1252\" or\n * \"utf-16le\". Without it graph-io uses a byte order mark, then the encoding the file declares\n * (an XML declaration, DOT's `charset`), then UTF-8, and reads bytes that are not UTF-8 as\n * windows-1252 with a warning. A byte order mark wins over this option. A string input is\n * already text: setting this option for one adds a W_OPTION_IGNORED warning, once per input (a\n * CSV import with a `nodes` table has two inputs).\n */\n encoding?: string | undefined;\n}\n\n/**\n * Which graph to read from a file that holds several: by position or by name, never both. Without\n * either, the first graph is read.\n * @category Loading\n */\nexport interface GraphChoiceOptions {\n /**\n * The 0-based position of the graph to read from a file that holds several (`listGraphs()`\n * gives each graph's `index`). A position past the last graph stops the import with an\n * ImportError whose `issue.code` is E_GRAPH_NOT_FOUND; its message lists the file's graphs.\n * @defaultValue 0\n */\n graphIndex?: number | undefined;\n /**\n * The name of the graph to read from a file that holds several (`listGraphs()` gives each\n * graph's `name`). A name no graph has stops the import with an ImportError whose `issue.code`\n * is E_GRAPH_NOT_FOUND, and a name two graphs share with one whose `issue.code` is\n * E_AMBIGUOUS_GRAPH_NAME.\n */\n graphName?: string | undefined;\n}\n\n/**\n * One graph of an input that can hold several, as an importer's listGraphs() describes it.\n * @category Loading\n */\nexport interface GraphListing {\n /** The value graphIndex takes to read it. */\n readonly index: number;\n /** The value graphName takes to read it, or null when the graph has no name. */\n readonly name: string | null;\n /** The node count when the input states it cheaply, else null. */\n readonly nodes: number | null;\n /** The edge count when the input states it cheaply, else null. */\n readonly edges: number | null;\n}\n\n/**\n * A format's reader. It reads the input once, from start to end, and adds each node, edge and\n * attribute to a graph builder (`GraphSink`, which `GraphBuilder` from @graphty/graph-format\n * implements); importGraph() then builds the snapshot. Register one with\n * `registry.registerImporter()` to teach graph-io a new format. `Opts` is the type of the format's\n * own options.\n * @category Writing a format\n */\nexport interface GraphImporter<Opts = unknown> {\n /** The name callers pass as `format`, such as \"graphml\" or \"csv\"; lowercase, unique in a registry. */\n readonly format: string;\n /** File extensions with the leading dot, most common first; used to detect the format from a file name. */\n readonly extensions: readonly string[];\n /** MIME types the format is served as, most specific first; used to detect the format from a Content-Type. */\n readonly mimeTypes: readonly string[];\n /**\n * The names of this format's own options (`[\"separator\"]`), when you want misspelled options\n * reported. While every registered importer lists its options, a load warns `W_UNKNOWN_OPTION` for\n * a name that no format and no load function takes. Leave it out to report nothing.\n */\n readonly options?: readonly string[] | undefined;\n /**\n * How sure you are that `head`, the first bytes of a file (up to SNIFF_HEAD_BYTES), is this\n * format: 0 for no, up to 1 for certain. Below 0.5 counts as a weak guess, which loses to a\n * file extension another format claims. Without this method the format is detected only by\n * file name and MIME type.\n * @param head - the first bytes of the input\n * @returns a confidence in 0..1\n */\n sniff?(head: Uint8Array): number;\n /**\n * Read `input` into `sink`. Record each problem in an ImportReportBuilder and skip the element;\n * the builder throws ImportError once there are more errors than `errorLimit`.\n * @param input - the text, bytes or stream to read\n * @param sink - the graph builder to add nodes, edges and attributes to\n * @param options - the format's own options and the options every importer takes\n * @returns the import report (`report.finish()`)\n */\n import(input: ImportInput, sink: GraphSink, options?: Opts & CommonImportOptions): Promise<ImportReport>;\n /**\n * Optional, for a format whose files can hold several graphs: read every graph, each into its\n * own sink. importAllGraphs() calls it; with it, importGraph() also honors `graphIndex` and\n * `graphName` by reading every graph and returning the chosen one. `import()` should read the\n * first graph and warn W_MULTIPLE_GRAPHS with the number skipped.\n * @param input - the text, bytes or stream to read\n * @param sinkFor - called once per graph, in document order, before that graph's first push\n * @param options - format-specific and common options\n * @returns one report per graph, in document order\n */\n importAll?(\n input: ImportInput,\n sinkFor: (index: number) => GraphSink,\n options?: Opts & CommonImportOptions,\n ): Promise<ImportReport[]>;\n /**\n * Optional: list the graphs of a file without importing them, so a caller can offer a choice.\n * listGraphs() calls it. An importer that has it must also honor `graphIndex` and `graphName`\n * in `import()` itself (`chooseGraph()` resolves them); one without it lists nothing and the\n * registry makes the choice through `importAll()`.\n * @param input - the text, bytes or stream to read\n * @param options - format-specific and common options\n * @returns one listing per graph, in document order\n */\n listGraphs?(input: ImportInput, options?: Opts & CommonImportOptions): Promise<readonly GraphListing[]>;\n /**\n * Optional: the file's styles, read after the import from the snapshot it built. Called only when a caller asks\n * for styles (`importGraph(input, { styles: true })`). The simple path names the snapshot columns that hold\n * each style and the dialect they are spelled in, and graph-io does the rest:\n * `styles: () => ({ dialect: \"css\", node: { fill: { data: \"color\" } } })`. The advanced path returns canonical\n * values and the rules the file declares (`{ canonical: true, ... }`). Style data that is not per element\n * reaches it as `context.kept`: whatever this import's `import()` passed to `report.keepForStyles()`. Without\n * this member, graph-io reads the columns whose role is `color`, `size`, `shape`, `thickness` or `hidden`.\n * @param snapshot - the graph this import built\n * @param context - the cancel signal, the work budget and what `import()` kept\n * @returns the styles, or null when the file has none\n */\n styles?(snapshot: GraphSnapshot, context: StyleReadContext): ImporterStyles | null;\n /**\n * Optional: where this format's stored node coordinates are and how they are spelled, for\n * `extractPositions()` (`@graphty/graph-io/positions`). Without it, the role-`position` column\n * is read as its `meta.extra` declares (y up, center, file units when it says nothing). With it,\n * the answer wins over the column's `meta.extra`; null falls back to the column.\n *\n * The simple form names plain numeric columns: `() => ({ x: \"x\", y: \"y\", yAxis: \"down\", units: \"px\" })`.\n * The advanced form names a 3-component `column` and may add `anchor`, `width` / `height` size\n * columns, `groups` (container boxes), `medianNodeSize` and `tool`.\n * @param snapshot - the graph this importer read\n * @param ctx - `signal` to abort\n * @returns the spelling, or null to read the role-`position` column as declared\n */\n positions?(snapshot: GraphSnapshot, ctx: PositionReadContext): ImporterPositions | null;\n}\n\n/**\n * What a format can store exactly. checkCapabilities() compares a graph against it and returns a\n * loss note for everything the graph has that the format cannot store.\n * @category Saving\n */\nexport interface ExportCapabilities {\n /**\n * Whether one file can hold directed and undirected edges together. When false, a graph with both\n * needs `onMixedDirection` (\"directed\" or \"undirected\") to be saved.\n */\n readonly mixedDirection: boolean;\n /**\n * Whether the file can hold two edges between the same pair of nodes. When false, the extra\n * edges are not kept as separate edges.\n */\n readonly multiEdges: boolean;\n /** Whether the file can hold an edge from a node to itself. When false, such edges are lost. */\n readonly selfLoops: boolean;\n /**\n * Whether edges carry ids. \"required\": every edge has one, and ids are made up (e0, e1, ...)\n * for a graph without them. \"optional\": edge ids are written when the graph has them. \"none\":\n * edge ids are lost.\n */\n readonly edgeIds: \"required\" | \"optional\" | \"none\";\n /**\n * Which node ids the format can write as they are: \"any\"; \"nmtoken\" (XML name tokens: letters,\n * digits and `. - _ :`, no spaces); \"integer\"; or \"dense-1-based\" (the nodes are always numbered\n * 1 to N). Other ids need `sanitizeIds: \"mangle\"`, which writes the original ids too.\n */\n readonly idCharset: \"any\" | \"nmtoken\" | \"integer\" | \"dense-1-based\";\n /**\n * The attribute types the format keeps exactly: \"bool\", \"i32\" (32-bit integer), \"u32\" (unsigned\n * 32-bit integer), \"u8\" (byte), \"f32\" (32-bit float), \"f64\" (64-bit float, a JavaScript number),\n * \"string\" (text), \"dict\" (text stored as a dictionary of repeated values), \"list\" and \"json\".\n * An attribute of another type is written as the nearest one the format has, with a\n * W_DTYPE_UNSUPPORTED note.\n */\n readonly dtypes: readonly Dtype[];\n /**\n * Whether an attribute other than the node position can hold several numbers per node or edge\n * (a vector). When false, such an attribute does not read back as one attribute. Positions\n * are covered by `positions`.\n */\n readonly components: boolean;\n /** Whether an attribute can hold a list per node or edge. When false, list attributes are lost or flattened. */\n readonly lists: boolean;\n /**\n * Whether an attribute can hold nested JSON objects and arrays. When false, such attributes are\n * written as text or lost.\n */\n readonly json: boolean;\n /** Whether the file can declare a default value for an attribute. When false, declared defaults are lost. */\n readonly defaults: boolean;\n /**\n * Whether the file can declare the allowed values of an attribute (GEXF `options`). When false,\n * those declarations are lost; the values themselves are kept.\n */\n readonly options: boolean;\n /** Whether nodes can sit inside other nodes (groups or clusters). When false, the nesting is lost. */\n readonly hierarchy: boolean;\n /**\n * What the file can say about time: \"none\" (time attributes are lost), \"intervals\" (one start\n * and end per element), \"spells\" (several intervals per element), or \"dynamic-values\"\n * (attribute values that change over time, as well).\n */\n readonly temporal: \"none\" | \"intervals\" | \"spells\" | \"dynamic-values\";\n /** Whether the file can hold attributes of the graph itself. When false, graph attributes are lost. */\n readonly graphAttributes: boolean;\n /** Whether the file can hold node positions. When false, the layout is lost. */\n readonly positions: boolean;\n /**\n * Whether the file can hold node and edge color, size, shape and thickness. When false, they are lost.\n * @deprecated This describes the `color`, `size`, `shape` and `thickness` role columns, the old way styles\n * reached a file. Use {@link ExportCapabilities.styles}, what the format's style writer can hold. Removed in\n * the next major version.\n */\n readonly viz: boolean;\n /**\n * What the format's writer can hold of a graph's styles (the exporter's `styles.capabilities`): per target the\n * properties written natively, and where the `graphty.styles` block goes. Absent for a format that writes no\n * styles: every style is then reported as W_STYLE_NOT_WRITTEN and W_STYLE_RULES_NOT_KEPT.\n */\n readonly styles?: StyleWriteCapabilities | undefined;\n}\n\n/**\n * One thing a format cannot store, returned by checkExport() before anything is written.\n * @category Saving\n */\nexport interface LossNote {\n /**\n * A stable code. Codes starting with \"E_\" mean the export refuses to write under these options:\n * the exportGraph*() functions throw a GraphFormatError. Codes starting with \"W_\" mean the file\n * is written, but this part will not read back the same.\n */\n readonly code: string;\n /** A plain-English explanation. */\n readonly message: string;\n /** The attribute column involved, or null. */\n readonly column: string | null;\n /** How many nodes, edges or values are affected, or null when not counted. */\n readonly count: number | null;\n /**\n * Every column the note is about, when it is about several and `column` is null: the graph\n * attributes a format has no place for, or the node columns a CSV edge table leaves for the node\n * table. Absent on a note about one column or none.\n */\n readonly columns?: readonly string[];\n /**\n * The style a W_STYLE_ note is about: nodes, edges or the graph, and the neutral property (`fill`, `width`).\n * Absent on every other note.\n */\n readonly style?:\n | {\n /** Nodes, edges or the graph. */\n readonly target: \"node\" | \"edge\" | \"graph\";\n /** The neutral property. */\n readonly property: NodeStyleProperty | EdgeStyleProperty | GraphStyleProperty;\n }\n | undefined;\n}\n\n/**\n * The options every exporter accepts next to its format-specific ones.\n * @category Saving\n */\nexport interface CommonExportOptions {\n /**\n * What to do with node ids the format cannot hold. \"error\": the export throws (E_INVALID_ID) and\n * no node is renamed. \"mangle\": such ids are rewritten and the originals are written to the\n * file too, so an import with `restoreMangledIds` (on by default) reads the original ids back.\n * Pajek is the exception: it always numbers nodes 1 to N and keeps the old ids as labels.\n * @defaultValue \"error\"\n */\n sanitizeIds?: \"error\" | \"mangle\" | undefined;\n /**\n * What a format with one direction per file does with a graph that has both directed and\n * undirected edges: \"error\" throws (E_DIRECTED), \"directed\" writes every edge as directed (an\n * undirected edge once, as one directed edge), \"undirected\" writes the whole graph undirected.\n * A format that keeps each edge's own direction (GraphML, GEXF, CSV, Pajek, XGMML, Cytoscape\n * sessions, and the JGF and graphology JSON dialects) ignores it and writes both kinds; to make\n * such a graph all one direction, read it with the import option `onMixedDirection`.\n * @defaultValue \"error\"\n */\n onMixedDirection?: \"error\" | \"directed\" | \"undirected\" | undefined;\n}\n\n/**\n * A format's writer. Register one with `registry.registerExporter()` to make a format writable by\n * every save function. `Opts` is the type of the format's own options.\n * @category Writing a format\n */\nexport interface GraphExporter<Opts = unknown> {\n /** The name callers pass as `format`; the same as the importer's when the format has both. */\n readonly format: string;\n /** What the format can store exactly; build it with `capabilities()`. */\n readonly capabilities: ExportCapabilities;\n /**\n * File extensions with the leading dot, most common first. Optional; listFormats() uses them\n * when no importer is registered for the format (an export-only format).\n */\n readonly extensions?: readonly string[] | undefined;\n /** MIME types, most specific first. Optional; used the same way as `extensions`. */\n readonly mimeTypes?: readonly string[] | undefined;\n /**\n * The names of this format's own save options, when you want misspelled options reported. While\n * every registered exporter lists its options, `checkExport()` returns a `W_UNKNOWN_OPTION` note for\n * a name that no format and no save function takes. Leave it out to report nothing.\n */\n readonly options?: readonly string[] | undefined;\n /**\n * What a save would lose, without writing anything; checkExport(snapshot, format, options) calls\n * it. Start from `checkCapabilities(snapshot, capabilities, resolveExportOptions(options))` and\n * add a note for anything else your format changes. Every difference a re-import would show\n * needs a note.\n * @param snapshot - the graph to check\n * @param options - the format's own options and the options every exporter takes\n * @returns the loss notes, empty when the save is exact\n */\n check(snapshot: GraphSnapshot, options?: Opts & CommonExportOptions): readonly LossNote[];\n /**\n * Write the graph as byte chunks: UTF-8 text for a text format (`encodeChunks()` turns string\n * parts into them), the raw bytes for a binary one. Throw a GraphFormatError before writing for\n * every \"E_\" note `check()` returns.\n * @param snapshot - the graph to write\n * @param options - the format's own options and the options every exporter takes\n * @returns the file's bytes, chunk by chunk\n */\n export(snapshot: GraphSnapshot, options?: Opts & CommonExportOptions): AsyncIterable<Uint8Array>;\n /**\n * Write the graph as one string (`joinText()` joins string parts). A binary format rejects with\n * a GraphFormatError E_UNSUPPORTED (`details.reason` \"binary\") instead.\n * @param snapshot - the graph to write\n * @param options - the format's own options and the options every exporter takes\n * @returns the whole file\n */\n exportToString(snapshot: GraphSnapshot, options?: Opts & CommonExportOptions): Promise<string>;\n /**\n * Optional: the styles this format can write. With it, `exportGraph(snapshot, format, { styles })` hands\n * `export()`, `exportToString()` and `check()` an `options.styles` (`ExporterStyleInput`): each element's value\n * per property (`picture()`), the `graphty.styles` block, the tagged per-element values and the rules. With\n * `block: \"attributes\"` graph-io adds the block and the tagged values to the snapshot as a graph attribute and\n * element attributes, so a format that writes attributes keeps every style for graphty with no code:\n * `styles: { capabilities: { node: [], edge: [], block: \"attributes\" } }`. Every property not listed natively\n * is reported as W_STYLE_NOT_WRITTEN, and a format without this member loses every style, reported the same way.\n */\n readonly styles?:\n | {\n /** What the writer holds natively, and where the block goes. */\n readonly capabilities: StyleWriteCapabilities;\n }\n | undefined;\n}\n\n/**\n * What an ImportIssue is about, for errors and warnings alike: \"parse-error\" (the text is not valid\n * in the format), \"missing-value\" (something required is absent), \"validation-error\" (a value\n * breaks a rule of the format or of an option; an error skips it, a warning keeps it as written,\n * such as an id with spaces around it), \"unsupported\" (the file uses something graph-io does not\n * read), \"precision\" (a value was rounded), \"coercion\" (a value or id changed type) and \"merged\"\n * (elements were combined). Sort by `severity` first: the category says what kind of problem it\n * is, not how serious.\n * @category Reports and errors\n */\nexport type IssueCategory =\n \"parse-error\" | \"missing-value\" | \"validation-error\" | \"unsupported\" | \"precision\" | \"coercion\" | \"merged\";\n\n/**\n * One problem found while importing.\n * @category Reports and errors\n */\nexport interface ImportIssue {\n /** The category. */\n readonly category: IssueCategory;\n /**\n * \"error\": the element was skipped and counts toward `errorLimit`. \"warning\": the element was\n * kept, possibly changed.\n */\n readonly severity: \"error\" | \"warning\";\n /** A stable code; E_ for errors, W_ for warnings (\"E_UNKNOWN_NODE\", \"W_WIDENED\"). */\n readonly code: string;\n /** A plain-English message. */\n readonly message: string;\n /** The 1-based line in the input, or null when the format has no lines or it is unknown. */\n readonly line: number | null;\n /** The node id, edge id or attribute name involved, or null. */\n readonly element: string | null;\n}\n\n/**\n * What happened while a file was read.\n * @category Reports and errors\n */\nexport interface ImportReport {\n /** The format the file was read as. */\n readonly format: string;\n /**\n * What was read from the file, counted before the graph was built: `duplicateEdges` and\n * `selfLoops: \"drop\"` can leave fewer edges in the snapshot (each reported as a warning).\n */\n readonly counts: {\n /** Nodes read. */\n readonly nodes: number;\n /** Edges read (an undirected edge expanded into two by onMixedDirection \"expand\" counts twice). */\n readonly edges: number;\n /** Nodes skipped after an error. */\n readonly skippedNodes: number;\n /** Edges skipped after an error. */\n readonly skippedEdges: number;\n /** Undirected edges expanded into two by onMixedDirection \"expand\". */\n readonly expandedMixed: number;\n };\n /** Every issue recorded, in order. */\n readonly issues: readonly ImportIssue[];\n /** Issues with severity \"error\". */\n readonly errorCount: number;\n /** Issues with severity \"warning\". */\n readonly warningCount: number;\n /** Whether the error limit was reached and the import aborted. */\n readonly truncated: boolean;\n /** What the importer could not represent. */\n readonly lossy: readonly LossNote[];\n /** How long reading the file took, in milliseconds. */\n readonly durationMs: number;\n}\n\n/**\n * What a load function throws when the input cannot be read: the URL failed, the format was not\n * recognized, the file could not be parsed, or there were more errors than `errorLimit`. It is a\n * GraphFormatError with code \"E_IMPORT\"; `issue` says what stopped the import and `report` holds\n * everything recorded until then.\n * @category Reports and errors\n */\nexport class ImportError extends GraphFormatError {\n /**\n * Everything recorded up to the point the import stopped. It is not an enumerable property, so an\n * uncaught ImportError prints its message and issue, not every issue of the report.\n */\n declare readonly report: ImportReport;\n\n /**\n * The issue that stopped the import: its `code` (\"E_FETCH\", \"E_UNKNOWN_FORMAT\", \"E_CSV_UNCLOSED_QUOTE\", ...),\n * `message`, `line` and `element`. This is the value to branch on; `code` is always \"E_IMPORT\".\n * Null only for an ImportError constructed by hand without a matching issue.\n * @example\n * ```ts\n * if (err instanceof ImportError) {\n * switch (err.issue?.code) {\n * case \"E_FETCH\":\n * console.error(`download failed with status ${String(err.details.status)}`);\n * break;\n * case \"E_UNKNOWN_FORMAT\":\n * console.error(\"not a graph file this library can read; pass `format`\");\n * break;\n * default:\n * console.error(err.message);\n * }\n * }\n * ```\n */\n readonly issue: ImportIssue | null;\n\n /**\n * Create an ImportError.\n * @param message - a plain-ASCII human-readable message\n * @param report - the partial report\n * @param details - optional machine-readable context; its `code` names the issue that stopped the import\n */\n constructor(message: string, report: ImportReport, details?: Readonly<Record<string, unknown>>) {\n super(\"E_IMPORT\", message, details);\n this.name = \"ImportError\";\n Object.defineProperty(this, \"report\", { value: report, enumerable: false });\n this.issue = stoppingIssue(report.issues, details?.code);\n }\n}\n\n/**\n * The issue that stopped an import: the last one with the code the abort named, else the last error.\n * @param issues - the report's issues\n * @param code - the code the abort named, if any\n * @returns the issue, or null\n */\nfunction stoppingIssue(issues: readonly ImportIssue[], code: unknown): ImportIssue | null {\n let lastError: ImportIssue | null = null;\n for (let i = issues.length - 1; i >= 0; i--) {\n if (issues[i].code === code) {\n return issues[i];\n }\n if (lastError === null && issues[i].severity === \"error\") {\n lastError = issues[i];\n }\n }\n return lastError;\n}\n","/**\n * The ImportReport builder shared by every importer (design section 8.6): issues by category and\n * severity, the element counts, loss notes, the error limit with truncation, and the ImportError\n * that carries the partial report when the importer aborts.\n *\n * Layering (design section 8.6): the builder throws on the first hard error; the importer catches\n * per element, records an ImportIssue through this class, skips the element and continues until the\n * error limit, then aborts with E_IMPORT. `recordError()` is that catch: it turns a thrown\n * GraphFormatError into an issue with the category its code implies and re-throws everything else\n * (an ImportError, an abort reason, a programming error) unchanged.\n */\n\nimport { GraphFormatError, type GraphFormatErrorCode } from \"@graphty/graph-format\";\n\nimport { ImportError, type ImportIssue, type ImportReport, type IssueCategory, type LossNote } from \"../types.js\";\nimport { ISSUES_SUPPRESSED_CODE } from \"./codes.js\";\nimport { agree, plural } from \"./plural.js\";\n\n/**\n * The most warnings of one code a report keeps; later ones are counted in one W_ISSUES_SUPPRESSED\n * warning, so a per-row warning on a large file cannot grow the report without bound.\n * @category Issue and loss codes\n */\nexport const MAX_WARNINGS_PER_CODE = 1000;\n\n/** What each finished report's import kept for its styles: per report object, so imports running at once never mix. */\nconst KEPT_FOR_STYLES = new WeakMap<ImportReport, unknown>();\n\n/** The value of a builder that kept nothing. */\nconst NOTHING_KEPT: unique symbol = Symbol(\"nothing kept\");\n\n/**\n * What the import that produced a report passed to `ImportReportBuilder.keepForStyles()`, or undefined when it kept\n * nothing. graph-io passes it to the same importer's `styles()` as `context.kept`.\n * @param report - a report an importer's `import()` returned\n * @returns the kept value\n * @category Writing a format\n */\nexport function keptForStyles(report: ImportReport): unknown {\n return KEPT_FOR_STYLES.get(report);\n}\n\n/**\n * Where an issue was found: the 1-based line and the element (id or attribute name) when known.\n * @public\n * @category Writing a format\n */\nexport interface IssueLocation {\n /** The 1-based source line, when known. */\n readonly line?: number | null | undefined;\n /** The element the issue is about, when known. */\n readonly element?: string | null | undefined;\n}\n\n/**\n * The mutable element counters of a report in progress; importers increment them directly in hot loops.\n * @public\n * @category Plugin helpers\n */\nexport interface MutableCounts {\n /** Nodes pushed. */\n nodes: number;\n /** Logical edges pushed (both halves of an expanded edge count). */\n edges: number;\n /** Nodes skipped after an error. */\n skippedNodes: number;\n /** Edges skipped after an error. */\n skippedEdges: number;\n /** Source edges expanded into two logical edges. */\n expandedMixed: number;\n}\n\n/**\n * The category a thrown GraphFormatError maps to when an importer catches it per element: the codes\n * that mean \"the file referenced something it never declared\" are missing values, a refused\n * direction change is a coercion, size and feature limits are unsupported, everything else is a\n * validation error of the element.\n */\nconst CATEGORY_BY_CODE: Readonly<Partial<Record<GraphFormatErrorCode, IssueCategory>>> = {\n E_UNKNOWN_NODE: \"missing-value\",\n E_UNKNOWN_COLUMN: \"missing-value\",\n E_DIRECTED: \"coercion\",\n E_TOO_LARGE: \"unsupported\",\n E_UNSUPPORTED: \"unsupported\",\n E_GPU_INELIGIBLE: \"unsupported\",\n};\n\n/**\n * No longer recorded; kept so code that switches on older reports still compiles.\n * @category Issue and loss codes\n */\nexport const PARSE_ERROR_CODE = \"E_PARSE\";\n\n/**\n * An issue message as the ImportError shows it: prefixed with its line when the issue has one and the\n * message does not already name it.\n * @param message - the issue message\n * @param where - the issue location\n * @returns the message for the error\n */\nfunction withLine(message: string, where: IssueLocation | undefined): string {\n const line = where?.line;\n return line === undefined || line === null || message.includes(`line ${line}`)\n ? message\n : `line ${line}: ${message}`;\n}\n\n/**\n * Accumulates an ImportReport while an importer runs. Errors count toward the error limit; the\n * error that takes the count beyond the limit is still recorded, `truncated` is set, and an\n * ImportError carrying the report so far is thrown. Warnings never abort.\n * @category Writing a format\n */\nexport class ImportReportBuilder {\n /** The importer's format name. */\n readonly format: string;\n\n /** The error limit the report was created with. */\n readonly errorLimit: number;\n\n /** The element counters; importers increment them directly. */\n readonly counts: MutableCounts = { nodes: 0, edges: 0, skippedNodes: 0, skippedEdges: 0, expandedMixed: 0 };\n\n private readonly issueList: ImportIssue[] = [];\n\n private readonly lossList: LossNote[] = [];\n\n private readonly onceCodes = new Set<string>();\n\n /** Warnings recorded per code, kept or not. */\n private readonly warningsByCode = new Map<string, number>();\n\n private errors = 0;\n\n private warnings = 0;\n\n private truncatedFlag = false;\n\n private kept: unknown = NOTHING_KEPT;\n\n private readonly startedAt: number;\n\n /**\n * Create a builder for one import call.\n * @param format - the importer's format name\n * @param errorLimit - errors tolerated before the import aborts; Infinity for no limit\n */\n constructor(format: string, errorLimit: number) {\n this.format = format;\n this.errorLimit = errorLimit;\n this.startedAt = now();\n }\n\n /**\n * Issues recorded so far, in order.\n * @returns the live list (not copied; finish() copies)\n */\n get issues(): readonly ImportIssue[] {\n return this.issueList;\n }\n\n /**\n * Issues with severity \"error\".\n * @returns the count\n */\n get errorCount(): number {\n return this.errors;\n }\n\n /**\n * Issues with severity \"warning\".\n * @returns the count\n */\n get warningCount(): number {\n return this.warnings;\n }\n\n /**\n * Whether the error limit was exceeded.\n * @returns true once an error beyond the limit was recorded\n */\n get truncated(): boolean {\n return this.truncatedFlag;\n }\n\n /**\n * Loss notes recorded so far.\n * @returns the live list\n */\n get lossy(): readonly LossNote[] {\n return this.lossList;\n }\n\n /**\n * Record an error. When the count goes beyond the error limit the report is marked truncated\n * and an ImportError carrying it is thrown; the importer does not catch that.\n * @param category - the issue category\n * @param code - a stable code such as \"E_UNKNOWN_NODE\"\n * @param message - a plain-ASCII message\n * @param where - the line and element, when known\n * @returns the recorded issue\n */\n error(category: IssueCategory, code: string, message: string, where?: IssueLocation): ImportIssue {\n const issue = makeIssue(category, \"error\", code, message, where);\n this.issueList.push(issue);\n this.errors++;\n if (this.errors > this.errorLimit) {\n this.truncatedFlag = true;\n throw this.abort(`error limit of ${this.errorLimit} exceeded: ${withLine(message, where)}`, {\n code,\n limit: this.errorLimit,\n });\n }\n return issue;\n }\n\n /**\n * Record a warning; warnings never count toward the limit. Beyond MAX_WARNINGS_PER_CODE\n * warnings of one code the warning is counted, not kept: finish() adds one W_ISSUES_SUPPRESSED\n * warning per such code with the number dropped.\n * @param category - the issue category\n * @param code - a stable code such as \"W_WIDENED\"\n * @param message - a plain-ASCII message\n * @param where - the line and element, when known\n * @returns the recorded issue\n */\n warning(category: IssueCategory, code: string, message: string, where?: IssueLocation): ImportIssue {\n const issue = makeIssue(category, \"warning\", code, message, where);\n const seen = (this.warningsByCode.get(code) ?? 0) + 1;\n this.warningsByCode.set(code, seen);\n if (seen <= MAX_WARNINGS_PER_CODE) {\n this.issueList.push(issue);\n this.warnings++;\n }\n return issue;\n }\n\n /**\n * Record a warning the first time its key is seen and ignore later repeats, for conditions\n * that would otherwise produce one warning per row.\n * @param category - the issue category\n * @param code - the stable code\n * @param message - a plain-ASCII message\n * @param where - the line and element, when known\n * @param key - what repeats are deduplicated on; the code itself by default (pass `code:column`\n * to warn once per column)\n * @returns the recorded issue, or null when the key was already recorded\n */\n warnOnce(\n category: IssueCategory,\n code: string,\n message: string,\n where?: IssueLocation,\n key: string = code,\n ): ImportIssue | null {\n if (this.onceCodes.has(key)) {\n return null;\n }\n this.onceCodes.add(key);\n return this.warning(category, code, message, where);\n }\n\n /**\n * Record something the importer could not represent.\n * @param code - a stable code\n * @param message - a plain-ASCII message\n * @param column - the affected column, or null\n * @param count - the affected count, or null\n * @returns the recorded note\n */\n loss(code: string, message: string, column: string | null = null, count: number | null = null): LossNote {\n const note: LossNote = Object.freeze({ code, message, column, count });\n this.lossList.push(note);\n return note;\n }\n\n /**\n * The per-element catch: record a thrown GraphFormatError as an error\n * issue with its code and the category the code implies. Anything else is re-thrown unchanged:\n * an ImportError (the import already aborted), an abort reason, and any other thrown value (a\n * TypeError or RangeError is a programming error in the importer or the sink, never a defect of\n * the input, so it must surface as an exception rather than as an issue blamed on the file).\n * @param err - the thrown value\n * @param where - the line and element, when known\n * @returns the recorded issue\n */\n recordError(err: unknown, where?: IssueLocation): ImportIssue {\n if (err instanceof GraphFormatError && !(err instanceof ImportError)) {\n const category = CATEGORY_BY_CODE[err.code] ?? \"validation-error\";\n if (err.code === \"E_TOO_LARGE\") {\n // the sink is full: every later element would fail the same way, so the import stops\n return this.failWith(category, err.code, err.message, where);\n }\n return this.error(category, err.code, err.message, where);\n }\n throw err;\n }\n\n /**\n * Keep style data that is not per element (a stylesheet, a groups object, a legend, the file's default styles)\n * for this import's `styles()`: graph-io passes it back as `context.kept` when styles are requested. Kept per\n * report, never on the importer object, so imports running at once each get their own. A later call replaces\n * the value.\n * @param value - anything the importer's `styles()` needs\n * @returns this builder\n */\n keepForStyles(value: unknown): this {\n this.kept = value;\n return this;\n }\n\n /**\n * A builder that starts from everything this one recorded so far: issues, counts, loss notes,\n * the warnOnce keys, the error and warning counts and the truncation flag. For an importer that\n * reads its input once and emits several graphs, each with its own report.\n * @returns the copy; later records to either builder do not reach the other\n */\n fork(): ImportReportBuilder {\n const copy = new ImportReportBuilder(this.format, this.errorLimit);\n Object.assign(copy.counts, this.counts);\n copy.issueList.push(...this.issueList);\n copy.lossList.push(...this.lossList);\n for (const key of this.onceCodes) {\n copy.onceCodes.add(key);\n }\n for (const [code, count] of this.warningsByCode) {\n copy.warningsByCode.set(code, count);\n }\n copy.errors = this.errors;\n copy.warnings = this.warnings;\n copy.truncatedFlag = this.truncatedFlag;\n copy.kept = this.kept;\n return copy;\n }\n\n /**\n * Build the ImportError that aborts the import, carrying the report so far. The caller throws\n * it; this method only constructs it so it can be used in expression position.\n * @param message - a plain-ASCII message\n * @param details - optional machine-readable context\n * @returns the error to throw\n */\n abort(message: string, details?: Readonly<Record<string, unknown>>): ImportError {\n return new ImportError(message, this.finish(), details);\n }\n\n /**\n * Record a fatal parse error and abort: the issue is recorded (even beyond the error limit)\n * and an ImportError carrying the report is thrown.\n * @param code - a stable code such as \"E_INVALID_UTF8\"\n * @param message - a plain-ASCII message\n * @param where - the line and element, when known\n * @param details - optional machine-readable context for the ImportError\n */\n fail(code: string, message: string, where?: IssueLocation, details?: Readonly<Record<string, unknown>>): never {\n this.failWith(\"parse-error\", code, message, where, details);\n }\n\n /**\n * Record a fatal error of any category and abort, as fail() does for a parse error: a size\n * limit (E_TOO_LARGE, category \"unsupported\") stops an import without being a defect of the\n * syntax. A fatal error is not the error limit: `truncated` stays as it was.\n * @param category - the issue category\n * @param code - a stable code\n * @param message - a plain-ASCII message\n * @param where - the line and element, when known\n * @param details - optional machine-readable context for the ImportError\n */\n failWith(\n category: IssueCategory,\n code: string,\n message: string,\n where?: IssueLocation,\n details?: Readonly<Record<string, unknown>>,\n ): never {\n this.issueList.push(makeIssue(category, \"error\", code, message, where));\n this.errors++;\n throw this.abort(withLine(message, where), { code, ...details });\n }\n\n /**\n * Add a finished report to this one: its issues after the ones recorded so far, its counts, its\n * loss notes and its truncated flag. Use it when an importer hands part of the work to another\n * importer (for example, a wrapper around the CSV importer) and returns one report for both. The issues\n * keep their codes; errors added this way do not count toward this report's error limit, since\n * the other importer applied its own.\n * @param report - the report the other importer returned\n * @returns this builder\n * @example\n * ```ts\n * const report = new ImportReportBuilder(\"netscope\", opts.errorLimit);\n * const text = await readText(input, report, opts);\n * report.include(await csvImporter.import(text, sink, options));\n * return report.finish();\n * ```\n */\n include(report: ImportReport): this {\n for (const issue of report.issues) {\n this.issueList.push(issue);\n if (issue.severity === \"error\") {\n this.errors++;\n } else {\n this.warnings++;\n }\n }\n const { counts } = report;\n this.counts.nodes += counts.nodes;\n this.counts.edges += counts.edges;\n this.counts.skippedNodes += counts.skippedNodes;\n this.counts.skippedEdges += counts.skippedEdges;\n this.counts.expandedMixed += counts.expandedMixed;\n this.lossList.push(...report.lossy);\n this.truncatedFlag ||= report.truncated;\n if (this.kept === NOTHING_KEPT && KEPT_FOR_STYLES.has(report)) {\n this.kept = KEPT_FOR_STYLES.get(report);\n }\n return this;\n }\n\n /**\n * The report as it stands: a frozen snapshot with the parse duration so far. Can be called more\n * than once; each call reflects everything recorded up to that point.\n * @returns the report\n */\n finish(): ImportReport {\n const { nodes, edges, skippedNodes, skippedEdges, expandedMixed } = this.counts;\n const suppressed: ImportIssue[] = [];\n for (const [code, seen] of this.warningsByCode) {\n if (seen > MAX_WARNINGS_PER_CODE) {\n const more = seen - MAX_WARNINGS_PER_CODE;\n suppressed.push(\n makeIssue(\n \"unsupported\",\n \"warning\",\n ISSUES_SUPPRESSED_CODE,\n `${more} more ${code} warning${plural(more)} ${agree(more, \"was\", \"were\")} not kept (the report keeps the first ${MAX_WARNINGS_PER_CODE})`,\n { element: code },\n ),\n );\n }\n }\n const report: ImportReport = Object.freeze({\n format: this.format,\n counts: Object.freeze({ nodes, edges, skippedNodes, skippedEdges, expandedMixed }),\n issues: Object.freeze([...this.issueList, ...suppressed]),\n errorCount: this.errors,\n warningCount: this.warnings + suppressed.length,\n truncated: this.truncatedFlag,\n lossy: Object.freeze([...this.lossList]),\n durationMs: now() - this.startedAt,\n });\n if (this.kept !== NOTHING_KEPT) {\n KEPT_FOR_STYLES.set(report, this.kept);\n }\n return report;\n }\n}\n\n/**\n * Build a frozen ImportIssue.\n * @param category - the category\n * @param severity - error or warning\n * @param code - the stable code\n * @param message - the message\n * @param where - the location, when known\n * @returns the issue\n */\nfunction makeIssue(\n category: IssueCategory,\n severity: \"error\" | \"warning\",\n code: string,\n message: string,\n where: IssueLocation | undefined,\n): ImportIssue {\n return Object.freeze({\n category,\n severity,\n code,\n message,\n line: where?.line ?? null,\n element: where?.element ?? null,\n });\n}\n\n/**\n * Whether a thrown value means the load was cancelled rather than failed: the DOMException or Error\n * named \"AbortError\" that an aborted signal throws, or the \"TimeoutError\" of AbortSignal.timeout().\n * Use it in a `catch` block to say nothing to the user when they cancelled. A custom reason passed\n * to `abort(reason)` is not recognized: compare it with `signal.reason`. A format plugin uses it to\n * let a cancellation through untouched.\n * @param err - the thrown value\n * @returns true for an AbortError or a TimeoutError\n * @example\n * ```ts\n * try {\n * await loadFromUrl(url, { signal });\n * } catch (err) {\n * if (!isAbortError(err)) {\n * showError(err);\n * }\n * }\n * ```\n * @category Reports and errors\n */\nexport function isAbortError(err: unknown): boolean {\n if (typeof err !== \"object\" || err === null) {\n return false;\n }\n const { name } = err as { name?: unknown };\n return name === \"AbortError\" || name === \"TimeoutError\";\n}\n\n/**\n * The message of a thrown value: an Error's message, a string as is, anything else described by type.\n * @param err - the thrown value\n * @returns a plain message\n * @category Plugin helpers\n */\nexport function messageOf(err: unknown): string {\n if (err instanceof Error) {\n return err.message;\n }\n if (typeof err === \"string\") {\n return err;\n }\n return `non-error thrown (${typeof err})`;\n}\n\n/**\n * A monotonic millisecond clock: performance.now() where it exists, Date.now() otherwise.\n * @returns milliseconds\n */\nfunction now(): number {\n return typeof performance === \"object\" ? performance.now() : Date.now();\n}\n","/**\n * Number formatting for exporters (design section 3.7): an f32 weight is written as the shortest\n * decimal that round-trips through Math.fround (never `String(x)`, which prints\n * 0.10000000149011612 for a stored 0.1); an f64 value as its shortest JS text; a GML real always\n * with a decimal point so the dtype survives (design section 8.5); non-finite values as the\n * spelling the target syntax accepts.\n */\n\nimport type { NodeId } from \"@graphty/graph-format\";\n\n/**\n * The shortest decimal text that reads back to the same f32 value through Math.fround.\n * @param value - an f32 value (a JS number holding one)\n * @returns the text; \"Infinity\" / \"-Infinity\" / \"NaN\" for the non-finite values, \"-0\" for negative zero\n * @category Plugin helpers\n */\nexport function formatF32(value: number): string {\n if (!Number.isFinite(value)) {\n return String(value);\n }\n if (value === 0) {\n return Object.is(value, -0) ? \"-0\" : \"0\";\n }\n for (let digits = 1; digits <= 9; digits++) {\n const text = value.toPrecision(digits);\n if (Math.fround(Number(text)) === value) {\n return String(Number(text));\n }\n }\n return String(value);\n}\n\n/**\n * The shortest text of an f64 value: `String(x)`, which is already the shortest round-tripping\n * decimal in JS, except for negative zero, which `String()` writes as \"0\".\n * @param value - the value\n * @returns the text; \"Infinity\" / \"-Infinity\" / \"NaN\" for the non-finite values, \"-0\" for negative zero\n * @category Plugin helpers\n */\nexport function formatF64(value: number): string {\n return Object.is(value, -0) ? \"-0\" : String(value);\n}\n\n/**\n * The text of a node id for the text formats that write ids bare (DOT, Pajek, XGMML): the string\n * itself, or the shortest decimal of a number (formatF64).\n * @param id - the id\n * @returns the text\n */\nexport function idText(id: NodeId): string {\n return typeof id === \"number\" ? formatF64(id) : id;\n}\n\n/**\n * A decimal text with a decimal point or an exponent guaranteed for a finite value (`2.0`,\n * `1e+21`, `1.5e-7`), so an\n * untyped re-import keeps the column f64 rather than i32; negative zero is\n * written `-0.0` so it reads back as -0; non-finite values are the JS spellings (`Infinity`,\n * `-Infinity`, `NaN`), which the CSV / DOT / Pajek importers read back as text. The one\n * implementation of the \"decimal point guaranteed\" rule for every text format; GML has its own\n * spellings of the non-finite values in formatGmlReal().\n * @param value - the value\n * @param dtype - the column dtype the value comes from; f32 values use the shortest fround-round-trip text\n * @returns the text\n * @category Plugin helpers\n */\nexport function formatDecimal(value: number, dtype: \"f32\" | \"f64\" | \"i32\" | \"u32\" | \"u8\" = \"f64\"): string {\n if (!Number.isFinite(value)) {\n return String(value);\n }\n if (Object.is(value, -0)) {\n return \"-0.0\";\n }\n const text = formatNumber(value, dtype);\n // an exponent form (`1e+21`, `1.5e-7`) is already f64 text under the 5.1 grammar\n return text.includes(\".\") || text.includes(\"e\") ? text : `${text}.0`;\n}\n\n/**\n * A GML real: the shortest text with a decimal point guaranteed (`2.0`, `1.0e-7`), so a re-import\n * keeps the column real rather than int. Non-finite values have no GML spelling and are written\n * as the texts NetworkX's writer emits and its reader accepts, `+INF`, `-INF` and `NAN` (the\n * lowercase `inf` / `nan` would lex as keys there).\n * @param value - the value\n * @param dtype - the column dtype the value comes from; f32 values use the shortest fround-round-trip text\n * @returns the text\n * @category Plugin helpers\n */\nexport function formatGmlReal(value: number, dtype: \"f32\" | \"f64\" | \"i32\" | \"u32\" | \"u8\" = \"f64\"): string {\n if (Number.isNaN(value)) {\n return \"NAN\";\n }\n if (!Number.isFinite(value)) {\n return value > 0 ? \"+INF\" : \"-INF\";\n }\n const text = formatDecimal(value, dtype);\n if (text.includes(\".\")) {\n return text;\n }\n // NetworkX's real pattern requires a decimal point even in the exponent form (`1.0e-7`)\n const e = text.indexOf(\"e\");\n return `${text.slice(0, e)}.0${text.slice(e)}`;\n}\n\n/**\n * An integer text for a value known to be integral (an i32 / u32 / u8 cell, an f64 that holds an\n * integer), avoiding the exponent form `String()` uses above 1e21.\n * @param value - an integral value\n * @returns the digits\n * @category Plugin helpers\n */\nexport function formatInteger(value: number): string {\n if (Number.isSafeInteger(value) || !Number.isFinite(value)) {\n return String(value);\n }\n return BigInt(value).toString();\n}\n\n/**\n * The text of a numeric cell of any numeric dtype, dispatching on the dtype: f32 through\n * formatF32, everything else through formatF64.\n * @param value - the value\n * @param dtype - the column dtype the value came from\n * @returns the text\n * @category Plugin helpers\n */\nexport function formatNumber(value: number, dtype: \"f32\" | \"f64\" | \"i32\" | \"u32\" | \"u8\"): string {\n return dtype === \"f32\" ? formatF32(value) : formatF64(value);\n}\n"],"names":[],"mappings":"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"}
|