@graphty/graph-io 0.3.42 → 0.3.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/approximations-3Q4TsdTh.js +40 -0
- package/dist/chunks/approximations-3Q4TsdTh.js.map +1 -0
- package/dist/chunks/block-JQiwViEt.js +2777 -0
- package/dist/chunks/block-JQiwViEt.js.map +1 -0
- package/dist/chunks/{choose-DvpbdRuz.js → choose-BemygfH8.js} +3 -2
- package/dist/chunks/{choose-DvpbdRuz.js.map → choose-BemygfH8.js.map} +1 -1
- package/dist/chunks/{constants-fT3E8JYY.js → constants-BFUR_CtU.js} +6 -2
- package/dist/chunks/constants-BFUR_CtU.js.map +1 -0
- package/dist/chunks/convert-BcQ8_jMo.js +59 -0
- package/dist/chunks/convert-BcQ8_jMo.js.map +1 -0
- package/dist/chunks/emit-DCwFLts5.js +3456 -0
- package/dist/chunks/emit-DCwFLts5.js.map +1 -0
- package/dist/chunks/{escape-B62ZGM_a.js → escape-B1rMftd9.js} +43 -20
- package/dist/chunks/escape-B1rMftd9.js.map +1 -0
- package/dist/chunks/{export-rKLeGQMo.js → export-D7IGzTG4.js} +196 -792
- package/dist/chunks/export-D7IGzTG4.js.map +1 -0
- package/dist/chunks/{exporter-BWwEuOPT.js → exporter-BtnqYuuj.js} +22 -12
- package/dist/chunks/exporter-BtnqYuuj.js.map +1 -0
- package/dist/chunks/{exporter-yLxKBvLE.js → exporter-ChPyhBOv.js} +4 -3
- package/dist/chunks/{exporter-yLxKBvLE.js.map → exporter-ChPyhBOv.js.map} +1 -1
- package/dist/chunks/{exporter-8hLNemFk.js → exporter-KEPxYUXD.js} +133 -74
- package/dist/chunks/exporter-KEPxYUXD.js.map +1 -0
- package/dist/chunks/{exporter-CpRyHZ3H.js → exporter-quPUCBiC.js} +1807 -288
- package/dist/chunks/exporter-quPUCBiC.js.map +1 -0
- package/dist/chunks/format-GDmO6m6Q.js +676 -0
- package/dist/chunks/format-GDmO6m6Q.js.map +1 -0
- package/dist/chunks/generic-BL06jrJf.js +1347 -0
- package/dist/chunks/generic-BL06jrJf.js.map +1 -0
- package/dist/chunks/{importer-WrGRZb0N.js → importer-B7r2owVf.js} +449 -102
- package/dist/chunks/importer-B7r2owVf.js.map +1 -0
- package/dist/chunks/{importer-Ht7LNg8L.js → importer-BFmOP96W.js} +116 -296
- package/dist/chunks/importer-BFmOP96W.js.map +1 -0
- package/dist/chunks/{importer-BbNb7eNg.js → importer-C2nzGhdV.js} +1390 -129
- package/dist/chunks/importer-C2nzGhdV.js.map +1 -0
- package/dist/chunks/{importer-Dz7tI8Sa.js → importer-CbX2_rNF.js} +617 -115
- package/dist/chunks/importer-CbX2_rNF.js.map +1 -0
- package/dist/chunks/{importer-D794XUTe.js → importer-CdzeN6X4.js} +31 -8
- package/dist/chunks/importer-CdzeN6X4.js.map +1 -0
- package/dist/chunks/{importer-xZ-3suY1.js → importer-ChKNC_GN.js} +791 -135
- package/dist/chunks/importer-ChKNC_GN.js.map +1 -0
- package/dist/chunks/{importer-C98dpSH4.js → importer-dwoYpSqb.js} +141 -82
- package/dist/chunks/importer-dwoYpSqb.js.map +1 -0
- package/dist/chunks/index-B9fdNpTA.js +4310 -0
- package/dist/chunks/index-B9fdNpTA.js.map +1 -0
- package/dist/chunks/{json-elements-DKSqpNW1.js → json-elements-C4FwgnH5.js} +123 -32
- package/dist/chunks/json-elements-C4FwgnH5.js.map +1 -0
- package/dist/chunks/lexicon-B-knUi-l.js +508 -0
- package/dist/chunks/lexicon-B-knUi-l.js.map +1 -0
- package/dist/chunks/{ontology-export-CtRXjg_i.js → ontology-export-BSpbY5FL.js} +3 -2
- package/dist/chunks/{ontology-export-CtRXjg_i.js.map → ontology-export-BSpbY5FL.js.map} +1 -1
- package/dist/chunks/{records-Cu4bxYOm.js → records-Nwz_rbNt.js} +2 -2
- package/dist/chunks/{records-Cu4bxYOm.js.map → records-Nwz_rbNt.js.map} +1 -1
- package/dist/chunks/styles-Brt9JMfs.js +690 -0
- package/dist/chunks/styles-Brt9JMfs.js.map +1 -0
- package/dist/chunks/styles-_N-C8S-U.js +2102 -0
- package/dist/chunks/styles-_N-C8S-U.js.map +1 -0
- package/dist/chunks/styles-yed-DAfcIkf7.js +842 -0
- package/dist/chunks/styles-yed-DAfcIkf7.js.map +1 -0
- package/dist/chunks/{text-DHOJXnED.js → text-CgzMqHQb.js} +2 -2
- package/dist/chunks/{text-DHOJXnED.js.map → text-CgzMqHQb.js.map} +1 -1
- package/dist/chunks/units-XMZFIFe1.js +19 -0
- package/dist/chunks/units-XMZFIFe1.js.map +1 -0
- package/dist/csv.js +5 -4
- package/dist/csv.js.map +1 -1
- package/dist/cx.js +1 -1
- package/dist/cx2.js +2 -2
- package/dist/cys.js +1 -1
- package/dist/dot.js +5 -2
- package/dist/dot.js.map +1 -1
- package/dist/gexf.js +295 -414
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +8 -3031
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +354 -240
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +4 -2
- package/dist/graphml.js.map +1 -1
- package/dist/json.js +1 -1
- package/dist/neo4j.js +4 -3
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +1 -1
- package/dist/pajek.js +4 -2
- package/dist/positions.d.ts +1 -0
- package/dist/positions.js +427 -0
- package/dist/positions.js.map +1 -0
- package/dist/src/common/codes.d.ts +6 -0
- package/dist/src/common/codes.d.ts.map +1 -1
- package/dist/src/common/codes.js +6 -0
- package/dist/src/common/codes.js.map +1 -1
- package/dist/src/common/escape.d.ts.map +1 -1
- package/dist/src/common/escape.js +4 -2
- package/dist/src/common/escape.js.map +1 -1
- package/dist/src/common/export.d.ts +10 -0
- package/dist/src/common/export.d.ts.map +1 -1
- package/dist/src/common/export.js +123 -100
- package/dist/src/common/export.js.map +1 -1
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +8 -1
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/json-elements.d.ts +12 -9
- package/dist/src/common/json-elements.d.ts.map +1 -1
- package/dist/src/common/json-elements.js +160 -37
- package/dist/src/common/json-elements.js.map +1 -1
- package/dist/src/common/notes.d.ts +42 -0
- package/dist/src/common/notes.d.ts.map +1 -0
- package/dist/src/common/notes.js +72 -0
- package/dist/src/common/notes.js.map +1 -0
- package/dist/src/common/report.d.ts +18 -0
- package/dist/src/common/report.d.ts.map +1 -1
- package/dist/src/common/report.js +36 -1
- package/dist/src/common/report.js.map +1 -1
- package/dist/src/common/units.d.ts +24 -0
- package/dist/src/common/units.d.ts.map +1 -0
- package/dist/src/common/units.js +26 -0
- package/dist/src/common/units.js.map +1 -0
- package/dist/src/common/xml.d.ts +18 -0
- package/dist/src/common/xml.d.ts.map +1 -1
- package/dist/src/common/xml.js +42 -5
- package/dist/src/common/xml.js.map +1 -1
- package/dist/src/formats/cx/exporter.d.ts +6 -0
- package/dist/src/formats/cx/exporter.d.ts.map +1 -1
- package/dist/src/formats/cx/exporter.js +71 -8
- package/dist/src/formats/cx/exporter.js.map +1 -1
- package/dist/src/formats/cx/importer.d.ts +5 -2
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +102 -72
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx/styles.d.ts +102 -0
- package/dist/src/formats/cx/styles.d.ts.map +1 -0
- package/dist/src/formats/cx/styles.js +225 -0
- package/dist/src/formats/cx/styles.js.map +1 -0
- package/dist/src/formats/cx2/exporter.d.ts +5 -0
- package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
- package/dist/src/formats/cx2/exporter.js +181 -71
- package/dist/src/formats/cx2/exporter.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts +4 -1
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +19 -1
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/cx2/styles.d.ts +18 -0
- package/dist/src/formats/cx2/styles.d.ts.map +1 -0
- package/dist/src/formats/cx2/styles.js +24 -0
- package/dist/src/formats/cx2/styles.js.map +1 -0
- package/dist/src/formats/cys/constants.d.ts +2 -0
- package/dist/src/formats/cys/constants.d.ts.map +1 -1
- package/dist/src/formats/cys/constants.js +2 -0
- package/dist/src/formats/cys/constants.js.map +1 -1
- package/dist/src/formats/cys/exporter.d.ts +6 -2
- package/dist/src/formats/cys/exporter.d.ts.map +1 -1
- package/dist/src/formats/cys/exporter.js +215 -53
- package/dist/src/formats/cys/exporter.js.map +1 -1
- package/dist/src/formats/cys/importer.d.ts +2 -1
- package/dist/src/formats/cys/importer.d.ts.map +1 -1
- package/dist/src/formats/cys/importer.js +119 -6
- package/dist/src/formats/cys/importer.js.map +1 -1
- package/dist/src/formats/cys/session.d.ts +2 -0
- package/dist/src/formats/cys/session.d.ts.map +1 -1
- package/dist/src/formats/cys/session.js +5 -0
- package/dist/src/formats/cys/session.js.map +1 -1
- package/dist/src/formats/cys/styles.d.ts +38 -0
- package/dist/src/formats/cys/styles.d.ts.map +1 -0
- package/dist/src/formats/cys/styles.js +213 -0
- package/dist/src/formats/cys/styles.js.map +1 -0
- package/dist/src/formats/cys/tables.d.ts +8 -3
- package/dist/src/formats/cys/tables.d.ts.map +1 -1
- package/dist/src/formats/cys/tables.js +88 -34
- package/dist/src/formats/cys/tables.js.map +1 -1
- package/dist/src/formats/dot/exporter.d.ts +2 -0
- package/dist/src/formats/dot/exporter.d.ts.map +1 -1
- package/dist/src/formats/dot/exporter.js +195 -81
- package/dist/src/formats/dot/exporter.js.map +1 -1
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +100 -20
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/index.d.ts +1 -0
- package/dist/src/formats/dot/index.d.ts.map +1 -1
- package/dist/src/formats/dot/index.js +1 -0
- package/dist/src/formats/dot/index.js.map +1 -1
- package/dist/src/formats/dot/positions.d.ts +14 -0
- package/dist/src/formats/dot/positions.d.ts.map +1 -0
- package/dist/src/formats/dot/positions.js +70 -0
- package/dist/src/formats/dot/positions.js.map +1 -0
- package/dist/src/formats/dot/styles.d.ts +82 -0
- package/dist/src/formats/dot/styles.d.ts.map +1 -0
- package/dist/src/formats/dot/styles.js +1484 -0
- package/dist/src/formats/dot/styles.js.map +1 -0
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +23 -7
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts +8 -1
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +251 -131
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/index.d.ts +8 -0
- package/dist/src/formats/gexf/index.d.ts.map +1 -1
- package/dist/src/formats/gexf/index.js +10 -2
- package/dist/src/formats/gexf/index.js.map +1 -1
- package/dist/src/formats/gexf/schema.d.ts +5 -0
- package/dist/src/formats/gexf/schema.d.ts.map +1 -1
- package/dist/src/formats/gexf/schema.js +5 -0
- package/dist/src/formats/gexf/schema.js.map +1 -1
- package/dist/src/formats/gexf/styles.d.ts +74 -0
- package/dist/src/formats/gexf/styles.d.ts.map +1 -0
- package/dist/src/formats/gexf/styles.js +604 -0
- package/dist/src/formats/gexf/styles.js.map +1 -0
- package/dist/src/formats/gml/exporter.d.ts +1 -5
- package/dist/src/formats/gml/exporter.d.ts.map +1 -1
- package/dist/src/formats/gml/exporter.js +19 -8
- package/dist/src/formats/gml/exporter.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +4 -0
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/index.d.ts +2 -1
- package/dist/src/formats/gml/index.d.ts.map +1 -1
- package/dist/src/formats/gml/index.js +2 -1
- package/dist/src/formats/gml/index.js.map +1 -1
- package/dist/src/formats/gml/positions.d.ts +14 -0
- package/dist/src/formats/gml/positions.d.ts.map +1 -0
- package/dist/src/formats/gml/positions.js +46 -0
- package/dist/src/formats/gml/positions.js.map +1 -0
- package/dist/src/formats/gml/styles.d.ts +59 -0
- package/dist/src/formats/gml/styles.d.ts.map +1 -0
- package/dist/src/formats/gml/styles.js +1056 -0
- package/dist/src/formats/gml/styles.js.map +1 -0
- package/dist/src/formats/gml/syntax.d.ts +11 -0
- package/dist/src/formats/gml/syntax.d.ts.map +1 -1
- package/dist/src/formats/gml/syntax.js +151 -62
- package/dist/src/formats/gml/syntax.js.map +1 -1
- package/dist/src/formats/graphml/constants.d.ts +4 -0
- package/dist/src/formats/graphml/constants.d.ts.map +1 -1
- package/dist/src/formats/graphml/constants.js +5 -1
- package/dist/src/formats/graphml/constants.js.map +1 -1
- package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
- package/dist/src/formats/graphml/exporter.js +133 -65
- package/dist/src/formats/graphml/exporter.js.map +1 -1
- package/dist/src/formats/graphml/importer.d.ts +4 -1
- package/dist/src/formats/graphml/importer.d.ts.map +1 -1
- package/dist/src/formats/graphml/importer.js +100 -44
- package/dist/src/formats/graphml/importer.js.map +1 -1
- package/dist/src/formats/graphml/index.d.ts +1 -0
- package/dist/src/formats/graphml/index.d.ts.map +1 -1
- package/dist/src/formats/graphml/index.js +1 -0
- package/dist/src/formats/graphml/index.js.map +1 -1
- package/dist/src/formats/graphml/styles-plain.d.ts +19 -0
- package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -0
- package/dist/src/formats/graphml/styles-plain.js +187 -0
- package/dist/src/formats/graphml/styles-plain.js.map +1 -0
- package/dist/src/formats/graphml/styles-yed.d.ts +179 -0
- package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -0
- package/dist/src/formats/graphml/styles-yed.js +1086 -0
- package/dist/src/formats/graphml/styles-yed.js.map +1 -0
- package/dist/src/formats/graphml/styles-yfiles3.d.ts +19 -0
- package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -0
- package/dist/src/formats/graphml/styles-yfiles3.js +508 -0
- package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -0
- package/dist/src/formats/graphml/tree.d.ts.map +1 -1
- package/dist/src/formats/graphml/tree.js +34 -19
- package/dist/src/formats/graphml/tree.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts +16 -2
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +83 -12
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/exporter.d.ts +5 -0
- package/dist/src/formats/json/exporter.d.ts.map +1 -1
- package/dist/src/formats/json/exporter.js +68 -25
- package/dist/src/formats/json/exporter.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts +22 -3
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +441 -265
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/positions.d.ts +16 -0
- package/dist/src/formats/json/positions.d.ts.map +1 -0
- package/dist/src/formats/json/positions.js +44 -0
- package/dist/src/formats/json/positions.js.map +1 -0
- package/dist/src/formats/json/styles.d.ts +102 -0
- package/dist/src/formats/json/styles.d.ts.map +1 -0
- package/dist/src/formats/json/styles.js +1753 -0
- package/dist/src/formats/json/styles.js.map +1 -0
- package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
- package/dist/src/formats/neo4j/exporter.js +2 -1
- package/dist/src/formats/neo4j/exporter.js.map +1 -1
- package/dist/src/formats/pajek/exporter.d.ts +2 -0
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +142 -76
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts +4 -0
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +60 -6
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/index.d.ts +2 -0
- package/dist/src/formats/pajek/index.d.ts.map +1 -1
- package/dist/src/formats/pajek/index.js +2 -0
- package/dist/src/formats/pajek/index.js.map +1 -1
- package/dist/src/formats/pajek/styles.d.ts +50 -0
- package/dist/src/formats/pajek/styles.d.ts.map +1 -0
- package/dist/src/formats/pajek/styles.js +569 -0
- package/dist/src/formats/pajek/styles.js.map +1 -0
- package/dist/src/formats/pajek/syntax.d.ts +6 -0
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +6 -0
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
- package/dist/src/formats/xgmml/columns.js +34 -9
- package/dist/src/formats/xgmml/columns.js.map +1 -1
- package/dist/src/formats/xgmml/constants.d.ts +2 -0
- package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
- package/dist/src/formats/xgmml/constants.js +3 -1
- package/dist/src/formats/xgmml/constants.js.map +1 -1
- package/dist/src/formats/xgmml/document.d.ts +12 -8
- package/dist/src/formats/xgmml/document.d.ts.map +1 -1
- package/dist/src/formats/xgmml/document.js +56 -13
- package/dist/src/formats/xgmml/document.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +12 -6
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/exporter.d.ts +3 -1
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
- package/dist/src/formats/xgmml/exporter.js +22 -9
- package/dist/src/formats/xgmml/exporter.js.map +1 -1
- package/dist/src/formats/xgmml/importer.d.ts +2 -1
- package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
- package/dist/src/formats/xgmml/importer.js +31 -24
- package/dist/src/formats/xgmml/importer.js.map +1 -1
- package/dist/src/formats/xgmml/styles.d.ts +104 -0
- package/dist/src/formats/xgmml/styles.d.ts.map +1 -0
- package/dist/src/formats/xgmml/styles.js +310 -0
- package/dist/src/formats/xgmml/styles.js.map +1 -0
- package/dist/src/index.d.ts +9 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -7
- package/dist/src/index.js.map +1 -1
- package/dist/src/positions/codes.d.ts +31 -0
- package/dist/src/positions/codes.d.ts.map +1 -0
- package/dist/src/positions/codes.js +26 -0
- package/dist/src/positions/codes.js.map +1 -0
- package/dist/src/positions/convert.d.ts +58 -0
- package/dist/src/positions/convert.d.ts.map +1 -0
- package/dist/src/positions/convert.js +107 -0
- package/dist/src/positions/convert.js.map +1 -0
- package/dist/src/positions/extract.d.ts +27 -0
- package/dist/src/positions/extract.d.ts.map +1 -0
- package/dist/src/positions/extract.js +526 -0
- package/dist/src/positions/extract.js.map +1 -0
- package/dist/src/positions/index.d.ts +10 -0
- package/dist/src/positions/index.d.ts.map +1 -0
- package/dist/src/positions/index.js +9 -0
- package/dist/src/positions/index.js.map +1 -0
- package/dist/src/positions/types.d.ts +208 -0
- package/dist/src/positions/types.d.ts.map +1 -0
- package/dist/src/positions/types.js +10 -0
- package/dist/src/positions/types.js.map +1 -0
- package/dist/src/registry.d.ts +30 -0
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +130 -9
- package/dist/src/registry.js.map +1 -1
- package/dist/src/styles/annotations.d.ts +132 -0
- package/dist/src/styles/annotations.d.ts.map +1 -0
- package/dist/src/styles/annotations.js +320 -0
- package/dist/src/styles/annotations.js.map +1 -0
- package/dist/src/styles/budget.d.ts +45 -0
- package/dist/src/styles/budget.d.ts.map +1 -0
- package/dist/src/styles/budget.js +58 -0
- package/dist/src/styles/budget.js.map +1 -0
- package/dist/src/styles/canon/bends.d.ts +32 -0
- package/dist/src/styles/canon/bends.d.ts.map +1 -0
- package/dist/src/styles/canon/bends.js +74 -0
- package/dist/src/styles/canon/bends.js.map +1 -0
- package/dist/src/styles/canon/color-tables.d.ts +22 -0
- package/dist/src/styles/canon/color-tables.d.ts.map +1 -0
- package/dist/src/styles/canon/color-tables.js +369 -0
- package/dist/src/styles/canon/color-tables.js.map +1 -0
- package/dist/src/styles/canon/color.d.ts +66 -0
- package/dist/src/styles/canon/color.d.ts.map +1 -0
- package/dist/src/styles/canon/color.js +548 -0
- package/dist/src/styles/canon/color.js.map +1 -0
- package/dist/src/styles/canon/enums.d.ts +25 -0
- package/dist/src/styles/canon/enums.d.ts.map +1 -0
- package/dist/src/styles/canon/enums.js +187 -0
- package/dist/src/styles/canon/enums.js.map +1 -0
- package/dist/src/styles/canon/graphviz.d.ts +48 -0
- package/dist/src/styles/canon/graphviz.d.ts.map +1 -0
- package/dist/src/styles/canon/graphviz.js +160 -0
- package/dist/src/styles/canon/graphviz.js.map +1 -0
- package/dist/src/styles/canon/index.d.ts +13 -0
- package/dist/src/styles/canon/index.d.ts.map +1 -0
- package/dist/src/styles/canon/index.js +13 -0
- package/dist/src/styles/canon/index.js.map +1 -0
- package/dist/src/styles/canon/number.d.ts +59 -0
- package/dist/src/styles/canon/number.d.ts.map +1 -0
- package/dist/src/styles/canon/number.js +142 -0
- package/dist/src/styles/canon/number.js.map +1 -0
- package/dist/src/styles/canon/site.d.ts +51 -0
- package/dist/src/styles/canon/site.d.ts.map +1 -0
- package/dist/src/styles/canon/site.js +63 -0
- package/dist/src/styles/canon/site.js.map +1 -0
- package/dist/src/styles/canon/text.d.ts +61 -0
- package/dist/src/styles/canon/text.d.ts.map +1 -0
- package/dist/src/styles/canon/text.js +199 -0
- package/dist/src/styles/canon/text.js.map +1 -0
- package/dist/src/styles/codes.d.ts +95 -0
- package/dist/src/styles/codes.d.ts.map +1 -0
- package/dist/src/styles/codes.js +97 -0
- package/dist/src/styles/codes.js.map +1 -0
- package/dist/src/styles/cyjs/cascade.d.ts +134 -0
- package/dist/src/styles/cyjs/cascade.d.ts.map +1 -0
- package/dist/src/styles/cyjs/cascade.js +2252 -0
- package/dist/src/styles/cyjs/cascade.js.map +1 -0
- package/dist/src/styles/cyjs/defaults-table.d.ts +25 -0
- package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -0
- package/dist/src/styles/cyjs/defaults-table.js +76 -0
- package/dist/src/styles/cyjs/defaults-table.js.map +1 -0
- package/dist/src/styles/cyjs/emit.d.ts +82 -0
- package/dist/src/styles/cyjs/emit.d.ts.map +1 -0
- package/dist/src/styles/cyjs/emit.js +790 -0
- package/dist/src/styles/cyjs/emit.js.map +1 -0
- package/dist/src/styles/cyjs/index.d.ts +13 -0
- package/dist/src/styles/cyjs/index.d.ts.map +1 -0
- package/dist/src/styles/cyjs/index.js +13 -0
- package/dist/src/styles/cyjs/index.js.map +1 -0
- package/dist/src/styles/cyjs/live.d.ts +46 -0
- package/dist/src/styles/cyjs/live.d.ts.map +1 -0
- package/dist/src/styles/cyjs/live.js +108 -0
- package/dist/src/styles/cyjs/live.js.map +1 -0
- package/dist/src/styles/cyjs/mappers.d.ts +147 -0
- package/dist/src/styles/cyjs/mappers.d.ts.map +1 -0
- package/dist/src/styles/cyjs/mappers.js +744 -0
- package/dist/src/styles/cyjs/mappers.js.map +1 -0
- package/dist/src/styles/cyjs/selector.d.ts +113 -0
- package/dist/src/styles/cyjs/selector.d.ts.map +1 -0
- package/dist/src/styles/cyjs/selector.js +611 -0
- package/dist/src/styles/cyjs/selector.js.map +1 -0
- package/dist/src/styles/cyjs/stylesheet-text.d.ts +37 -0
- package/dist/src/styles/cyjs/stylesheet-text.d.ts.map +1 -0
- package/dist/src/styles/cyjs/stylesheet-text.js +181 -0
- package/dist/src/styles/cyjs/stylesheet-text.js.map +1 -0
- package/dist/src/styles/cytoscape/emit.d.ts +125 -0
- package/dist/src/styles/cytoscape/emit.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/emit.js +1025 -0
- package/dist/src/styles/cytoscape/emit.js.map +1 -0
- package/dist/src/styles/cytoscape/index.d.ts +10 -0
- package/dist/src/styles/cytoscape/index.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/index.js +10 -0
- package/dist/src/styles/cytoscape/index.js.map +1 -0
- package/dist/src/styles/cytoscape/lexicon.d.ts +49 -0
- package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/lexicon.js +603 -0
- package/dist/src/styles/cytoscape/lexicon.js.map +1 -0
- package/dist/src/styles/cytoscape/mappings.d.ts +171 -0
- package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/mappings.js +460 -0
- package/dist/src/styles/cytoscape/mappings.js.map +1 -0
- package/dist/src/styles/cytoscape/resolve.d.ts +137 -0
- package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/resolve.js +381 -0
- package/dist/src/styles/cytoscape/resolve.js.map +1 -0
- package/dist/src/styles/cytoscape/translate.d.ts +50 -0
- package/dist/src/styles/cytoscape/translate.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/translate.js +156 -0
- package/dist/src/styles/cytoscape/translate.js.map +1 -0
- package/dist/src/styles/defaults.d.ts +90 -0
- package/dist/src/styles/defaults.d.ts.map +1 -0
- package/dist/src/styles/defaults.js +414 -0
- package/dist/src/styles/defaults.js.map +1 -0
- package/dist/src/styles/index.d.ts +15 -0
- package/dist/src/styles/index.d.ts.map +1 -0
- package/dist/src/styles/index.js +14 -0
- package/dist/src/styles/index.js.map +1 -0
- package/dist/src/styles/internal.d.ts +17 -0
- package/dist/src/styles/internal.d.ts.map +1 -0
- package/dist/src/styles/internal.js +16 -0
- package/dist/src/styles/internal.js.map +1 -0
- package/dist/src/styles/io/approximations.d.ts +24 -0
- package/dist/src/styles/io/approximations.d.ts.map +1 -0
- package/dist/src/styles/io/approximations.js +51 -0
- package/dist/src/styles/io/approximations.js.map +1 -0
- package/dist/src/styles/io/block.d.ts +166 -0
- package/dist/src/styles/io/block.d.ts.map +1 -0
- package/dist/src/styles/io/block.js +930 -0
- package/dist/src/styles/io/block.js.map +1 -0
- package/dist/src/styles/io/generic.d.ts +88 -0
- package/dist/src/styles/io/generic.d.ts.map +1 -0
- package/dist/src/styles/io/generic.js +516 -0
- package/dist/src/styles/io/generic.js.map +1 -0
- package/dist/src/styles/io/index.d.ts +8 -0
- package/dist/src/styles/io/index.d.ts.map +1 -0
- package/dist/src/styles/io/index.js +7 -0
- package/dist/src/styles/io/index.js.map +1 -0
- package/dist/src/styles/io/writer.d.ts +80 -0
- package/dist/src/styles/io/writer.d.ts.map +1 -0
- package/dist/src/styles/io/writer.js +596 -0
- package/dist/src/styles/io/writer.js.map +1 -0
- package/dist/src/styles/notes.d.ts +47 -0
- package/dist/src/styles/notes.d.ts.map +1 -0
- package/dist/src/styles/notes.js +140 -0
- package/dist/src/styles/notes.js.map +1 -0
- package/dist/src/styles/plan/classes.d.ts +31 -0
- package/dist/src/styles/plan/classes.d.ts.map +1 -0
- package/dist/src/styles/plan/classes.js +139 -0
- package/dist/src/styles/plan/classes.js.map +1 -0
- package/dist/src/styles/plan/continuous.d.ts +32 -0
- package/dist/src/styles/plan/continuous.d.ts.map +1 -0
- package/dist/src/styles/plan/continuous.js +165 -0
- package/dist/src/styles/plan/continuous.js.map +1 -0
- package/dist/src/styles/plan/discrete.d.ts +39 -0
- package/dist/src/styles/plan/discrete.d.ts.map +1 -0
- package/dist/src/styles/plan/discrete.js +127 -0
- package/dist/src/styles/plan/discrete.js.map +1 -0
- package/dist/src/styles/plan/families.d.ts +31 -0
- package/dist/src/styles/plan/families.d.ts.map +1 -0
- package/dist/src/styles/plan/families.js +95 -0
- package/dist/src/styles/plan/families.js.map +1 -0
- package/dist/src/styles/plan/features.d.ts +58 -0
- package/dist/src/styles/plan/features.d.ts.map +1 -0
- package/dist/src/styles/plan/features.js +185 -0
- package/dist/src/styles/plan/features.js.map +1 -0
- package/dist/src/styles/plan/index.d.ts +7 -0
- package/dist/src/styles/plan/index.d.ts.map +1 -0
- package/dist/src/styles/plan/index.js +7 -0
- package/dist/src/styles/plan/index.js.map +1 -0
- package/dist/src/styles/plan/plan.d.ts +71 -0
- package/dist/src/styles/plan/plan.d.ts.map +1 -0
- package/dist/src/styles/plan/plan.js +893 -0
- package/dist/src/styles/plan/plan.js.map +1 -0
- package/dist/src/styles/plan/resolve.d.ts +137 -0
- package/dist/src/styles/plan/resolve.d.ts.map +1 -0
- package/dist/src/styles/plan/resolve.js +587 -0
- package/dist/src/styles/plan/resolve.js.map +1 -0
- package/dist/src/styles/types.d.ts +702 -0
- package/dist/src/styles/types.d.ts.map +1 -0
- package/dist/src/styles/types.js +10 -0
- package/dist/src/styles/types.js.map +1 -0
- package/dist/src/styles/vocabulary.d.ts +41 -0
- package/dist/src/styles/vocabulary.d.ts.map +1 -0
- package/dist/src/styles/vocabulary.js +140 -0
- package/dist/src/styles/vocabulary.js.map +1 -0
- package/dist/src/types.d.ts +64 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/styles.d.ts +1 -0
- package/dist/styles.js +322 -0
- package/dist/styles.js.map +1 -0
- package/dist/xgmml.js +5 -4
- package/dist/xgmml.js.map +1 -1
- package/package.json +13 -2
- package/src/common/codes.ts +7 -0
- package/src/common/escape.ts +5 -2
- package/src/common/export.ts +179 -140
- package/src/common/input.ts +8 -4
- package/src/common/json-elements.ts +169 -38
- package/src/common/notes.ts +94 -0
- package/src/common/report.ts +41 -1
- package/src/common/units.ts +42 -0
- package/src/common/xml.ts +45 -5
- package/src/formats/cx/exporter.ts +95 -11
- package/src/formats/cx/importer.ts +126 -90
- package/src/formats/cx/styles.ts +304 -0
- package/src/formats/cx2/exporter.ts +234 -77
- package/src/formats/cx2/importer.ts +19 -1
- package/src/formats/cx2/styles.ts +29 -0
- package/src/formats/cys/constants.ts +3 -0
- package/src/formats/cys/exporter.ts +246 -60
- package/src/formats/cys/importer.ts +125 -9
- package/src/formats/cys/session.ts +6 -0
- package/src/formats/cys/styles.ts +254 -0
- package/src/formats/cys/tables.ts +117 -48
- package/src/formats/dot/exporter.ts +262 -126
- package/src/formats/dot/importer.ts +111 -20
- package/src/formats/dot/index.ts +1 -0
- package/src/formats/dot/positions.ts +77 -0
- package/src/formats/dot/styles.ts +1741 -0
- package/src/formats/gexf/exporter.ts +30 -13
- package/src/formats/gexf/importer.ts +308 -158
- package/src/formats/gexf/index.ts +10 -0
- package/src/formats/gexf/schema.ts +5 -0
- package/src/formats/gexf/styles.ts +719 -0
- package/src/formats/gml/exporter.ts +33 -14
- package/src/formats/gml/importer.ts +4 -0
- package/src/formats/gml/index.ts +2 -1
- package/src/formats/gml/positions.ts +52 -0
- package/src/formats/gml/styles.ts +1248 -0
- package/src/formats/gml/syntax.ts +173 -62
- package/src/formats/graphml/constants.ts +5 -0
- package/src/formats/graphml/exporter.ts +163 -71
- package/src/formats/graphml/importer.ts +119 -45
- package/src/formats/graphml/index.ts +1 -0
- package/src/formats/graphml/styles-plain.ts +236 -0
- package/src/formats/graphml/styles-yed.ts +1221 -0
- package/src/formats/graphml/styles-yfiles3.ts +573 -0
- package/src/formats/graphml/tree.ts +36 -20
- package/src/formats/graphml/yfiles.ts +89 -13
- package/src/formats/json/exporter.ts +76 -26
- package/src/formats/json/importer.ts +543 -323
- package/src/formats/json/positions.ts +50 -0
- package/src/formats/json/styles.ts +2082 -0
- package/src/formats/neo4j/exporter.ts +2 -1
- package/src/formats/pajek/exporter.ts +195 -106
- package/src/formats/pajek/importer.ts +78 -9
- package/src/formats/pajek/index.ts +2 -0
- package/src/formats/pajek/styles.ts +685 -0
- package/src/formats/pajek/syntax.ts +7 -0
- package/src/formats/xgmml/columns.ts +39 -9
- package/src/formats/xgmml/constants.ts +3 -0
- package/src/formats/xgmml/document.ts +54 -12
- package/src/formats/xgmml/emit.ts +11 -6
- package/src/formats/xgmml/exporter.ts +32 -13
- package/src/formats/xgmml/importer.ts +43 -29
- package/src/formats/xgmml/styles.ts +400 -0
- package/src/index.ts +16 -0
- package/src/positions/codes.ts +32 -0
- package/src/positions/convert.ts +123 -0
- package/src/positions/extract.ts +619 -0
- package/src/positions/index.ts +23 -0
- package/src/positions/types.ts +221 -0
- package/src/registry.ts +179 -8
- package/src/styles/annotations.ts +478 -0
- package/src/styles/budget.ts +60 -0
- package/src/styles/canon/bends.ts +84 -0
- package/src/styles/canon/color-tables.ts +386 -0
- package/src/styles/canon/color.ts +624 -0
- package/src/styles/canon/enums.ts +211 -0
- package/src/styles/canon/graphviz.ts +189 -0
- package/src/styles/canon/index.ts +13 -0
- package/src/styles/canon/number.ts +152 -0
- package/src/styles/canon/site.ts +87 -0
- package/src/styles/canon/text.ts +221 -0
- package/src/styles/codes.ts +104 -0
- package/src/styles/cyjs/cascade.ts +2670 -0
- package/src/styles/cyjs/defaults-table.ts +82 -0
- package/src/styles/cyjs/emit.ts +951 -0
- package/src/styles/cyjs/index.ts +37 -0
- package/src/styles/cyjs/live.ts +147 -0
- package/src/styles/cyjs/mappers.ts +879 -0
- package/src/styles/cyjs/selector.ts +778 -0
- package/src/styles/cyjs/stylesheet-text.ts +214 -0
- package/src/styles/cytoscape/emit.ts +1264 -0
- package/src/styles/cytoscape/index.ts +40 -0
- package/src/styles/cytoscape/lexicon.ts +656 -0
- package/src/styles/cytoscape/mappings.ts +603 -0
- package/src/styles/cytoscape/resolve.ts +521 -0
- package/src/styles/cytoscape/translate.ts +237 -0
- package/src/styles/defaults.ts +504 -0
- package/src/styles/index.ts +57 -0
- package/src/styles/internal.ts +17 -0
- package/src/styles/io/approximations.ts +47 -0
- package/src/styles/io/block.ts +1138 -0
- package/src/styles/io/generic.ts +687 -0
- package/src/styles/io/index.ts +18 -0
- package/src/styles/io/writer.ts +745 -0
- package/src/styles/notes.ts +165 -0
- package/src/styles/plan/classes.ts +166 -0
- package/src/styles/plan/continuous.ts +218 -0
- package/src/styles/plan/discrete.ts +165 -0
- package/src/styles/plan/families.ts +115 -0
- package/src/styles/plan/features.ts +234 -0
- package/src/styles/plan/index.ts +7 -0
- package/src/styles/plan/plan.ts +1129 -0
- package/src/styles/plan/resolve.ts +685 -0
- package/src/styles/types.ts +814 -0
- package/src/styles/vocabulary.ts +172 -0
- package/src/types.ts +76 -1
- package/dist/chunks/constants-fT3E8JYY.js.map +0 -1
- package/dist/chunks/escape-B62ZGM_a.js.map +0 -1
- package/dist/chunks/export-rKLeGQMo.js.map +0 -1
- package/dist/chunks/exporter-8hLNemFk.js.map +0 -1
- package/dist/chunks/exporter-BWwEuOPT.js.map +0 -1
- package/dist/chunks/exporter-CpRyHZ3H.js.map +0 -1
- package/dist/chunks/importer-BbNb7eNg.js.map +0 -1
- package/dist/chunks/importer-C98dpSH4.js.map +0 -1
- package/dist/chunks/importer-D794XUTe.js.map +0 -1
- package/dist/chunks/importer-Dz7tI8Sa.js.map +0 -1
- package/dist/chunks/importer-Ht7LNg8L.js.map +0 -1
- package/dist/chunks/importer-WrGRZb0N.js.map +0 -1
- package/dist/chunks/importer-xZ-3suY1.js.map +0 -1
- package/dist/chunks/json-elements-DKSqpNW1.js.map +0 -1
|
@@ -0,0 +1,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
|