@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.
Files changed (581) hide show
  1. package/README.md +49 -414
  2. package/dist/chunks/children-CL3Cy0ez.js.map +1 -1
  3. package/dist/chunks/choose-BbJI55dx.js +56 -0
  4. package/dist/chunks/choose-BbJI55dx.js.map +1 -0
  5. package/dist/chunks/constants-BCsFsMj4.js +231 -0
  6. package/dist/chunks/constants-BCsFsMj4.js.map +1 -0
  7. package/dist/chunks/{escape-B-tkk_Cl.js → escape-D0g6NNUy.js} +382 -92
  8. package/dist/chunks/escape-D0g6NNUy.js.map +1 -0
  9. package/dist/chunks/export-BTI4yQgy.js +4333 -0
  10. package/dist/chunks/export-BTI4yQgy.js.map +1 -0
  11. package/dist/chunks/exporter-BMqk5oxW.js +3465 -0
  12. package/dist/chunks/exporter-BMqk5oxW.js.map +1 -0
  13. package/dist/chunks/{importer-eUREhBGj.js → exporter-Cra2GYcN.js} +4969 -3201
  14. package/dist/chunks/exporter-Cra2GYcN.js.map +1 -0
  15. package/dist/chunks/{exporter-BGrsWamJ.js → exporter-Dxh231ZF.js} +38 -229
  16. package/dist/chunks/exporter-Dxh231ZF.js.map +1 -0
  17. package/dist/chunks/{exporter-DIeGJXAZ.js → exporter-tne475KK.js} +22 -20
  18. package/dist/chunks/exporter-tne475KK.js.map +1 -0
  19. package/dist/chunks/importer-90YWhJoF.js +2811 -0
  20. package/dist/chunks/importer-90YWhJoF.js.map +1 -0
  21. package/dist/chunks/{importer-D_e7e7LX.js → importer-Bcl1d4xH.js} +398 -145
  22. package/dist/chunks/importer-Bcl1d4xH.js.map +1 -0
  23. package/dist/chunks/{importer-BWY2FFc5.js → importer-BfIsp1f9.js} +255 -77
  24. package/dist/chunks/importer-BfIsp1f9.js.map +1 -0
  25. package/dist/chunks/{importer-zGLo8Dg_.js → importer-C_TEA1zJ.js} +484 -157
  26. package/dist/chunks/importer-C_TEA1zJ.js.map +1 -0
  27. package/dist/chunks/{importer-DET1tg6s.js → importer-DCjOvO7U.js} +1687 -310
  28. package/dist/chunks/importer-DCjOvO7U.js.map +1 -0
  29. package/dist/chunks/{importer-vi3bSdtw.js → importer-DfVu6j59.js} +509 -76
  30. package/dist/chunks/importer-DfVu6j59.js.map +1 -0
  31. package/dist/chunks/{importer-DIrbbnAf.js → importer-Dku_VAIY.js} +585 -226
  32. package/dist/chunks/importer-Dku_VAIY.js.map +1 -0
  33. package/dist/chunks/json-elements-3tnyt5uZ.js +1225 -0
  34. package/dist/chunks/json-elements-3tnyt5uZ.js.map +1 -0
  35. package/dist/chunks/ontology-export-B9Tcf37D.js +357 -0
  36. package/dist/chunks/ontology-export-B9Tcf37D.js.map +1 -0
  37. package/dist/chunks/{records-dbRkxwaq.js → records-CQXT__mY.js} +298 -114
  38. package/dist/chunks/records-CQXT__mY.js.map +1 -0
  39. package/dist/chunks/{text-Dr0Ifpag.js → text-DmcUs5_Q.js} +29 -11
  40. package/dist/chunks/text-DmcUs5_Q.js.map +1 -0
  41. package/dist/chunks/{writer-C7flM-Ih.js → writer-DxjgHwSe.js} +19 -1
  42. package/dist/chunks/writer-DxjgHwSe.js.map +1 -0
  43. package/dist/csv.js +951 -261
  44. package/dist/csv.js.map +1 -1
  45. package/dist/cx.js +6 -3
  46. package/dist/cx2.js +2 -2
  47. package/dist/cys.js +6 -3
  48. package/dist/dot.js +1 -1
  49. package/dist/gexf.js +554 -122
  50. package/dist/gexf.js.map +1 -1
  51. package/dist/gml.js +342 -85
  52. package/dist/gml.js.map +1 -1
  53. package/dist/graph-io.js +1105 -213
  54. package/dist/graph-io.js.map +1 -1
  55. package/dist/graphml.js +3 -2
  56. package/dist/graphml.js.map +1 -1
  57. package/dist/json.js +3 -2
  58. package/dist/neo4j.js +564 -157
  59. package/dist/neo4j.js.map +1 -1
  60. package/dist/obo.js +6 -3
  61. package/dist/pajek.js +1 -1
  62. package/dist/src/children.d.ts +18 -6
  63. package/dist/src/children.d.ts.map +1 -1
  64. package/dist/src/children.js +6 -3
  65. package/dist/src/children.js.map +1 -1
  66. package/dist/src/common/attributes.d.ts +29 -11
  67. package/dist/src/common/attributes.d.ts.map +1 -1
  68. package/dist/src/common/attributes.js +25 -7
  69. package/dist/src/common/attributes.js.map +1 -1
  70. package/dist/src/common/cell-budget.d.ts +9 -2
  71. package/dist/src/common/cell-budget.d.ts.map +1 -1
  72. package/dist/src/common/cell-budget.js +11 -3
  73. package/dist/src/common/cell-budget.js.map +1 -1
  74. package/dist/src/common/choose.d.ts +19 -0
  75. package/dist/src/common/choose.d.ts.map +1 -0
  76. package/dist/src/common/choose.js +72 -0
  77. package/dist/src/common/choose.js.map +1 -0
  78. package/dist/src/common/codes.d.ts +456 -66
  79. package/dist/src/common/codes.d.ts.map +1 -1
  80. package/dist/src/common/codes.js +458 -66
  81. package/dist/src/common/codes.js.map +1 -1
  82. package/dist/src/common/compare.d.ts +81 -0
  83. package/dist/src/common/compare.d.ts.map +1 -0
  84. package/dist/src/common/compare.js +394 -0
  85. package/dist/src/common/compare.js.map +1 -0
  86. package/dist/src/common/cx-export.d.ts +123 -0
  87. package/dist/src/common/cx-export.d.ts.map +1 -0
  88. package/dist/src/common/cx-export.js +334 -0
  89. package/dist/src/common/cx-export.js.map +1 -0
  90. package/dist/src/common/declared-types.d.ts +22 -2
  91. package/dist/src/common/declared-types.d.ts.map +1 -1
  92. package/dist/src/common/declared-types.js +19 -1
  93. package/dist/src/common/declared-types.js.map +1 -1
  94. package/dist/src/common/direction.d.ts +74 -50
  95. package/dist/src/common/direction.d.ts.map +1 -1
  96. package/dist/src/common/direction.js +47 -27
  97. package/dist/src/common/direction.js.map +1 -1
  98. package/dist/src/common/escape.d.ts +21 -9
  99. package/dist/src/common/escape.d.ts.map +1 -1
  100. package/dist/src/common/escape.js +33 -17
  101. package/dist/src/common/escape.js.map +1 -1
  102. package/dist/src/common/export.d.ts +144 -32
  103. package/dist/src/common/export.d.ts.map +1 -1
  104. package/dist/src/common/export.js +216 -42
  105. package/dist/src/common/export.js.map +1 -1
  106. package/dist/src/common/format.d.ts +23 -1
  107. package/dist/src/common/format.d.ts.map +1 -1
  108. package/dist/src/common/format.js +26 -1
  109. package/dist/src/common/format.js.map +1 -1
  110. package/dist/src/common/ids.d.ts +9 -2
  111. package/dist/src/common/ids.d.ts.map +1 -1
  112. package/dist/src/common/ids.js +6 -2
  113. package/dist/src/common/ids.js.map +1 -1
  114. package/dist/src/common/input.d.ts +122 -28
  115. package/dist/src/common/input.d.ts.map +1 -1
  116. package/dist/src/common/input.js +890 -124
  117. package/dist/src/common/input.js.map +1 -1
  118. package/dist/src/common/json-elements.d.ts +144 -20
  119. package/dist/src/common/json-elements.d.ts.map +1 -1
  120. package/dist/src/common/json-elements.js +868 -188
  121. package/dist/src/common/json-elements.js.map +1 -1
  122. package/dist/src/common/line-format.d.ts +90 -0
  123. package/dist/src/common/line-format.d.ts.map +1 -0
  124. package/dist/src/common/line-format.js +185 -0
  125. package/dist/src/common/line-format.js.map +1 -0
  126. package/dist/src/common/lists.d.ts +6 -1
  127. package/dist/src/common/lists.d.ts.map +1 -1
  128. package/dist/src/common/lists.js +2 -0
  129. package/dist/src/common/lists.js.map +1 -1
  130. package/dist/src/common/ontology-export.d.ts +167 -0
  131. package/dist/src/common/ontology-export.d.ts.map +1 -0
  132. package/dist/src/common/ontology-export.js +359 -0
  133. package/dist/src/common/ontology-export.js.map +1 -0
  134. package/dist/src/common/ontology.d.ts +25 -3
  135. package/dist/src/common/ontology.d.ts.map +1 -1
  136. package/dist/src/common/ontology.js +30 -9
  137. package/dist/src/common/ontology.js.map +1 -1
  138. package/dist/src/common/options.d.ts +62 -12
  139. package/dist/src/common/options.d.ts.map +1 -1
  140. package/dist/src/common/options.js +89 -11
  141. package/dist/src/common/options.js.map +1 -1
  142. package/dist/src/common/plural.d.ts +31 -0
  143. package/dist/src/common/plural.d.ts.map +1 -0
  144. package/dist/src/common/plural.js +46 -0
  145. package/dist/src/common/plural.js.map +1 -0
  146. package/dist/src/common/report.d.ts +72 -14
  147. package/dist/src/common/report.d.ts.map +1 -1
  148. package/dist/src/common/report.js +146 -22
  149. package/dist/src/common/report.js.map +1 -1
  150. package/dist/src/common/temporal.d.ts +22 -5
  151. package/dist/src/common/temporal.d.ts.map +1 -1
  152. package/dist/src/common/temporal.js +13 -2
  153. package/dist/src/common/temporal.js.map +1 -1
  154. package/dist/src/common/text.d.ts +39 -23
  155. package/dist/src/common/text.d.ts.map +1 -1
  156. package/dist/src/common/text.js +51 -21
  157. package/dist/src/common/text.js.map +1 -1
  158. package/dist/src/common/weights.d.ts +37 -4
  159. package/dist/src/common/weights.d.ts.map +1 -1
  160. package/dist/src/common/weights.js +61 -2
  161. package/dist/src/common/weights.js.map +1 -1
  162. package/dist/src/common/writer.d.ts +19 -3
  163. package/dist/src/common/writer.d.ts.map +1 -1
  164. package/dist/src/common/writer.js +30 -2
  165. package/dist/src/common/writer.js.map +1 -1
  166. package/dist/src/common/xml.d.ts +125 -9
  167. package/dist/src/common/xml.d.ts.map +1 -1
  168. package/dist/src/common/xml.js +400 -83
  169. package/dist/src/common/xml.js.map +1 -1
  170. package/dist/src/common/zip.d.ts +44 -4
  171. package/dist/src/common/zip.d.ts.map +1 -1
  172. package/dist/src/common/zip.js +134 -5
  173. package/dist/src/common/zip.js.map +1 -1
  174. package/dist/src/formats/csv/exporter.d.ts +80 -24
  175. package/dist/src/formats/csv/exporter.d.ts.map +1 -1
  176. package/dist/src/formats/csv/exporter.js +145 -32
  177. package/dist/src/formats/csv/exporter.js.map +1 -1
  178. package/dist/src/formats/csv/header.d.ts +38 -9
  179. package/dist/src/formats/csv/header.d.ts.map +1 -1
  180. package/dist/src/formats/csv/header.js +46 -10
  181. package/dist/src/formats/csv/header.js.map +1 -1
  182. package/dist/src/formats/csv/importer.d.ts +187 -37
  183. package/dist/src/formats/csv/importer.d.ts.map +1 -1
  184. package/dist/src/formats/csv/importer.js +835 -204
  185. package/dist/src/formats/csv/importer.js.map +1 -1
  186. package/dist/src/formats/csv/index.d.ts +100 -19
  187. package/dist/src/formats/csv/index.d.ts.map +1 -1
  188. package/dist/src/formats/csv/index.js +94 -21
  189. package/dist/src/formats/csv/index.js.map +1 -1
  190. package/dist/src/formats/csv/records.d.ts +95 -10
  191. package/dist/src/formats/csv/records.d.ts.map +1 -1
  192. package/dist/src/formats/csv/records.js +333 -122
  193. package/dist/src/formats/csv/records.js.map +1 -1
  194. package/dist/src/formats/csv/values.d.ts +1 -0
  195. package/dist/src/formats/csv/values.d.ts.map +1 -1
  196. package/dist/src/formats/csv/values.js +1 -0
  197. package/dist/src/formats/csv/values.js.map +1 -1
  198. package/dist/src/formats/cx/exporter.d.ts +102 -0
  199. package/dist/src/formats/cx/exporter.d.ts.map +1 -0
  200. package/dist/src/formats/cx/exporter.js +1217 -0
  201. package/dist/src/formats/cx/exporter.js.map +1 -0
  202. package/dist/src/formats/cx/importer.d.ts +79 -32
  203. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  204. package/dist/src/formats/cx/importer.js +680 -285
  205. package/dist/src/formats/cx/importer.js.map +1 -1
  206. package/dist/src/formats/cx/index.d.ts +4 -3
  207. package/dist/src/formats/cx/index.d.ts.map +1 -1
  208. package/dist/src/formats/cx/index.js +4 -3
  209. package/dist/src/formats/cx/index.js.map +1 -1
  210. package/dist/src/formats/cx2/exporter.d.ts +29 -11
  211. package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
  212. package/dist/src/formats/cx2/exporter.js +39 -268
  213. package/dist/src/formats/cx2/exporter.js.map +1 -1
  214. package/dist/src/formats/cx2/importer.d.ts +78 -28
  215. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  216. package/dist/src/formats/cx2/importer.js +226 -79
  217. package/dist/src/formats/cx2/importer.js.map +1 -1
  218. package/dist/src/formats/cx2/index.d.ts +2 -1
  219. package/dist/src/formats/cx2/index.d.ts.map +1 -1
  220. package/dist/src/formats/cx2/index.js +2 -1
  221. package/dist/src/formats/cx2/index.js.map +1 -1
  222. package/dist/src/formats/cys/constants.d.ts +66 -17
  223. package/dist/src/formats/cys/constants.d.ts.map +1 -1
  224. package/dist/src/formats/cys/constants.js +59 -18
  225. package/dist/src/formats/cys/constants.js.map +1 -1
  226. package/dist/src/formats/cys/exporter.d.ts +118 -0
  227. package/dist/src/formats/cys/exporter.d.ts.map +1 -0
  228. package/dist/src/formats/cys/exporter.js +1072 -0
  229. package/dist/src/formats/cys/exporter.js.map +1 -0
  230. package/dist/src/formats/cys/importer.d.ts +22 -8
  231. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  232. package/dist/src/formats/cys/importer.js +510 -149
  233. package/dist/src/formats/cys/importer.js.map +1 -1
  234. package/dist/src/formats/cys/index.d.ts +4 -2
  235. package/dist/src/formats/cys/index.d.ts.map +1 -1
  236. package/dist/src/formats/cys/index.js +4 -2
  237. package/dist/src/formats/cys/index.js.map +1 -1
  238. package/dist/src/formats/cys/session.d.ts +46 -7
  239. package/dist/src/formats/cys/session.d.ts.map +1 -1
  240. package/dist/src/formats/cys/session.js +98 -24
  241. package/dist/src/formats/cys/session.js.map +1 -1
  242. package/dist/src/formats/cys/tables.d.ts +9 -2
  243. package/dist/src/formats/cys/tables.d.ts.map +1 -1
  244. package/dist/src/formats/cys/tables.js +29 -7
  245. package/dist/src/formats/cys/tables.js.map +1 -1
  246. package/dist/src/formats/dot/exporter.d.ts +42 -14
  247. package/dist/src/formats/dot/exporter.d.ts.map +1 -1
  248. package/dist/src/formats/dot/exporter.js +56 -29
  249. package/dist/src/formats/dot/exporter.js.map +1 -1
  250. package/dist/src/formats/dot/importer.d.ts +91 -29
  251. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  252. package/dist/src/formats/dot/importer.js +190 -39
  253. package/dist/src/formats/dot/importer.js.map +1 -1
  254. package/dist/src/formats/dot/index.d.ts +2 -1
  255. package/dist/src/formats/dot/index.d.ts.map +1 -1
  256. package/dist/src/formats/dot/index.js +2 -1
  257. package/dist/src/formats/dot/index.js.map +1 -1
  258. package/dist/src/formats/dot/names.d.ts +44 -11
  259. package/dist/src/formats/dot/names.d.ts.map +1 -1
  260. package/dist/src/formats/dot/names.js +44 -11
  261. package/dist/src/formats/dot/names.js.map +1 -1
  262. package/dist/src/formats/dot/tokenizer.d.ts +9 -2
  263. package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
  264. package/dist/src/formats/dot/tokenizer.js +20 -5
  265. package/dist/src/formats/dot/tokenizer.js.map +1 -1
  266. package/dist/src/formats/gexf/exporter.d.ts +46 -15
  267. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  268. package/dist/src/formats/gexf/exporter.js +45 -15
  269. package/dist/src/formats/gexf/exporter.js.map +1 -1
  270. package/dist/src/formats/gexf/importer.d.ts +87 -23
  271. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  272. package/dist/src/formats/gexf/importer.js +471 -90
  273. package/dist/src/formats/gexf/importer.js.map +1 -1
  274. package/dist/src/formats/gexf/index.d.ts +84 -21
  275. package/dist/src/formats/gexf/index.d.ts.map +1 -1
  276. package/dist/src/formats/gexf/index.js +80 -23
  277. package/dist/src/formats/gexf/index.js.map +1 -1
  278. package/dist/src/formats/gexf/schema.d.ts +67 -15
  279. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  280. package/dist/src/formats/gexf/schema.js +59 -13
  281. package/dist/src/formats/gexf/schema.js.map +1 -1
  282. package/dist/src/formats/gml/exporter.d.ts +69 -21
  283. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  284. package/dist/src/formats/gml/exporter.js +74 -29
  285. package/dist/src/formats/gml/exporter.js.map +1 -1
  286. package/dist/src/formats/gml/importer.d.ts +116 -25
  287. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  288. package/dist/src/formats/gml/importer.js +290 -61
  289. package/dist/src/formats/gml/importer.js.map +1 -1
  290. package/dist/src/formats/gml/index.d.ts +87 -24
  291. package/dist/src/formats/gml/index.d.ts.map +1 -1
  292. package/dist/src/formats/gml/index.js +79 -26
  293. package/dist/src/formats/gml/index.js.map +1 -1
  294. package/dist/src/formats/gml/syntax.d.ts +67 -18
  295. package/dist/src/formats/gml/syntax.d.ts.map +1 -1
  296. package/dist/src/formats/gml/syntax.js +108 -26
  297. package/dist/src/formats/gml/syntax.js.map +1 -1
  298. package/dist/src/formats/graphml/constants.d.ts +174 -44
  299. package/dist/src/formats/graphml/constants.d.ts.map +1 -1
  300. package/dist/src/formats/graphml/constants.js +165 -44
  301. package/dist/src/formats/graphml/constants.js.map +1 -1
  302. package/dist/src/formats/graphml/exporter.d.ts +17 -9
  303. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  304. package/dist/src/formats/graphml/exporter.js +33 -12
  305. package/dist/src/formats/graphml/exporter.js.map +1 -1
  306. package/dist/src/formats/graphml/importer.d.ts +19 -7
  307. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  308. package/dist/src/formats/graphml/importer.js +466 -39
  309. package/dist/src/formats/graphml/importer.js.map +1 -1
  310. package/dist/src/formats/graphml/index.d.ts +2 -1
  311. package/dist/src/formats/graphml/index.d.ts.map +1 -1
  312. package/dist/src/formats/graphml/index.js +2 -1
  313. package/dist/src/formats/graphml/index.js.map +1 -1
  314. package/dist/src/formats/graphml/tree.d.ts +6 -2
  315. package/dist/src/formats/graphml/tree.d.ts.map +1 -1
  316. package/dist/src/formats/graphml/tree.js +6 -2
  317. package/dist/src/formats/graphml/tree.js.map +1 -1
  318. package/dist/src/formats/graphml/yfiles.d.ts +8 -3
  319. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  320. package/dist/src/formats/graphml/yfiles.js +36 -15
  321. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  322. package/dist/src/formats/json/dialect.d.ts +88 -24
  323. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  324. package/dist/src/formats/json/dialect.js +109 -19
  325. package/dist/src/formats/json/dialect.js.map +1 -1
  326. package/dist/src/formats/json/exporter.d.ts +134 -22
  327. package/dist/src/formats/json/exporter.d.ts.map +1 -1
  328. package/dist/src/formats/json/exporter.js +135 -54
  329. package/dist/src/formats/json/exporter.js.map +1 -1
  330. package/dist/src/formats/json/importer.d.ts +173 -52
  331. package/dist/src/formats/json/importer.d.ts.map +1 -1
  332. package/dist/src/formats/json/importer.js +899 -220
  333. package/dist/src/formats/json/importer.js.map +1 -1
  334. package/dist/src/formats/json/index.d.ts +3 -2
  335. package/dist/src/formats/json/index.d.ts.map +1 -1
  336. package/dist/src/formats/json/index.js +3 -2
  337. package/dist/src/formats/json/index.js.map +1 -1
  338. package/dist/src/formats/json/obographs-export.d.ts +68 -0
  339. package/dist/src/formats/json/obographs-export.d.ts.map +1 -0
  340. package/dist/src/formats/json/obographs-export.js +941 -0
  341. package/dist/src/formats/json/obographs-export.js.map +1 -0
  342. package/dist/src/formats/json/obographs.d.ts +26 -0
  343. package/dist/src/formats/json/obographs.d.ts.map +1 -1
  344. package/dist/src/formats/json/obographs.js +297 -80
  345. package/dist/src/formats/json/obographs.js.map +1 -1
  346. package/dist/src/formats/neo4j/exporter.d.ts +109 -21
  347. package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
  348. package/dist/src/formats/neo4j/exporter.js +238 -85
  349. package/dist/src/formats/neo4j/exporter.js.map +1 -1
  350. package/dist/src/formats/neo4j/header.d.ts +17 -4
  351. package/dist/src/formats/neo4j/header.d.ts.map +1 -1
  352. package/dist/src/formats/neo4j/header.js +36 -4
  353. package/dist/src/formats/neo4j/header.js.map +1 -1
  354. package/dist/src/formats/neo4j/importer.d.ts +107 -27
  355. package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
  356. package/dist/src/formats/neo4j/importer.js +415 -63
  357. package/dist/src/formats/neo4j/importer.js.map +1 -1
  358. package/dist/src/formats/neo4j/index.d.ts +73 -23
  359. package/dist/src/formats/neo4j/index.d.ts.map +1 -1
  360. package/dist/src/formats/neo4j/index.js +65 -25
  361. package/dist/src/formats/neo4j/index.js.map +1 -1
  362. package/dist/src/formats/obo/exporter.d.ts +150 -0
  363. package/dist/src/formats/obo/exporter.d.ts.map +1 -0
  364. package/dist/src/formats/obo/exporter.js +1736 -0
  365. package/dist/src/formats/obo/exporter.js.map +1 -0
  366. package/dist/src/formats/obo/importer.d.ts +95 -19
  367. package/dist/src/formats/obo/importer.d.ts.map +1 -1
  368. package/dist/src/formats/obo/importer.js +475 -104
  369. package/dist/src/formats/obo/importer.js.map +1 -1
  370. package/dist/src/formats/obo/index.d.ts +6 -3
  371. package/dist/src/formats/obo/index.d.ts.map +1 -1
  372. package/dist/src/formats/obo/index.js +6 -3
  373. package/dist/src/formats/obo/index.js.map +1 -1
  374. package/dist/src/formats/obo/syntax.d.ts +108 -4
  375. package/dist/src/formats/obo/syntax.d.ts.map +1 -1
  376. package/dist/src/formats/obo/syntax.js +211 -34
  377. package/dist/src/formats/obo/syntax.js.map +1 -1
  378. package/dist/src/formats/pajek/exporter.d.ts +54 -16
  379. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  380. package/dist/src/formats/pajek/exporter.js +66 -34
  381. package/dist/src/formats/pajek/exporter.js.map +1 -1
  382. package/dist/src/formats/pajek/importer.d.ts +84 -22
  383. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  384. package/dist/src/formats/pajek/importer.js +303 -83
  385. package/dist/src/formats/pajek/importer.js.map +1 -1
  386. package/dist/src/formats/pajek/index.d.ts +2 -1
  387. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  388. package/dist/src/formats/pajek/index.js +2 -1
  389. package/dist/src/formats/pajek/index.js.map +1 -1
  390. package/dist/src/formats/pajek/syntax.d.ts +77 -14
  391. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  392. package/dist/src/formats/pajek/syntax.js +183 -51
  393. package/dist/src/formats/pajek/syntax.js.map +1 -1
  394. package/dist/src/formats/xgmml/columns.d.ts +1 -0
  395. package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
  396. package/dist/src/formats/xgmml/columns.js +4 -0
  397. package/dist/src/formats/xgmml/columns.js.map +1 -1
  398. package/dist/src/formats/xgmml/constants.d.ts +186 -56
  399. package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
  400. package/dist/src/formats/xgmml/constants.js +181 -57
  401. package/dist/src/formats/xgmml/constants.js.map +1 -1
  402. package/dist/src/formats/xgmml/document.d.ts +65 -11
  403. package/dist/src/formats/xgmml/document.d.ts.map +1 -1
  404. package/dist/src/formats/xgmml/document.js +157 -28
  405. package/dist/src/formats/xgmml/document.js.map +1 -1
  406. package/dist/src/formats/xgmml/emit.d.ts +61 -3
  407. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  408. package/dist/src/formats/xgmml/emit.js +129 -26
  409. package/dist/src/formats/xgmml/emit.js.map +1 -1
  410. package/dist/src/formats/xgmml/exporter.d.ts +13 -6
  411. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
  412. package/dist/src/formats/xgmml/exporter.js +20 -21
  413. package/dist/src/formats/xgmml/exporter.js.map +1 -1
  414. package/dist/src/formats/xgmml/importer.d.ts +33 -12
  415. package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
  416. package/dist/src/formats/xgmml/importer.js +35 -72
  417. package/dist/src/formats/xgmml/importer.js.map +1 -1
  418. package/dist/src/formats/xgmml/index.d.ts +1 -0
  419. package/dist/src/formats/xgmml/index.d.ts.map +1 -1
  420. package/dist/src/formats/xgmml/index.js +1 -0
  421. package/dist/src/formats/xgmml/index.js.map +1 -1
  422. package/dist/src/formats/xgmml/values.d.ts +8 -1
  423. package/dist/src/formats/xgmml/values.d.ts.map +1 -1
  424. package/dist/src/formats/xgmml/values.js +7 -2
  425. package/dist/src/formats/xgmml/values.js.map +1 -1
  426. package/dist/src/index.d.ts +23 -18
  427. package/dist/src/index.d.ts.map +1 -1
  428. package/dist/src/index.js +28 -16
  429. package/dist/src/index.js.map +1 -1
  430. package/dist/src/registry.d.ts +478 -92
  431. package/dist/src/registry.d.ts.map +1 -1
  432. package/dist/src/registry.js +807 -88
  433. package/dist/src/registry.js.map +1 -1
  434. package/dist/src/sniff.d.ts +61 -19
  435. package/dist/src/sniff.d.ts.map +1 -1
  436. package/dist/src/sniff.js +121 -29
  437. package/dist/src/sniff.js.map +1 -1
  438. package/dist/src/types.d.ts +362 -112
  439. package/dist/src/types.d.ts.map +1 -1
  440. package/dist/src/types.js +28 -7
  441. package/dist/src/types.js.map +1 -1
  442. package/dist/xgmml.js +2 -2
  443. package/docs/samples/README.md +25 -0
  444. package/docs/samples/got-edges.csv +353 -0
  445. package/docs/samples/got-network.graphml +1384 -0
  446. package/docs/samples/got-nodes.csv +108 -0
  447. package/docs/samples/got.cx +930 -0
  448. package/docs/samples/got.cx2 +465 -0
  449. package/docs/samples/got.gexf +471 -0
  450. package/docs/samples/got.gml +2650 -0
  451. package/docs/samples/got.json +2546 -0
  452. package/docs/samples/got.net +461 -0
  453. package/docs/samples/movies-nodes.csv +9 -0
  454. package/docs/samples/movies-rels.csv +8 -0
  455. package/docs/samples/networks.cys +0 -0
  456. package/docs/samples/proteins.xgmml +9 -0
  457. package/docs/samples/teams.gv +24 -0
  458. package/docs/samples/vehicles.obo +25 -0
  459. package/package.json +9 -4
  460. package/src/children.ts +18 -6
  461. package/src/common/attributes.ts +29 -11
  462. package/src/common/cell-budget.ts +11 -3
  463. package/src/common/choose.ts +89 -0
  464. package/src/common/codes.ts +490 -66
  465. package/src/common/compare.ts +472 -0
  466. package/src/common/cx-export.ts +432 -0
  467. package/src/common/declared-types.ts +38 -4
  468. package/src/common/direction.ts +78 -51
  469. package/src/common/escape.ts +33 -17
  470. package/src/common/export.ts +284 -47
  471. package/src/common/format.ts +30 -1
  472. package/src/common/ids.ts +14 -3
  473. package/src/common/input.ts +1057 -134
  474. package/src/common/json-elements.ts +1034 -198
  475. package/src/common/line-format.ts +249 -0
  476. package/src/common/lists.ts +6 -1
  477. package/src/common/ontology-export.ts +461 -0
  478. package/src/common/ontology.ts +31 -9
  479. package/src/common/options.ts +110 -15
  480. package/src/common/plural.ts +49 -0
  481. package/src/common/report.ts +168 -25
  482. package/src/common/temporal.ts +22 -5
  483. package/src/common/text.ts +62 -23
  484. package/src/common/weights.ts +74 -4
  485. package/src/common/writer.ts +37 -3
  486. package/src/common/xml.ts +477 -88
  487. package/src/common/zip.ts +169 -7
  488. package/src/formats/csv/exporter.ts +201 -46
  489. package/src/formats/csv/header.ts +50 -11
  490. package/src/formats/csv/importer.ts +1133 -245
  491. package/src/formats/csv/index.ts +106 -19
  492. package/src/formats/csv/records.ts +396 -122
  493. package/src/formats/csv/values.ts +1 -0
  494. package/src/formats/cx/exporter.ts +1483 -0
  495. package/src/formats/cx/importer.ts +888 -300
  496. package/src/formats/cx/index.ts +4 -3
  497. package/src/formats/cx2/exporter.ts +61 -338
  498. package/src/formats/cx2/importer.ts +317 -86
  499. package/src/formats/cx2/index.ts +2 -1
  500. package/src/formats/cys/constants.ts +62 -17
  501. package/src/formats/cys/exporter.ts +1368 -0
  502. package/src/formats/cys/importer.ts +659 -157
  503. package/src/formats/cys/index.ts +4 -2
  504. package/src/formats/cys/session.ts +139 -31
  505. package/src/formats/cys/tables.ts +47 -9
  506. package/src/formats/dot/exporter.ts +83 -37
  507. package/src/formats/dot/importer.ts +248 -54
  508. package/src/formats/dot/index.ts +2 -1
  509. package/src/formats/dot/names.ts +44 -11
  510. package/src/formats/dot/tokenizer.ts +25 -6
  511. package/src/formats/gexf/exporter.ts +57 -18
  512. package/src/formats/gexf/importer.ts +636 -105
  513. package/src/formats/gexf/index.ts +90 -21
  514. package/src/formats/gexf/schema.ts +67 -15
  515. package/src/formats/gml/exporter.ts +90 -36
  516. package/src/formats/gml/importer.ts +388 -67
  517. package/src/formats/gml/index.ts +85 -24
  518. package/src/formats/gml/syntax.ts +111 -26
  519. package/src/formats/graphml/constants.ts +178 -44
  520. package/src/formats/graphml/exporter.ts +52 -18
  521. package/src/formats/graphml/importer.ts +640 -60
  522. package/src/formats/graphml/index.ts +2 -1
  523. package/src/formats/graphml/tree.ts +6 -2
  524. package/src/formats/graphml/yfiles.ts +37 -15
  525. package/src/formats/json/dialect.ts +128 -29
  526. package/src/formats/json/exporter.ts +205 -68
  527. package/src/formats/json/importer.ts +1163 -253
  528. package/src/formats/json/index.ts +3 -1
  529. package/src/formats/json/obographs-export.ts +1197 -0
  530. package/src/formats/json/obographs.ts +353 -92
  531. package/src/formats/neo4j/exporter.ts +320 -101
  532. package/src/formats/neo4j/header.ts +44 -6
  533. package/src/formats/neo4j/importer.ts +512 -73
  534. package/src/formats/neo4j/index.ts +75 -23
  535. package/src/formats/obo/exporter.ts +2210 -0
  536. package/src/formats/obo/importer.ts +622 -109
  537. package/src/formats/obo/index.ts +6 -3
  538. package/src/formats/obo/syntax.ts +232 -37
  539. package/src/formats/pajek/exporter.ts +89 -41
  540. package/src/formats/pajek/importer.ts +407 -93
  541. package/src/formats/pajek/index.ts +2 -1
  542. package/src/formats/pajek/syntax.ts +213 -52
  543. package/src/formats/xgmml/columns.ts +10 -0
  544. package/src/formats/xgmml/constants.ts +183 -56
  545. package/src/formats/xgmml/document.ts +212 -34
  546. package/src/formats/xgmml/emit.ts +175 -34
  547. package/src/formats/xgmml/exporter.ts +35 -27
  548. package/src/formats/xgmml/importer.ts +64 -86
  549. package/src/formats/xgmml/index.ts +1 -0
  550. package/src/formats/xgmml/values.ts +11 -3
  551. package/src/index.ts +81 -11
  552. package/src/registry.ts +1121 -135
  553. package/src/sniff.ts +163 -32
  554. package/src/types.ts +385 -114
  555. package/dist/chunks/escape-B-tkk_Cl.js.map +0 -1
  556. package/dist/chunks/export-Bh60Dv-n.js +0 -582
  557. package/dist/chunks/export-Bh60Dv-n.js.map +0 -1
  558. package/dist/chunks/exporter-BGrsWamJ.js.map +0 -1
  559. package/dist/chunks/exporter-DIeGJXAZ.js.map +0 -1
  560. package/dist/chunks/importer-BWY2FFc5.js.map +0 -1
  561. package/dist/chunks/importer-DD-xv9_Y.js +0 -1471
  562. package/dist/chunks/importer-DD-xv9_Y.js.map +0 -1
  563. package/dist/chunks/importer-DET1tg6s.js.map +0 -1
  564. package/dist/chunks/importer-DEcKhsmQ.js +0 -1614
  565. package/dist/chunks/importer-DEcKhsmQ.js.map +0 -1
  566. package/dist/chunks/importer-DIrbbnAf.js.map +0 -1
  567. package/dist/chunks/importer-D_e7e7LX.js.map +0 -1
  568. package/dist/chunks/importer-eUREhBGj.js.map +0 -1
  569. package/dist/chunks/importer-vi3bSdtw.js.map +0 -1
  570. package/dist/chunks/importer-zGLo8Dg_.js.map +0 -1
  571. package/dist/chunks/json-elements-DDS8N2Dd.js +0 -779
  572. package/dist/chunks/json-elements-DDS8N2Dd.js.map +0 -1
  573. package/dist/chunks/ontology-BnrJ4I98.js +0 -113
  574. package/dist/chunks/ontology-BnrJ4I98.js.map +0 -1
  575. package/dist/chunks/records-dbRkxwaq.js.map +0 -1
  576. package/dist/chunks/report-B1z4WT9e.js +0 -2372
  577. package/dist/chunks/report-B1z4WT9e.js.map +0 -1
  578. package/dist/chunks/text-Dr0Ifpag.js.map +0 -1
  579. package/dist/chunks/weights-Dzba96G3.js +0 -176
  580. package/dist/chunks/weights-Dzba96G3.js.map +0 -1
  581. 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
