@graphty/graph-io 0.3.43 → 0.3.45

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 (674) hide show
  1. package/dist/chunks/approximations-DJMHdDvv.js +40 -0
  2. package/dist/chunks/approximations-DJMHdDvv.js.map +1 -0
  3. package/dist/chunks/block-CPCHkX42.js +2777 -0
  4. package/dist/chunks/block-CPCHkX42.js.map +1 -0
  5. package/dist/chunks/{choose-DvpbdRuz.js → choose--jM0yYCo.js} +3 -2
  6. package/dist/chunks/{choose-DvpbdRuz.js.map → choose--jM0yYCo.js.map} +1 -1
  7. package/dist/chunks/{constants-fT3E8JYY.js → constants-BKwqelYD.js} +6 -2
  8. package/dist/chunks/constants-BKwqelYD.js.map +1 -0
  9. package/dist/chunks/convert-BcQ8_jMo.js +59 -0
  10. package/dist/chunks/convert-BcQ8_jMo.js.map +1 -0
  11. package/dist/chunks/emit-DZy6JgdA.js +3456 -0
  12. package/dist/chunks/emit-DZy6JgdA.js.map +1 -0
  13. package/dist/chunks/{escape-B62ZGM_a.js → escape-CgzxiYPg.js} +44 -21
  14. package/dist/chunks/escape-CgzxiYPg.js.map +1 -0
  15. package/dist/chunks/{export-rKLeGQMo.js → export-BvqAXCKh.js} +196 -792
  16. package/dist/chunks/export-BvqAXCKh.js.map +1 -0
  17. package/dist/chunks/{exporter-yLxKBvLE.js → exporter--Mk9gXCJ.js} +4 -3
  18. package/dist/chunks/{exporter-yLxKBvLE.js.map → exporter--Mk9gXCJ.js.map} +1 -1
  19. package/dist/chunks/{exporter-RVtXVetw.js → exporter-C-9cgZKa.js} +1805 -287
  20. package/dist/chunks/exporter-C-9cgZKa.js.map +1 -0
  21. package/dist/chunks/{exporter-8hLNemFk.js → exporter-DFqJhBnj.js} +133 -74
  22. package/dist/chunks/exporter-DFqJhBnj.js.map +1 -0
  23. package/dist/chunks/{exporter-BWwEuOPT.js → exporter-DteVeJki.js} +22 -12
  24. package/dist/chunks/exporter-DteVeJki.js.map +1 -0
  25. package/dist/chunks/format-BpQBx8MZ.js +676 -0
  26. package/dist/chunks/format-BpQBx8MZ.js.map +1 -0
  27. package/dist/chunks/generic-BGO71QBv.js +1347 -0
  28. package/dist/chunks/generic-BGO71QBv.js.map +1 -0
  29. package/dist/chunks/{importer-C98dpSH4.js → importer-B-9Rc1zO.js} +141 -82
  30. package/dist/chunks/importer-B-9Rc1zO.js.map +1 -0
  31. package/dist/chunks/{importer-D794XUTe.js → importer-BVVR740x.js} +31 -8
  32. package/dist/chunks/importer-BVVR740x.js.map +1 -0
  33. package/dist/chunks/{importer-WrGRZb0N.js → importer-C0AjA3Ax.js} +449 -102
  34. package/dist/chunks/importer-C0AjA3Ax.js.map +1 -0
  35. package/dist/chunks/{importer-BbNb7eNg.js → importer-C7pvJe1L.js} +1398 -129
  36. package/dist/chunks/importer-C7pvJe1L.js.map +1 -0
  37. package/dist/chunks/{importer-xZ-3suY1.js → importer-ClwoVx3O.js} +791 -135
  38. package/dist/chunks/importer-ClwoVx3O.js.map +1 -0
  39. package/dist/chunks/{importer-Ht7LNg8L.js → importer-D0sC_6bO.js} +116 -296
  40. package/dist/chunks/importer-D0sC_6bO.js.map +1 -0
  41. package/dist/chunks/{importer-Dz7tI8Sa.js → importer-EHQk1jbM.js} +617 -115
  42. package/dist/chunks/importer-EHQk1jbM.js.map +1 -0
  43. package/dist/chunks/{json-elements-DKSqpNW1.js → json-elements-DJZRZ6jd.js} +123 -32
  44. package/dist/chunks/json-elements-DJZRZ6jd.js.map +1 -0
  45. package/dist/chunks/lexicon-WMsNddyU.js +509 -0
  46. package/dist/chunks/lexicon-WMsNddyU.js.map +1 -0
  47. package/dist/chunks/{ontology-export-CtRXjg_i.js → ontology-export-G4MqRdux.js} +3 -2
  48. package/dist/chunks/{ontology-export-CtRXjg_i.js.map → ontology-export-G4MqRdux.js.map} +1 -1
  49. package/dist/chunks/{records-Cu4bxYOm.js → records-CiaWZrFH.js} +2 -2
  50. package/dist/chunks/{records-Cu4bxYOm.js.map → records-CiaWZrFH.js.map} +1 -1
  51. package/dist/chunks/styles-DvoFBKCK.js +690 -0
  52. package/dist/chunks/styles-DvoFBKCK.js.map +1 -0
  53. package/dist/chunks/styles-yed-Cz9rLBCP.js +842 -0
  54. package/dist/chunks/styles-yed-Cz9rLBCP.js.map +1 -0
  55. package/dist/chunks/styles-zNTmz5R7.js +2102 -0
  56. package/dist/chunks/styles-zNTmz5R7.js.map +1 -0
  57. package/dist/chunks/{text-DHOJXnED.js → text-CzJNFOS9.js} +2 -2
  58. package/dist/chunks/{text-DHOJXnED.js.map → text-CzJNFOS9.js.map} +1 -1
  59. package/dist/chunks/units-XMZFIFe1.js +19 -0
  60. package/dist/chunks/units-XMZFIFe1.js.map +1 -0
  61. package/dist/chunks/writer-gQ8kx99H.js +448 -0
  62. package/dist/chunks/writer-gQ8kx99H.js.map +1 -0
  63. package/dist/csv.js +5 -4
  64. package/dist/csv.js.map +1 -1
  65. package/dist/cx.js +1 -1
  66. package/dist/cx2.js +2 -2
  67. package/dist/cys.js +1 -1
  68. package/dist/dot.js +5 -2
  69. package/dist/dot.js.map +1 -1
  70. package/dist/gexf.js +292 -412
  71. package/dist/gexf.js.map +1 -1
  72. package/dist/gml.js +927 -74
  73. package/dist/gml.js.map +1 -1
  74. package/dist/graph-io.js +351 -236
  75. package/dist/graph-io.js.map +1 -1
  76. package/dist/graphml.js +4 -2
  77. package/dist/graphml.js.map +1 -1
  78. package/dist/json.js +1 -1
  79. package/dist/neo4j.js +4 -3
  80. package/dist/neo4j.js.map +1 -1
  81. package/dist/obo.js +1 -1
  82. package/dist/pajek.js +4 -2
  83. package/dist/positions.d.ts +1 -0
  84. package/dist/positions.js +427 -0
  85. package/dist/positions.js.map +1 -0
  86. package/dist/src/common/codes.d.ts +6 -0
  87. package/dist/src/common/codes.d.ts.map +1 -1
  88. package/dist/src/common/codes.js +6 -0
  89. package/dist/src/common/codes.js.map +1 -1
  90. package/dist/src/common/escape.d.ts.map +1 -1
  91. package/dist/src/common/escape.js +4 -2
  92. package/dist/src/common/escape.js.map +1 -1
  93. package/dist/src/common/export.d.ts +10 -0
  94. package/dist/src/common/export.d.ts.map +1 -1
  95. package/dist/src/common/export.js +123 -100
  96. package/dist/src/common/export.js.map +1 -1
  97. package/dist/src/common/input.d.ts.map +1 -1
  98. package/dist/src/common/input.js +8 -1
  99. package/dist/src/common/input.js.map +1 -1
  100. package/dist/src/common/json-elements.d.ts +12 -9
  101. package/dist/src/common/json-elements.d.ts.map +1 -1
  102. package/dist/src/common/json-elements.js +160 -37
  103. package/dist/src/common/json-elements.js.map +1 -1
  104. package/dist/src/common/notes.d.ts +42 -0
  105. package/dist/src/common/notes.d.ts.map +1 -0
  106. package/dist/src/common/notes.js +72 -0
  107. package/dist/src/common/notes.js.map +1 -0
  108. package/dist/src/common/report.d.ts +18 -0
  109. package/dist/src/common/report.d.ts.map +1 -1
  110. package/dist/src/common/report.js +36 -1
  111. package/dist/src/common/report.js.map +1 -1
  112. package/dist/src/common/units.d.ts +24 -0
  113. package/dist/src/common/units.d.ts.map +1 -0
  114. package/dist/src/common/units.js +26 -0
  115. package/dist/src/common/units.js.map +1 -0
  116. package/dist/src/common/xml.d.ts +18 -0
  117. package/dist/src/common/xml.d.ts.map +1 -1
  118. package/dist/src/common/xml.js +42 -5
  119. package/dist/src/common/xml.js.map +1 -1
  120. package/dist/src/formats/cx/exporter.d.ts +6 -0
  121. package/dist/src/formats/cx/exporter.d.ts.map +1 -1
  122. package/dist/src/formats/cx/exporter.js +71 -8
  123. package/dist/src/formats/cx/exporter.js.map +1 -1
  124. package/dist/src/formats/cx/importer.d.ts +5 -2
  125. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  126. package/dist/src/formats/cx/importer.js +102 -72
  127. package/dist/src/formats/cx/importer.js.map +1 -1
  128. package/dist/src/formats/cx/styles.d.ts +102 -0
  129. package/dist/src/formats/cx/styles.d.ts.map +1 -0
  130. package/dist/src/formats/cx/styles.js +225 -0
  131. package/dist/src/formats/cx/styles.js.map +1 -0
  132. package/dist/src/formats/cx2/exporter.d.ts +5 -0
  133. package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
  134. package/dist/src/formats/cx2/exporter.js +181 -71
  135. package/dist/src/formats/cx2/exporter.js.map +1 -1
  136. package/dist/src/formats/cx2/importer.d.ts +4 -1
  137. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  138. package/dist/src/formats/cx2/importer.js +19 -1
  139. package/dist/src/formats/cx2/importer.js.map +1 -1
  140. package/dist/src/formats/cx2/styles.d.ts +18 -0
  141. package/dist/src/formats/cx2/styles.d.ts.map +1 -0
  142. package/dist/src/formats/cx2/styles.js +24 -0
  143. package/dist/src/formats/cx2/styles.js.map +1 -0
  144. package/dist/src/formats/cys/constants.d.ts +2 -0
  145. package/dist/src/formats/cys/constants.d.ts.map +1 -1
  146. package/dist/src/formats/cys/constants.js +2 -0
  147. package/dist/src/formats/cys/constants.js.map +1 -1
  148. package/dist/src/formats/cys/exporter.d.ts +6 -2
  149. package/dist/src/formats/cys/exporter.d.ts.map +1 -1
  150. package/dist/src/formats/cys/exporter.js +215 -53
  151. package/dist/src/formats/cys/exporter.js.map +1 -1
  152. package/dist/src/formats/cys/importer.d.ts +2 -1
  153. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  154. package/dist/src/formats/cys/importer.js +119 -6
  155. package/dist/src/formats/cys/importer.js.map +1 -1
  156. package/dist/src/formats/cys/session.d.ts +2 -0
  157. package/dist/src/formats/cys/session.d.ts.map +1 -1
  158. package/dist/src/formats/cys/session.js +5 -0
  159. package/dist/src/formats/cys/session.js.map +1 -1
  160. package/dist/src/formats/cys/styles.d.ts +38 -0
  161. package/dist/src/formats/cys/styles.d.ts.map +1 -0
  162. package/dist/src/formats/cys/styles.js +213 -0
  163. package/dist/src/formats/cys/styles.js.map +1 -0
  164. package/dist/src/formats/cys/tables.d.ts +8 -3
  165. package/dist/src/formats/cys/tables.d.ts.map +1 -1
  166. package/dist/src/formats/cys/tables.js +88 -34
  167. package/dist/src/formats/cys/tables.js.map +1 -1
  168. package/dist/src/formats/dot/exporter.d.ts +2 -0
  169. package/dist/src/formats/dot/exporter.d.ts.map +1 -1
  170. package/dist/src/formats/dot/exporter.js +195 -81
  171. package/dist/src/formats/dot/exporter.js.map +1 -1
  172. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  173. package/dist/src/formats/dot/importer.js +100 -20
  174. package/dist/src/formats/dot/importer.js.map +1 -1
  175. package/dist/src/formats/dot/index.d.ts +1 -0
  176. package/dist/src/formats/dot/index.d.ts.map +1 -1
  177. package/dist/src/formats/dot/index.js +1 -0
  178. package/dist/src/formats/dot/index.js.map +1 -1
  179. package/dist/src/formats/dot/positions.d.ts +14 -0
  180. package/dist/src/formats/dot/positions.d.ts.map +1 -0
  181. package/dist/src/formats/dot/positions.js +70 -0
  182. package/dist/src/formats/dot/positions.js.map +1 -0
  183. package/dist/src/formats/dot/styles.d.ts +82 -0
  184. package/dist/src/formats/dot/styles.d.ts.map +1 -0
  185. package/dist/src/formats/dot/styles.js +1496 -0
  186. package/dist/src/formats/dot/styles.js.map +1 -0
  187. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  188. package/dist/src/formats/gexf/exporter.js +20 -5
  189. package/dist/src/formats/gexf/exporter.js.map +1 -1
  190. package/dist/src/formats/gexf/importer.d.ts +8 -1
  191. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  192. package/dist/src/formats/gexf/importer.js +251 -131
  193. package/dist/src/formats/gexf/importer.js.map +1 -1
  194. package/dist/src/formats/gexf/index.d.ts +8 -0
  195. package/dist/src/formats/gexf/index.d.ts.map +1 -1
  196. package/dist/src/formats/gexf/index.js +10 -2
  197. package/dist/src/formats/gexf/index.js.map +1 -1
  198. package/dist/src/formats/gexf/schema.d.ts +5 -0
  199. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  200. package/dist/src/formats/gexf/schema.js +5 -0
  201. package/dist/src/formats/gexf/schema.js.map +1 -1
  202. package/dist/src/formats/gexf/styles.d.ts +74 -0
  203. package/dist/src/formats/gexf/styles.d.ts.map +1 -0
  204. package/dist/src/formats/gexf/styles.js +604 -0
  205. package/dist/src/formats/gexf/styles.js.map +1 -0
  206. package/dist/src/formats/gml/exporter.d.ts +1 -5
  207. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  208. package/dist/src/formats/gml/exporter.js +19 -8
  209. package/dist/src/formats/gml/exporter.js.map +1 -1
  210. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  211. package/dist/src/formats/gml/importer.js +4 -0
  212. package/dist/src/formats/gml/importer.js.map +1 -1
  213. package/dist/src/formats/gml/index.d.ts +2 -1
  214. package/dist/src/formats/gml/index.d.ts.map +1 -1
  215. package/dist/src/formats/gml/index.js +2 -1
  216. package/dist/src/formats/gml/index.js.map +1 -1
  217. package/dist/src/formats/gml/positions.d.ts +14 -0
  218. package/dist/src/formats/gml/positions.d.ts.map +1 -0
  219. package/dist/src/formats/gml/positions.js +46 -0
  220. package/dist/src/formats/gml/positions.js.map +1 -0
  221. package/dist/src/formats/gml/styles.d.ts +59 -0
  222. package/dist/src/formats/gml/styles.d.ts.map +1 -0
  223. package/dist/src/formats/gml/styles.js +1056 -0
  224. package/dist/src/formats/gml/styles.js.map +1 -0
  225. package/dist/src/formats/gml/syntax.d.ts +11 -0
  226. package/dist/src/formats/gml/syntax.d.ts.map +1 -1
  227. package/dist/src/formats/gml/syntax.js +151 -62
  228. package/dist/src/formats/gml/syntax.js.map +1 -1
  229. package/dist/src/formats/graphml/constants.d.ts +4 -0
  230. package/dist/src/formats/graphml/constants.d.ts.map +1 -1
  231. package/dist/src/formats/graphml/constants.js +5 -1
  232. package/dist/src/formats/graphml/constants.js.map +1 -1
  233. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  234. package/dist/src/formats/graphml/exporter.js +133 -65
  235. package/dist/src/formats/graphml/exporter.js.map +1 -1
  236. package/dist/src/formats/graphml/importer.d.ts +4 -1
  237. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  238. package/dist/src/formats/graphml/importer.js +100 -44
  239. package/dist/src/formats/graphml/importer.js.map +1 -1
  240. package/dist/src/formats/graphml/index.d.ts +1 -0
  241. package/dist/src/formats/graphml/index.d.ts.map +1 -1
  242. package/dist/src/formats/graphml/index.js +1 -0
  243. package/dist/src/formats/graphml/index.js.map +1 -1
  244. package/dist/src/formats/graphml/styles-plain.d.ts +19 -0
  245. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -0
  246. package/dist/src/formats/graphml/styles-plain.js +187 -0
  247. package/dist/src/formats/graphml/styles-plain.js.map +1 -0
  248. package/dist/src/formats/graphml/styles-yed.d.ts +179 -0
  249. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -0
  250. package/dist/src/formats/graphml/styles-yed.js +1086 -0
  251. package/dist/src/formats/graphml/styles-yed.js.map +1 -0
  252. package/dist/src/formats/graphml/styles-yfiles3.d.ts +19 -0
  253. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -0
  254. package/dist/src/formats/graphml/styles-yfiles3.js +508 -0
  255. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -0
  256. package/dist/src/formats/graphml/tree.d.ts.map +1 -1
  257. package/dist/src/formats/graphml/tree.js +34 -19
  258. package/dist/src/formats/graphml/tree.js.map +1 -1
  259. package/dist/src/formats/graphml/yfiles.d.ts +16 -2
  260. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  261. package/dist/src/formats/graphml/yfiles.js +83 -12
  262. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  263. package/dist/src/formats/json/exporter.d.ts +5 -0
  264. package/dist/src/formats/json/exporter.d.ts.map +1 -1
  265. package/dist/src/formats/json/exporter.js +68 -25
  266. package/dist/src/formats/json/exporter.js.map +1 -1
  267. package/dist/src/formats/json/importer.d.ts +22 -3
  268. package/dist/src/formats/json/importer.d.ts.map +1 -1
  269. package/dist/src/formats/json/importer.js +439 -264
  270. package/dist/src/formats/json/importer.js.map +1 -1
  271. package/dist/src/formats/json/positions.d.ts +16 -0
  272. package/dist/src/formats/json/positions.d.ts.map +1 -0
  273. package/dist/src/formats/json/positions.js +44 -0
  274. package/dist/src/formats/json/positions.js.map +1 -0
  275. package/dist/src/formats/json/styles.d.ts +102 -0
  276. package/dist/src/formats/json/styles.d.ts.map +1 -0
  277. package/dist/src/formats/json/styles.js +1753 -0
  278. package/dist/src/formats/json/styles.js.map +1 -0
  279. package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
  280. package/dist/src/formats/neo4j/exporter.js +2 -1
  281. package/dist/src/formats/neo4j/exporter.js.map +1 -1
  282. package/dist/src/formats/pajek/exporter.d.ts +2 -0
  283. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  284. package/dist/src/formats/pajek/exporter.js +142 -76
  285. package/dist/src/formats/pajek/exporter.js.map +1 -1
  286. package/dist/src/formats/pajek/importer.d.ts +4 -0
  287. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  288. package/dist/src/formats/pajek/importer.js +60 -6
  289. package/dist/src/formats/pajek/importer.js.map +1 -1
  290. package/dist/src/formats/pajek/index.d.ts +2 -0
  291. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  292. package/dist/src/formats/pajek/index.js +2 -0
  293. package/dist/src/formats/pajek/index.js.map +1 -1
  294. package/dist/src/formats/pajek/styles.d.ts +50 -0
  295. package/dist/src/formats/pajek/styles.d.ts.map +1 -0
  296. package/dist/src/formats/pajek/styles.js +569 -0
  297. package/dist/src/formats/pajek/styles.js.map +1 -0
  298. package/dist/src/formats/pajek/syntax.d.ts +6 -0
  299. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  300. package/dist/src/formats/pajek/syntax.js +6 -0
  301. package/dist/src/formats/pajek/syntax.js.map +1 -1
  302. package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
  303. package/dist/src/formats/xgmml/columns.js +34 -9
  304. package/dist/src/formats/xgmml/columns.js.map +1 -1
  305. package/dist/src/formats/xgmml/constants.d.ts +2 -0
  306. package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
  307. package/dist/src/formats/xgmml/constants.js +3 -1
  308. package/dist/src/formats/xgmml/constants.js.map +1 -1
  309. package/dist/src/formats/xgmml/document.d.ts +12 -8
  310. package/dist/src/formats/xgmml/document.d.ts.map +1 -1
  311. package/dist/src/formats/xgmml/document.js +56 -13
  312. package/dist/src/formats/xgmml/document.js.map +1 -1
  313. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  314. package/dist/src/formats/xgmml/emit.js +12 -6
  315. package/dist/src/formats/xgmml/emit.js.map +1 -1
  316. package/dist/src/formats/xgmml/exporter.d.ts +3 -1
  317. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
  318. package/dist/src/formats/xgmml/exporter.js +22 -9
  319. package/dist/src/formats/xgmml/exporter.js.map +1 -1
  320. package/dist/src/formats/xgmml/importer.d.ts +2 -1
  321. package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
  322. package/dist/src/formats/xgmml/importer.js +31 -24
  323. package/dist/src/formats/xgmml/importer.js.map +1 -1
  324. package/dist/src/formats/xgmml/styles.d.ts +104 -0
  325. package/dist/src/formats/xgmml/styles.d.ts.map +1 -0
  326. package/dist/src/formats/xgmml/styles.js +310 -0
  327. package/dist/src/formats/xgmml/styles.js.map +1 -0
  328. package/dist/src/index.d.ts +9 -7
  329. package/dist/src/index.d.ts.map +1 -1
  330. package/dist/src/index.js +7 -7
  331. package/dist/src/index.js.map +1 -1
  332. package/dist/src/positions/codes.d.ts +31 -0
  333. package/dist/src/positions/codes.d.ts.map +1 -0
  334. package/dist/src/positions/codes.js +26 -0
  335. package/dist/src/positions/codes.js.map +1 -0
  336. package/dist/src/positions/convert.d.ts +58 -0
  337. package/dist/src/positions/convert.d.ts.map +1 -0
  338. package/dist/src/positions/convert.js +107 -0
  339. package/dist/src/positions/convert.js.map +1 -0
  340. package/dist/src/positions/extract.d.ts +27 -0
  341. package/dist/src/positions/extract.d.ts.map +1 -0
  342. package/dist/src/positions/extract.js +526 -0
  343. package/dist/src/positions/extract.js.map +1 -0
  344. package/dist/src/positions/index.d.ts +10 -0
  345. package/dist/src/positions/index.d.ts.map +1 -0
  346. package/dist/src/positions/index.js +9 -0
  347. package/dist/src/positions/index.js.map +1 -0
  348. package/dist/src/positions/types.d.ts +208 -0
  349. package/dist/src/positions/types.d.ts.map +1 -0
  350. package/dist/src/positions/types.js +10 -0
  351. package/dist/src/positions/types.js.map +1 -0
  352. package/dist/src/registry.d.ts +30 -0
  353. package/dist/src/registry.d.ts.map +1 -1
  354. package/dist/src/registry.js +130 -9
  355. package/dist/src/registry.js.map +1 -1
  356. package/dist/src/styles/annotations.d.ts +132 -0
  357. package/dist/src/styles/annotations.d.ts.map +1 -0
  358. package/dist/src/styles/annotations.js +320 -0
  359. package/dist/src/styles/annotations.js.map +1 -0
  360. package/dist/src/styles/budget.d.ts +45 -0
  361. package/dist/src/styles/budget.d.ts.map +1 -0
  362. package/dist/src/styles/budget.js +58 -0
  363. package/dist/src/styles/budget.js.map +1 -0
  364. package/dist/src/styles/canon/bends.d.ts +32 -0
  365. package/dist/src/styles/canon/bends.d.ts.map +1 -0
  366. package/dist/src/styles/canon/bends.js +74 -0
  367. package/dist/src/styles/canon/bends.js.map +1 -0
  368. package/dist/src/styles/canon/color-tables.d.ts +22 -0
  369. package/dist/src/styles/canon/color-tables.d.ts.map +1 -0
  370. package/dist/src/styles/canon/color-tables.js +369 -0
  371. package/dist/src/styles/canon/color-tables.js.map +1 -0
  372. package/dist/src/styles/canon/color.d.ts +66 -0
  373. package/dist/src/styles/canon/color.d.ts.map +1 -0
  374. package/dist/src/styles/canon/color.js +548 -0
  375. package/dist/src/styles/canon/color.js.map +1 -0
  376. package/dist/src/styles/canon/enums.d.ts +25 -0
  377. package/dist/src/styles/canon/enums.d.ts.map +1 -0
  378. package/dist/src/styles/canon/enums.js +187 -0
  379. package/dist/src/styles/canon/enums.js.map +1 -0
  380. package/dist/src/styles/canon/graphviz.d.ts +48 -0
  381. package/dist/src/styles/canon/graphviz.d.ts.map +1 -0
  382. package/dist/src/styles/canon/graphviz.js +160 -0
  383. package/dist/src/styles/canon/graphviz.js.map +1 -0
  384. package/dist/src/styles/canon/index.d.ts +13 -0
  385. package/dist/src/styles/canon/index.d.ts.map +1 -0
  386. package/dist/src/styles/canon/index.js +13 -0
  387. package/dist/src/styles/canon/index.js.map +1 -0
  388. package/dist/src/styles/canon/number.d.ts +59 -0
  389. package/dist/src/styles/canon/number.d.ts.map +1 -0
  390. package/dist/src/styles/canon/number.js +142 -0
  391. package/dist/src/styles/canon/number.js.map +1 -0
  392. package/dist/src/styles/canon/site.d.ts +51 -0
  393. package/dist/src/styles/canon/site.d.ts.map +1 -0
  394. package/dist/src/styles/canon/site.js +63 -0
  395. package/dist/src/styles/canon/site.js.map +1 -0
  396. package/dist/src/styles/canon/text.d.ts +61 -0
  397. package/dist/src/styles/canon/text.d.ts.map +1 -0
  398. package/dist/src/styles/canon/text.js +199 -0
  399. package/dist/src/styles/canon/text.js.map +1 -0
  400. package/dist/src/styles/codes.d.ts +95 -0
  401. package/dist/src/styles/codes.d.ts.map +1 -0
  402. package/dist/src/styles/codes.js +97 -0
  403. package/dist/src/styles/codes.js.map +1 -0
  404. package/dist/src/styles/cyjs/cascade.d.ts +134 -0
  405. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -0
  406. package/dist/src/styles/cyjs/cascade.js +2252 -0
  407. package/dist/src/styles/cyjs/cascade.js.map +1 -0
  408. package/dist/src/styles/cyjs/defaults-table.d.ts +25 -0
  409. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -0
  410. package/dist/src/styles/cyjs/defaults-table.js +76 -0
  411. package/dist/src/styles/cyjs/defaults-table.js.map +1 -0
  412. package/dist/src/styles/cyjs/emit.d.ts +82 -0
  413. package/dist/src/styles/cyjs/emit.d.ts.map +1 -0
  414. package/dist/src/styles/cyjs/emit.js +791 -0
  415. package/dist/src/styles/cyjs/emit.js.map +1 -0
  416. package/dist/src/styles/cyjs/index.d.ts +13 -0
  417. package/dist/src/styles/cyjs/index.d.ts.map +1 -0
  418. package/dist/src/styles/cyjs/index.js +13 -0
  419. package/dist/src/styles/cyjs/index.js.map +1 -0
  420. package/dist/src/styles/cyjs/live.d.ts +46 -0
  421. package/dist/src/styles/cyjs/live.d.ts.map +1 -0
  422. package/dist/src/styles/cyjs/live.js +108 -0
  423. package/dist/src/styles/cyjs/live.js.map +1 -0
  424. package/dist/src/styles/cyjs/mappers.d.ts +147 -0
  425. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -0
  426. package/dist/src/styles/cyjs/mappers.js +744 -0
  427. package/dist/src/styles/cyjs/mappers.js.map +1 -0
  428. package/dist/src/styles/cyjs/selector.d.ts +113 -0
  429. package/dist/src/styles/cyjs/selector.d.ts.map +1 -0
  430. package/dist/src/styles/cyjs/selector.js +611 -0
  431. package/dist/src/styles/cyjs/selector.js.map +1 -0
  432. package/dist/src/styles/cyjs/stylesheet-text.d.ts +37 -0
  433. package/dist/src/styles/cyjs/stylesheet-text.d.ts.map +1 -0
  434. package/dist/src/styles/cyjs/stylesheet-text.js +181 -0
  435. package/dist/src/styles/cyjs/stylesheet-text.js.map +1 -0
  436. package/dist/src/styles/cytoscape/emit.d.ts +125 -0
  437. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -0
  438. package/dist/src/styles/cytoscape/emit.js +1025 -0
  439. package/dist/src/styles/cytoscape/emit.js.map +1 -0
  440. package/dist/src/styles/cytoscape/index.d.ts +10 -0
  441. package/dist/src/styles/cytoscape/index.d.ts.map +1 -0
  442. package/dist/src/styles/cytoscape/index.js +10 -0
  443. package/dist/src/styles/cytoscape/index.js.map +1 -0
  444. package/dist/src/styles/cytoscape/lexicon.d.ts +49 -0
  445. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -0
  446. package/dist/src/styles/cytoscape/lexicon.js +605 -0
  447. package/dist/src/styles/cytoscape/lexicon.js.map +1 -0
  448. package/dist/src/styles/cytoscape/mappings.d.ts +171 -0
  449. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -0
  450. package/dist/src/styles/cytoscape/mappings.js +460 -0
  451. package/dist/src/styles/cytoscape/mappings.js.map +1 -0
  452. package/dist/src/styles/cytoscape/resolve.d.ts +137 -0
  453. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -0
  454. package/dist/src/styles/cytoscape/resolve.js +381 -0
  455. package/dist/src/styles/cytoscape/resolve.js.map +1 -0
  456. package/dist/src/styles/cytoscape/translate.d.ts +50 -0
  457. package/dist/src/styles/cytoscape/translate.d.ts.map +1 -0
  458. package/dist/src/styles/cytoscape/translate.js +156 -0
  459. package/dist/src/styles/cytoscape/translate.js.map +1 -0
  460. package/dist/src/styles/defaults.d.ts +90 -0
  461. package/dist/src/styles/defaults.d.ts.map +1 -0
  462. package/dist/src/styles/defaults.js +414 -0
  463. package/dist/src/styles/defaults.js.map +1 -0
  464. package/dist/src/styles/index.d.ts +15 -0
  465. package/dist/src/styles/index.d.ts.map +1 -0
  466. package/dist/src/styles/index.js +14 -0
  467. package/dist/src/styles/index.js.map +1 -0
  468. package/dist/src/styles/internal.d.ts +17 -0
  469. package/dist/src/styles/internal.d.ts.map +1 -0
  470. package/dist/src/styles/internal.js +16 -0
  471. package/dist/src/styles/internal.js.map +1 -0
  472. package/dist/src/styles/io/approximations.d.ts +24 -0
  473. package/dist/src/styles/io/approximations.d.ts.map +1 -0
  474. package/dist/src/styles/io/approximations.js +51 -0
  475. package/dist/src/styles/io/approximations.js.map +1 -0
  476. package/dist/src/styles/io/block.d.ts +166 -0
  477. package/dist/src/styles/io/block.d.ts.map +1 -0
  478. package/dist/src/styles/io/block.js +930 -0
  479. package/dist/src/styles/io/block.js.map +1 -0
  480. package/dist/src/styles/io/generic.d.ts +88 -0
  481. package/dist/src/styles/io/generic.d.ts.map +1 -0
  482. package/dist/src/styles/io/generic.js +516 -0
  483. package/dist/src/styles/io/generic.js.map +1 -0
  484. package/dist/src/styles/io/index.d.ts +8 -0
  485. package/dist/src/styles/io/index.d.ts.map +1 -0
  486. package/dist/src/styles/io/index.js +7 -0
  487. package/dist/src/styles/io/index.js.map +1 -0
  488. package/dist/src/styles/io/writer.d.ts +89 -0
  489. package/dist/src/styles/io/writer.d.ts.map +1 -0
  490. package/dist/src/styles/io/writer.js +626 -0
  491. package/dist/src/styles/io/writer.js.map +1 -0
  492. package/dist/src/styles/notes.d.ts +47 -0
  493. package/dist/src/styles/notes.d.ts.map +1 -0
  494. package/dist/src/styles/notes.js +140 -0
  495. package/dist/src/styles/notes.js.map +1 -0
  496. package/dist/src/styles/plan/classes.d.ts +31 -0
  497. package/dist/src/styles/plan/classes.d.ts.map +1 -0
  498. package/dist/src/styles/plan/classes.js +139 -0
  499. package/dist/src/styles/plan/classes.js.map +1 -0
  500. package/dist/src/styles/plan/continuous.d.ts +32 -0
  501. package/dist/src/styles/plan/continuous.d.ts.map +1 -0
  502. package/dist/src/styles/plan/continuous.js +165 -0
  503. package/dist/src/styles/plan/continuous.js.map +1 -0
  504. package/dist/src/styles/plan/discrete.d.ts +39 -0
  505. package/dist/src/styles/plan/discrete.d.ts.map +1 -0
  506. package/dist/src/styles/plan/discrete.js +127 -0
  507. package/dist/src/styles/plan/discrete.js.map +1 -0
  508. package/dist/src/styles/plan/families.d.ts +31 -0
  509. package/dist/src/styles/plan/families.d.ts.map +1 -0
  510. package/dist/src/styles/plan/families.js +95 -0
  511. package/dist/src/styles/plan/families.js.map +1 -0
  512. package/dist/src/styles/plan/features.d.ts +58 -0
  513. package/dist/src/styles/plan/features.d.ts.map +1 -0
  514. package/dist/src/styles/plan/features.js +185 -0
  515. package/dist/src/styles/plan/features.js.map +1 -0
  516. package/dist/src/styles/plan/index.d.ts +7 -0
  517. package/dist/src/styles/plan/index.d.ts.map +1 -0
  518. package/dist/src/styles/plan/index.js +7 -0
  519. package/dist/src/styles/plan/index.js.map +1 -0
  520. package/dist/src/styles/plan/plan.d.ts +71 -0
  521. package/dist/src/styles/plan/plan.d.ts.map +1 -0
  522. package/dist/src/styles/plan/plan.js +893 -0
  523. package/dist/src/styles/plan/plan.js.map +1 -0
  524. package/dist/src/styles/plan/resolve.d.ts +137 -0
  525. package/dist/src/styles/plan/resolve.d.ts.map +1 -0
  526. package/dist/src/styles/plan/resolve.js +587 -0
  527. package/dist/src/styles/plan/resolve.js.map +1 -0
  528. package/dist/src/styles/types.d.ts +702 -0
  529. package/dist/src/styles/types.d.ts.map +1 -0
  530. package/dist/src/styles/types.js +10 -0
  531. package/dist/src/styles/types.js.map +1 -0
  532. package/dist/src/styles/vocabulary.d.ts +41 -0
  533. package/dist/src/styles/vocabulary.d.ts.map +1 -0
  534. package/dist/src/styles/vocabulary.js +140 -0
  535. package/dist/src/styles/vocabulary.js.map +1 -0
  536. package/dist/src/types.d.ts +64 -1
  537. package/dist/src/types.d.ts.map +1 -1
  538. package/dist/src/types.js.map +1 -1
  539. package/dist/styles.d.ts +1 -0
  540. package/dist/styles.js +322 -0
  541. package/dist/styles.js.map +1 -0
  542. package/dist/xgmml.js +5 -4
  543. package/dist/xgmml.js.map +1 -1
  544. package/package.json +13 -2
  545. package/src/common/codes.ts +7 -0
  546. package/src/common/escape.ts +5 -2
  547. package/src/common/export.ts +179 -140
  548. package/src/common/input.ts +8 -4
  549. package/src/common/json-elements.ts +169 -38
  550. package/src/common/notes.ts +94 -0
  551. package/src/common/report.ts +41 -1
  552. package/src/common/units.ts +42 -0
  553. package/src/common/xml.ts +45 -5
  554. package/src/formats/cx/exporter.ts +95 -11
  555. package/src/formats/cx/importer.ts +126 -90
  556. package/src/formats/cx/styles.ts +304 -0
  557. package/src/formats/cx2/exporter.ts +234 -77
  558. package/src/formats/cx2/importer.ts +19 -1
  559. package/src/formats/cx2/styles.ts +29 -0
  560. package/src/formats/cys/constants.ts +3 -0
  561. package/src/formats/cys/exporter.ts +246 -60
  562. package/src/formats/cys/importer.ts +125 -9
  563. package/src/formats/cys/session.ts +6 -0
  564. package/src/formats/cys/styles.ts +254 -0
  565. package/src/formats/cys/tables.ts +117 -48
  566. package/src/formats/dot/exporter.ts +262 -126
  567. package/src/formats/dot/importer.ts +111 -20
  568. package/src/formats/dot/index.ts +1 -0
  569. package/src/formats/dot/positions.ts +77 -0
  570. package/src/formats/dot/styles.ts +1755 -0
  571. package/src/formats/gexf/exporter.ts +27 -11
  572. package/src/formats/gexf/importer.ts +308 -158
  573. package/src/formats/gexf/index.ts +10 -0
  574. package/src/formats/gexf/schema.ts +5 -0
  575. package/src/formats/gexf/styles.ts +719 -0
  576. package/src/formats/gml/exporter.ts +33 -14
  577. package/src/formats/gml/importer.ts +4 -0
  578. package/src/formats/gml/index.ts +2 -1
  579. package/src/formats/gml/positions.ts +52 -0
  580. package/src/formats/gml/styles.ts +1248 -0
  581. package/src/formats/gml/syntax.ts +173 -62
  582. package/src/formats/graphml/constants.ts +5 -0
  583. package/src/formats/graphml/exporter.ts +163 -71
  584. package/src/formats/graphml/importer.ts +119 -45
  585. package/src/formats/graphml/index.ts +1 -0
  586. package/src/formats/graphml/styles-plain.ts +236 -0
  587. package/src/formats/graphml/styles-yed.ts +1221 -0
  588. package/src/formats/graphml/styles-yfiles3.ts +573 -0
  589. package/src/formats/graphml/tree.ts +36 -20
  590. package/src/formats/graphml/yfiles.ts +89 -13
  591. package/src/formats/json/exporter.ts +76 -26
  592. package/src/formats/json/importer.ts +541 -322
  593. package/src/formats/json/positions.ts +50 -0
  594. package/src/formats/json/styles.ts +2082 -0
  595. package/src/formats/neo4j/exporter.ts +2 -1
  596. package/src/formats/pajek/exporter.ts +195 -106
  597. package/src/formats/pajek/importer.ts +78 -9
  598. package/src/formats/pajek/index.ts +2 -0
  599. package/src/formats/pajek/styles.ts +685 -0
  600. package/src/formats/pajek/syntax.ts +7 -0
  601. package/src/formats/xgmml/columns.ts +39 -9
  602. package/src/formats/xgmml/constants.ts +3 -0
  603. package/src/formats/xgmml/document.ts +54 -12
  604. package/src/formats/xgmml/emit.ts +11 -6
  605. package/src/formats/xgmml/exporter.ts +32 -13
  606. package/src/formats/xgmml/importer.ts +43 -29
  607. package/src/formats/xgmml/styles.ts +400 -0
  608. package/src/index.ts +16 -0
  609. package/src/positions/codes.ts +32 -0
  610. package/src/positions/convert.ts +123 -0
  611. package/src/positions/extract.ts +619 -0
  612. package/src/positions/index.ts +23 -0
  613. package/src/positions/types.ts +221 -0
  614. package/src/registry.ts +179 -8
  615. package/src/styles/annotations.ts +478 -0
  616. package/src/styles/budget.ts +60 -0
  617. package/src/styles/canon/bends.ts +84 -0
  618. package/src/styles/canon/color-tables.ts +386 -0
  619. package/src/styles/canon/color.ts +624 -0
  620. package/src/styles/canon/enums.ts +211 -0
  621. package/src/styles/canon/graphviz.ts +189 -0
  622. package/src/styles/canon/index.ts +13 -0
  623. package/src/styles/canon/number.ts +152 -0
  624. package/src/styles/canon/site.ts +87 -0
  625. package/src/styles/canon/text.ts +221 -0
  626. package/src/styles/codes.ts +104 -0
  627. package/src/styles/cyjs/cascade.ts +2670 -0
  628. package/src/styles/cyjs/defaults-table.ts +82 -0
  629. package/src/styles/cyjs/emit.ts +952 -0
  630. package/src/styles/cyjs/index.ts +37 -0
  631. package/src/styles/cyjs/live.ts +147 -0
  632. package/src/styles/cyjs/mappers.ts +879 -0
  633. package/src/styles/cyjs/selector.ts +778 -0
  634. package/src/styles/cyjs/stylesheet-text.ts +214 -0
  635. package/src/styles/cytoscape/emit.ts +1264 -0
  636. package/src/styles/cytoscape/index.ts +40 -0
  637. package/src/styles/cytoscape/lexicon.ts +658 -0
  638. package/src/styles/cytoscape/mappings.ts +603 -0
  639. package/src/styles/cytoscape/resolve.ts +521 -0
  640. package/src/styles/cytoscape/translate.ts +237 -0
  641. package/src/styles/defaults.ts +504 -0
  642. package/src/styles/index.ts +57 -0
  643. package/src/styles/internal.ts +17 -0
  644. package/src/styles/io/approximations.ts +47 -0
  645. package/src/styles/io/block.ts +1138 -0
  646. package/src/styles/io/generic.ts +687 -0
  647. package/src/styles/io/index.ts +18 -0
  648. package/src/styles/io/writer.ts +780 -0
  649. package/src/styles/notes.ts +165 -0
  650. package/src/styles/plan/classes.ts +166 -0
  651. package/src/styles/plan/continuous.ts +218 -0
  652. package/src/styles/plan/discrete.ts +165 -0
  653. package/src/styles/plan/families.ts +115 -0
  654. package/src/styles/plan/features.ts +234 -0
  655. package/src/styles/plan/index.ts +7 -0
  656. package/src/styles/plan/plan.ts +1129 -0
  657. package/src/styles/plan/resolve.ts +685 -0
  658. package/src/styles/types.ts +814 -0
  659. package/src/styles/vocabulary.ts +172 -0
  660. package/src/types.ts +76 -1
  661. package/dist/chunks/constants-fT3E8JYY.js.map +0 -1
  662. package/dist/chunks/escape-B62ZGM_a.js.map +0 -1
  663. package/dist/chunks/export-rKLeGQMo.js.map +0 -1
  664. package/dist/chunks/exporter-8hLNemFk.js.map +0 -1
  665. package/dist/chunks/exporter-BWwEuOPT.js.map +0 -1
  666. package/dist/chunks/exporter-RVtXVetw.js.map +0 -1
  667. package/dist/chunks/importer-BbNb7eNg.js.map +0 -1
  668. package/dist/chunks/importer-C98dpSH4.js.map +0 -1
  669. package/dist/chunks/importer-D794XUTe.js.map +0 -1
  670. package/dist/chunks/importer-Dz7tI8Sa.js.map +0 -1
  671. package/dist/chunks/importer-Ht7LNg8L.js.map +0 -1
  672. package/dist/chunks/importer-WrGRZb0N.js.map +0 -1
  673. package/dist/chunks/importer-xZ-3suY1.js.map +0 -1
  674. package/dist/chunks/json-elements-DKSqpNW1.js.map +0 -1
