@graphty/graph-io 0.3.24 → 0.3.26
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/README.md +49 -414
- package/dist/chunks/children-CL3Cy0ez.js.map +1 -1
- package/dist/chunks/choose-BbJI55dx.js +56 -0
- package/dist/chunks/choose-BbJI55dx.js.map +1 -0
- package/dist/chunks/constants-BCsFsMj4.js +231 -0
- package/dist/chunks/constants-BCsFsMj4.js.map +1 -0
- package/dist/chunks/{escape-B-tkk_Cl.js → escape-D0g6NNUy.js} +382 -92
- package/dist/chunks/escape-D0g6NNUy.js.map +1 -0
- package/dist/chunks/export-BTI4yQgy.js +4333 -0
- package/dist/chunks/export-BTI4yQgy.js.map +1 -0
- package/dist/chunks/exporter-BMqk5oxW.js +3465 -0
- package/dist/chunks/exporter-BMqk5oxW.js.map +1 -0
- package/dist/chunks/{importer-eUREhBGj.js → exporter-Cra2GYcN.js} +4969 -3201
- package/dist/chunks/exporter-Cra2GYcN.js.map +1 -0
- package/dist/chunks/{exporter-BGrsWamJ.js → exporter-Dxh231ZF.js} +38 -229
- package/dist/chunks/exporter-Dxh231ZF.js.map +1 -0
- package/dist/chunks/{exporter-DIeGJXAZ.js → exporter-tne475KK.js} +22 -20
- package/dist/chunks/exporter-tne475KK.js.map +1 -0
- package/dist/chunks/importer-90YWhJoF.js +2811 -0
- package/dist/chunks/importer-90YWhJoF.js.map +1 -0
- package/dist/chunks/{importer-D_e7e7LX.js → importer-Bcl1d4xH.js} +398 -145
- package/dist/chunks/importer-Bcl1d4xH.js.map +1 -0
- package/dist/chunks/{importer-BWY2FFc5.js → importer-BfIsp1f9.js} +255 -77
- package/dist/chunks/importer-BfIsp1f9.js.map +1 -0
- package/dist/chunks/{importer-zGLo8Dg_.js → importer-C_TEA1zJ.js} +484 -157
- package/dist/chunks/importer-C_TEA1zJ.js.map +1 -0
- package/dist/chunks/{importer-DET1tg6s.js → importer-DCjOvO7U.js} +1687 -310
- package/dist/chunks/importer-DCjOvO7U.js.map +1 -0
- package/dist/chunks/{importer-vi3bSdtw.js → importer-DfVu6j59.js} +509 -76
- package/dist/chunks/importer-DfVu6j59.js.map +1 -0
- package/dist/chunks/{importer-DIrbbnAf.js → importer-Dku_VAIY.js} +585 -226
- package/dist/chunks/importer-Dku_VAIY.js.map +1 -0
- package/dist/chunks/json-elements-3tnyt5uZ.js +1225 -0
- package/dist/chunks/json-elements-3tnyt5uZ.js.map +1 -0
- package/dist/chunks/ontology-export-B9Tcf37D.js +357 -0
- package/dist/chunks/ontology-export-B9Tcf37D.js.map +1 -0
- package/dist/chunks/{records-dbRkxwaq.js → records-CQXT__mY.js} +298 -114
- package/dist/chunks/records-CQXT__mY.js.map +1 -0
- package/dist/chunks/{text-Dr0Ifpag.js → text-DmcUs5_Q.js} +29 -11
- package/dist/chunks/text-DmcUs5_Q.js.map +1 -0
- package/dist/chunks/{writer-C7flM-Ih.js → writer-DxjgHwSe.js} +19 -1
- package/dist/chunks/writer-DxjgHwSe.js.map +1 -0
- package/dist/csv.js +951 -261
- package/dist/csv.js.map +1 -1
- package/dist/cx.js +6 -3
- package/dist/cx2.js +2 -2
- package/dist/cys.js +6 -3
- package/dist/dot.js +1 -1
- package/dist/gexf.js +554 -122
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +342 -85
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +1105 -213
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +3 -2
- package/dist/graphml.js.map +1 -1
- package/dist/json.js +3 -2
- package/dist/neo4j.js +564 -157
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +6 -3
- package/dist/pajek.js +1 -1
- package/dist/src/children.d.ts +18 -6
- package/dist/src/children.d.ts.map +1 -1
- package/dist/src/children.js +6 -3
- package/dist/src/children.js.map +1 -1
- package/dist/src/common/attributes.d.ts +29 -11
- package/dist/src/common/attributes.d.ts.map +1 -1
- package/dist/src/common/attributes.js +25 -7
- package/dist/src/common/attributes.js.map +1 -1
- package/dist/src/common/cell-budget.d.ts +9 -2
- package/dist/src/common/cell-budget.d.ts.map +1 -1
- package/dist/src/common/cell-budget.js +11 -3
- package/dist/src/common/cell-budget.js.map +1 -1
- package/dist/src/common/choose.d.ts +19 -0
- package/dist/src/common/choose.d.ts.map +1 -0
- package/dist/src/common/choose.js +72 -0
- package/dist/src/common/choose.js.map +1 -0
- package/dist/src/common/codes.d.ts +456 -66
- package/dist/src/common/codes.d.ts.map +1 -1
- package/dist/src/common/codes.js +458 -66
- package/dist/src/common/codes.js.map +1 -1
- package/dist/src/common/compare.d.ts +81 -0
- package/dist/src/common/compare.d.ts.map +1 -0
- package/dist/src/common/compare.js +394 -0
- package/dist/src/common/compare.js.map +1 -0
- package/dist/src/common/cx-export.d.ts +123 -0
- package/dist/src/common/cx-export.d.ts.map +1 -0
- package/dist/src/common/cx-export.js +334 -0
- package/dist/src/common/cx-export.js.map +1 -0
- package/dist/src/common/declared-types.d.ts +22 -2
- package/dist/src/common/declared-types.d.ts.map +1 -1
- package/dist/src/common/declared-types.js +19 -1
- package/dist/src/common/declared-types.js.map +1 -1
- package/dist/src/common/direction.d.ts +74 -50
- package/dist/src/common/direction.d.ts.map +1 -1
- package/dist/src/common/direction.js +47 -27
- package/dist/src/common/direction.js.map +1 -1
- package/dist/src/common/escape.d.ts +21 -9
- package/dist/src/common/escape.d.ts.map +1 -1
- package/dist/src/common/escape.js +33 -17
- package/dist/src/common/escape.js.map +1 -1
- package/dist/src/common/export.d.ts +144 -32
- package/dist/src/common/export.d.ts.map +1 -1
- package/dist/src/common/export.js +216 -42
- package/dist/src/common/export.js.map +1 -1
- package/dist/src/common/format.d.ts +23 -1
- package/dist/src/common/format.d.ts.map +1 -1
- package/dist/src/common/format.js +26 -1
- package/dist/src/common/format.js.map +1 -1
- package/dist/src/common/ids.d.ts +9 -2
- package/dist/src/common/ids.d.ts.map +1 -1
- package/dist/src/common/ids.js +6 -2
- package/dist/src/common/ids.js.map +1 -1
- package/dist/src/common/input.d.ts +122 -28
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +890 -124
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/json-elements.d.ts +144 -20
- package/dist/src/common/json-elements.d.ts.map +1 -1
- package/dist/src/common/json-elements.js +868 -188
- package/dist/src/common/json-elements.js.map +1 -1
- package/dist/src/common/line-format.d.ts +90 -0
- package/dist/src/common/line-format.d.ts.map +1 -0
- package/dist/src/common/line-format.js +185 -0
- package/dist/src/common/line-format.js.map +1 -0
- package/dist/src/common/lists.d.ts +6 -1
- package/dist/src/common/lists.d.ts.map +1 -1
- package/dist/src/common/lists.js +2 -0
- package/dist/src/common/lists.js.map +1 -1
- package/dist/src/common/ontology-export.d.ts +167 -0
- package/dist/src/common/ontology-export.d.ts.map +1 -0
- package/dist/src/common/ontology-export.js +359 -0
- package/dist/src/common/ontology-export.js.map +1 -0
- package/dist/src/common/ontology.d.ts +25 -3
- package/dist/src/common/ontology.d.ts.map +1 -1
- package/dist/src/common/ontology.js +30 -9
- package/dist/src/common/ontology.js.map +1 -1
- package/dist/src/common/options.d.ts +62 -12
- package/dist/src/common/options.d.ts.map +1 -1
- package/dist/src/common/options.js +89 -11
- package/dist/src/common/options.js.map +1 -1
- package/dist/src/common/plural.d.ts +31 -0
- package/dist/src/common/plural.d.ts.map +1 -0
- package/dist/src/common/plural.js +46 -0
- package/dist/src/common/plural.js.map +1 -0
- package/dist/src/common/report.d.ts +72 -14
- package/dist/src/common/report.d.ts.map +1 -1
- package/dist/src/common/report.js +146 -22
- package/dist/src/common/report.js.map +1 -1
- package/dist/src/common/temporal.d.ts +22 -5
- package/dist/src/common/temporal.d.ts.map +1 -1
- package/dist/src/common/temporal.js +13 -2
- package/dist/src/common/temporal.js.map +1 -1
- package/dist/src/common/text.d.ts +39 -23
- package/dist/src/common/text.d.ts.map +1 -1
- package/dist/src/common/text.js +51 -21
- package/dist/src/common/text.js.map +1 -1
- package/dist/src/common/weights.d.ts +37 -4
- package/dist/src/common/weights.d.ts.map +1 -1
- package/dist/src/common/weights.js +61 -2
- package/dist/src/common/weights.js.map +1 -1
- package/dist/src/common/writer.d.ts +19 -3
- package/dist/src/common/writer.d.ts.map +1 -1
- package/dist/src/common/writer.js +30 -2
- package/dist/src/common/writer.js.map +1 -1
- package/dist/src/common/xml.d.ts +125 -9
- package/dist/src/common/xml.d.ts.map +1 -1
- package/dist/src/common/xml.js +400 -83
- package/dist/src/common/xml.js.map +1 -1
- package/dist/src/common/zip.d.ts +44 -4
- package/dist/src/common/zip.d.ts.map +1 -1
- package/dist/src/common/zip.js +134 -5
- package/dist/src/common/zip.js.map +1 -1
- package/dist/src/formats/csv/exporter.d.ts +80 -24
- package/dist/src/formats/csv/exporter.d.ts.map +1 -1
- package/dist/src/formats/csv/exporter.js +145 -32
- package/dist/src/formats/csv/exporter.js.map +1 -1
- package/dist/src/formats/csv/header.d.ts +38 -9
- package/dist/src/formats/csv/header.d.ts.map +1 -1
- package/dist/src/formats/csv/header.js +46 -10
- package/dist/src/formats/csv/header.js.map +1 -1
- package/dist/src/formats/csv/importer.d.ts +187 -37
- package/dist/src/formats/csv/importer.d.ts.map +1 -1
- package/dist/src/formats/csv/importer.js +835 -204
- package/dist/src/formats/csv/importer.js.map +1 -1
- package/dist/src/formats/csv/index.d.ts +100 -19
- package/dist/src/formats/csv/index.d.ts.map +1 -1
- package/dist/src/formats/csv/index.js +94 -21
- package/dist/src/formats/csv/index.js.map +1 -1
- package/dist/src/formats/csv/records.d.ts +95 -10
- package/dist/src/formats/csv/records.d.ts.map +1 -1
- package/dist/src/formats/csv/records.js +333 -122
- package/dist/src/formats/csv/records.js.map +1 -1
- package/dist/src/formats/csv/values.d.ts +1 -0
- package/dist/src/formats/csv/values.d.ts.map +1 -1
- package/dist/src/formats/csv/values.js +1 -0
- package/dist/src/formats/csv/values.js.map +1 -1
- package/dist/src/formats/cx/exporter.d.ts +102 -0
- package/dist/src/formats/cx/exporter.d.ts.map +1 -0
- package/dist/src/formats/cx/exporter.js +1217 -0
- package/dist/src/formats/cx/exporter.js.map +1 -0
- package/dist/src/formats/cx/importer.d.ts +79 -32
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +680 -285
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx/index.d.ts +4 -3
- package/dist/src/formats/cx/index.d.ts.map +1 -1
- package/dist/src/formats/cx/index.js +4 -3
- package/dist/src/formats/cx/index.js.map +1 -1
- package/dist/src/formats/cx2/exporter.d.ts +29 -11
- package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
- package/dist/src/formats/cx2/exporter.js +39 -268
- package/dist/src/formats/cx2/exporter.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts +78 -28
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +226 -79
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/cx2/index.d.ts +2 -1
- package/dist/src/formats/cx2/index.d.ts.map +1 -1
- package/dist/src/formats/cx2/index.js +2 -1
- package/dist/src/formats/cx2/index.js.map +1 -1
- package/dist/src/formats/cys/constants.d.ts +66 -17
- package/dist/src/formats/cys/constants.d.ts.map +1 -1
- package/dist/src/formats/cys/constants.js +59 -18
- package/dist/src/formats/cys/constants.js.map +1 -1
- package/dist/src/formats/cys/exporter.d.ts +118 -0
- package/dist/src/formats/cys/exporter.d.ts.map +1 -0
- package/dist/src/formats/cys/exporter.js +1072 -0
- package/dist/src/formats/cys/exporter.js.map +1 -0
- package/dist/src/formats/cys/importer.d.ts +22 -8
- package/dist/src/formats/cys/importer.d.ts.map +1 -1
- package/dist/src/formats/cys/importer.js +510 -149
- package/dist/src/formats/cys/importer.js.map +1 -1
- package/dist/src/formats/cys/index.d.ts +4 -2
- package/dist/src/formats/cys/index.d.ts.map +1 -1
- package/dist/src/formats/cys/index.js +4 -2
- package/dist/src/formats/cys/index.js.map +1 -1
- package/dist/src/formats/cys/session.d.ts +46 -7
- package/dist/src/formats/cys/session.d.ts.map +1 -1
- package/dist/src/formats/cys/session.js +98 -24
- package/dist/src/formats/cys/session.js.map +1 -1
- package/dist/src/formats/cys/tables.d.ts +9 -2
- package/dist/src/formats/cys/tables.d.ts.map +1 -1
- package/dist/src/formats/cys/tables.js +29 -7
- package/dist/src/formats/cys/tables.js.map +1 -1
- package/dist/src/formats/dot/exporter.d.ts +42 -14
- package/dist/src/formats/dot/exporter.d.ts.map +1 -1
- package/dist/src/formats/dot/exporter.js +56 -29
- package/dist/src/formats/dot/exporter.js.map +1 -1
- package/dist/src/formats/dot/importer.d.ts +91 -29
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +190 -39
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/index.d.ts +2 -1
- package/dist/src/formats/dot/index.d.ts.map +1 -1
- package/dist/src/formats/dot/index.js +2 -1
- package/dist/src/formats/dot/index.js.map +1 -1
- package/dist/src/formats/dot/names.d.ts +44 -11
- package/dist/src/formats/dot/names.d.ts.map +1 -1
- package/dist/src/formats/dot/names.js +44 -11
- package/dist/src/formats/dot/names.js.map +1 -1
- package/dist/src/formats/dot/tokenizer.d.ts +9 -2
- package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
- package/dist/src/formats/dot/tokenizer.js +20 -5
- package/dist/src/formats/dot/tokenizer.js.map +1 -1
- package/dist/src/formats/gexf/exporter.d.ts +46 -15
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +45 -15
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts +87 -23
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +471 -90
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/index.d.ts +84 -21
- package/dist/src/formats/gexf/index.d.ts.map +1 -1
- package/dist/src/formats/gexf/index.js +80 -23
- package/dist/src/formats/gexf/index.js.map +1 -1
- package/dist/src/formats/gexf/schema.d.ts +67 -15
- package/dist/src/formats/gexf/schema.d.ts.map +1 -1
- package/dist/src/formats/gexf/schema.js +59 -13
- package/dist/src/formats/gexf/schema.js.map +1 -1
- package/dist/src/formats/gml/exporter.d.ts +69 -21
- package/dist/src/formats/gml/exporter.d.ts.map +1 -1
- package/dist/src/formats/gml/exporter.js +74 -29
- package/dist/src/formats/gml/exporter.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts +116 -25
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +290 -61
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/index.d.ts +87 -24
- package/dist/src/formats/gml/index.d.ts.map +1 -1
- package/dist/src/formats/gml/index.js +79 -26
- package/dist/src/formats/gml/index.js.map +1 -1
- package/dist/src/formats/gml/syntax.d.ts +67 -18
- package/dist/src/formats/gml/syntax.d.ts.map +1 -1
- package/dist/src/formats/gml/syntax.js +108 -26
- package/dist/src/formats/gml/syntax.js.map +1 -1
- package/dist/src/formats/graphml/constants.d.ts +174 -44
- package/dist/src/formats/graphml/constants.d.ts.map +1 -1
- package/dist/src/formats/graphml/constants.js +165 -44
- package/dist/src/formats/graphml/constants.js.map +1 -1
- package/dist/src/formats/graphml/exporter.d.ts +17 -9
- package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
- package/dist/src/formats/graphml/exporter.js +33 -12
- package/dist/src/formats/graphml/exporter.js.map +1 -1
- package/dist/src/formats/graphml/importer.d.ts +19 -7
- package/dist/src/formats/graphml/importer.d.ts.map +1 -1
- package/dist/src/formats/graphml/importer.js +466 -39
- package/dist/src/formats/graphml/importer.js.map +1 -1
- package/dist/src/formats/graphml/index.d.ts +2 -1
- package/dist/src/formats/graphml/index.d.ts.map +1 -1
- package/dist/src/formats/graphml/index.js +2 -1
- package/dist/src/formats/graphml/index.js.map +1 -1
- package/dist/src/formats/graphml/tree.d.ts +6 -2
- package/dist/src/formats/graphml/tree.d.ts.map +1 -1
- package/dist/src/formats/graphml/tree.js +6 -2
- package/dist/src/formats/graphml/tree.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts +8 -3
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +36 -15
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/dialect.d.ts +88 -24
- package/dist/src/formats/json/dialect.d.ts.map +1 -1
- package/dist/src/formats/json/dialect.js +109 -19
- package/dist/src/formats/json/dialect.js.map +1 -1
- package/dist/src/formats/json/exporter.d.ts +134 -22
- package/dist/src/formats/json/exporter.d.ts.map +1 -1
- package/dist/src/formats/json/exporter.js +135 -54
- package/dist/src/formats/json/exporter.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts +173 -52
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +899 -220
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/index.d.ts +3 -2
- package/dist/src/formats/json/index.d.ts.map +1 -1
- package/dist/src/formats/json/index.js +3 -2
- package/dist/src/formats/json/index.js.map +1 -1
- package/dist/src/formats/json/obographs-export.d.ts +68 -0
- package/dist/src/formats/json/obographs-export.d.ts.map +1 -0
- package/dist/src/formats/json/obographs-export.js +941 -0
- package/dist/src/formats/json/obographs-export.js.map +1 -0
- package/dist/src/formats/json/obographs.d.ts +26 -0
- package/dist/src/formats/json/obographs.d.ts.map +1 -1
- package/dist/src/formats/json/obographs.js +297 -80
- package/dist/src/formats/json/obographs.js.map +1 -1
- package/dist/src/formats/neo4j/exporter.d.ts +109 -21
- package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
- package/dist/src/formats/neo4j/exporter.js +238 -85
- package/dist/src/formats/neo4j/exporter.js.map +1 -1
- package/dist/src/formats/neo4j/header.d.ts +17 -4
- package/dist/src/formats/neo4j/header.d.ts.map +1 -1
- package/dist/src/formats/neo4j/header.js +36 -4
- package/dist/src/formats/neo4j/header.js.map +1 -1
- package/dist/src/formats/neo4j/importer.d.ts +107 -27
- package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
- package/dist/src/formats/neo4j/importer.js +415 -63
- package/dist/src/formats/neo4j/importer.js.map +1 -1
- package/dist/src/formats/neo4j/index.d.ts +73 -23
- package/dist/src/formats/neo4j/index.d.ts.map +1 -1
- package/dist/src/formats/neo4j/index.js +65 -25
- package/dist/src/formats/neo4j/index.js.map +1 -1
- package/dist/src/formats/obo/exporter.d.ts +150 -0
- package/dist/src/formats/obo/exporter.d.ts.map +1 -0
- package/dist/src/formats/obo/exporter.js +1736 -0
- package/dist/src/formats/obo/exporter.js.map +1 -0
- package/dist/src/formats/obo/importer.d.ts +95 -19
- package/dist/src/formats/obo/importer.d.ts.map +1 -1
- package/dist/src/formats/obo/importer.js +475 -104
- package/dist/src/formats/obo/importer.js.map +1 -1
- package/dist/src/formats/obo/index.d.ts +6 -3
- package/dist/src/formats/obo/index.d.ts.map +1 -1
- package/dist/src/formats/obo/index.js +6 -3
- package/dist/src/formats/obo/index.js.map +1 -1
- package/dist/src/formats/obo/syntax.d.ts +108 -4
- package/dist/src/formats/obo/syntax.d.ts.map +1 -1
- package/dist/src/formats/obo/syntax.js +211 -34
- package/dist/src/formats/obo/syntax.js.map +1 -1
- package/dist/src/formats/pajek/exporter.d.ts +54 -16
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +66 -34
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts +84 -22
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +303 -83
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/index.d.ts +2 -1
- package/dist/src/formats/pajek/index.d.ts.map +1 -1
- package/dist/src/formats/pajek/index.js +2 -1
- package/dist/src/formats/pajek/index.js.map +1 -1
- package/dist/src/formats/pajek/syntax.d.ts +77 -14
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +183 -51
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/columns.d.ts +1 -0
- package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
- package/dist/src/formats/xgmml/columns.js +4 -0
- package/dist/src/formats/xgmml/columns.js.map +1 -1
- package/dist/src/formats/xgmml/constants.d.ts +186 -56
- package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
- package/dist/src/formats/xgmml/constants.js +181 -57
- package/dist/src/formats/xgmml/constants.js.map +1 -1
- package/dist/src/formats/xgmml/document.d.ts +65 -11
- package/dist/src/formats/xgmml/document.d.ts.map +1 -1
- package/dist/src/formats/xgmml/document.js +157 -28
- package/dist/src/formats/xgmml/document.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts +61 -3
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +129 -26
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/exporter.d.ts +13 -6
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
- package/dist/src/formats/xgmml/exporter.js +20 -21
- package/dist/src/formats/xgmml/exporter.js.map +1 -1
- package/dist/src/formats/xgmml/importer.d.ts +33 -12
- package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
- package/dist/src/formats/xgmml/importer.js +35 -72
- package/dist/src/formats/xgmml/importer.js.map +1 -1
- package/dist/src/formats/xgmml/index.d.ts +1 -0
- package/dist/src/formats/xgmml/index.d.ts.map +1 -1
- package/dist/src/formats/xgmml/index.js +1 -0
- package/dist/src/formats/xgmml/index.js.map +1 -1
- package/dist/src/formats/xgmml/values.d.ts +8 -1
- package/dist/src/formats/xgmml/values.d.ts.map +1 -1
- package/dist/src/formats/xgmml/values.js +7 -2
- package/dist/src/formats/xgmml/values.js.map +1 -1
- package/dist/src/index.d.ts +23 -18
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +28 -16
- package/dist/src/index.js.map +1 -1
- package/dist/src/registry.d.ts +478 -92
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +807 -88
- package/dist/src/registry.js.map +1 -1
- package/dist/src/sniff.d.ts +61 -19
- package/dist/src/sniff.d.ts.map +1 -1
- package/dist/src/sniff.js +121 -29
- package/dist/src/sniff.js.map +1 -1
- package/dist/src/types.d.ts +362 -112
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +28 -7
- package/dist/src/types.js.map +1 -1
- package/dist/xgmml.js +2 -2
- package/docs/samples/README.md +25 -0
- package/docs/samples/got-edges.csv +353 -0
- package/docs/samples/got-network.graphml +1384 -0
- package/docs/samples/got-nodes.csv +108 -0
- package/docs/samples/got.cx +930 -0
- package/docs/samples/got.cx2 +465 -0
- package/docs/samples/got.gexf +471 -0
- package/docs/samples/got.gml +2650 -0
- package/docs/samples/got.json +2546 -0
- package/docs/samples/got.net +461 -0
- package/docs/samples/movies-nodes.csv +9 -0
- package/docs/samples/movies-rels.csv +8 -0
- package/docs/samples/networks.cys +0 -0
- package/docs/samples/proteins.xgmml +9 -0
- package/docs/samples/teams.gv +24 -0
- package/docs/samples/vehicles.obo +25 -0
- package/package.json +9 -4
- package/src/children.ts +18 -6
- package/src/common/attributes.ts +29 -11
- package/src/common/cell-budget.ts +11 -3
- package/src/common/choose.ts +89 -0
- package/src/common/codes.ts +490 -66
- package/src/common/compare.ts +472 -0
- package/src/common/cx-export.ts +432 -0
- package/src/common/declared-types.ts +38 -4
- package/src/common/direction.ts +78 -51
- package/src/common/escape.ts +33 -17
- package/src/common/export.ts +284 -47
- package/src/common/format.ts +30 -1
- package/src/common/ids.ts +14 -3
- package/src/common/input.ts +1057 -134
- package/src/common/json-elements.ts +1034 -198
- package/src/common/line-format.ts +249 -0
- package/src/common/lists.ts +6 -1
- package/src/common/ontology-export.ts +461 -0
- package/src/common/ontology.ts +31 -9
- package/src/common/options.ts +110 -15
- package/src/common/plural.ts +49 -0
- package/src/common/report.ts +168 -25
- package/src/common/temporal.ts +22 -5
- package/src/common/text.ts +62 -23
- package/src/common/weights.ts +74 -4
- package/src/common/writer.ts +37 -3
- package/src/common/xml.ts +477 -88
- package/src/common/zip.ts +169 -7
- package/src/formats/csv/exporter.ts +201 -46
- package/src/formats/csv/header.ts +50 -11
- package/src/formats/csv/importer.ts +1133 -245
- package/src/formats/csv/index.ts +106 -19
- package/src/formats/csv/records.ts +396 -122
- package/src/formats/csv/values.ts +1 -0
- package/src/formats/cx/exporter.ts +1483 -0
- package/src/formats/cx/importer.ts +888 -300
- package/src/formats/cx/index.ts +4 -3
- package/src/formats/cx2/exporter.ts +61 -338
- package/src/formats/cx2/importer.ts +317 -86
- package/src/formats/cx2/index.ts +2 -1
- package/src/formats/cys/constants.ts +62 -17
- package/src/formats/cys/exporter.ts +1368 -0
- package/src/formats/cys/importer.ts +659 -157
- package/src/formats/cys/index.ts +4 -2
- package/src/formats/cys/session.ts +139 -31
- package/src/formats/cys/tables.ts +47 -9
- package/src/formats/dot/exporter.ts +83 -37
- package/src/formats/dot/importer.ts +248 -54
- package/src/formats/dot/index.ts +2 -1
- package/src/formats/dot/names.ts +44 -11
- package/src/formats/dot/tokenizer.ts +25 -6
- package/src/formats/gexf/exporter.ts +57 -18
- package/src/formats/gexf/importer.ts +636 -105
- package/src/formats/gexf/index.ts +90 -21
- package/src/formats/gexf/schema.ts +67 -15
- package/src/formats/gml/exporter.ts +90 -36
- package/src/formats/gml/importer.ts +388 -67
- package/src/formats/gml/index.ts +85 -24
- package/src/formats/gml/syntax.ts +111 -26
- package/src/formats/graphml/constants.ts +178 -44
- package/src/formats/graphml/exporter.ts +52 -18
- package/src/formats/graphml/importer.ts +640 -60
- package/src/formats/graphml/index.ts +2 -1
- package/src/formats/graphml/tree.ts +6 -2
- package/src/formats/graphml/yfiles.ts +37 -15
- package/src/formats/json/dialect.ts +128 -29
- package/src/formats/json/exporter.ts +205 -68
- package/src/formats/json/importer.ts +1163 -253
- package/src/formats/json/index.ts +3 -1
- package/src/formats/json/obographs-export.ts +1197 -0
- package/src/formats/json/obographs.ts +353 -92
- package/src/formats/neo4j/exporter.ts +320 -101
- package/src/formats/neo4j/header.ts +44 -6
- package/src/formats/neo4j/importer.ts +512 -73
- package/src/formats/neo4j/index.ts +75 -23
- package/src/formats/obo/exporter.ts +2210 -0
- package/src/formats/obo/importer.ts +622 -109
- package/src/formats/obo/index.ts +6 -3
- package/src/formats/obo/syntax.ts +232 -37
- package/src/formats/pajek/exporter.ts +89 -41
- package/src/formats/pajek/importer.ts +407 -93
- package/src/formats/pajek/index.ts +2 -1
- package/src/formats/pajek/syntax.ts +213 -52
- package/src/formats/xgmml/columns.ts +10 -0
- package/src/formats/xgmml/constants.ts +183 -56
- package/src/formats/xgmml/document.ts +212 -34
- package/src/formats/xgmml/emit.ts +175 -34
- package/src/formats/xgmml/exporter.ts +35 -27
- package/src/formats/xgmml/importer.ts +64 -86
- package/src/formats/xgmml/index.ts +1 -0
- package/src/formats/xgmml/values.ts +11 -3
- package/src/index.ts +81 -11
- package/src/registry.ts +1121 -135
- package/src/sniff.ts +163 -32
- package/src/types.ts +385 -114
- package/dist/chunks/escape-B-tkk_Cl.js.map +0 -1
- package/dist/chunks/export-Bh60Dv-n.js +0 -582
- package/dist/chunks/export-Bh60Dv-n.js.map +0 -1
- package/dist/chunks/exporter-BGrsWamJ.js.map +0 -1
- package/dist/chunks/exporter-DIeGJXAZ.js.map +0 -1
- package/dist/chunks/importer-BWY2FFc5.js.map +0 -1
- package/dist/chunks/importer-DD-xv9_Y.js +0 -1471
- package/dist/chunks/importer-DD-xv9_Y.js.map +0 -1
- package/dist/chunks/importer-DET1tg6s.js.map +0 -1
- package/dist/chunks/importer-DEcKhsmQ.js +0 -1614
- package/dist/chunks/importer-DEcKhsmQ.js.map +0 -1
- package/dist/chunks/importer-DIrbbnAf.js.map +0 -1
- package/dist/chunks/importer-D_e7e7LX.js.map +0 -1
- package/dist/chunks/importer-eUREhBGj.js.map +0 -1
- package/dist/chunks/importer-vi3bSdtw.js.map +0 -1
- package/dist/chunks/importer-zGLo8Dg_.js.map +0 -1
- package/dist/chunks/json-elements-DDS8N2Dd.js +0 -779
- package/dist/chunks/json-elements-DDS8N2Dd.js.map +0 -1
- package/dist/chunks/ontology-BnrJ4I98.js +0 -113
- package/dist/chunks/ontology-BnrJ4I98.js.map +0 -1
- package/dist/chunks/records-dbRkxwaq.js.map +0 -1
- package/dist/chunks/report-B1z4WT9e.js +0 -2372
- package/dist/chunks/report-B1z4WT9e.js.map +0 -1
- package/dist/chunks/text-Dr0Ifpag.js.map +0 -1
- package/dist/chunks/weights-Dzba96G3.js +0 -176
- package/dist/chunks/weights-Dzba96G3.js.map +0 -1
- package/dist/chunks/writer-C7flM-Ih.js.map +0 -1
package/src/common/export.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* the ids the format cannot hold and hands the exporter the originals to write into its
|
|
6
6
|
* `graphty:originalId` attribute).
|
|
7
7
|
*
|
|
8
|
-
* Every exporter's check() calls checkCapabilities() first and appends its format-specific notes
|
|
9
|
-
*
|
|
8
|
+
* Every exporter's check() calls checkCapabilities() first and appends its format-specific notes;
|
|
9
|
+
* export() calls
|
|
10
10
|
* sanitizeIds() before writing anything.
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -15,12 +15,14 @@ import {
|
|
|
15
15
|
type Dtype,
|
|
16
16
|
GraphFormatError,
|
|
17
17
|
type GraphSnapshot,
|
|
18
|
+
type IdCoercion,
|
|
18
19
|
INVALID_INDEX,
|
|
19
20
|
type NodeId,
|
|
20
21
|
} from "@graphty/graph-format";
|
|
21
22
|
|
|
22
23
|
import { type ExportCapabilities, type LossNote } from "../types.js";
|
|
23
24
|
import {
|
|
25
|
+
COLUMN_DROPPED_CODE,
|
|
24
26
|
COLUMN_RENAMED_LOSS_CODE,
|
|
25
27
|
EMPTY_COLUMN_DROPPED_CODE,
|
|
26
28
|
ID_TEXT_COLLISION_CODE,
|
|
@@ -29,6 +31,7 @@ import {
|
|
|
29
31
|
MIXED_DIRECTION_CODE,
|
|
30
32
|
MUTUAL_AS_UNDIRECTED_CODE,
|
|
31
33
|
MUTUAL_EXPANDED_CODE,
|
|
34
|
+
NONFINITE_AS_NULL_CODE,
|
|
32
35
|
OPTIONS_GAINED_CODE,
|
|
33
36
|
PARENTS_DROPPED_CODE,
|
|
34
37
|
ROLE_ASSUMED_CODE,
|
|
@@ -38,33 +41,67 @@ import {
|
|
|
38
41
|
TEMPORAL_TEXT_DROPPED_CODE,
|
|
39
42
|
TEXT_INFERRED_CODE,
|
|
40
43
|
WEIGHT_KEY_CLASH_CODE,
|
|
44
|
+
WEIGHTS_DROPPED_CODE,
|
|
41
45
|
XML_ILLEGAL_CHAR_CODE,
|
|
42
46
|
} from "./codes.js";
|
|
47
|
+
import { coerceIdText } from "./ids.js";
|
|
43
48
|
import { type ResolvedExportOptions } from "./options.js";
|
|
49
|
+
import { agree, plural } from "./plural.js";
|
|
50
|
+
import { explicitWeights } from "./weights.js";
|
|
44
51
|
|
|
45
|
-
/** The
|
|
52
|
+
/** The code of node ids the format cannot write under `sanitizeIds: "error"`. */
|
|
53
|
+
const ID_CHARSET_REFUSAL = "E_ID_CHARSET";
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The shared LossNote codes of checkCapabilities().
|
|
57
|
+
* @category Issue and loss codes
|
|
58
|
+
*/
|
|
46
59
|
export const LOSS = Object.freeze({
|
|
47
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* A node or edge attribute is not written: the format has no attributes, or none of this kind
|
|
62
|
+
* (`CheckExtras.attributes` false).
|
|
63
|
+
*/
|
|
64
|
+
COLUMN_DROPPED: COLUMN_DROPPED_CODE,
|
|
65
|
+
/**
|
|
66
|
+
* The graph has both directed and undirected edges, the format holds one direction per file, and
|
|
67
|
+
* `onMixedDirection` is "directed" or "undirected": every edge is written with that direction.
|
|
68
|
+
*/
|
|
48
69
|
MIXED_DIRECTION: "W_MIXED_DIRECTION",
|
|
49
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* The graph has both directed and undirected edges and `onMixedDirection` is "error". An import stops; a save to a
|
|
72
|
+
* format that holds one direction per file fails with E_DIRECTED. Pass "directed" or "undirected" to read or write
|
|
73
|
+
* it anyway.
|
|
74
|
+
*/
|
|
50
75
|
MIXED_DIRECTION_ERROR: MIXED_DIRECTION_CODE,
|
|
51
76
|
/** Parallel edges in a format without them. */
|
|
52
77
|
MULTI_EDGES: "W_MULTI_EDGES",
|
|
53
78
|
/** Self-loops in a format without them. */
|
|
54
79
|
SELF_LOOPS: "W_SELF_LOOPS",
|
|
55
|
-
/**
|
|
80
|
+
/**
|
|
81
|
+
* The format needs an id on every edge and the graph has none, so the file gets ids e0, e1, e2 and so on, which
|
|
82
|
+
* read back as edge ids.
|
|
83
|
+
*/
|
|
56
84
|
EDGE_IDS_GENERATED: "W_EDGE_IDS_GENERATED",
|
|
57
|
-
/** The
|
|
85
|
+
/** The graph has edge ids and the format has no place for them, so they are not written. */
|
|
58
86
|
EDGE_IDS_DROPPED: "W_EDGE_IDS_DROPPED",
|
|
59
87
|
/** Ids outside the format's charset are rewritten (sanitizeIds "mangle"). */
|
|
60
88
|
ID_MANGLED: "W_ID_MANGLED",
|
|
61
|
-
/**
|
|
62
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Node ids the format cannot write, under `sanitizeIds: "error"`; the save fails with E_INVALID_ID. Pass
|
|
91
|
+
* `sanitizeIds: "mangle"` to rewrite them.
|
|
92
|
+
*/
|
|
93
|
+
ID_CHARSET: ID_CHARSET_REFUSAL,
|
|
63
94
|
/** The format numbers nodes 1..N; ids that are not their 1-based index are kept as labels only. */
|
|
64
95
|
ID_RENUMBERED: "W_ID_RENUMBERED",
|
|
65
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* An attribute's type is one the format cannot store as it is (for example, a 32-bit float in a format that has only 64-bit
|
|
98
|
+
* numbers), so it reads back with the nearest type the format has.
|
|
99
|
+
*/
|
|
66
100
|
DTYPE: "W_DTYPE_UNSUPPORTED",
|
|
67
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* An attribute with several numbers per element (other than a position) is written as separate values or a list,
|
|
103
|
+
* and does not read back as one attribute.
|
|
104
|
+
*/
|
|
68
105
|
COMPONENTS: "W_COMPONENTS_FLATTENED",
|
|
69
106
|
/** A list column in a format without lists. */
|
|
70
107
|
LIST: "W_LIST_UNSUPPORTED",
|
|
@@ -78,9 +115,9 @@ export const LOSS = Object.freeze({
|
|
|
78
115
|
HIERARCHY: "W_HIERARCHY_DROPPED",
|
|
79
116
|
/** A start / end / timestamp column in a format without temporal support. */
|
|
80
117
|
TEMPORAL: TEMPORAL_DROPPED_CODE,
|
|
81
|
-
/** A `<column>.text` companion
|
|
118
|
+
/** A `<column>.text` companion the format cannot carry. */
|
|
82
119
|
TEMPORAL_TEXT: TEMPORAL_TEXT_DROPPED_CODE,
|
|
83
|
-
/**
|
|
120
|
+
/** An attribute with a role the format has no place for is written as a plain attribute; the role is lost. */
|
|
84
121
|
ROLE: ROLE_DROPPED_CODE,
|
|
85
122
|
/** A parents (multi-parent) column in a format with single containment only. */
|
|
86
123
|
PARENTS: PARENTS_DROPPED_CODE,
|
|
@@ -90,31 +127,55 @@ export const LOSS = Object.freeze({
|
|
|
90
127
|
MUTUAL_AS_UNDIRECTED: MUTUAL_AS_UNDIRECTED_CODE,
|
|
91
128
|
/** Node ids whose written text reads back as the other type under the importer's id rule. */
|
|
92
129
|
ID_TEXT_TYPE: ID_TEXT_TYPE_CODE,
|
|
93
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* Two node ids would be written as the same text (the number 5 and the text "5"); the save fails with
|
|
132
|
+
* E_INVALID_ID.
|
|
133
|
+
*/
|
|
94
134
|
ID_TEXT_COLLISION: ID_TEXT_COLLISION_CODE,
|
|
95
|
-
/**
|
|
135
|
+
/**
|
|
136
|
+
* An attribute without the weight role is named like the attribute graph-io reads weights from (for example, `weight`), so
|
|
137
|
+
* it reads back as the edge weight.
|
|
138
|
+
*/
|
|
96
139
|
WEIGHT_KEY_CLASH: WEIGHT_KEY_CLASH_CODE,
|
|
97
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* An attribute without a role is written where the format keeps a role (for example, a `name` column as the label), and
|
|
142
|
+
* reads back with that role.
|
|
143
|
+
*/
|
|
98
144
|
ROLE_ASSUMED: ROLE_ASSUMED_CODE,
|
|
99
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* An attribute with a role (for example, the label) is written where the format keeps that role, and reads back under the
|
|
147
|
+
* name the format's importer gives it.
|
|
148
|
+
*/
|
|
100
149
|
COLUMN_NAME_CHANGED: COLUMN_RENAMED_LOSS_CODE,
|
|
101
150
|
/** A declared column whose every row is unset vanishes through a format without declarations. */
|
|
102
151
|
EMPTY_COLUMN: EMPTY_COLUMN_DROPPED_CODE,
|
|
103
|
-
/**
|
|
152
|
+
/**
|
|
153
|
+
* A text attribute reads back as a dictionary attribute, or the reverse, because the importer chooses by how often
|
|
154
|
+
* its values repeat. The values are the same.
|
|
155
|
+
*/
|
|
104
156
|
STORAGE_CLASS: STORAGE_CLASS_CODE,
|
|
105
|
-
/**
|
|
157
|
+
/**
|
|
158
|
+
* A number attribute whose values are all whole numbers reads back as integers, because the format does not record
|
|
159
|
+
* the type.
|
|
160
|
+
*/
|
|
106
161
|
INTEGRAL_F64: INTEGRAL_F64_CODE,
|
|
107
|
-
/**
|
|
162
|
+
/**
|
|
163
|
+
* A text value that reads back as a number or a boolean, because the format does not record that it was text (the
|
|
164
|
+
* text "42" reads back as the number 42).
|
|
165
|
+
*/
|
|
108
166
|
TEXT_INFERRED: TEXT_INFERRED_CODE,
|
|
109
|
-
/** A
|
|
167
|
+
/** A text value holds a character XML 1.0 forbids (most control characters); the save fails with E_COLUMN_TYPE. */
|
|
110
168
|
XML_ILLEGAL_CHAR: XML_ILLEGAL_CHAR_CODE,
|
|
111
|
-
/**
|
|
169
|
+
/**
|
|
170
|
+
* A text attribute stored as a dictionary, without a declared list of allowed values, reads back with its distinct
|
|
171
|
+
* values as that list.
|
|
172
|
+
*/
|
|
112
173
|
OPTIONS_GAINED: OPTIONS_GAINED_CODE,
|
|
113
174
|
/** A spells column in a format without spells. */
|
|
114
175
|
SPELLS: "W_SPELLS_DROPPED",
|
|
115
176
|
/** Dynamic attribute values (extension tables) in a format without them. */
|
|
116
177
|
DYNAMIC_VALUES: "W_DYNAMIC_VALUES_DROPPED",
|
|
117
|
-
/** An open-interval column in a format without open intervals
|
|
178
|
+
/** An open-interval column in a format without open intervals. */
|
|
118
179
|
OPEN_INTERVAL: "W_OPEN_INTERVAL",
|
|
119
180
|
/** Graph-level attributes in a format without them. */
|
|
120
181
|
GRAPH_ATTRIBUTES: "W_GRAPH_ATTRIBUTES_DROPPED",
|
|
@@ -124,9 +185,54 @@ export const LOSS = Object.freeze({
|
|
|
124
185
|
VIZ: "W_VIZ_DROPPED",
|
|
125
186
|
/** An extension table the format cannot carry. */
|
|
126
187
|
EXTENSION_TABLE: "W_EXTENSION_TABLE_DROPPED",
|
|
188
|
+
/** A NaN or infinite number the format cannot spell; not written (or written as null), it reads back unset. */
|
|
189
|
+
NONFINITE_AS_NULL: NONFINITE_AS_NULL_CODE,
|
|
190
|
+
/**
|
|
191
|
+
* The graph has edge weights and the file does not keep them (the format has no weights, or an option turned them
|
|
192
|
+
* off): every edge reads back with the default weight 1.
|
|
193
|
+
*/
|
|
194
|
+
WEIGHTS_DROPPED: WEIGHTS_DROPPED_CODE,
|
|
127
195
|
});
|
|
128
196
|
|
|
129
|
-
/**
|
|
197
|
+
/**
|
|
198
|
+
* The error a save throws for the first `E_` note of a check() result, or null when there is none.
|
|
199
|
+
* An exporter calls it before it writes anything, so every format refuses a save the same way: an
|
|
200
|
+
* id note (E_ID_CHARSET, E_ID_TEXT_COLLISION) throws E_INVALID_ID, E_MIXED_DIRECTION throws
|
|
201
|
+
* E_DIRECTED, E_XML_ILLEGAL_CHAR throws E_COLUMN_TYPE, and any other note E_UNSUPPORTED. Map your
|
|
202
|
+
* own note codes onto these with `codes`. The error's `details.code` is the note's code.
|
|
203
|
+
* @param notes - what check() returned
|
|
204
|
+
* @param codes - the error code for each of your own note codes, such as
|
|
205
|
+
* `{ E_PAIRS_BAD_ID: "E_INVALID_ID" }`
|
|
206
|
+
* @returns the error to throw, or null
|
|
207
|
+
* @category Writing a format
|
|
208
|
+
*/
|
|
209
|
+
export function refusedSave(
|
|
210
|
+
notes: readonly LossNote[],
|
|
211
|
+
codes: Readonly<Record<string, "E_INVALID_ID" | "E_DIRECTED" | "E_COLUMN_TYPE" | "E_UNSUPPORTED">> = {},
|
|
212
|
+
): GraphFormatError | null {
|
|
213
|
+
const note = notes.find((n) => n.code.startsWith("E_"));
|
|
214
|
+
if (note === undefined) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
const code = codes[note.code] ?? REFUSAL_CODES[note.code] ?? "E_UNSUPPORTED";
|
|
218
|
+
return new GraphFormatError(code, note.message, { code: note.code, column: note.column, count: note.count });
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** The error codes a refused save throws. */
|
|
222
|
+
type RefusalCode = "E_INVALID_ID" | "E_DIRECTED" | "E_COLUMN_TYPE" | "E_UNSUPPORTED";
|
|
223
|
+
|
|
224
|
+
/** The error code a save throws for each shared refusal note. */
|
|
225
|
+
const REFUSAL_CODES: Readonly<Record<string, RefusalCode>> = {
|
|
226
|
+
[ID_CHARSET_REFUSAL]: "E_INVALID_ID",
|
|
227
|
+
[ID_TEXT_COLLISION_CODE]: "E_INVALID_ID",
|
|
228
|
+
[MIXED_DIRECTION_CODE]: "E_DIRECTED",
|
|
229
|
+
[XML_ILLEGAL_CHAR_CODE]: "E_COLUMN_TYPE",
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* The capabilities of a format that keeps nothing beyond plain topology; the base every exporter overrides.
|
|
234
|
+
* @category Plugin helpers
|
|
235
|
+
*/
|
|
130
236
|
export const NO_CAPABILITIES: ExportCapabilities = Object.freeze({
|
|
131
237
|
mixedDirection: false,
|
|
132
238
|
multiEdges: false,
|
|
@@ -151,21 +257,22 @@ export const NO_CAPABILITIES: ExportCapabilities = Object.freeze({
|
|
|
151
257
|
* conservative NO_CAPABILITIES value, so an exporter states what it keeps and nothing is assumed.
|
|
152
258
|
* @param supported - the fields the format supports
|
|
153
259
|
* @returns a frozen table
|
|
260
|
+
* @category Writing a format
|
|
154
261
|
*/
|
|
155
262
|
export function capabilities(supported: Partial<ExportCapabilities>): ExportCapabilities {
|
|
156
263
|
return Object.freeze({ ...NO_CAPABILITIES, ...supported, dtypes: Object.freeze([...(supported.dtypes ?? [])]) });
|
|
157
264
|
}
|
|
158
265
|
|
|
159
266
|
/**
|
|
160
|
-
* Format facts checkCapabilities() needs that the
|
|
161
|
-
* Consumed by the per-format importers and exporters under src/formats.
|
|
267
|
+
* Format facts checkCapabilities() needs that the capabilities table does not carry.
|
|
162
268
|
* @public
|
|
269
|
+
* @category Writing a format
|
|
163
270
|
*/
|
|
164
271
|
export interface CheckExtras {
|
|
165
272
|
/** Whether the format can write open intervals (GEXF 1.2 startopen / endopen); default false. */
|
|
166
273
|
readonly openIntervals?: boolean | undefined;
|
|
167
274
|
/**
|
|
168
|
-
* Whether the format carries the `<column>.text`
|
|
275
|
+
* Whether the format carries the `<column>.text` companion columns (the lexical
|
|
169
276
|
* form of a temporal value); default false, and every companion is then reported as
|
|
170
277
|
* W_TEMPORAL_TEXT_DROPPED.
|
|
171
278
|
*/
|
|
@@ -189,6 +296,34 @@ export interface CheckExtras {
|
|
|
189
296
|
* importer gives it). Defaults to none.
|
|
190
297
|
*/
|
|
191
298
|
readonly roleNames?: Readonly<Record<string, string>> | undefined;
|
|
299
|
+
/**
|
|
300
|
+
* False for a format that writes no node or edge attributes except the ones whose role is in
|
|
301
|
+
* `roles`: every other attribute column is reported once as W_COLUMN_DROPPED, instead of the
|
|
302
|
+
* type and role notes a written column gets. Default true. `nodeAttributes` and
|
|
303
|
+
* `edgeAttributes` override it for one kind.
|
|
304
|
+
*/
|
|
305
|
+
readonly attributes?: boolean | undefined;
|
|
306
|
+
/** Like `attributes`, for node attributes only: false for a format that writes no node attributes. */
|
|
307
|
+
readonly nodeAttributes?: boolean | undefined;
|
|
308
|
+
/** Like `attributes`, for edge attributes only: false for a format that writes no edge attributes. */
|
|
309
|
+
readonly edgeAttributes?: boolean | undefined;
|
|
310
|
+
/**
|
|
311
|
+
* Columns the format writes although it writes no other attributes: a column a format option
|
|
312
|
+
* names, such as an edge label column. Keyed by `node` or `edge`. They get no W_COLUMN_DROPPED
|
|
313
|
+
* note; the type notes of a written column still apply.
|
|
314
|
+
*/
|
|
315
|
+
readonly writtenColumns?: Readonly<Partial<Record<"node" | "edge", readonly string[]>>> | undefined;
|
|
316
|
+
/**
|
|
317
|
+
* False for a format (or an option) that writes no edge weights: a weighted graph gets one
|
|
318
|
+
* W_WEIGHTS_DROPPED note. Default true.
|
|
319
|
+
*/
|
|
320
|
+
readonly weights?: boolean | undefined;
|
|
321
|
+
/**
|
|
322
|
+
* How the format's importer turns id text back into ids ("canonical" for most text formats), so
|
|
323
|
+
* an id that comes back with another type (the text "7" as the number 7) is reported as
|
|
324
|
+
* W_ID_TEXT_TYPE. Omit it when the format records each id's type.
|
|
325
|
+
*/
|
|
326
|
+
readonly idsReadBack?: IdCoercion | undefined;
|
|
192
327
|
}
|
|
193
328
|
|
|
194
329
|
/** The roles checkCapabilities() treats structurally rather than as attribute columns. */
|
|
@@ -198,7 +333,7 @@ const TEMPORAL_ROLES: ReadonlySet<string> = new Set(["start", "end", "timestamp"
|
|
|
198
333
|
const HIERARCHY_ROLES: ReadonlySet<string> = new Set(["parent", "parents"]);
|
|
199
334
|
|
|
200
335
|
/**
|
|
201
|
-
* The generic pre-flight
|
|
336
|
+
* The generic pre-flight check: compare a snapshot with a format's capabilities
|
|
202
337
|
* and return one LossNote per gap, with the shared codes of LOSS. Format-specific notes are the
|
|
203
338
|
* exporter's to append.
|
|
204
339
|
* @param snapshot - the snapshot about to be exported
|
|
@@ -206,6 +341,7 @@ const HIERARCHY_ROLES: ReadonlySet<string> = new Set(["parent", "parents"]);
|
|
|
206
341
|
* @param options - the resolved common export options
|
|
207
342
|
* @param extras - format facts the capabilities table does not carry
|
|
208
343
|
* @returns the notes, empty when the export is exact
|
|
344
|
+
* @category Writing a format
|
|
209
345
|
*/
|
|
210
346
|
export function checkCapabilities(
|
|
211
347
|
snapshot: GraphSnapshot,
|
|
@@ -224,14 +360,14 @@ export function checkCapabilities(
|
|
|
224
360
|
if (options.onMixedDirection === "error") {
|
|
225
361
|
note(
|
|
226
362
|
LOSS.MIXED_DIRECTION_ERROR,
|
|
227
|
-
`${mixed} undirected edge(
|
|
363
|
+
`${mixed} undirected edge${plural(mixed)} in a directed graph, and the format holds one direction per file, so the save fails unless onMixedDirection is "directed" or "undirected"`,
|
|
228
364
|
null,
|
|
229
365
|
mixed,
|
|
230
366
|
);
|
|
231
367
|
} else {
|
|
232
368
|
note(
|
|
233
369
|
LOSS.MIXED_DIRECTION,
|
|
234
|
-
`${mixed} undirected edge(
|
|
370
|
+
`${mixed} undirected edge${plural(mixed)} in a directed graph ${agree(mixed, "is", "are")} written as ${options.onMixedDirection} (onMixedDirection), and the format holds one direction per file`,
|
|
235
371
|
null,
|
|
236
372
|
mixed,
|
|
237
373
|
);
|
|
@@ -240,12 +376,17 @@ export function checkCapabilities(
|
|
|
240
376
|
|
|
241
377
|
if (snapshot.flags.multigraph && !caps.multiEdges) {
|
|
242
378
|
const parallel = countParallelArcs(snapshot);
|
|
243
|
-
note(
|
|
379
|
+
note(
|
|
380
|
+
LOSS.MULTI_EDGES,
|
|
381
|
+
`${parallel} parallel edge${plural(parallel)}; the format has no parallel edges`,
|
|
382
|
+
null,
|
|
383
|
+
parallel,
|
|
384
|
+
);
|
|
244
385
|
}
|
|
245
386
|
if (snapshot.selfLoopCount > 0 && !caps.selfLoops) {
|
|
246
387
|
note(
|
|
247
388
|
LOSS.SELF_LOOPS,
|
|
248
|
-
`${snapshot.selfLoopCount} self-loop(
|
|
389
|
+
`${snapshot.selfLoopCount} self-loop${plural(snapshot.selfLoopCount)}; the format has no self-loops`,
|
|
249
390
|
null,
|
|
250
391
|
snapshot.selfLoopCount,
|
|
251
392
|
);
|
|
@@ -255,7 +396,7 @@ export function checkCapabilities(
|
|
|
255
396
|
if (caps.edgeIds === "required" && edgeIds === null && snapshot.edgeCount > 0) {
|
|
256
397
|
note(
|
|
257
398
|
LOSS.EDGE_IDS_GENERATED,
|
|
258
|
-
"the format requires edge ids;
|
|
399
|
+
"the format requires edge ids, and the graph has none; the edges are written with generated ids, which read back as a new edge id column",
|
|
259
400
|
null,
|
|
260
401
|
snapshot.edgeCount,
|
|
261
402
|
);
|
|
@@ -274,28 +415,47 @@ export function checkCapabilities(
|
|
|
274
415
|
note(
|
|
275
416
|
LOSS.ID_RENUMBERED,
|
|
276
417
|
options.sanitizeIds === "mangle"
|
|
277
|
-
? `${unrepresentable} node id(
|
|
278
|
-
: `${unrepresentable} node id(
|
|
418
|
+
? `${unrepresentable} node id${plural(unrepresentable)} ${agree(unrepresentable, "is", "are")} not their 1-based index; nodes are numbered 1..N, the original ids are written too, and an import with restoreMangledIds: true reads them back as the ids; they are also the labels of nodes without a label value`
|
|
419
|
+
: `${unrepresentable} node id${plural(unrepresentable)} ${agree(unrepresentable, "is", "are")} not their 1-based index; nodes are numbered 1..N and ids kept as labels of the nodes without a label value (a node with one loses its id)`,
|
|
279
420
|
null,
|
|
280
421
|
unrepresentable,
|
|
281
422
|
);
|
|
282
423
|
} else if (options.sanitizeIds === "mangle") {
|
|
283
424
|
note(
|
|
284
425
|
LOSS.ID_MANGLED,
|
|
285
|
-
`${unrepresentable} node id(
|
|
426
|
+
`${unrepresentable} node id${plural(unrepresentable)} ${charsetText(caps.idCharset, unrepresentable)}, so they are rewritten; the original ids are written too, and an import with restoreMangledIds: true reads them back`,
|
|
286
427
|
null,
|
|
287
428
|
unrepresentable,
|
|
288
429
|
);
|
|
289
430
|
} else {
|
|
290
431
|
note(
|
|
291
432
|
LOSS.ID_CHARSET,
|
|
292
|
-
`${unrepresentable} node id(
|
|
433
|
+
`${unrepresentable} node id${plural(unrepresentable)} ${charsetText(caps.idCharset, unrepresentable)}, so the save fails unless sanitizeIds is "mangle"`,
|
|
293
434
|
null,
|
|
294
435
|
unrepresentable,
|
|
295
436
|
);
|
|
296
437
|
}
|
|
297
438
|
}
|
|
298
439
|
|
|
440
|
+
if (extras.idsReadBack !== undefined) {
|
|
441
|
+
let retyped = 0;
|
|
442
|
+
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
443
|
+
const id = snapshot.ids.idOf(i);
|
|
444
|
+
if (coerceIdText(String(id), extras.idsReadBack) !== id) {
|
|
445
|
+
retyped++;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
if (retyped > 0) {
|
|
449
|
+
note(
|
|
450
|
+
LOSS.ID_TEXT_TYPE,
|
|
451
|
+
`${retyped} node id${plural(retyped)} ${agree(retyped, "reads", "read")} back with another type (a number as text, or text as a number)`,
|
|
452
|
+
null,
|
|
453
|
+
retyped,
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
checkWeights(snapshot, extras, note);
|
|
299
459
|
checkColumns(snapshot.nodes, "node", caps, extras, note);
|
|
300
460
|
checkColumns(snapshot.edges, "edge", caps, extras, note);
|
|
301
461
|
const graphColumns = snapshot.graph.names();
|
|
@@ -305,7 +465,7 @@ export function checkCapabilities(
|
|
|
305
465
|
} else {
|
|
306
466
|
note(
|
|
307
467
|
LOSS.GRAPH_ATTRIBUTES,
|
|
308
|
-
`${graphColumns.length} graph attribute(
|
|
468
|
+
`${graphColumns.length} graph attribute${plural(graphColumns.length)} cannot be written`,
|
|
309
469
|
null,
|
|
310
470
|
graphColumns.length,
|
|
311
471
|
);
|
|
@@ -317,7 +477,7 @@ export function checkCapabilities(
|
|
|
317
477
|
if (caps.temporal !== "dynamic-values") {
|
|
318
478
|
note(
|
|
319
479
|
LOSS.DYNAMIC_VALUES,
|
|
320
|
-
`dynamic values of "${name}" (${table.rowCount} row(
|
|
480
|
+
`dynamic values of "${name}" (${table.rowCount} row${plural(table.rowCount)}) cannot be written`,
|
|
321
481
|
name,
|
|
322
482
|
table.rowCount,
|
|
323
483
|
);
|
|
@@ -325,7 +485,7 @@ export function checkCapabilities(
|
|
|
325
485
|
} else {
|
|
326
486
|
note(
|
|
327
487
|
LOSS.EXTENSION_TABLE,
|
|
328
|
-
`extension table "${name}" (${table.rowCount} row(
|
|
488
|
+
`extension table "${name}" (${table.rowCount} row${plural(table.rowCount)}) cannot be written`,
|
|
329
489
|
name,
|
|
330
490
|
table.rowCount,
|
|
331
491
|
);
|
|
@@ -334,9 +494,69 @@ export function checkCapabilities(
|
|
|
334
494
|
return notes;
|
|
335
495
|
}
|
|
336
496
|
|
|
497
|
+
/**
|
|
498
|
+
* The ids a charset cannot hold, as a message phrase.
|
|
499
|
+
* @param charset - the format's id charset
|
|
500
|
+
* @param n - how many ids, for the verb
|
|
501
|
+
* @returns the phrase
|
|
502
|
+
*/
|
|
503
|
+
function charsetText(charset: ExportCapabilities["idCharset"], n: number): string {
|
|
504
|
+
const are = agree(n, "is", "are");
|
|
505
|
+
switch (charset) {
|
|
506
|
+
case "nmtoken":
|
|
507
|
+
return `${are} not XML name tokens (letters, digits and . - _ : only; no spaces)`;
|
|
508
|
+
case "integer":
|
|
509
|
+
return `${are} not integers`;
|
|
510
|
+
default:
|
|
511
|
+
return `cannot be written as ${charset} ids`;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Whether a format writes the attributes of one kind (CheckExtras.nodeAttributes / edgeAttributes, else attributes).
|
|
517
|
+
* @param domain - "node", "edge" or "graph"
|
|
518
|
+
* @param extras - format extras
|
|
519
|
+
* @returns false when it writes none, undefined when the extras do not say
|
|
520
|
+
*/
|
|
521
|
+
function writesAttributes(domain: string, extras: CheckExtras): boolean | undefined {
|
|
522
|
+
if (domain === "node") {
|
|
523
|
+
return extras.nodeAttributes ?? extras.attributes;
|
|
524
|
+
}
|
|
525
|
+
if (domain === "edge") {
|
|
526
|
+
return extras.edgeAttributes ?? extras.attributes;
|
|
527
|
+
}
|
|
528
|
+
return extras.attributes;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* The note of a format (or an option) that writes no weights, for a weighted graph.
|
|
533
|
+
* @param snapshot - the snapshot
|
|
534
|
+
* @param extras - format extras
|
|
535
|
+
* @param note - the recorder
|
|
536
|
+
*/
|
|
537
|
+
function checkWeights(snapshot: GraphSnapshot, extras: CheckExtras, note: NoteFn): void {
|
|
538
|
+
if (extras.weights === false && explicitWeights(snapshot).weighted) {
|
|
539
|
+
note(
|
|
540
|
+
LOSS.WEIGHTS_DROPPED,
|
|
541
|
+
`the edge weights are not written; ${snapshot.edgeCount} edge${plural(snapshot.edgeCount)} ${agree(snapshot.edgeCount, "reads", "read")} back with weight 1`,
|
|
542
|
+
null,
|
|
543
|
+
snapshot.edgeCount,
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
337
548
|
/** A note-recording callback. */
|
|
338
549
|
type NoteFn = (code: string, message: string, column?: string | null, count?: number | null) => void;
|
|
339
550
|
|
|
551
|
+
/** How messages name what a column of a role holds. */
|
|
552
|
+
const ROLE_WORDS: Readonly<Record<string, string>> = {
|
|
553
|
+
label: "labels",
|
|
554
|
+
weight: "weights",
|
|
555
|
+
id: "ids",
|
|
556
|
+
position: "positions",
|
|
557
|
+
originalId: "original ids",
|
|
558
|
+
};
|
|
559
|
+
|
|
340
560
|
/**
|
|
341
561
|
* The per-column checks of checkCapabilities().
|
|
342
562
|
* @param table - the table
|
|
@@ -364,7 +584,7 @@ function checkColumns(
|
|
|
364
584
|
if (fixed !== undefined && fixed !== name) {
|
|
365
585
|
note(
|
|
366
586
|
LOSS.COLUMN_NAME_CHANGED,
|
|
367
|
-
`${label} (${role}) is written
|
|
587
|
+
`${label} (the ${ROLE_WORDS[role] ?? role}) is written as the format's own ${role} and reads back as "${fixed}"`,
|
|
368
588
|
name,
|
|
369
589
|
column.length - column.nullCount,
|
|
370
590
|
);
|
|
@@ -373,11 +593,20 @@ function checkColumns(
|
|
|
373
593
|
if (domain === "edge" && role === "id") {
|
|
374
594
|
continue;
|
|
375
595
|
}
|
|
596
|
+
const named = extras.writtenColumns?.[domain as "node" | "edge"]?.includes(name) ?? false;
|
|
597
|
+
if (
|
|
598
|
+
writesAttributes(domain, extras) === false &&
|
|
599
|
+
!named &&
|
|
600
|
+
!(role !== null && (extras.roles?.has(role) ?? false))
|
|
601
|
+
) {
|
|
602
|
+
note(LOSS.COLUMN_DROPPED, `${label} is not written`, name, column.length - column.nullCount);
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
376
605
|
if (role === "timeText") {
|
|
377
606
|
if (extras.temporalText !== true) {
|
|
378
607
|
note(
|
|
379
608
|
LOSS.TEMPORAL_TEXT,
|
|
380
|
-
`${label} (the
|
|
609
|
+
`${label} (the original text of a date or time column) cannot be written`,
|
|
381
610
|
name,
|
|
382
611
|
column.length - column.nullCount,
|
|
383
612
|
);
|
|
@@ -509,6 +738,7 @@ function checkDtype(column: Column, label: string, caps: ExportCapabilities, not
|
|
|
509
738
|
* expanded pair count once; an expanded self-loop has no mirror and counts once).
|
|
510
739
|
* @param snapshot - the snapshot
|
|
511
740
|
* @returns the count; 0 for an undirected snapshot or one without the directed role
|
|
741
|
+
* @category Plugin helpers
|
|
512
742
|
*/
|
|
513
743
|
export function countMixedEdges(snapshot: GraphSnapshot): number {
|
|
514
744
|
if (!snapshot.directed) {
|
|
@@ -537,6 +767,7 @@ export function countMixedEdges(snapshot: GraphSnapshot): number {
|
|
|
537
767
|
* over the forward CSR; an undirected parallel edge is counted in both rows.
|
|
538
768
|
* @param snapshot - the snapshot
|
|
539
769
|
* @returns the count
|
|
770
|
+
* @category Plugin helpers
|
|
540
771
|
*/
|
|
541
772
|
export function countParallelArcs(snapshot: GraphSnapshot): number {
|
|
542
773
|
const { rowPtr, colIdx, nodeCount } = snapshot;
|
|
@@ -555,15 +786,15 @@ export function countParallelArcs(snapshot: GraphSnapshot): number {
|
|
|
555
786
|
|
|
556
787
|
/**
|
|
557
788
|
* The id charsets of ExportCapabilities.
|
|
558
|
-
* Consumed by the per-format importers and exporters under src/formats.
|
|
559
789
|
* @public
|
|
790
|
+
* @category Plugin helpers
|
|
560
791
|
*/
|
|
561
792
|
export type IdCharset = ExportCapabilities["idCharset"];
|
|
562
793
|
|
|
563
794
|
/**
|
|
564
|
-
* The ids to write for every node after sanitising
|
|
565
|
-
* Consumed by the per-format importers and exporters under src/formats.
|
|
795
|
+
* The ids to write for every node after sanitising.
|
|
566
796
|
* @public
|
|
797
|
+
* @category Writing a format
|
|
567
798
|
*/
|
|
568
799
|
export interface SanitizedIds {
|
|
569
800
|
/** The charset applied. */
|
|
@@ -616,6 +847,7 @@ const NAME_CHAR_RANGES: readonly (readonly [number, number])[] = [
|
|
|
616
847
|
* Whether a code point is an XML NameChar.
|
|
617
848
|
* @param cp - the code point
|
|
618
849
|
* @returns true when it may appear in an NMTOKEN
|
|
850
|
+
* @category Plugin helpers
|
|
619
851
|
*/
|
|
620
852
|
export function isNameChar(cp: number): boolean {
|
|
621
853
|
for (const [lo, hi] of NAME_CHAR_RANGES) {
|
|
@@ -633,6 +865,7 @@ export function isNameChar(cp: number): boolean {
|
|
|
633
865
|
* Whether a text is an XML NMTOKEN (one or more NameChars; GraphML node and edge ids).
|
|
634
866
|
* @param text - the text
|
|
635
867
|
* @returns true for a non-empty text of NameChars
|
|
868
|
+
* @category Plugin helpers
|
|
636
869
|
*/
|
|
637
870
|
export function isNmtoken(text: string): boolean {
|
|
638
871
|
if (text.length === 0) {
|
|
@@ -652,6 +885,7 @@ export function isNmtoken(text: string): boolean {
|
|
|
652
885
|
* @param id - the id
|
|
653
886
|
* @param charset - the charset
|
|
654
887
|
* @returns true when the id needs no rewriting ("dense-1-based" is never true: see sanitizeIds)
|
|
888
|
+
* @category Plugin helpers
|
|
655
889
|
*/
|
|
656
890
|
export function isRepresentableId(id: NodeId, charset: IdCharset): boolean {
|
|
657
891
|
switch (charset) {
|
|
@@ -676,6 +910,7 @@ export function isRepresentableId(id: NodeId, charset: IdCharset): boolean {
|
|
|
676
910
|
* @param snapshot - the snapshot
|
|
677
911
|
* @param charset - the charset
|
|
678
912
|
* @returns the count
|
|
913
|
+
* @category Plugin helpers
|
|
679
914
|
*/
|
|
680
915
|
export function countUnrepresentableIds(snapshot: GraphSnapshot, charset: IdCharset): number {
|
|
681
916
|
const { ids } = snapshot;
|
|
@@ -704,7 +939,7 @@ export function countUnrepresentableIds(snapshot: GraphSnapshot, charset: IdChar
|
|
|
704
939
|
}
|
|
705
940
|
|
|
706
941
|
/**
|
|
707
|
-
* Sanitise the node ids for a charset
|
|
942
|
+
* Sanitise the node ids for a charset. Under "error" any id the charset
|
|
708
943
|
* cannot hold is E_INVALID_ID (details.reason "charset") and nothing is written; under "mangle"
|
|
709
944
|
* such ids are rewritten deterministically and uniquely: NMTOKEN by replacing every other
|
|
710
945
|
* character with `_` (an empty result becomes `_`) and suffixing `_2`, `_3`... on collision;
|
|
@@ -716,6 +951,7 @@ export function countUnrepresentableIds(snapshot: GraphSnapshot, charset: IdChar
|
|
|
716
951
|
* @param charset - the charset
|
|
717
952
|
* @param mode - the resolved sanitizeIds option
|
|
718
953
|
* @returns the ids to write
|
|
954
|
+
* @category Writing a format
|
|
719
955
|
*/
|
|
720
956
|
export function sanitizeIds(snapshot: GraphSnapshot, charset: IdCharset, mode: "error" | "mangle"): SanitizedIds {
|
|
721
957
|
const { ids } = snapshot;
|
|
@@ -753,7 +989,7 @@ export function sanitizeIds(snapshot: GraphSnapshot, charset: IdCharset, mode: "
|
|
|
753
989
|
const first = ids.idOf(bad[0]);
|
|
754
990
|
throw new GraphFormatError(
|
|
755
991
|
"E_INVALID_ID",
|
|
756
|
-
`${bad.length} node id(
|
|
992
|
+
`${bad.length} node id${plural(bad.length)} ${charsetText(charset, bad.length)} (first: ${JSON.stringify(first)} at index ${bad[0]}); pass sanitizeIds: "mangle" to rewrite them`,
|
|
757
993
|
{ reason: "charset", charset, count: bad.length, id: first, index: bad[0] },
|
|
758
994
|
);
|
|
759
995
|
}
|
|
@@ -806,6 +1042,7 @@ export function sanitizeIds(snapshot: GraphSnapshot, charset: IdCharset, mode: "
|
|
|
806
1042
|
* Rewrite a text as an NMTOKEN: every character that is not a NameChar becomes `_`.
|
|
807
1043
|
* @param text - the text
|
|
808
1044
|
* @returns a non-empty NMTOKEN
|
|
1045
|
+
* @category Plugin helpers
|
|
809
1046
|
*/
|
|
810
1047
|
export function mangleNmtoken(text: string): string {
|
|
811
1048
|
let out = "";
|