- /** Issue code: a quoted field is never closed; the import aborts (everything after it would be one cell). */
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
- /** Issue code: a closing quote is followed by text other than a delimiter or a line break; the import aborts. */
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
- /** The delimiters tried, in priority order, when none is given. */
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), honouring quotes; for
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 rows = [];
90
- const delimiterCode = delimiter.charCodeAt(0);
91
- const quoteCode = quote.charCodeAt(0);
92
- let cells = [];
93
- let state = START;
94
- let segment = 0;
95
- let field = "";
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
- if (state === CLOSING) {
107
- if (c === quoteCode) {
108
- field += quote;
109
- segment = i + 1;
110
- state = QUOTED;
111
- continue;
112
- }
113
- if (strictQuotes && c !== delimiterCode && c !== LF && c !== CR) {
114
- return null;
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
- state = AFTER_QUOTED;
117
- segment = i;
157
+ return i + 1;
118
158
  }
119
- if (c === delimiterCode || c === LF || c === CR) {
120
- if (state === UNQUOTED || state === AFTER_QUOTED) {
121
- field += text.slice(segment, i);
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 (state === START) {
144
- if (c === quoteCode) {
145
- state = QUOTED;
146
- segment = i + 1;
147
- }
148
- else {
149
- state = UNQUOTED;
150
- segment = i;
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
- if (rows.length < maxRows && (state !== START || cells.length > 0)) {
155
- if (state === UNQUOTED || state === AFTER_QUOTED || state === QUOTED) {
156
- field += text.slice(segment, n);
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
- cells.push(field);
159
- rows.push(cells);
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 && comments.includes(text[at])) {
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 + 1;
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 (ties broken by the higher field count); a
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 && (delta < bestDelta || (delta === bestDelta && average > bestAverage))) {
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, `line ${line}: text after the closing quote of a quoted field`, {
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 if (c === CR) {
377
- breaks++;
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 body = stripLeadingComments(text.slice(0, PREVIEW_CHARS), this.syntax.comments ?? []);
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 += chunk.slice(this.segment, i);
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 += chunk.slice(this.segment, q);
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 += this.quoteText;
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 (c !== delimiterCode && c !== LF && c !== CR) {
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 (c === delimiterCode || c === LF || c === CR) {
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 += chunk.slice(this.segment, i);
653
+ this.field = this.grow(this.field, chunk.slice(this.segment, i));
524
654
  }
525
- if (c === delimiterCode) {
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
- const blank = this.state === START && this.count === 0;
534
- if (!blank) {
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 += chunk.slice(this.segment, n);
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 += chunk.slice(this.segment, n);
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.push();
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
- let { line, lastWasCr } = this;
617
- for (let i = from; i < to; i++) {
618
- const c = chunk.charCodeAt(i);
619
- if (c === LF) {
620
- if (!lastWasCr) {
621
- line++;
622
- }
623
- lastWasCr = false;
624
- }
625
- else if (c === CR) {
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
- lastWasCr = true;
772
+ lastCr = cr;
773
+ cr = run.indexOf("\r", cr + 1);
628
774
  }
629
775
  else {
630
- lastWasCr = false;
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 = 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 and whitespace-only single-cell lines are skipped.
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
- }, { signal: options.signal, onProgress: options.onProgress, encoding: options.encoding });
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 (count === 1 && !inner.quoted[0] && inner.cells[0].trim().length === 0) {
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