@@ -0,0 +1,893 @@
1
+ /**
2
+ * The planner: turns a file's per-element style values into a few readable rules that reproduce them exactly. It
3
+ * groups properties into families, explains each family by a discrete or continuous mapping on one feature, a
4
+ * passthrough on an existing column, style classes or a copy, orders the rules, caps them at 15 per target and
5
+ * replays them: every element whose resolved value differs from the file's goes into one sparse exceptions column
6
+ * per property on top. One counted budget bounds the work; when it runs out the rest is copied.
7
+ */
8
+ import { StyleBudget } from "../budget.js";
9
+ import { STYLE_ISSUE } from "../codes.js";
10
+ import { toolDefaults } from "../defaults.js";
11
+ import { StyleNotes } from "../notes.js";
12
+ import { isStyleValue, STYLE_PROPERTIES } from "../vocabulary.js";
13
+ import { CLASS_COLUMN, styleClasses } from "./classes.js";
14
+ import { continuousCandidate } from "./continuous.js";
15
+ import { discreteCandidate } from "./discrete.js";
16
+ import { familiesOf } from "./families.js";
17
+ import { describeFeature } from "./features.js";
18
+ import { canonicalFor, evalContinuous, isShortPredicate, matches, numberOf, refSource, resolveRules, within, } from "./resolve.js";
19
+ /**
20
+ * The most rules per target: the planner keeps at most 15 plus the exceptions rule.
21
+ * @category Styles
22
+ */
23
+ export const MAX_STYLE_RULES = 16;
24
+ /** The most candidate features tested per target, fewest distinct values first. */
25
+ const MAX_FEATURES = 64;
26
+ /** Lengths a tool states in its own unit; they are left out when the file's unit differs. */
27
+ const LENGTHS = new Set(["width", "height", "borderWidth", "labelSize"]);
28
+ /**
29
+ * Plans a file's styles: the rules that reproduce its per-element values, with the columns they read.
30
+ * @param values - the canonical values, the declared rules and the graph they belong to
31
+ * @param features - the candidate explaining columns per target (`featuresOf()` of the snapshot)
32
+ * @param options - tool defaults, the budget, the notes collector, the raw columns and a cancel signal
33
+ * @returns the styles, exact for every element
34
+ * @category Styles
35
+ */
36
+ export function planStyles(values, features, options = {}) {
37
+ const notes = options.notes ?? new StyleNotes();
38
+ const budget = options.budget ?? new StyleBudget();
39
+ const defaults = options.toolDefaults !== false && values.tool !== undefined && values.tool !== null
40
+ ? toolDefaults(values.tool)
41
+ : null;
42
+ const units = values.units ?? "px";
43
+ const rules = [];
44
+ const columns = { node: new Map(), edge: new Map() };
45
+ const allFeatures = { node: [], edge: [] };
46
+ for (const target of ["node", "edge"]) {
47
+ const given = values[target];
48
+ // a reader's own tool-default rules (Gephi's arrows on directed edges) go with the tool's constants
49
+ const out = options.toolDefaults === false && given?.rules !== undefined
50
+ ? { ...given, rules: given.rules.filter((r) => r.origin !== "tool") }
51
+ : given;
52
+ allFeatures[target] = [...features[target], ...(out?.features ?? [])];
53
+ const toolSet = defaults === null ? null : toolSetOf(defaults, target, units);
54
+ const plan = {
55
+ target,
56
+ n: target === "node" ? values.fingerprint.nodes : values.fingerprint.edges,
57
+ notes,
58
+ budget,
59
+ spend: (ops) => {
60
+ budget.spend(target, ops);
61
+ },
62
+ columns: columns[target],
63
+ ids: new Set(),
64
+ };
65
+ rules.push(...planTarget(plan, out, allFeatures[target], new Set(options.rawColumns?.[target] ?? []), toolSet, options.signal));
66
+ }
67
+ const graph = graphStyles(defaults, values.graph ?? {});
68
+ return {
69
+ styles: {
70
+ version: 1,
71
+ source: {
72
+ format: values.format,
73
+ dialect: values.dialect ?? null,
74
+ tool: defaults === null ? null : defaults.tool,
75
+ },
76
+ units: { length: units },
77
+ graph: graph,
78
+ rules,
79
+ notes: notes.list(),
80
+ },
81
+ columns,
82
+ features: allFeatures,
83
+ fingerprint: values.fingerprint,
84
+ };
85
+ }
86
+ /**
87
+ * The tool's default values of a target, as one defaults rule sets them; a length in other units than the file's is
88
+ * left out.
89
+ * @param defaults - the tool's defaults
90
+ * @param target - nodes or edges
91
+ * @param units - the file's length units
92
+ * @returns the values, or null when none applies
93
+ */
94
+ function toolSetOf(defaults, target, units) {
95
+ const toolSet = {};
96
+ for (const [p, d] of Object.entries(defaults[target])) {
97
+ const fits = d !== undefined && isStyleValue(target, p, d.value);
98
+ if (fits && !(LENGTHS.has(p) && defaults.units !== units)) {
99
+ toolSet[p] = d.value;
100
+ }
101
+ }
102
+ return Object.keys(toolSet).length === 0 ? null : toolSet;
103
+ }
104
+ /**
105
+ * The graph's styles: the tool's defaults, then the file's own values over them.
106
+ * @param defaults - the tool's defaults, or null
107
+ * @param given - the file's graph values
108
+ * @returns the values
109
+ */
110
+ function graphStyles(defaults, given) {
111
+ const graph = {};
112
+ const own = Object.entries(defaults?.graph ?? {});
113
+ for (const [p, d] of own) {
114
+ if (d !== undefined && isStyleValue("graph", p, d.value)) {
115
+ graph[p] = d.value;
116
+ }
117
+ }
118
+ for (const [p, v] of Object.entries(given)) {
119
+ if (isStyleValue("graph", p, v)) {
120
+ graph[p] = v;
121
+ }
122
+ }
123
+ return graph;
124
+ }
125
+ /**
126
+ * A rule id not used yet in this target.
127
+ * @param plan - the target's state
128
+ * @param base - the wanted id
129
+ * @returns the id, suffixed when taken
130
+ */
131
+ function uniqueId(plan, base) {
132
+ let id = base;
133
+ let k = 2;
134
+ while (plan.ids.has(id)) {
135
+ id = `${base}#${String(k)}`;
136
+ k++;
137
+ }
138
+ plan.ids.add(id);
139
+ return id;
140
+ }
141
+ /**
142
+ * Sets one property's mapping of a rule, making the rule's mappings on first use.
143
+ * @param rule - the rule, changed in place
144
+ * @param property - the property
145
+ * @param mapping - the mapping
146
+ */
147
+ function setMapping(rule, property, mapping) {
148
+ rule.map ?? (rule.map = {});
149
+ rule.map[property] = mapping;
150
+ }
151
+ /**
152
+ * The type-checked per-element values of a target: a value of the wrong kind is noted and dropped.
153
+ * @param plan - the target's state
154
+ * @param out - the reader's output
155
+ * @returns the values per property that have at least one value
156
+ */
157
+ function checkedTruth(plan, out) {
158
+ const truth = new Map();
159
+ for (const [p, arr] of Object.entries(out?.values ?? {})) {
160
+ if (arr === undefined) {
161
+ continue;
162
+ }
163
+ if (!STYLE_PROPERTIES[plan.target].has(p) && !p.startsWith("graphty:")) {
164
+ plan.notes.add(STYLE_ISSUE.NOT_CARRIED, plan.target, p, { sample: p });
165
+ continue;
166
+ }
167
+ const vals = checkedValues(plan, p, arr);
168
+ plan.spend(plan.n);
169
+ if (vals.some((v) => v !== null)) {
170
+ truth.set(p, vals);
171
+ }
172
+ }
173
+ return truth;
174
+ }
175
+ /**
176
+ * One property's values, a value of the wrong kind noted and dropped.
177
+ * @param plan - the target's state
178
+ * @param p - the property
179
+ * @param arr - the reader's values
180
+ * @returns the values, one per element
181
+ */
182
+ function checkedValues(plan, p, arr) {
183
+ const vals = new Array(plan.n).fill(null);
184
+ for (let i = 0; i < plan.n && i < arr.length; i++) {
185
+ const v = arr[i] ?? null;
186
+ if (v !== null && isStyleValue(plan.target, p, v)) {
187
+ vals[i] = v;
188
+ }
189
+ else if (v !== null) {
190
+ plan.notes.add(STYLE_ISSUE.BAD_VALUE, plan.target, p, { sample: v, element: i });
191
+ }
192
+ }
193
+ return vals;
194
+ }
195
+ /**
196
+ * A copy of a property record without its undefined entries.
197
+ * @param o - the record
198
+ * @returns the copy, or undefined
199
+ */
200
+ function defined(o) {
201
+ if (o === undefined) {
202
+ return undefined;
203
+ }
204
+ const out = {};
205
+ for (const [k, v] of Object.entries(o)) {
206
+ if (v !== undefined) {
207
+ out[k] = v;
208
+ }
209
+ }
210
+ return out;
211
+ }
212
+ /**
213
+ * The properties a rule writes.
214
+ * @param r - the rule
215
+ * @returns the property names
216
+ */
217
+ function writes(r) {
218
+ return [...Object.keys(r.set ?? {}), ...Object.keys(r.map ?? {})];
219
+ }
220
+ /**
221
+ * The declared rules, with every predicate longer than a short one evaluated into a membership style column and
222
+ * runs of rules that set values on every element merged into one defaults rule.
223
+ * @param plan - the target's state
224
+ * @param declared - the reader's rules
225
+ * @param features - the features, for evaluating predicates over data columns
226
+ * @returns the rules to keep
227
+ */
228
+ function prepareDeclared(plan, declared, features) {
229
+ const src = refSource(plan.target, plan.n, plan.columns, features);
230
+ const drafts = [];
231
+ for (const r of declared.filter((x) => x.target === plan.target)) {
232
+ const d = { ...r, set: defined(r.set), map: defined(r.map) };
233
+ if (d.set === undefined) {
234
+ delete d.set;
235
+ }
236
+ if (d.map === undefined) {
237
+ delete d.map;
238
+ }
239
+ if (!isShortPredicate(r.where)) {
240
+ asMembership(plan, d, r, src);
241
+ }
242
+ drafts.push(d);
243
+ }
244
+ const merged = mergedDefaults(plan.target, drafts);
245
+ for (const d of merged) {
246
+ d.id = uniqueId(plan, d.id);
247
+ }
248
+ return merged;
249
+ }
250
+ /**
251
+ * Evaluates a long predicate into a membership style column the rule selects instead.
252
+ * @param plan - the target's state
253
+ * @param d - the rule's draft, changed in place
254
+ * @param r - the declared rule
255
+ * @param src - the reference source
256
+ */
257
+ function asMembership(plan, d, r, src) {
258
+ let member = 1;
259
+ while (plan.columns.has(`member.${String(member)}`)) {
260
+ member++;
261
+ }
262
+ const key = `member.${String(member)}`;
263
+ const col = new Array(plan.n).fill(null);
264
+ let count = 0;
265
+ for (let i = 0; i < plan.n; i++) {
266
+ if (matches(r.where, src, i)) {
267
+ col[i] = true;
268
+ count++;
269
+ }
270
+ }
271
+ plan.spend(plan.n * 8);
272
+ plan.columns.set(key, col);
273
+ d.where = { has: { style: key } };
274
+ d.facts = { ...r.facts, elements: count, reason: r.facts?.reason ?? "SELECTOR" };
275
+ plan.notes.add(STYLE_ISSUE.SELECTOR_AS_COLUMN, plan.target, r.id, { count });
276
+ }
277
+ /**
278
+ * Consecutive declared rules that select everything and only set values, as one defaults rule (later wins).
279
+ * @param target - nodes or edges
280
+ * @param drafts - the declared rules
281
+ * @returns the rules, runs merged
282
+ */
283
+ function mergedDefaults(target, drafts) {
284
+ const merged = [];
285
+ const plain = (x) => "all" in x.where && x.set !== undefined && x.map === undefined;
286
+ let i = 0;
287
+ while (i < drafts.length) {
288
+ let j = i + 1;
289
+ while (plain(drafts[i]) && j < drafts.length && plain(drafts[j])) {
290
+ j++;
291
+ }
292
+ if (j - i >= 2) {
293
+ merged.push({
294
+ id: drafts[i].id,
295
+ target,
296
+ role: "defaults",
297
+ origin: "declared",
298
+ where: { all: true },
299
+ set: Object.assign({}, ...drafts.slice(i, j).map((x) => x.set)),
300
+ });
301
+ }
302
+ else {
303
+ merged.push(drafts[i]);
304
+ }
305
+ i = j;
306
+ }
307
+ return merged;
308
+ }
309
+ const ORDER = ["passdata", "discrete", "continuous", "opaque"];
310
+ /**
311
+ * Tests a passthrough on existing data columns: one column per property whose canonical value equals the style on
312
+ * every element.
313
+ * @param plan - the target's state
314
+ * @param fam - the family
315
+ * @param truth - the values per property
316
+ * @param infos - the features
317
+ * @returns the candidate, or null
318
+ */
319
+ function passCandidate(plan, fam, truth, infos) {
320
+ const cols = new Map();
321
+ for (const p of fam.props) {
322
+ const canon = canonicalFor(plan.target, p);
323
+ const isColor = STYLE_PROPERTIES[plan.target].get(p) === "color";
324
+ const t = truth.get(p) ?? [];
325
+ const hit = infos.find((f) => {
326
+ if (!("data" in f.feature.ref)) {
327
+ return false;
328
+ }
329
+ plan.spend(plan.n);
330
+ for (let i = 0; i < plan.n; i++) {
331
+ const raw = f.feature.values[i];
332
+ // a color column is reused only when it already holds "#rrggbb": other spellings read differently
333
+ if (isColor && raw !== null && !(typeof raw === "string" && /^#[0-9a-fA-F]{6}$/.test(raw))) {
334
+ return false;
335
+ }
336
+ if ((raw === null ? null : canon(raw)) !== t[i]) {
337
+ return false;
338
+ }
339
+ }
340
+ return true;
341
+ });
342
+ if (hit === undefined) {
343
+ return null;
344
+ }
345
+ cols.set(p, hit);
346
+ }
347
+ const raw = Array.from(cols.values()).some((f) => f.raw);
348
+ // a passthrough on the raw style column itself recovers nothing: nearly as opaque as a copy
349
+ return { type: "passdata", cols, raw, cost: raw ? 240 : 50 };
350
+ }
351
+ /**
352
+ * Plans one target.
353
+ * @param plan - the target's state
354
+ * @param out - the reader's output
355
+ * @param features - the candidate features
356
+ * @param rawNames - the data columns the values were read from
357
+ * @param toolSet - the tool's default values, or null
358
+ * @param signal - cancels the planning
359
+ * @returns the target's rules, bottom to top
360
+ */
361
+ function planTarget(plan, out, features, rawNames, toolSet, signal) {
362
+ const { target, n } = plan;
363
+ for (const [k, v] of out?.columns ?? []) {
364
+ plan.columns.set(k, v);
365
+ }
366
+ const truth = checkedTruth(plan, out);
367
+ const toolRule = toolSet === null
368
+ ? []
369
+ : [
370
+ {
371
+ id: uniqueId(plan, `${target}.tool`),
372
+ target,
373
+ role: "defaults",
374
+ origin: "tool",
375
+ where: { all: true },
376
+ set: toolSet,
377
+ },
378
+ ];
379
+ const declared = prepareDeclared(plan, out?.rules ?? [], features);
380
+ const declaredProps = new Set(declared.flatMap(writes));
381
+ const { defaults, rest } = splitDefaults(n, truth, declaredProps);
382
+ plan.spend(n * truth.size);
383
+ const inferred = [];
384
+ if (Object.keys(defaults).length > 0) {
385
+ inferred.push({
386
+ id: uniqueId(plan, `${target}.defaults`),
387
+ target,
388
+ role: "defaults",
389
+ origin: "inferred",
390
+ where: { all: true },
391
+ set: defaults,
392
+ });
393
+ }
394
+ const families = familiesOf(rest);
395
+ plan.spend(n * rest.length);
396
+ const infos = features
397
+ .map((f) => describeFeature(f, "data" in f.ref && rawNames.has(f.ref.data)))
398
+ .sort((a, b) => a.distinct - b.distinct);
399
+ plan.spend(n * features.length);
400
+ const testable = infos.filter((f) => f.categorical || f.numeric).slice(0, MAX_FEATURES);
401
+ const groups = [];
402
+ const mappings = new Map();
403
+ const passData = {
404
+ id: `${target}.passthrough`,
405
+ target,
406
+ role: "passthrough",
407
+ origin: "inferred",
408
+ where: { all: true },
409
+ map: {},
410
+ };
411
+ const passRaw = {
412
+ id: `${target}.passthrough.raw`,
413
+ target,
414
+ role: "passthrough",
415
+ origin: "inferred",
416
+ where: { all: true },
417
+ map: {},
418
+ facts: { reason: "NO_EXPLANATION" },
419
+ };
420
+ const copy = {
421
+ id: `${target}.copy`,
422
+ target,
423
+ role: "passthrough",
424
+ origin: "inferred",
425
+ where: { all: true },
426
+ map: {},
427
+ facts: { reason: "NO_EXPLANATION" },
428
+ };
429
+ const opaque = [];
430
+ const tolerated = new Map();
431
+ let budgetHit = 0;
432
+ const st = { groups, mappings, passData, passRaw, copy, opaque, tolerated };
433
+ for (const fam of families) {
434
+ signal?.throwIfAborted();
435
+ if (plan.budget.exhausted(target)) {
436
+ budgetHit++;
437
+ opaque.push({ fam, raw: null });
438
+ continue;
439
+ }
440
+ applyChoice(plan, st, fam, chooseCandidate(plan, fam, testable, infos, truth), truth);
441
+ }
442
+ if (budgetHit > 0) {
443
+ plan.notes.add(STYLE_ISSUE.BUDGET, target, null, { count: budgetHit });
444
+ }
445
+ poolOpaque(plan, st, budgetHit, truth);
446
+ const nonEmpty = (r) => Object.keys(r.map ?? {}).length > 0;
447
+ const sortedMappings = Array.from(mappings.values()).sort((a, b) => compareText(a.id, b.id));
448
+ const drafts = [
449
+ ...toolRule,
450
+ ...declared,
451
+ ...inferred,
452
+ ...groups,
453
+ ...sortedMappings,
454
+ ...[passData, passRaw, copy].filter(nonEmpty),
455
+ ];
456
+ for (const d of drafts.slice(toolRule.length + declared.length + inferred.length)) {
457
+ d.id = uniqueId(plan, d.id);
458
+ }
459
+ const src = refSource(target, n, plan.columns, features);
460
+ enforceCap(plan, drafts, truth, src);
461
+ const exceptions = replay(plan, drafts, truth, toolSet, tolerated, src);
462
+ if (exceptions !== null) {
463
+ drafts.push(exceptions);
464
+ }
465
+ return drafts.map(finish);
466
+ }
467
+ /**
468
+ * The inferred defaults: each property non-null and equal on every element; the others are left to explain. A
469
+ * property a declared rule writes is the declared rule's.
470
+ * @param n - the element count
471
+ * @param truth - the values per property
472
+ * @param declaredProps - the properties the declared rules write
473
+ * @returns the defaults, and the properties left
474
+ */
475
+ function splitDefaults(n, truth, declaredProps) {
476
+ const defaults = {};
477
+ const rest = [];
478
+ for (const [p, a] of truth) {
479
+ const first = a[0];
480
+ if (declaredProps.has(p)) {
481
+ continue;
482
+ }
483
+ if (n > 0 && first !== null && a.every((v) => v === first)) {
484
+ defaults[p] = first;
485
+ }
486
+ else {
487
+ rest.push([p, a]);
488
+ }
489
+ }
490
+ return { defaults, rest };
491
+ }
492
+ /**
493
+ * The cheapest explanation of one family: a discrete or continuous mapping over a feature, a passthrough over existing
494
+ * columns, or the opaque floor.
495
+ * @param plan - the target's state
496
+ * @param fam - the family
497
+ * @param testable - the features worth testing
498
+ * @param infos - every feature
499
+ * @param truth - the values per property
500
+ * @returns the chosen candidate
501
+ */
502
+ function chooseCandidate(plan, fam, testable, infos, truth) {
503
+ const { target, n } = plan;
504
+ const cands = [];
505
+ // text is per element by nature: a label is never explained by another column's table
506
+ const textual = fam.props.some((p) => STYLE_PROPERTIES[target].get(p) === "text");
507
+ if (!textual) {
508
+ for (const f of testable) {
509
+ const d = discreteCandidate(fam, f, n, plan.spend);
510
+ if (d !== null) {
511
+ cands.push(d);
512
+ }
513
+ const c = continuousCandidate(fam, f, truth, plan.spend);
514
+ if (c !== null) {
515
+ cands.push(c);
516
+ }
517
+ if (plan.budget.exhausted(target)) {
518
+ break;
519
+ }
520
+ }
521
+ }
522
+ const pass = passCandidate(plan, fam, truth, infos);
523
+ if (pass !== null) {
524
+ cands.push(pass);
525
+ }
526
+ cands.push({ type: "opaque", cost: 250 });
527
+ cands.sort((a, b) => a.cost - b.cost || ORDER.indexOf(a.type) - ORDER.indexOf(b.type));
528
+ return cands[0];
529
+ }
530
+ /**
531
+ * Records a family's chosen explanation in the target's inference.
532
+ * @param plan - the target's state
533
+ * @param st - the inference so far; changed in place
534
+ * @param fam - the family
535
+ * @param c - the chosen candidate
536
+ * @param truth - the values per property
537
+ */
538
+ function applyChoice(plan, st, fam, c, truth) {
539
+ if (c.type === "discrete") {
540
+ applyDiscrete(plan, st, fam, c, truth);
541
+ }
542
+ else if (c.type === "continuous") {
543
+ applyContinuous(plan, st, fam, c, truth);
544
+ }
545
+ else if (c.type === "passdata" && !c.raw) {
546
+ for (const p of fam.props) {
547
+ setMapping(st.passData, p, { kind: "passthrough", by: c.cols.get(p).feature.ref });
548
+ }
549
+ }
550
+ else {
551
+ // the raw style column recovers nothing: the family joins the opaque pool, where it may become part
552
+ // of a style class, and otherwise reads the raw column
553
+ st.opaque.push({ fam, raw: c.type === "passdata" ? c.cols : null });
554
+ }
555
+ }
556
+ /**
557
+ * The mapping rule of a feature, made on first use; one rule holds every family the feature explains.
558
+ * @param plan - the target's state
559
+ * @param st - the inference so far; changed in place
560
+ * @param key - the rule's key among the mappings
561
+ * @param id - its id
562
+ * @returns the rule
563
+ */
564
+ function mappingRule(plan, st, key, id) {
565
+ let r = st.mappings.get(key);
566
+ if (r === undefined) {
567
+ r = { id, target: plan.target, role: "mapping", origin: "inferred", where: { all: true }, map: {} };
568
+ st.mappings.set(key, r);
569
+ }
570
+ return r;
571
+ }
572
+ /**
573
+ * Makes a feature computed for the inference (a style column) a column of the styles.
574
+ * @param plan - the target's state
575
+ * @param info - the feature
576
+ */
577
+ function materialize(plan, info) {
578
+ if ("style" in info.feature.ref) {
579
+ plan.columns.set(info.feature.ref.style, info.feature.values);
580
+ }
581
+ }
582
+ /**
583
+ * Records a discrete mapping: one table per property, and a group for the elements the feature gives no value.
584
+ * @param plan - the target's state
585
+ * @param st - the inference so far; changed in place
586
+ * @param fam - the family
587
+ * @param c - the candidate
588
+ * @param truth - the values per property
589
+ */
590
+ function applyDiscrete(plan, st, fam, c, truth) {
591
+ const { target } = plan;
592
+ materialize(plan, c.info);
593
+ const rule = mappingRule(plan, st, `discrete|${c.info.name}`, `${target}.by.${c.info.name}`);
594
+ // the first element of each block stands for the block
595
+ const rep = new Map();
596
+ for (const i of fam.styled) {
597
+ if (!rep.has(fam.blocks[i])) {
598
+ rep.set(fam.blocks[i], i);
599
+ }
600
+ }
601
+ for (const p of fam.props) {
602
+ const t = truth.get(p) ?? [];
603
+ const table = Array.from(c.table.values(), ({ raw, block }) => [
604
+ raw,
605
+ t[rep.get(block) ?? -1],
606
+ ]);
607
+ setMapping(rule, p, { kind: "discrete", by: c.info.feature.ref, table });
608
+ }
609
+ if (c.bucket === null) {
610
+ return;
611
+ }
612
+ const set = {};
613
+ for (const p of fam.props) {
614
+ set[p] = (truth.get(p) ?? [])[rep.get(c.bucket) ?? -1];
615
+ }
616
+ st.groups.push({
617
+ id: `${target}.missing.${c.info.name}`,
618
+ target,
619
+ role: "group",
620
+ origin: "inferred",
621
+ where: { not: { has: c.info.feature.ref } },
622
+ set,
623
+ });
624
+ }
625
+ /**
626
+ * Records a continuous mapping: one ramp per property; a ramp that matches only within the tool's rounding tolerates
627
+ * those elements, noted.
628
+ * @param plan - the target's state
629
+ * @param st - the inference so far; changed in place
630
+ * @param fam - the family
631
+ * @param c - the candidate
632
+ * @param truth - the values per property
633
+ */
634
+ function applyContinuous(plan, st, fam, c, truth) {
635
+ const { target } = plan;
636
+ materialize(plan, c.info);
637
+ const rule = mappingRule(plan, st, `continuous|${c.info.name}`, `${target}.ramp.${c.info.name}`);
638
+ for (const p of fam.props) {
639
+ const points = c.points.get(p) ?? [];
640
+ setMapping(rule, p, { kind: "continuous", by: c.info.feature.ref, points });
641
+ if (!c.tolerant) {
642
+ continue;
643
+ }
644
+ const t = truth.get(p) ?? [];
645
+ const set = new Set();
646
+ for (const i of fam.styled) {
647
+ if (evalContinuous(points, numberOf(c.info.feature.values[i])) !== t[i]) {
648
+ set.add(i);
649
+ plan.notes.add(STYLE_ISSUE.RAMP_ROUNDED, target, p, { element: i, sample: t[i] });
650
+ }
651
+ }
652
+ st.tolerated.set(p, set);
653
+ }
654
+ }
655
+ /**
656
+ * The opaque pool: style classes when the file uses few combinations, else one copy per property.
657
+ * @param plan - the target's state
658
+ * @param st - the inference so far; changed in place
659
+ * @param budgetHit - how many families the budget sent to the pool
660
+ * @param truth - the values per property
661
+ */
662
+ function poolOpaque(plan, st, budgetHit, truth) {
663
+ const { target, n } = plan;
664
+ if (st.opaque.length === 0) {
665
+ return;
666
+ }
667
+ const props = st.opaque.flatMap((o) => o.fam.props);
668
+ const classes = budgetHit > 0 ? null : styleClasses(target, props, truth, n, plan.spend);
669
+ const classed = new Set(classes?.classed ?? []);
670
+ if (classes !== null) {
671
+ addClassRules(plan, st, classes);
672
+ }
673
+ let distinct = 0;
674
+ for (const { fam, raw } of st.opaque) {
675
+ for (const p of fam.props.filter((x) => !classed.has(x))) {
676
+ const viaRaw = raw?.get(p);
677
+ if (viaRaw === undefined) {
678
+ distinct = Math.max(distinct, copyProperty(plan, st.copy, p, truth.get(p) ?? []));
679
+ }
680
+ else {
681
+ setMapping(st.passRaw, p, { kind: "passthrough", by: viaRaw.feature.ref });
682
+ }
683
+ }
684
+ }
685
+ st.copy.facts = { reason: budgetHit > 0 ? "BUDGET" : "NO_EXPLANATION", distinctValues: distinct };
686
+ }
687
+ /**
688
+ * Adds the style classes' column and rules.
689
+ * @param plan - the target's state
690
+ * @param st - the inference so far; changed in place
691
+ * @param classes - the style classes
692
+ */
693
+ function addClassRules(plan, st, classes) {
694
+ plan.columns.set(CLASS_COLUMN, classes.column);
695
+ for (const r of classes.rules) {
696
+ if (r.role === "group") {
697
+ st.groups.push({ ...r, id: r.id, set: { ...r.set } });
698
+ }
699
+ else {
700
+ st.mappings.set(r.id, { ...r, map: { ...r.map } });
701
+ }
702
+ }
703
+ }
704
+ /**
705
+ * Copies a property's values into a style column the copy rule passes through.
706
+ * @param plan - the target's state
707
+ * @param copy - the copy rule, changed in place
708
+ * @param p - the property
709
+ * @param t - its values
710
+ * @returns how many distinct values it holds
711
+ */
712
+ function copyProperty(plan, copy, p, t) {
713
+ plan.columns.set(`copy.${p}`, t.slice());
714
+ setMapping(copy, p, { kind: "passthrough", by: { style: `copy.${p}` } });
715
+ plan.spend(plan.n);
716
+ return new Set(t.filter((v) => v !== null)).size;
717
+ }
718
+ /**
719
+ * The rule as a plain JSON-stable object.
720
+ * @param d - the draft
721
+ * @returns the rule
722
+ */
723
+ function finish(d) {
724
+ const r = { id: d.id, target: d.target, role: d.role, origin: d.origin, where: d.where };
725
+ if (d.set !== undefined && Object.keys(d.set).length > 0) {
726
+ r.set = d.set;
727
+ }
728
+ if (d.map !== undefined && Object.keys(d.map).length > 0) {
729
+ r.map = d.map;
730
+ }
731
+ if (d.facts !== undefined) {
732
+ r.facts = Object.fromEntries(Object.entries(d.facts).filter(([, v]) => v !== undefined));
733
+ }
734
+ if (d.ext !== undefined) {
735
+ r.ext = d.ext;
736
+ }
737
+ return r;
738
+ }
739
+ /**
740
+ * Compares two texts by code unit, the same everywhere.
741
+ * @param a - one text
742
+ * @param b - the other
743
+ * @returns negative, zero or positive
744
+ */
745
+ function compareText(a, b) {
746
+ if (a === b) {
747
+ return 0;
748
+ }
749
+ return a < b ? -1 : 1;
750
+ }
751
+ /**
752
+ * The entries a person would edit in a rule.
753
+ * @param r - the rule
754
+ * @returns its size
755
+ */
756
+ function ruleSize(r) {
757
+ let size = Object.keys(r.set ?? {}).length;
758
+ for (const m of Object.values(r.map ?? {})) {
759
+ if (m.kind === "discrete") {
760
+ size += m.table.length;
761
+ }
762
+ else if (m.kind === "continuous") {
763
+ size += m.points.length;
764
+ }
765
+ else {
766
+ size += 1;
767
+ }
768
+ }
769
+ return size;
770
+ }
771
+ /** The order in which rules are folded into the copy: inferred first, the tool's defaults last. */
772
+ const FOLD_ORDER = { inferred: 0, declared: 1, tool: 2 };
773
+ /**
774
+ * Keeps at most 15 rules (the exceptions rule makes 16) by moving the least readable rules into the copy, with each
775
+ * property's values as they resolved: exact, never a silent delete.
776
+ * @param plan - the target's state
777
+ * @param drafts - the rules, bottom to top; changed in place
778
+ * @param truth - the file's values per property
779
+ * @param src - the reference source
780
+ */
781
+ function enforceCap(plan, drafts, truth, src) {
782
+ const cap = MAX_STYLE_RULES - 1;
783
+ const copyId = `${plan.target}.copy`;
784
+ let folded = 0;
785
+ while (drafts.length > cap) {
786
+ const cands = drafts.filter((r) => r.id !== copyId);
787
+ if (cands.length === 0) {
788
+ break;
789
+ }
790
+ cands.sort((a, b) => {
791
+ const pa = a.role === "passthrough" ? 1 : 0;
792
+ const pb = b.role === "passthrough" ? 1 : 0;
793
+ return (pa - pb ||
794
+ (FOLD_ORDER[a.origin] ?? 1) - (FOLD_ORDER[b.origin] ?? 1) ||
795
+ ruleSize(b) - ruleSize(a) ||
796
+ drafts.indexOf(b) - drafts.indexOf(a));
797
+ });
798
+ const victim = cands[0];
799
+ const before = drafts.map(finish);
800
+ drafts.splice(drafts.indexOf(victim), 1);
801
+ let copy = drafts.find((r) => r.id === copyId);
802
+ if (copy === undefined) {
803
+ copy = {
804
+ id: copyId,
805
+ target: plan.target,
806
+ role: "passthrough",
807
+ origin: "inferred",
808
+ where: { all: true },
809
+ map: {},
810
+ };
811
+ plan.ids.add(copyId);
812
+ }
813
+ else {
814
+ drafts.splice(drafts.indexOf(copy), 1);
815
+ }
816
+ for (const p of new Set(writes(victim))) {
817
+ // the property's values as the whole stack resolved them, supplied on top for every element
818
+ const t = truth.get(p);
819
+ const vals = t === undefined ? resolveRules(before, plan.target, p, src, plan.budget) : t.slice();
820
+ plan.columns.set(`copy.${p}`, vals);
821
+ setMapping(copy, p, { kind: "passthrough", by: { style: `copy.${p}` } });
822
+ }
823
+ copy.facts = { ...copy.facts, reason: "LAYER_CAP" };
824
+ drafts.push(copy);
825
+ folded++;
826
+ }
827
+ if (folded > 0) {
828
+ plan.notes.add(STYLE_ISSUE.LAYER_CAP, plan.target, null, { count: folded });
829
+ }
830
+ }
831
+ /**
832
+ * The elements whose resolved value is not the one wanted, with the wanted value; none where nothing is wanted, and
833
+ * none where a ramp is tolerated within the tool's rounding.
834
+ * @param n - the element count
835
+ * @param got - the resolved values
836
+ * @param want - the value wanted for an element, or null for none
837
+ * @param tolerated - the elements a ramp matches only within the tool's rounding
838
+ * @returns the wanted values where they differ, or null when none does
839
+ */
840
+ function differences(n, got, want, tolerated) {
841
+ let col = null;
842
+ for (let i = 0; i < n; i++) {
843
+ const w = want(i);
844
+ const differs = w !== null && got[i] !== w && !(tolerated?.has(i) === true && within(got[i], w));
845
+ if (differs) {
846
+ col ?? (col = new Array(n).fill(null));
847
+ col[i] = w;
848
+ }
849
+ }
850
+ return col;
851
+ }
852
+ /**
853
+ * The replay: resolves every property the file gives and compares it with the file's value, or the tool's default
854
+ * where the file gives none. Each difference goes into one sparse exceptions column per property.
855
+ * @param plan - the target's state
856
+ * @param drafts - the rules, bottom to top
857
+ * @param truth - the file's values per property
858
+ * @param toolSet - the tool's default values, or null
859
+ * @param tolerated - per property, the elements a ramp matches only within the tool's rounding
860
+ * @param src - the reference source
861
+ * @returns the exceptions rule, or null when nothing differs
862
+ */
863
+ function replay(plan, drafts, truth, toolSet, tolerated, src) {
864
+ const rules = drafts.map(finish);
865
+ // where the file gives no value, the tool draws its default: its constants, and where a reader adds tool rules
866
+ // of its own (Graphviz's target arrow on directed edges), what those rules give over the constants
867
+ const toolRules = rules.filter((r) => r.origin === "tool");
868
+ const ownToolRules = toolRules.length > (toolSet === null ? 0 : 1);
869
+ const map = {};
870
+ for (const [p, t] of truth) {
871
+ const got = resolveRules(rules, plan.target, p, src, plan.budget);
872
+ const perElement = ownToolRules ? resolveRules(toolRules, plan.target, p, src, plan.budget) : null;
873
+ const constant = toolSet?.[p] ?? null;
874
+ const want = (i) => t[i] ?? (perElement === null ? constant : perElement[i]);
875
+ const col = differences(plan.n, got, want, tolerated.get(p));
876
+ if (col !== null) {
877
+ plan.columns.set(`exceptions.${p}`, col);
878
+ map[p] = { kind: "passthrough", by: { style: `exceptions.${p}` } };
879
+ }
880
+ }
881
+ if (Object.keys(map).length === 0) {
882
+ return null;
883
+ }
884
+ return {
885
+ id: uniqueId(plan, `${plan.target}.exceptions`),
886
+ target: plan.target,
887
+ role: "exceptions",
888
+ origin: "inferred",
889
+ where: { all: true },
890
+ map,
891
+ };
892
+ }
893
+ //# sourceMappingURL=plan.js.map