@graphty/graph-io 0.3.25 → 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
|
@@ -14,12 +14,21 @@
|
|
|
14
14
|
* the file, and text after a closing quote makes every later cell boundary unreliable.
|
|
15
15
|
*/
|
|
16
16
|
import { GraphFormatError } from "@graphty/graph-format";
|
|
17
|
-
import { textChunks } from "../../common/input.js";
|
|
18
|
-
/**
|
|
17
|
+
import { MAX_TEXT_LENGTH, textChunks, tooLarge } from "../../common/input.js";
|
|
18
|
+
/**
|
|
19
|
+
* A quoted field is never closed; the import aborts (everything after it would be one cell).
|
|
20
|
+
* @category Issue and loss codes
|
|
21
|
+
*/
|
|
19
22
|
export const UNCLOSED_QUOTE_CODE = "E_CSV_UNCLOSED_QUOTE";
|
|
20
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* A closing quote is followed by text other than a delimiter or a line break; the import aborts.
|
|
25
|
+
* @category Issue and loss codes
|
|
26
|
+
*/
|
|
21
27
|
export const BAD_QUOTE_CODE = "E_CSV_QUOTE";
|
|
22
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* The delimiters tried, in priority order, when none is given.
|
|
30
|
+
* @category Plugin helpers
|
|
31
|
+
*/
|
|
23
32
|
export const DELIMITER_CANDIDATES = Object.freeze([",", "\t", ";", "|", " "]);
|
|
24
33
|
/** Rows the delimiter sniff looks at. */
|
|
25
34
|
const PREVIEW_ROWS = 10;
|
|
@@ -27,6 +36,10 @@ const PREVIEW_ROWS = 10;
|
|
|
27
36
|
const PREVIEW_CHARS = 64 * 1024;
|
|
28
37
|
const LF = 10;
|
|
29
38
|
const CR = 13;
|
|
39
|
+
const TAB = 9;
|
|
40
|
+
const SPACE = 32;
|
|
41
|
+
/** An Excel delimiter directive: a first line `sep=;` names the delimiter and is not a record. */
|
|
42
|
+
const SEP_DIRECTIVE = /^sep=([^\r\n])(?:\r\n|\n|\r|$)/i;
|
|
30
43
|
/** Tokeniser state: at the start of a field. */
|
|
31
44
|
const START = 0;
|
|
32
45
|
/** Tokeniser state: inside an unquoted field. */
|
|
@@ -44,6 +57,7 @@ const COMMENT = 5;
|
|
|
44
57
|
* must differ.
|
|
45
58
|
* @param syntax - the delimiter (or null for sniffing) and quote
|
|
46
59
|
* @returns the syntax unchanged; E_UNSUPPORTED when invalid
|
|
60
|
+
* @category Plugin helpers
|
|
47
61
|
*/
|
|
48
62
|
export function checkRecordSyntax(syntax) {
|
|
49
63
|
for (const [option, value] of [
|
|
@@ -70,12 +84,13 @@ export function checkRecordSyntax(syntax) {
|
|
|
70
84
|
* (classic Mac files); `\n` otherwise.
|
|
71
85
|
* @param text - the preview text
|
|
72
86
|
* @returns "\n" or "\r"
|
|
87
|
+
* @category Plugin helpers
|
|
73
88
|
*/
|
|
74
89
|
export function sniffNewline(text) {
|
|
75
90
|
return !text.includes("\n") && text.includes("\r") ? "\r" : "\n";
|
|
76
91
|
}
|
|
77
92
|
/**
|
|
78
|
-
* Split a text into records synchronously (the first `maxRows` of them),
|
|
93
|
+
* Split a text into records synchronously (the first `maxRows` of them), honoring quotes; for
|
|
79
94
|
* the delimiter sniff and the registry's head sniff, where the input is a bounded preview.
|
|
80
95
|
* @param text - the text
|
|
81
96
|
* @param delimiter - the delimiter
|
|
@@ -83,82 +98,158 @@ export function sniffNewline(text) {
|
|
|
83
98
|
* @param maxRows - the most rows to return
|
|
84
99
|
* @param strictQuotes - return null when a closing quote is followed by text other than the
|
|
85
100
|
* delimiter or a line break (the import would abort under this delimiter)
|
|
101
|
+
* @param collapse - the whitespace dialect (RecordSyntax.collapseSpaces) for a space delimiter
|
|
86
102
|
* @returns the rows as cell arrays (blank lines skipped), or null (see strictQuotes)
|
|
103
|
+
* @category Plugin helpers
|
|
87
104
|
*/
|
|
88
|
-
function splitRecords(text, delimiter, quote, maxRows, strictQuotes = false) {
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const n = text.length;
|
|
97
|
-
for (let i = 0; i < n && rows.length < maxRows; i++) {
|
|
98
|
-
const c = text.charCodeAt(i);
|
|
99
|
-
if (state === QUOTED) {
|
|
100
|
-
if (c === quoteCode) {
|
|
101
|
-
field += text.slice(segment, i);
|
|
102
|
-
state = CLOSING;
|
|
103
|
-
}
|
|
104
|
-
continue;
|
|
105
|
+
export function splitRecords(text, delimiter, quote, maxRows, strictQuotes = false, collapse = false) {
|
|
106
|
+
const delimiterCode = delimiter.codePointAt(0);
|
|
107
|
+
const splitter = new RecordSplitter(text, quote, delimiterCode, collapse && delimiterCode === SPACE, strictQuotes);
|
|
108
|
+
let i = 0;
|
|
109
|
+
while (i < text.length && splitter.rows.length < maxRows) {
|
|
110
|
+
i = splitter.step(i);
|
|
111
|
+
if (i < 0) {
|
|
112
|
+
return null;
|
|
105
113
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
}
|
|
115
|
+
if (splitter.rows.length < maxRows) {
|
|
116
|
+
splitter.finish();
|
|
117
|
+
}
|
|
118
|
+
return splitter.rows;
|
|
119
|
+
}
|
|
120
|
+
/** The state machine of splitRecords(): one character at a time, quotes honored. */
|
|
121
|
+
class RecordSplitter {
|
|
122
|
+
/**
|
|
123
|
+
* Create a splitter.
|
|
124
|
+
* @param text - the text
|
|
125
|
+
* @param quote - the quote character
|
|
126
|
+
* @param delimiterCode - the delimiter's code
|
|
127
|
+
* @param whitespace - whether runs of spaces and tabs are one separator
|
|
128
|
+
* @param strictQuotes - whether text after a closing quote gives up
|
|
129
|
+
*/
|
|
130
|
+
constructor(text, quote, delimiterCode, whitespace, strictQuotes) {
|
|
131
|
+
this.text = text;
|
|
132
|
+
this.quote = quote;
|
|
133
|
+
this.delimiterCode = delimiterCode;
|
|
134
|
+
this.whitespace = whitespace;
|
|
135
|
+
this.strictQuotes = strictQuotes;
|
|
136
|
+
/** The rows read so far. */
|
|
137
|
+
this.rows = [];
|
|
138
|
+
this.cells = [];
|
|
139
|
+
this.state = START;
|
|
140
|
+
/** Where the unread part of the current field starts. */
|
|
141
|
+
this.segment = 0;
|
|
142
|
+
this.field = "";
|
|
143
|
+
this.quoteCode = quote.codePointAt(0);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Read one character.
|
|
147
|
+
* @param i - its index
|
|
148
|
+
* @returns the index of the next character to read, or -1 to give up (strictQuotes)
|
|
149
|
+
*/
|
|
150
|
+
step(i) {
|
|
151
|
+
const c = this.text.codePointAt(i);
|
|
152
|
+
if (this.state === QUOTED) {
|
|
153
|
+
if (c === this.quoteCode) {
|
|
154
|
+
this.field += this.text.slice(this.segment, i);
|
|
155
|
+
this.state = CLOSING;
|
|
115
156
|
}
|
|
116
|
-
|
|
117
|
-
segment = i;
|
|
157
|
+
return i + 1;
|
|
118
158
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
159
|
+
const isDelimiter = c === this.delimiterCode || (this.whitespace && c === TAB);
|
|
160
|
+
if (this.state === CLOSING) {
|
|
161
|
+
const next = this.afterQuote(i, c, isDelimiter || c === LF || c === CR);
|
|
162
|
+
if (next !== null) {
|
|
163
|
+
return next;
|
|
122
164
|
}
|
|
123
|
-
if (c === delimiterCode) {
|
|
124
|
-
cells.push(field);
|
|
125
|
-
field = "";
|
|
126
|
-
state = START;
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
if (state !== START || cells.length > 0) {
|
|
130
|
-
cells.push(field);
|
|
131
|
-
rows.push(cells);
|
|
132
|
-
cells = [];
|
|
133
|
-
field = "";
|
|
134
|
-
}
|
|
135
|
-
state = START;
|
|
136
|
-
if (c === CR && text.charCodeAt(i + 1) === LF) {
|
|
137
|
-
i++;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
segment = i + 1;
|
|
141
|
-
continue;
|
|
142
165
|
}
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
166
|
+
if (isDelimiter || c === LF || c === CR) {
|
|
167
|
+
return this.separator(i, isDelimiter);
|
|
168
|
+
}
|
|
169
|
+
if (this.state === START) {
|
|
170
|
+
const quoted = c === this.quoteCode;
|
|
171
|
+
this.state = quoted ? QUOTED : UNQUOTED;
|
|
172
|
+
this.segment = quoted ? i + 1 : i;
|
|
173
|
+
}
|
|
174
|
+
return i + 1;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Read the character after a quote that may close a quoted field: a second quote is a quote
|
|
178
|
+
* character in the field; anything else closes it.
|
|
179
|
+
* @param i - its index
|
|
180
|
+
* @param c - its code
|
|
181
|
+
* @param separates - whether it is a delimiter or a line break
|
|
182
|
+
* @returns the index of the next character to read, -1 to give up (strictQuotes), or null to
|
|
183
|
+
* read this character as the one after the field
|
|
184
|
+
*/
|
|
185
|
+
afterQuote(i, c, separates) {
|
|
186
|
+
if (c === this.quoteCode) {
|
|
187
|
+
this.field += this.quote;
|
|
188
|
+
this.segment = i + 1;
|
|
189
|
+
this.state = QUOTED;
|
|
190
|
+
return i + 1;
|
|
191
|
+
}
|
|
192
|
+
if (this.strictQuotes && !separates) {
|
|
193
|
+
return -1;
|
|
194
|
+
}
|
|
195
|
+
this.state = AFTER_QUOTED;
|
|
196
|
+
this.segment = i;
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Read a delimiter or a line break: end the field, and at a line break the row.
|
|
201
|
+
* @param i - its index
|
|
202
|
+
* @param isDelimiter - whether it is a delimiter
|
|
203
|
+
* @returns the index of the next character to read
|
|
204
|
+
*/
|
|
205
|
+
separator(i, isDelimiter) {
|
|
206
|
+
if (this.state === UNQUOTED || this.state === AFTER_QUOTED) {
|
|
207
|
+
this.field += this.text.slice(this.segment, i);
|
|
208
|
+
}
|
|
209
|
+
let next = i + 1;
|
|
210
|
+
if (isDelimiter && this.whitespace && this.state === START) {
|
|
211
|
+
// a run of whitespace, or indentation: one separator
|
|
212
|
+
}
|
|
213
|
+
else if (isDelimiter) {
|
|
214
|
+
this.cells.push(this.field);
|
|
215
|
+
this.field = "";
|
|
216
|
+
this.state = START;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
this.endRow();
|
|
220
|
+
this.state = START;
|
|
221
|
+
if (this.text.codePointAt(i) === CR && this.text.codePointAt(i + 1) === LF) {
|
|
222
|
+
next = i + 2;
|
|
151
223
|
}
|
|
152
224
|
}
|
|
225
|
+
this.segment = next;
|
|
226
|
+
return next;
|
|
153
227
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
228
|
+
/** End the row at a line break; a blank line is no row. */
|
|
229
|
+
endRow() {
|
|
230
|
+
if (this.state === START && this.cells.length === 0) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (!(this.whitespace && this.state === START)) {
|
|
234
|
+
this.cells.push(this.field);
|
|
235
|
+
}
|
|
236
|
+
this.rows.push(this.cells);
|
|
237
|
+
this.cells = [];
|
|
238
|
+
this.field = "";
|
|
239
|
+
}
|
|
240
|
+
/** End the text: the last row, when it has no line break after it. */
|
|
241
|
+
finish() {
|
|
242
|
+
if (this.state === START && this.cells.length === 0) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (this.state === UNQUOTED || this.state === AFTER_QUOTED || this.state === QUOTED) {
|
|
246
|
+
this.field += this.text.slice(this.segment);
|
|
157
247
|
}
|
|
158
|
-
|
|
159
|
-
|
|
248
|
+
if (!(this.whitespace && this.state === START)) {
|
|
249
|
+
this.cells.push(this.field);
|
|
250
|
+
}
|
|
251
|
+
this.rows.push(this.cells);
|
|
160
252
|
}
|
|
161
|
-
return rows;
|
|
162
253
|
}
|
|
163
254
|
/**
|
|
164
255
|
* The preview text without its leading comment lines (those starting with one of the comment
|
|
@@ -166,29 +257,36 @@ function splitRecords(text, delimiter, quote, maxRows, strictQuotes = false) {
|
|
|
166
257
|
* @param text - the preview text
|
|
167
258
|
* @param comments - the comment characters
|
|
168
259
|
* @returns the text from the first non-comment line on
|
|
260
|
+
* @category Plugin helpers
|
|
169
261
|
*/
|
|
170
|
-
function stripLeadingComments(text, comments) {
|
|
262
|
+
export function stripLeadingComments(text, comments) {
|
|
171
263
|
if (comments.length === 0) {
|
|
172
264
|
return text;
|
|
173
265
|
}
|
|
174
266
|
let at = 0;
|
|
175
|
-
while (at < text.length
|
|
267
|
+
while (at < text.length) {
|
|
268
|
+
if (text[at] === "\n" || text[at] === "\r") {
|
|
269
|
+
// a blank line among the leading comments (the scanner skips it too)
|
|
270
|
+
at++;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (!comments.includes(text[at])) {
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
176
276
|
const lf = text.indexOf("\n", at);
|
|
177
277
|
const cr = text.indexOf("\r", at);
|
|
178
278
|
const end = Math.min(lf < 0 ? Infinity : lf, cr < 0 ? Infinity : cr);
|
|
179
279
|
if (end === Infinity) {
|
|
180
280
|
return "";
|
|
181
281
|
}
|
|
182
|
-
at = end
|
|
183
|
-
if (text[at - 1] === "\r" && text[at] === "\n") {
|
|
184
|
-
at++;
|
|
185
|
-
}
|
|
282
|
+
at = end;
|
|
186
283
|
}
|
|
187
284
|
return at === 0 ? text : text.slice(at);
|
|
188
285
|
}
|
|
189
286
|
/**
|
|
190
287
|
* Sniff the delimiter of a text: every candidate is tried over the first rows and the one whose
|
|
191
|
-
* field count is most consistent across rows wins (
|
|
288
|
+
* field count is most consistent across rows wins (a tie goes to the earlier candidate, so a
|
|
289
|
+
* space inside comma-separated cells never beats the comma); a
|
|
192
290
|
* candidate that yields fewer than two fields per row on average is never chosen. `null` when no
|
|
193
291
|
* candidate qualifies (a single-column file).
|
|
194
292
|
* @param text - the preview text
|
|
@@ -200,18 +298,19 @@ function stripLeadingComments(text, comments) {
|
|
|
200
298
|
* by other text. Only for inputs whose field counts say nothing (an adjacency table's rows vary in
|
|
201
299
|
* width): elsewhere a stray character after a quote would make a worse candidate win silently
|
|
202
300
|
* instead of aborting the read
|
|
301
|
+
* @param collapse - read a space candidate in the whitespace dialect (RecordSyntax.collapseSpaces)
|
|
203
302
|
* @returns the delimiter, or null
|
|
303
|
+
* @category Plugin helpers
|
|
204
304
|
*/
|
|
205
|
-
export function sniffDelimiter(text, newline = "\n", candidates = DELIMITER_CANDIDATES, quote = '"', skipQuoteErrors = false) {
|
|
305
|
+
export function sniffDelimiter(text, newline = "\n", candidates = DELIMITER_CANDIDATES, quote = '"', skipQuoteErrors = false, collapse = false) {
|
|
206
306
|
let best = null;
|
|
207
307
|
let bestDelta = Infinity;
|
|
208
|
-
let bestAverage = 0;
|
|
209
308
|
const terminated = text.endsWith("\n") || text.endsWith("\r");
|
|
210
309
|
for (const delimiter of candidates) {
|
|
211
310
|
if (delimiter === quote || delimiter === newline) {
|
|
212
311
|
continue;
|
|
213
312
|
}
|
|
214
|
-
const split = splitRecords(text, delimiter, quote, PREVIEW_ROWS, skipQuoteErrors);
|
|
313
|
+
const split = splitRecords(text, delimiter, quote, PREVIEW_ROWS, skipQuoteErrors, collapse);
|
|
215
314
|
if (split === null) {
|
|
216
315
|
// a quoted cell this delimiter does not close: it is not the file's delimiter
|
|
217
316
|
continue;
|
|
@@ -234,10 +333,9 @@ export function sniffDelimiter(text, newline = "\n", candidates = DELIMITER_CAND
|
|
|
234
333
|
}
|
|
235
334
|
}
|
|
236
335
|
const average = total / rows.length;
|
|
237
|
-
if (average > 1.99 &&
|
|
336
|
+
if (average > 1.99 && delta < bestDelta) {
|
|
238
337
|
best = delimiter;
|
|
239
338
|
bestDelta = delta;
|
|
240
|
-
bestAverage = average;
|
|
241
339
|
}
|
|
242
340
|
}
|
|
243
341
|
return best;
|
|
@@ -257,6 +355,7 @@ function isBlankRow(row) {
|
|
|
257
355
|
* are skipped. The arrays are reused between records. When the syntax gives no delimiter, the
|
|
258
356
|
* first rows (PREVIEW_ROWS, or PREVIEW_CHARS characters) are buffered and the delimiter sniffed
|
|
259
357
|
* from them before the first record is yielded.
|
|
358
|
+
* @category Plugin helpers
|
|
260
359
|
*/
|
|
261
360
|
export class RecordReader {
|
|
262
361
|
/**
|
|
@@ -273,6 +372,12 @@ export class RecordReader {
|
|
|
273
372
|
this.quoted = [];
|
|
274
373
|
/** The leading comment lines (without their line breaks), in order; empty without `syntax.comments`. */
|
|
275
374
|
this.leadingComments = [];
|
|
375
|
+
/** The 1-based line of each leading comment, parallel to `leadingComments`. */
|
|
376
|
+
this.leadingCommentLines = [];
|
|
377
|
+
/** The line of the first quote inside an unquoted field (kept as text, RFC 4180 forbids it); 0 for none. */
|
|
378
|
+
this.strayQuoteLine = 0;
|
|
379
|
+
/** Whether the sniff took the delimiter from an Excel `sep=X` first line (yielded as the first record). */
|
|
380
|
+
this.sepDirective = false;
|
|
276
381
|
this.recordLine = 0;
|
|
277
382
|
this.input = input;
|
|
278
383
|
this.report = report;
|
|
@@ -324,12 +429,11 @@ export class RecordReader {
|
|
|
324
429
|
/**
|
|
325
430
|
* Record a text-after-quote error (fatal).
|
|
326
431
|
* @param line - the line the field started on
|
|
432
|
+
* @param field - the 1-based position of the field in its record
|
|
327
433
|
* @returns never
|
|
328
434
|
*/
|
|
329
|
-
badQuote(line) {
|
|
330
|
-
return this.report.fail(BAD_QUOTE_CODE, `
|
|
331
|
-
line,
|
|
332
|
-
});
|
|
435
|
+
badQuote(line, field) {
|
|
436
|
+
return this.report.fail(BAD_QUOTE_CODE, `text after the closing quote of quoted field ${field} (a quote inside a quoted field is written as two quotes)`, { line });
|
|
333
437
|
}
|
|
334
438
|
/**
|
|
335
439
|
* Record an unclosed-quote error (fatal).
|
|
@@ -359,6 +463,11 @@ export class RecordReader {
|
|
|
359
463
|
let breaks = 0;
|
|
360
464
|
let lastWasCr = false;
|
|
361
465
|
let sniffed = false;
|
|
466
|
+
// the leading comment lines are left out of the sniff, so they do not count toward its rows
|
|
467
|
+
const commentCodes = (this.syntax.comments ?? []).map((c) => c.codePointAt(0));
|
|
468
|
+
let leading = commentCodes.length > 0;
|
|
469
|
+
let lineStart = true;
|
|
470
|
+
let inComment = false;
|
|
362
471
|
for await (const chunk of source) {
|
|
363
472
|
if (sniffed) {
|
|
364
473
|
yield chunk;
|
|
@@ -368,13 +477,19 @@ export class RecordReader {
|
|
|
368
477
|
length += chunk.length;
|
|
369
478
|
for (let i = 0; i < chunk.length && breaks < PREVIEW_ROWS; i++) {
|
|
370
479
|
const c = chunk.charCodeAt(i);
|
|
371
|
-
if (c === LF) {
|
|
372
|
-
if (!lastWasCr) {
|
|
480
|
+
if (c === LF || c === CR) {
|
|
481
|
+
if (!(c === LF && lastWasCr) && !inComment) {
|
|
373
482
|
breaks++;
|
|
374
483
|
}
|
|
484
|
+
inComment = false;
|
|
485
|
+
lineStart = true;
|
|
375
486
|
}
|
|
376
|
-
else
|
|
377
|
-
|
|
487
|
+
else {
|
|
488
|
+
if (lineStart && leading) {
|
|
489
|
+
inComment = commentCodes.includes(c);
|
|
490
|
+
leading = inComment;
|
|
491
|
+
}
|
|
492
|
+
lineStart = false;
|
|
378
493
|
}
|
|
379
494
|
lastWasCr = c === CR;
|
|
380
495
|
}
|
|
@@ -400,13 +515,23 @@ export class RecordReader {
|
|
|
400
515
|
* @param text - the preview
|
|
401
516
|
*/
|
|
402
517
|
sniff(text) {
|
|
403
|
-
const candidates = this.syntax.candidates ?? DELIMITER_CANDIDATES;
|
|
404
518
|
// the sniff is a heuristic over the first rows: a single chunk holding a huge quoted cell
|
|
405
519
|
// is capped so the candidate scans stay bounded
|
|
406
|
-
const
|
|
520
|
+
const preview = text.slice(0, PREVIEW_CHARS);
|
|
521
|
+
const body = stripLeadingComments(preview, this.syntax.comments ?? []);
|
|
522
|
+
if (this.syntax.inspect !== undefined) {
|
|
523
|
+
const skipped = preview.slice(0, preview.length - body.length).match(/\r\n|\r|\n/g)?.length ?? 0;
|
|
524
|
+
this.syntax.inspect(body, skipped + 1);
|
|
525
|
+
}
|
|
526
|
+
const directive = this.syntax.sepDirective === true ? SEP_DIRECTIVE.exec(text) : null;
|
|
527
|
+
if (directive !== null && directive[1] !== this.syntax.quote) {
|
|
528
|
+
this.delimiterText = directive[1];
|
|
529
|
+
this.sepDirective = true;
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
const candidates = this.syntax.candidates ?? DELIMITER_CANDIDATES;
|
|
407
533
|
this.delimiterText =
|
|
408
|
-
sniffDelimiter(body, sniffNewline(body), candidates, this.syntax.quote, this.syntax.skipQuoteErrors) ??
|
|
409
|
-
candidates[0];
|
|
534
|
+
sniffDelimiter(body, sniffNewline(body), candidates, this.syntax.quote, this.syntax.skipQuoteErrors, this.syntax.collapseSpaces) ?? candidates[0];
|
|
410
535
|
}
|
|
411
536
|
}
|
|
412
537
|
/**
|
|
@@ -430,6 +555,8 @@ class RecordScanner {
|
|
|
430
555
|
/** The line the record in progress started on. */
|
|
431
556
|
this.startLine = 1;
|
|
432
557
|
this.delimiterCode = -1;
|
|
558
|
+
/** The whitespace dialect: the delimiter is a space and RecordSyntax.collapseSpaces is set. */
|
|
559
|
+
this.collapse = false;
|
|
433
560
|
this.state = START;
|
|
434
561
|
this.field = "";
|
|
435
562
|
this.fieldQuoted = false;
|
|
@@ -451,6 +578,7 @@ class RecordScanner {
|
|
|
451
578
|
setDelimiter(code) {
|
|
452
579
|
if (this.delimiterCode < 0) {
|
|
453
580
|
this.delimiterCode = code;
|
|
581
|
+
this.collapse = code === SPACE && this.reader.syntax.collapseSpaces === true;
|
|
454
582
|
}
|
|
455
583
|
}
|
|
456
584
|
/**
|
|
@@ -468,8 +596,9 @@ class RecordScanner {
|
|
|
468
596
|
const c = chunk.charCodeAt(i);
|
|
469
597
|
if (this.state === COMMENT) {
|
|
470
598
|
if (c === LF || c === CR) {
|
|
471
|
-
this.comment
|
|
599
|
+
this.comment = this.grow(this.comment, chunk.slice(this.segment, i));
|
|
472
600
|
this.reader.leadingComments.push(this.comment);
|
|
601
|
+
this.reader.leadingCommentLines.push(this.line);
|
|
473
602
|
this.comment = "";
|
|
474
603
|
this.state = START;
|
|
475
604
|
this.endLine(c);
|
|
@@ -489,29 +618,30 @@ class RecordScanner {
|
|
|
489
618
|
i = n;
|
|
490
619
|
break;
|
|
491
620
|
}
|
|
492
|
-
this.field
|
|
621
|
+
this.field = this.grow(this.field, chunk.slice(this.segment, q));
|
|
493
622
|
this.state = CLOSING;
|
|
494
623
|
this.lastWasCr = false;
|
|
495
624
|
i = q + 1;
|
|
496
625
|
continue;
|
|
497
626
|
}
|
|
627
|
+
const isDelimiter = c === delimiterCode || (this.collapse && c === TAB);
|
|
498
628
|
if (this.state === CLOSING) {
|
|
499
629
|
if (c === quoteCode) {
|
|
500
|
-
this.field
|
|
630
|
+
this.field = this.grow(this.field, this.quoteText);
|
|
501
631
|
this.segment = i + 1;
|
|
502
632
|
this.state = QUOTED;
|
|
503
633
|
this.lastWasCr = false;
|
|
504
634
|
i++;
|
|
505
635
|
continue;
|
|
506
636
|
}
|
|
507
|
-
if (
|
|
508
|
-
this.reader.badQuote(this.startLine);
|
|
637
|
+
if (!isDelimiter && c !== LF && c !== CR) {
|
|
638
|
+
this.reader.badQuote(this.startLine, this.count + 1);
|
|
509
639
|
}
|
|
510
640
|
this.state = AFTER_QUOTED;
|
|
511
641
|
this.segment = i;
|
|
512
642
|
// fall through to the delimiter / line-end handling below without consuming c
|
|
513
643
|
}
|
|
514
|
-
if (
|
|
644
|
+
if (isDelimiter || c === LF || c === CR) {
|
|
515
645
|
if (c === LF && this.lastWasCr) {
|
|
516
646
|
// the second half of a CRLF already ended the record
|
|
517
647
|
this.lastWasCr = false;
|
|
@@ -520,9 +650,16 @@ class RecordScanner {
|
|
|
520
650
|
continue;
|
|
521
651
|
}
|
|
522
652
|
if (this.state === UNQUOTED) {
|
|
523
|
-
this.field
|
|
653
|
+
this.field = this.grow(this.field, chunk.slice(this.segment, i));
|
|
524
654
|
}
|
|
525
|
-
if (
|
|
655
|
+
if (isDelimiter && this.collapse && this.state === START) {
|
|
656
|
+
// a run of whitespace, or indentation: one separator
|
|
657
|
+
this.lastWasCr = false;
|
|
658
|
+
this.segment = i + 1;
|
|
659
|
+
i++;
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
if (isDelimiter) {
|
|
526
663
|
this.push();
|
|
527
664
|
this.state = START;
|
|
528
665
|
this.lastWasCr = false;
|
|
@@ -530,9 +667,11 @@ class RecordScanner {
|
|
|
530
667
|
i++;
|
|
531
668
|
continue;
|
|
532
669
|
}
|
|
533
|
-
|
|
534
|
-
if (!
|
|
670
|
+
// a line ending right after a whitespace run in the whitespace dialect ends no field
|
|
671
|
+
if (!(this.state === START && (this.count === 0 || this.collapse))) {
|
|
535
672
|
this.push();
|
|
673
|
+
}
|
|
674
|
+
if (this.count > 0) {
|
|
536
675
|
this.ready = true;
|
|
537
676
|
this.recordLine = this.startLine;
|
|
538
677
|
}
|
|
@@ -564,6 +703,9 @@ class RecordScanner {
|
|
|
564
703
|
this.segment = i;
|
|
565
704
|
}
|
|
566
705
|
}
|
|
706
|
+
else if (c === quoteCode && this.state === UNQUOTED && this.reader.strayQuoteLine === 0) {
|
|
707
|
+
this.reader.strayQuoteLine = this.startLine;
|
|
708
|
+
}
|
|
567
709
|
i++;
|
|
568
710
|
}
|
|
569
711
|
return i;
|
|
@@ -578,10 +720,10 @@ class RecordScanner {
|
|
|
578
720
|
return;
|
|
579
721
|
}
|
|
580
722
|
if (this.state === COMMENT) {
|
|
581
|
-
this.comment
|
|
723
|
+
this.comment = this.grow(this.comment, chunk.slice(this.segment, n));
|
|
582
724
|
}
|
|
583
725
|
else if (this.state === QUOTED || this.state === UNQUOTED) {
|
|
584
|
-
this.field
|
|
726
|
+
this.field = this.grow(this.field, chunk.slice(this.segment, n));
|
|
585
727
|
}
|
|
586
728
|
this.segment = n;
|
|
587
729
|
}
|
|
@@ -594,13 +736,16 @@ class RecordScanner {
|
|
|
594
736
|
const { state } = this;
|
|
595
737
|
if (state === COMMENT) {
|
|
596
738
|
this.reader.leadingComments.push(this.comment);
|
|
739
|
+
this.reader.leadingCommentLines.push(this.line);
|
|
597
740
|
return false;
|
|
598
741
|
}
|
|
599
742
|
if (state === QUOTED) {
|
|
600
743
|
this.reader.unclosedQuote(this.startLine);
|
|
601
744
|
}
|
|
602
745
|
if (state !== START || this.count > 0) {
|
|
603
|
-
this.
|
|
746
|
+
if (!(state === START && this.collapse)) {
|
|
747
|
+
this.push();
|
|
748
|
+
}
|
|
604
749
|
this.recordLine = this.startLine;
|
|
605
750
|
return true;
|
|
606
751
|
}
|
|
@@ -613,25 +758,42 @@ class RecordScanner {
|
|
|
613
758
|
* @param to - the index after the run
|
|
614
759
|
*/
|
|
615
760
|
countLineBreaks(chunk, from, to) {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
761
|
+
// indexOf, not a charCodeAt loop: a quoted cell may be hundreds of MiB, and a per-character
|
|
762
|
+
// loop over it is the whole cost of reading it (and many times that under coverage)
|
|
763
|
+
const run = chunk.slice(from, to);
|
|
764
|
+
let { line } = this;
|
|
765
|
+
// the index of the last CR seen; -1 is a CR just before the run, -2 none
|
|
766
|
+
let lastCr = this.lastWasCr ? -1 : -2;
|
|
767
|
+
let lf = run.indexOf("\n");
|
|
768
|
+
let cr = run.indexOf("\r");
|
|
769
|
+
while (lf >= 0 || cr >= 0) {
|
|
770
|
+
if (lf < 0 || (cr >= 0 && cr < lf)) {
|
|
626
771
|
line++;
|
|
627
|
-
|
|
772
|
+
lastCr = cr;
|
|
773
|
+
cr = run.indexOf("\r", cr + 1);
|
|
628
774
|
}
|
|
629
775
|
else {
|
|
630
|
-
|
|
776
|
+
if (lf !== lastCr + 1) {
|
|
777
|
+
line++;
|
|
778
|
+
}
|
|
779
|
+
lf = run.indexOf("\n", lf + 1);
|
|
631
780
|
}
|
|
632
781
|
}
|
|
633
782
|
this.line = line;
|
|
634
|
-
this.lastWasCr =
|
|
783
|
+
this.lastWasCr = lastCr === run.length - 1;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Append to the field or comment in progress, failing with E_TOO_LARGE instead of a RangeError
|
|
787
|
+
* when the result would be longer than one JavaScript string can hold.
|
|
788
|
+
* @param text - the text so far
|
|
789
|
+
* @param piece - the text to append
|
|
790
|
+
* @returns the joined text
|
|
791
|
+
*/
|
|
792
|
+
grow(text, piece) {
|
|
793
|
+
if (text.length + piece.length > MAX_TEXT_LENGTH) {
|
|
794
|
+
tooLarge(this.reader.report, `a cell is longer than ${MAX_TEXT_LENGTH} characters, the most one JavaScript string holds`, this.startLine);
|
|
795
|
+
}
|
|
796
|
+
return text + piece;
|
|
635
797
|
}
|
|
636
798
|
/** Store the field in progress as the next cell. */
|
|
637
799
|
push() {
|
|
@@ -660,7 +822,10 @@ class RecordScanner {
|
|
|
660
822
|
* on. The delimiter is known after the first row (`reader.delimiter`). Rows come out as fresh
|
|
661
823
|
* arrays of cell texts exactly as written (no trimming, no typing); `reader.quoted` tells, for
|
|
662
824
|
* the row just yielded, which cells were quoted (a quoted empty cell is the empty string, an
|
|
663
|
-
* unquoted one is "not set"). Blank lines
|
|
825
|
+
* unquoted one is "not set"). Blank lines, whitespace-only lines and rows of empty unquoted cells
|
|
826
|
+
* are skipped. A space delimiter reads the whitespace dialect (RecordSyntax.collapseSpaces), and an
|
|
827
|
+
* Excel `sep=X` first line names the delimiter when none is given.
|
|
828
|
+
* @category Plugin helpers
|
|
664
829
|
*/
|
|
665
830
|
export class CsvRecordReader {
|
|
666
831
|
/**
|
|
@@ -675,7 +840,16 @@ export class CsvRecordReader {
|
|
|
675
840
|
quote: '"',
|
|
676
841
|
comments: options.comments,
|
|
677
842
|
skipQuoteErrors: options.skipQuoteErrors,
|
|
678
|
-
|
|
843
|
+
collapseSpaces: true,
|
|
844
|
+
sepDirective: true,
|
|
845
|
+
inspect: options.inspect,
|
|
846
|
+
}, {
|
|
847
|
+
signal: options.signal,
|
|
848
|
+
onProgress: options.onProgress,
|
|
849
|
+
encoding: options.encoding,
|
|
850
|
+
allowEmpty: options.allowEmpty,
|
|
851
|
+
nulIsBinary: true,
|
|
852
|
+
});
|
|
679
853
|
}
|
|
680
854
|
/**
|
|
681
855
|
* The leading comment lines the reader skipped (SNAP `#` lines, the KONECT `%` header), in order.
|
|
@@ -684,6 +858,13 @@ export class CsvRecordReader {
|
|
|
684
858
|
get leadingComments() {
|
|
685
859
|
return this.inner.leadingComments;
|
|
686
860
|
}
|
|
861
|
+
/**
|
|
862
|
+
* The 1-based line of each leading comment, parallel to `leadingComments`.
|
|
863
|
+
* @returns the lines
|
|
864
|
+
*/
|
|
865
|
+
get leadingCommentLines() {
|
|
866
|
+
return this.inner.leadingCommentLines;
|
|
867
|
+
}
|
|
687
868
|
/**
|
|
688
869
|
* The 1-based line the most recently yielded row starts on.
|
|
689
870
|
* @returns the line; 0 before the first row
|
|
@@ -705,6 +886,20 @@ export class CsvRecordReader {
|
|
|
705
886
|
get quoted() {
|
|
706
887
|
return this.inner.quoted;
|
|
707
888
|
}
|
|
889
|
+
/**
|
|
890
|
+
* The line of the first quote inside an unquoted field.
|
|
891
|
+
* @returns the line, or 0 when there was none
|
|
892
|
+
*/
|
|
893
|
+
get strayQuoteLine() {
|
|
894
|
+
return this.inner.strayQuoteLine;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Whether the first record is an Excel `sep=X` line the delimiter was taken from.
|
|
898
|
+
* @returns true when it is
|
|
899
|
+
*/
|
|
900
|
+
get sepDirective() {
|
|
901
|
+
return this.inner.sepDirective;
|
|
902
|
+
}
|
|
708
903
|
/**
|
|
709
904
|
* Iterate the rows.
|
|
710
905
|
* @yields one row at a time as its cell texts
|
|
@@ -713,11 +908,27 @@ export class CsvRecordReader {
|
|
|
713
908
|
async *[Symbol.asyncIterator]() {
|
|
714
909
|
const { inner } = this;
|
|
715
910
|
for await (const count of inner) {
|
|
716
|
-
if (
|
|
911
|
+
if (isBlankRecord(inner.cells, inner.quoted, count)) {
|
|
717
912
|
continue;
|
|
718
913
|
}
|
|
719
914
|
yield inner.cells.slice(0, count);
|
|
720
915
|
}
|
|
721
916
|
}
|
|
722
917
|
}
|
|
918
|
+
/**
|
|
919
|
+
* Whether a record holds nothing: every cell unquoted and blank (a blank line, a whitespace-only
|
|
920
|
+
* line, or an Excel empty row `,,,`). A quoted empty cell is a value.
|
|
921
|
+
* @param cells - the cells
|
|
922
|
+
* @param quoted - whether each was quoted
|
|
923
|
+
* @param count - the cell count
|
|
924
|
+
* @returns true when the record carries no value
|
|
925
|
+
*/
|
|
926
|
+
function isBlankRecord(cells, quoted, count) {
|
|
927
|
+
for (let k = 0; k < count; k++) {
|
|
928
|
+
if (quoted[k] || cells[k].trim().length > 0) {
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
return true;
|
|
933
|
+
}
|
|
723
934
|
//# sourceMappingURL=records.js.map
|