@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.
- package/dist/chunks/approximations-DJMHdDvv.js +40 -0
- package/dist/chunks/approximations-DJMHdDvv.js.map +1 -0
- package/dist/chunks/block-CPCHkX42.js +2777 -0
- package/dist/chunks/block-CPCHkX42.js.map +1 -0
- package/dist/chunks/{choose-DvpbdRuz.js → choose--jM0yYCo.js} +3 -2
- package/dist/chunks/{choose-DvpbdRuz.js.map → choose--jM0yYCo.js.map} +1 -1
- package/dist/chunks/{constants-fT3E8JYY.js → constants-BKwqelYD.js} +6 -2
- package/dist/chunks/constants-BKwqelYD.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-DZy6JgdA.js +3456 -0
- package/dist/chunks/emit-DZy6JgdA.js.map +1 -0
- package/dist/chunks/{escape-B62ZGM_a.js → escape-CgzxiYPg.js} +44 -21
- package/dist/chunks/escape-CgzxiYPg.js.map +1 -0
- package/dist/chunks/{export-rKLeGQMo.js → export-BvqAXCKh.js} +196 -792
- package/dist/chunks/export-BvqAXCKh.js.map +1 -0
- package/dist/chunks/{exporter-yLxKBvLE.js → exporter--Mk9gXCJ.js} +4 -3
- package/dist/chunks/{exporter-yLxKBvLE.js.map → exporter--Mk9gXCJ.js.map} +1 -1
- package/dist/chunks/{exporter-RVtXVetw.js → exporter-C-9cgZKa.js} +1805 -287
- package/dist/chunks/exporter-C-9cgZKa.js.map +1 -0
- package/dist/chunks/{exporter-8hLNemFk.js → exporter-DFqJhBnj.js} +133 -74
- package/dist/chunks/exporter-DFqJhBnj.js.map +1 -0
- package/dist/chunks/{exporter-BWwEuOPT.js → exporter-DteVeJki.js} +22 -12
- package/dist/chunks/exporter-DteVeJki.js.map +1 -0
- package/dist/chunks/format-BpQBx8MZ.js +676 -0
- package/dist/chunks/format-BpQBx8MZ.js.map +1 -0
- package/dist/chunks/generic-BGO71QBv.js +1347 -0
- package/dist/chunks/generic-BGO71QBv.js.map +1 -0
- package/dist/chunks/{importer-C98dpSH4.js → importer-B-9Rc1zO.js} +141 -82
- package/dist/chunks/importer-B-9Rc1zO.js.map +1 -0
- package/dist/chunks/{importer-D794XUTe.js → importer-BVVR740x.js} +31 -8
- package/dist/chunks/importer-BVVR740x.js.map +1 -0
- package/dist/chunks/{importer-WrGRZb0N.js → importer-C0AjA3Ax.js} +449 -102
- package/dist/chunks/importer-C0AjA3Ax.js.map +1 -0
- package/dist/chunks/{importer-BbNb7eNg.js → importer-C7pvJe1L.js} +1398 -129
- package/dist/chunks/importer-C7pvJe1L.js.map +1 -0
- package/dist/chunks/{importer-xZ-3suY1.js → importer-ClwoVx3O.js} +791 -135
- package/dist/chunks/importer-ClwoVx3O.js.map +1 -0
- package/dist/chunks/{importer-Ht7LNg8L.js → importer-D0sC_6bO.js} +116 -296
- package/dist/chunks/importer-D0sC_6bO.js.map +1 -0
- package/dist/chunks/{importer-Dz7tI8Sa.js → importer-EHQk1jbM.js} +617 -115
- package/dist/chunks/importer-EHQk1jbM.js.map +1 -0
- package/dist/chunks/{json-elements-DKSqpNW1.js → json-elements-DJZRZ6jd.js} +123 -32
- package/dist/chunks/json-elements-DJZRZ6jd.js.map +1 -0
- package/dist/chunks/lexicon-WMsNddyU.js +509 -0
- package/dist/chunks/lexicon-WMsNddyU.js.map +1 -0
- package/dist/chunks/{ontology-export-CtRXjg_i.js → ontology-export-G4MqRdux.js} +3 -2
- package/dist/chunks/{ontology-export-CtRXjg_i.js.map → ontology-export-G4MqRdux.js.map} +1 -1
- package/dist/chunks/{records-Cu4bxYOm.js → records-CiaWZrFH.js} +2 -2
- package/dist/chunks/{records-Cu4bxYOm.js.map → records-CiaWZrFH.js.map} +1 -1
- package/dist/chunks/styles-DvoFBKCK.js +690 -0
- package/dist/chunks/styles-DvoFBKCK.js.map +1 -0
- package/dist/chunks/styles-yed-Cz9rLBCP.js +842 -0
- package/dist/chunks/styles-yed-Cz9rLBCP.js.map +1 -0
- package/dist/chunks/styles-zNTmz5R7.js +2102 -0
- package/dist/chunks/styles-zNTmz5R7.js.map +1 -0
- package/dist/chunks/{text-DHOJXnED.js → text-CzJNFOS9.js} +2 -2
- package/dist/chunks/{text-DHOJXnED.js.map → text-CzJNFOS9.js.map} +1 -1
- package/dist/chunks/units-XMZFIFe1.js +19 -0
- package/dist/chunks/units-XMZFIFe1.js.map +1 -0
- package/dist/chunks/writer-gQ8kx99H.js +448 -0
- package/dist/chunks/writer-gQ8kx99H.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 +292 -412
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +927 -74
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +351 -236
- 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 +1496 -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 +20 -5
- 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 +439 -264
- 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 +791 -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 +605 -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 +89 -0
- package/dist/src/styles/io/writer.d.ts.map +1 -0
- package/dist/src/styles/io/writer.js +626 -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 +1755 -0
- package/src/formats/gexf/exporter.ts +27 -11
- 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 +541 -322
- 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 +952 -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 +658 -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 +780 -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-RVtXVetw.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,3456 @@
|
|
|
1
|
+
import { a as STYLE_ISSUE, i as num6, l as canonEnum, W as CSS_COLORS, t as StyleNotes, d as canonicalFor, p as plainCell, Q as evalContinuous, R as numberOf, e as degreeValues, L as refSource, B as STYLE_PROPERTIES, O as resolveRules, P as matches } from "./block-CPCHkX42.js";
|
|
2
|
+
const STYLE_WORK_BUDGET = 2e8;
|
|
3
|
+
class StyleBudget {
|
|
4
|
+
#used = { node: 0, edge: 0 };
|
|
5
|
+
/**
|
|
6
|
+
* Creates a budget.
|
|
7
|
+
* @param limit - operations allowed per target; defaults to `STYLE_WORK_BUDGET`
|
|
8
|
+
*/
|
|
9
|
+
constructor(limit = STYLE_WORK_BUDGET) {
|
|
10
|
+
this.limit = limit;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Spends operations for a target.
|
|
14
|
+
* @param target - nodes or edges
|
|
15
|
+
* @param operations - how many operations the work costs
|
|
16
|
+
* @returns true while the target has spent at most `limit` operations
|
|
17
|
+
*/
|
|
18
|
+
spend(target, operations) {
|
|
19
|
+
this.#used[target] += operations;
|
|
20
|
+
return this.#used[target] <= this.limit;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether a target has spent more than `limit` operations.
|
|
24
|
+
* @param target - nodes or edges
|
|
25
|
+
* @returns true once the target's budget is exhausted
|
|
26
|
+
*/
|
|
27
|
+
exhausted(target) {
|
|
28
|
+
return this.#used[target] > this.limit;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* How many operations a target has spent.
|
|
32
|
+
* @param target - nodes or edges
|
|
33
|
+
* @returns the operations spent so far
|
|
34
|
+
*/
|
|
35
|
+
used(target) {
|
|
36
|
+
return this.#used[target];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const CYJS_PROPERTY_DEFAULTS = /* @__PURE__ */ new Map([
|
|
40
|
+
["background-color", "rgb(153,153,153)"],
|
|
41
|
+
["background-opacity", "1"],
|
|
42
|
+
["opacity", "1"],
|
|
43
|
+
["border-color", "rgb(0,0,0)"],
|
|
44
|
+
["border-width", "0px"],
|
|
45
|
+
["border-style", "solid"],
|
|
46
|
+
["shape", "ellipse"],
|
|
47
|
+
["width", "30px"],
|
|
48
|
+
["height", "30px"],
|
|
49
|
+
["label", ""],
|
|
50
|
+
["color", "rgb(0,0,0)"],
|
|
51
|
+
["font-size", "16px"],
|
|
52
|
+
["font-family", "Helvetica Neue, Helvetica, sans-serif"],
|
|
53
|
+
["font-weight", "normal"],
|
|
54
|
+
["font-style", "normal"],
|
|
55
|
+
["visibility", "visible"],
|
|
56
|
+
["display", "element"],
|
|
57
|
+
["text-valign", "top"],
|
|
58
|
+
["text-halign", "center"],
|
|
59
|
+
["line-color", "rgb(153,153,153)"],
|
|
60
|
+
["line-style", "solid"],
|
|
61
|
+
["target-arrow-shape", "none"],
|
|
62
|
+
["source-arrow-shape", "none"],
|
|
63
|
+
["target-arrow-color", "rgb(153,153,153)"],
|
|
64
|
+
["source-arrow-color", "rgb(153,153,153)"],
|
|
65
|
+
["curve-style", "haystack"],
|
|
66
|
+
["arrow-scale", "1"],
|
|
67
|
+
["source-label", ""],
|
|
68
|
+
["target-label", ""]
|
|
69
|
+
]);
|
|
70
|
+
const CYJS_DEFAULT_STYLESHEET = [
|
|
71
|
+
{
|
|
72
|
+
selector: ":parent",
|
|
73
|
+
style: {
|
|
74
|
+
shape: "rectangle",
|
|
75
|
+
"background-color": "rgb(238,238,238)",
|
|
76
|
+
"border-color": "rgb(204,204,204)",
|
|
77
|
+
"border-width": "1px"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{ selector: "edge", style: { width: "3px" } },
|
|
81
|
+
{ selector: ":loop", style: { "curve-style": "bezier" } },
|
|
82
|
+
{ selector: "edge:compound", style: { "curve-style": "bezier" } },
|
|
83
|
+
{
|
|
84
|
+
selector: ":selected",
|
|
85
|
+
style: {
|
|
86
|
+
"background-color": "rgb(1,105,217)",
|
|
87
|
+
"line-color": "rgb(1,105,217)",
|
|
88
|
+
"source-arrow-color": "rgb(1,105,217)",
|
|
89
|
+
"target-arrow-color": "rgb(1,105,217)"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
selector: ":parent:selected",
|
|
94
|
+
style: { "background-color": "rgb(204,225,249)", "border-color": "rgb(174,200,229)" }
|
|
95
|
+
}
|
|
96
|
+
];
|
|
97
|
+
const NODE_SHAPES = [
|
|
98
|
+
"rectangle",
|
|
99
|
+
"roundrectangle",
|
|
100
|
+
"round-rectangle",
|
|
101
|
+
"cutrectangle",
|
|
102
|
+
"cut-rectangle",
|
|
103
|
+
"bottomroundrectangle",
|
|
104
|
+
"bottom-round-rectangle",
|
|
105
|
+
"barrel",
|
|
106
|
+
"ellipse",
|
|
107
|
+
"triangle",
|
|
108
|
+
"round-triangle",
|
|
109
|
+
"square",
|
|
110
|
+
"pentagon",
|
|
111
|
+
"round-pentagon",
|
|
112
|
+
"hexagon",
|
|
113
|
+
"round-hexagon",
|
|
114
|
+
"concavehexagon",
|
|
115
|
+
"concave-hexagon",
|
|
116
|
+
"heptagon",
|
|
117
|
+
"round-heptagon",
|
|
118
|
+
"octagon",
|
|
119
|
+
"round-octagon",
|
|
120
|
+
"tag",
|
|
121
|
+
"round-tag",
|
|
122
|
+
"star",
|
|
123
|
+
"diamond",
|
|
124
|
+
"round-diamond",
|
|
125
|
+
"vee",
|
|
126
|
+
"rhomboid",
|
|
127
|
+
"right-rhomboid",
|
|
128
|
+
"polygon"
|
|
129
|
+
];
|
|
130
|
+
const ARROWS = [
|
|
131
|
+
"tee",
|
|
132
|
+
"triangle",
|
|
133
|
+
"triangle-tee",
|
|
134
|
+
"circle-triangle",
|
|
135
|
+
"triangle-cross",
|
|
136
|
+
"triangle-backcurve",
|
|
137
|
+
"vee",
|
|
138
|
+
"square",
|
|
139
|
+
"circle",
|
|
140
|
+
"diamond",
|
|
141
|
+
"chevron",
|
|
142
|
+
"none"
|
|
143
|
+
];
|
|
144
|
+
const FONT_WEIGHTS = [
|
|
145
|
+
"normal",
|
|
146
|
+
"bold",
|
|
147
|
+
"bolder",
|
|
148
|
+
"lighter",
|
|
149
|
+
"100",
|
|
150
|
+
"200",
|
|
151
|
+
"300",
|
|
152
|
+
"400",
|
|
153
|
+
"500",
|
|
154
|
+
"600",
|
|
155
|
+
"800",
|
|
156
|
+
"900",
|
|
157
|
+
100,
|
|
158
|
+
200,
|
|
159
|
+
300,
|
|
160
|
+
400,
|
|
161
|
+
500,
|
|
162
|
+
600,
|
|
163
|
+
700,
|
|
164
|
+
800,
|
|
165
|
+
900
|
|
166
|
+
];
|
|
167
|
+
const CURVES = [
|
|
168
|
+
"bezier",
|
|
169
|
+
"unbundled-bezier",
|
|
170
|
+
"haystack",
|
|
171
|
+
"segments",
|
|
172
|
+
"straight",
|
|
173
|
+
"straight-triangle",
|
|
174
|
+
"taxi",
|
|
175
|
+
"round-segments",
|
|
176
|
+
"round-taxi"
|
|
177
|
+
];
|
|
178
|
+
const STRAIGHT = /* @__PURE__ */ new Set([
|
|
179
|
+
"haystack",
|
|
180
|
+
"straight",
|
|
181
|
+
"straight-triangle",
|
|
182
|
+
"segments",
|
|
183
|
+
"taxi",
|
|
184
|
+
"round-segments",
|
|
185
|
+
"round-taxi"
|
|
186
|
+
]);
|
|
187
|
+
const LABEL = [
|
|
188
|
+
["label", { property: "label", type: "text" }],
|
|
189
|
+
["color", { property: "labelColor", type: "color" }],
|
|
190
|
+
["font-size", { property: "labelSize", type: "size" }],
|
|
191
|
+
["font-family", { property: "labelFont", type: "fontFamily" }],
|
|
192
|
+
["font-weight", { property: "labelWeight", type: "fontWeight" }],
|
|
193
|
+
["font-style", { property: "labelItalic", type: "enum", enums: ["italic", "normal", "oblique"] }],
|
|
194
|
+
["visibility", { property: "_visibility", type: "enum", enums: ["hidden", "visible"] }],
|
|
195
|
+
["display", { property: "_display", type: "enum", enums: ["element", "none"] }],
|
|
196
|
+
["opacity", { property: "opacity", type: "zeroOne" }]
|
|
197
|
+
];
|
|
198
|
+
const CYJS_NODE_PROPERTIES = new Map([
|
|
199
|
+
["background-color", { property: "fill", type: "color" }],
|
|
200
|
+
["background-opacity", { property: "fillOpacity", type: "zeroOne" }],
|
|
201
|
+
["border-color", { property: "borderColor", type: "color" }],
|
|
202
|
+
["border-width", { property: "borderWidth", type: "size" }],
|
|
203
|
+
["border-style", { property: "borderStyle", type: "enum", enums: ["solid", "dotted", "dashed", "double"] }],
|
|
204
|
+
["shape", { property: "shape", type: "enum", enums: NODE_SHAPES }],
|
|
205
|
+
["corner-radius", { property: "cornerRadius", type: "size" }],
|
|
206
|
+
["width", { property: "width", type: "nodeSize" }],
|
|
207
|
+
["height", { property: "height", type: "nodeSize" }],
|
|
208
|
+
[
|
|
209
|
+
"text-valign",
|
|
210
|
+
{ property: "_valign", type: "enum", enums: ["top", "top-inside", "center", "bottom", "bottom-inside"] }
|
|
211
|
+
],
|
|
212
|
+
[
|
|
213
|
+
"text-halign",
|
|
214
|
+
{ property: "_halign", type: "enum", enums: ["left", "left-inside", "center", "right", "right-inside"] }
|
|
215
|
+
],
|
|
216
|
+
...LABEL
|
|
217
|
+
]);
|
|
218
|
+
const CYJS_EDGE_PROPERTIES = new Map([
|
|
219
|
+
["line-color", { property: "color", type: "color" }],
|
|
220
|
+
["width", { property: "width", type: "nodeSize" }],
|
|
221
|
+
["line-style", { property: "lineStyle", type: "enum", enums: ["solid", "dotted", "dashed"] }],
|
|
222
|
+
["target-arrow-shape", { property: "targetArrow", type: "enum", enums: ARROWS }],
|
|
223
|
+
["source-arrow-shape", { property: "sourceArrow", type: "enum", enums: ARROWS }],
|
|
224
|
+
["target-arrow-color", { property: "targetArrowColor", type: "color" }],
|
|
225
|
+
["source-arrow-color", { property: "sourceArrowColor", type: "color" }],
|
|
226
|
+
["curve-style", { property: "curved", type: "enum", enums: CURVES }],
|
|
227
|
+
["arrow-scale", { property: "arrowSize", type: "positive" }],
|
|
228
|
+
["source-label", { property: "sourceLabel", type: "text" }],
|
|
229
|
+
["target-label", { property: "targetLabel", type: "text" }],
|
|
230
|
+
...LABEL
|
|
231
|
+
]);
|
|
232
|
+
function cyjsProperties(target) {
|
|
233
|
+
return target === "node" ? CYJS_NODE_PROPERTIES : CYJS_EDGE_PROPERTIES;
|
|
234
|
+
}
|
|
235
|
+
function cyjsPropertyName(name) {
|
|
236
|
+
const dashed = name.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
237
|
+
return dashed === "content" ? "label" : dashed;
|
|
238
|
+
}
|
|
239
|
+
const CYJS_THROWS = "throws";
|
|
240
|
+
const NUM = String.raw`[-+]?(?:(?:\d+|\d*\.\d+)(?:[Ee][+-]?\d+)?)`;
|
|
241
|
+
const NUMBER_UNITS = new RegExp(`^(${NUM})(px|em)?$`);
|
|
242
|
+
const NUMBER_ONLY = new RegExp(String.raw`^\s*${NUM}\s*$`);
|
|
243
|
+
const RGBA = new RegExp(
|
|
244
|
+
String.raw`^rgb[a]?\((${NUM}[%]?)\s*,\s*(${NUM}[%]?)\s*,\s*(${NUM}[%]?)(?:\s*,\s*(${NUM}))?\)$`
|
|
245
|
+
);
|
|
246
|
+
const HSLA = new RegExp(String.raw`^hsl[a]?\((${NUM})\s*,\s*(${NUM}[%])\s*,\s*(${NUM}[%])(?:\s*,\s*(${NUM}))?\)$`);
|
|
247
|
+
const MAP_ARG = new RegExp(
|
|
248
|
+
String.raw`^(?:${NUM}|\w+|rgb[a]?\((?:${NUM}[%]?)\s*,\s*(?:${NUM}[%]?)\s*,\s*(?:${NUM}[%]?)(?:\s*,\s*(?:${NUM}))?\)` + String.raw`|hsl[a]?\((?:${NUM})\s*,\s*(?:${NUM}[%])\s*,\s*(?:${NUM}[%])(?:\s*,\s*(?:${NUM}))?\)` + String.raw`|\#[0-9a-fA-F]{3}|\#[0-9a-fA-F]{6})$`
|
|
249
|
+
);
|
|
250
|
+
const FIELD = /^[\w.]+$/;
|
|
251
|
+
const WORD_FONT = /^[\w\- "]$/;
|
|
252
|
+
function namedColor(name) {
|
|
253
|
+
if (name === "transparent") {
|
|
254
|
+
return "#000000";
|
|
255
|
+
}
|
|
256
|
+
return name === "rebeccapurple" ? void 0 : CSS_COLORS.get(name);
|
|
257
|
+
}
|
|
258
|
+
function colorTuple(value) {
|
|
259
|
+
const named = namedColor(value.toLowerCase());
|
|
260
|
+
if (named !== void 0) {
|
|
261
|
+
return [
|
|
262
|
+
Number.parseInt(named.slice(1, 3), 16),
|
|
263
|
+
Number.parseInt(named.slice(3, 5), 16),
|
|
264
|
+
Number.parseInt(named.slice(5, 7), 16)
|
|
265
|
+
];
|
|
266
|
+
}
|
|
267
|
+
if ((value.length === 4 || value.length === 7) && value.startsWith("#")) {
|
|
268
|
+
const short = value.length === 4;
|
|
269
|
+
const pair = (k) => Number.parseInt(short ? value[k] + value[k] : value.slice(2 * k - 1, 2 * k + 1), 16);
|
|
270
|
+
return [pair(1), pair(2), pair(3)];
|
|
271
|
+
}
|
|
272
|
+
const m = RGBA.exec(value);
|
|
273
|
+
return m === null ? hslTuple(value) : rgbaTuple(m);
|
|
274
|
+
}
|
|
275
|
+
function rgbaTuple(m) {
|
|
276
|
+
const pct = [1, 2, 3].map((k) => m[k].endsWith("%"));
|
|
277
|
+
if (pct.some(Boolean) && !pct.every(Boolean)) {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
const channels = [1, 2, 3].map((k) => {
|
|
281
|
+
const c = Number.parseFloat(m[k]);
|
|
282
|
+
return pct[k - 1] ? c / 100 * 255 : c;
|
|
283
|
+
});
|
|
284
|
+
if (channels.some((c) => c < 0 || c > 255)) {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
const alpha = m.at(4);
|
|
288
|
+
if (alpha !== void 0 && (Number.parseFloat(alpha) < 0 || Number.parseFloat(alpha) > 1)) {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
return [Math.floor(channels[0]), Math.floor(channels[1]), Math.floor(channels[2])];
|
|
292
|
+
}
|
|
293
|
+
function hslTuple(value) {
|
|
294
|
+
const m = HSLA.exec(value);
|
|
295
|
+
if (m === null) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
let h = Number.parseInt(m[1], 10);
|
|
299
|
+
if (h < 0) {
|
|
300
|
+
h = (360 - -1 * h % 360) % 360;
|
|
301
|
+
} else if (h > 360) {
|
|
302
|
+
h = h % 360;
|
|
303
|
+
}
|
|
304
|
+
h /= 360;
|
|
305
|
+
const s = Number.parseFloat(m[2]);
|
|
306
|
+
const l = Number.parseFloat(m[3]);
|
|
307
|
+
if (s < 0 || s > 100 || l < 0 || l > 100) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
const alpha = m.at(4);
|
|
311
|
+
if (alpha !== void 0 && (Number.parseFloat(alpha) < 0 || Number.parseFloat(alpha) > 1)) {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
const sn = s / 100;
|
|
315
|
+
const ln = l / 100;
|
|
316
|
+
if (sn === 0) {
|
|
317
|
+
const g = Math.round(ln * 255);
|
|
318
|
+
return [g, g, g];
|
|
319
|
+
}
|
|
320
|
+
const hue = (p2, q2, t0) => {
|
|
321
|
+
let t = t0;
|
|
322
|
+
if (t < 0) {
|
|
323
|
+
t += 1;
|
|
324
|
+
}
|
|
325
|
+
if (t > 1) {
|
|
326
|
+
t -= 1;
|
|
327
|
+
}
|
|
328
|
+
if (t < 1 / 6) {
|
|
329
|
+
return p2 + (q2 - p2) * 6 * t;
|
|
330
|
+
}
|
|
331
|
+
if (t < 1 / 2) {
|
|
332
|
+
return q2;
|
|
333
|
+
}
|
|
334
|
+
if (t < 2 / 3) {
|
|
335
|
+
return p2 + (q2 - p2) * (2 / 3 - t) * 6;
|
|
336
|
+
}
|
|
337
|
+
return p2;
|
|
338
|
+
};
|
|
339
|
+
const q = ln < 0.5 ? ln * (1 + sn) : ln + sn - ln * sn;
|
|
340
|
+
const p = 2 * ln - q;
|
|
341
|
+
return [
|
|
342
|
+
Math.round(255 * hue(p, q, h + 1 / 3)),
|
|
343
|
+
Math.round(255 * hue(p, q, h)),
|
|
344
|
+
Math.round(255 * hue(p, q, h - 1 / 3))
|
|
345
|
+
];
|
|
346
|
+
}
|
|
347
|
+
function isFontFamily(value) {
|
|
348
|
+
const parts = value.split(",");
|
|
349
|
+
if (parts.length === 1) {
|
|
350
|
+
return parts[0].length > 0 && allOf(parts[0], isFontChar);
|
|
351
|
+
}
|
|
352
|
+
return firstFontPart(parts[0]) && lastFontPart(parts.at(-1) ?? "") && parts.slice(1, -1).every((part) => middleFontPart(part));
|
|
353
|
+
}
|
|
354
|
+
function isFontChar(c) {
|
|
355
|
+
return WORD_FONT.test(c);
|
|
356
|
+
}
|
|
357
|
+
function isSpace$1(c) {
|
|
358
|
+
return /\s/.test(c);
|
|
359
|
+
}
|
|
360
|
+
function allOf(text, test) {
|
|
361
|
+
return Array.from(text).every(test);
|
|
362
|
+
}
|
|
363
|
+
function firstFontPart(part) {
|
|
364
|
+
let a = 0;
|
|
365
|
+
while (a < part.length && isFontChar(part[a])) {
|
|
366
|
+
a++;
|
|
367
|
+
}
|
|
368
|
+
return a > 0 && allOf(part.slice(a), isSpace$1);
|
|
369
|
+
}
|
|
370
|
+
function lastFontPart(part) {
|
|
371
|
+
let b = part.length;
|
|
372
|
+
while (b > 0 && isFontChar(part[b - 1])) {
|
|
373
|
+
b--;
|
|
374
|
+
}
|
|
375
|
+
return b < part.length && allOf(part.slice(0, b), isSpace$1);
|
|
376
|
+
}
|
|
377
|
+
function middleFontPart(part) {
|
|
378
|
+
let a = 0;
|
|
379
|
+
let b = part.length;
|
|
380
|
+
while (a < b && isSpace$1(part[a])) {
|
|
381
|
+
a++;
|
|
382
|
+
}
|
|
383
|
+
while (b > a && isSpace$1(part[b - 1])) {
|
|
384
|
+
b--;
|
|
385
|
+
}
|
|
386
|
+
return a === b ? part.includes(" ") : allOf(part.slice(a, b), isFontChar);
|
|
387
|
+
}
|
|
388
|
+
function parseFlat(spec, raw, rendered = false) {
|
|
389
|
+
const value = typeof raw === "string" ? raw.trim() : raw;
|
|
390
|
+
switch (spec.type) {
|
|
391
|
+
case "color":
|
|
392
|
+
return parseColorValue(value);
|
|
393
|
+
case "zeroOne":
|
|
394
|
+
case "positive": {
|
|
395
|
+
const x = Number.parseFloat(String(value));
|
|
396
|
+
const ok = spec.type === "zeroOne" ? x >= 0 && x <= 1 : x > 0;
|
|
397
|
+
return ok ? { kind: "number", value: x, units: null, str: String(x) } : null;
|
|
398
|
+
}
|
|
399
|
+
case "size":
|
|
400
|
+
case "nodeSize":
|
|
401
|
+
return parseSizeValue(spec, value, raw);
|
|
402
|
+
case "text":
|
|
403
|
+
return { kind: "word", value: String(value), str: String(value) };
|
|
404
|
+
case "fontFamily": {
|
|
405
|
+
const text = String(value);
|
|
406
|
+
return isFontFamily(text) ? { kind: "word", value: text, str: text } : null;
|
|
407
|
+
}
|
|
408
|
+
case "fontWeight":
|
|
409
|
+
case "enum": {
|
|
410
|
+
const enums = spec.type === "fontWeight" ? FONT_WEIGHTS : spec.enums ?? [];
|
|
411
|
+
const e = enums.find((x) => x === value || rendered && String(x) === value);
|
|
412
|
+
return e === void 0 ? null : { kind: "word", value: e, str: String(e) };
|
|
413
|
+
}
|
|
414
|
+
default:
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function parseColorValue(value) {
|
|
419
|
+
if (Array.isArray(value)) {
|
|
420
|
+
const [r, g, b] = value;
|
|
421
|
+
const t2 = [Number(r), Number(g), Number(b)];
|
|
422
|
+
return { kind: "color", rgb: t2, str: `rgb(${t2[0]},${t2[1]},${t2[2]})` };
|
|
423
|
+
}
|
|
424
|
+
if (typeof value !== "string") {
|
|
425
|
+
return CYJS_THROWS;
|
|
426
|
+
}
|
|
427
|
+
const t = colorTuple(value);
|
|
428
|
+
return t === null ? null : { kind: "color", rgb: t, str: `rgb(${t[0]},${t[1]},${t[2]})` };
|
|
429
|
+
}
|
|
430
|
+
function parseSizeValue(spec, value, raw) {
|
|
431
|
+
let units = "px";
|
|
432
|
+
let text = value;
|
|
433
|
+
if (typeof value === "string") {
|
|
434
|
+
const m = NUMBER_UNITS.exec(value);
|
|
435
|
+
if (m === null) {
|
|
436
|
+
units = null;
|
|
437
|
+
} else {
|
|
438
|
+
text = m[1];
|
|
439
|
+
units = m.at(2) === "em" ? "em" : "px";
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const x = Number.parseFloat(String(text));
|
|
443
|
+
if (Number.isNaN(x)) {
|
|
444
|
+
return spec.type === "nodeSize" && raw === "label" ? { kind: "word", value: "label", str: "label" } : null;
|
|
445
|
+
}
|
|
446
|
+
return x < 0 ? null : { kind: "number", value: x, units, str: `${String(x)}${units ?? ""}` };
|
|
447
|
+
}
|
|
448
|
+
function splitArgs(inner) {
|
|
449
|
+
const out = [];
|
|
450
|
+
let depth = 0;
|
|
451
|
+
let start = 0;
|
|
452
|
+
for (let i = 0; i < inner.length; i++) {
|
|
453
|
+
const c = inner[i];
|
|
454
|
+
if (c === "(") {
|
|
455
|
+
depth++;
|
|
456
|
+
} else if (c === ")") {
|
|
457
|
+
depth--;
|
|
458
|
+
} else if (c === "," && depth === 0) {
|
|
459
|
+
out.push(inner.slice(start, i));
|
|
460
|
+
start = i + 1;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
out.push(inner.slice(start));
|
|
464
|
+
return out;
|
|
465
|
+
}
|
|
466
|
+
function callArgs(value, name) {
|
|
467
|
+
if (!value.startsWith(name) || !value.endsWith(")")) {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
let i = name.length;
|
|
471
|
+
while (i < value.length && /\s/.test(value[i])) {
|
|
472
|
+
i++;
|
|
473
|
+
}
|
|
474
|
+
return value[i] === "(" ? value.slice(i + 1, -1) : null;
|
|
475
|
+
}
|
|
476
|
+
function parseCyjsValue(spec, raw, mode) {
|
|
477
|
+
if (raw === void 0) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
if (typeof raw === "function") {
|
|
481
|
+
return mode === "flat" ? null : { kind: "fn" };
|
|
482
|
+
}
|
|
483
|
+
const value = typeof raw === "string" ? raw.trim() : raw;
|
|
484
|
+
if (mode !== "flat" && typeof value === "string" && value.length >= 7 && value[1] === "a") {
|
|
485
|
+
const mapper = parseMapper(spec, value, mode);
|
|
486
|
+
if (mapper !== void 0) {
|
|
487
|
+
return mapper;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return parseFlat(spec, raw);
|
|
491
|
+
}
|
|
492
|
+
function parseMapper(spec, value, mode) {
|
|
493
|
+
if (value.startsWith("d")) {
|
|
494
|
+
const field = callArgs(value, "data")?.trim();
|
|
495
|
+
if (field === void 0 || !FIELD.test(field)) {
|
|
496
|
+
return void 0;
|
|
497
|
+
}
|
|
498
|
+
return mode === "bypass" ? null : { kind: "data", field };
|
|
499
|
+
}
|
|
500
|
+
if (!value.startsWith("m") || value.length < 10) {
|
|
501
|
+
return void 0;
|
|
502
|
+
}
|
|
503
|
+
return parseMapData(spec, value, mode);
|
|
504
|
+
}
|
|
505
|
+
function parseMapData(spec, value, mode) {
|
|
506
|
+
const inner = callArgs(value, "mapData");
|
|
507
|
+
if (inner === null) {
|
|
508
|
+
return void 0;
|
|
509
|
+
}
|
|
510
|
+
const args = splitArgs(inner);
|
|
511
|
+
if (!isMapDataArgs(args)) {
|
|
512
|
+
return void 0;
|
|
513
|
+
}
|
|
514
|
+
if (mode === "bypass") {
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
const numeric = spec.type === "zeroOne" || spec.type === "positive" || spec.type === "size" || spec.type === "nodeSize";
|
|
518
|
+
if (spec.type !== "color" && !numeric) {
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
const min = parseFlat(spec, args[3].trim());
|
|
522
|
+
const max = parseFlat(spec, args[4].trim());
|
|
523
|
+
if (min === null || max === null || min === CYJS_THROWS || max === CYJS_THROWS) {
|
|
524
|
+
return null;
|
|
525
|
+
}
|
|
526
|
+
if (min.str === max.str || min.kind === "number" && max.kind === "number" && pfValue(min) === pfValue(max)) {
|
|
527
|
+
const constant = parseFlat(spec, min.str);
|
|
528
|
+
return constant === CYJS_THROWS ? null : constant;
|
|
529
|
+
}
|
|
530
|
+
return {
|
|
531
|
+
kind: "mapData",
|
|
532
|
+
field: args[0].trim(),
|
|
533
|
+
fieldMin: Number.parseFloat(args[1]),
|
|
534
|
+
fieldMax: Number.parseFloat(args[2]),
|
|
535
|
+
min,
|
|
536
|
+
max
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
function isMapDataArgs(args) {
|
|
540
|
+
return args.length === 5 && /^[\w.]+\s*$/.test(args[0]) && NUMBER_ONLY.test(args[1]) && NUMBER_ONLY.test(args[2]) && MAP_ARG.test(args[3].trim()) && MAP_ARG.test(args[4].replace(/^\s+/, ""));
|
|
541
|
+
}
|
|
542
|
+
function pfValue(v) {
|
|
543
|
+
return v.value;
|
|
544
|
+
}
|
|
545
|
+
function mapperField(data, field) {
|
|
546
|
+
let v = data;
|
|
547
|
+
for (const step of field.split(".")) {
|
|
548
|
+
if (!v) {
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
v = v[step];
|
|
552
|
+
}
|
|
553
|
+
return v;
|
|
554
|
+
}
|
|
555
|
+
function applyCyjsMapper(spec, m, data) {
|
|
556
|
+
const v = mapperField(data, m.field);
|
|
557
|
+
if (v === null || v === void 0) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
if (m.kind === "data") {
|
|
561
|
+
return parseFlat(spec, v);
|
|
562
|
+
}
|
|
563
|
+
if (typeof v !== "number" || Number.isNaN(v)) {
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
const width = m.fieldMax - m.fieldMin;
|
|
567
|
+
const p = Math.min(1, Math.max(0, width === 0 ? 0 : (v - m.fieldMin) / width));
|
|
568
|
+
const { min, max } = m;
|
|
569
|
+
if (min.kind === "color" && max.kind === "color") {
|
|
570
|
+
const c = [0, 1, 2].map((k) => Math.round(min.rgb[k] + (max.rgb[k] - min.rgb[k]) * p));
|
|
571
|
+
return { kind: "color", rgb: c, str: `rgb(${c[0]}, ${c[1]}, ${c[2]})` };
|
|
572
|
+
}
|
|
573
|
+
if (min.kind === "number" && max.kind === "number") {
|
|
574
|
+
return parseFlat(spec, min.value + (max.value - min.value) * p);
|
|
575
|
+
}
|
|
576
|
+
return null;
|
|
577
|
+
}
|
|
578
|
+
function cyjsNeutral(spec, v, site) {
|
|
579
|
+
switch (v.kind) {
|
|
580
|
+
case "color": {
|
|
581
|
+
if (v.rgb.some((c) => !Number.isFinite(c) || c < 0 || c > 255)) {
|
|
582
|
+
site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, {
|
|
583
|
+
sample: v.str,
|
|
584
|
+
element: site.element
|
|
585
|
+
});
|
|
586
|
+
return void 0;
|
|
587
|
+
}
|
|
588
|
+
return `#${v.rgb.map((c) => Math.round(c).toString(16).padStart(2, "0")).join("")}`;
|
|
589
|
+
}
|
|
590
|
+
case "number":
|
|
591
|
+
if (v.units === "em") {
|
|
592
|
+
site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, {
|
|
593
|
+
sample: v.str,
|
|
594
|
+
element: site.element
|
|
595
|
+
});
|
|
596
|
+
return void 0;
|
|
597
|
+
}
|
|
598
|
+
return num6(v.value);
|
|
599
|
+
}
|
|
600
|
+
const word = v.value;
|
|
601
|
+
switch (spec.property) {
|
|
602
|
+
case "width":
|
|
603
|
+
case "height":
|
|
604
|
+
site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, { sample: v.str, element: site.element });
|
|
605
|
+
return void 0;
|
|
606
|
+
case "label":
|
|
607
|
+
case "sourceLabel":
|
|
608
|
+
case "targetLabel":
|
|
609
|
+
case "labelFont":
|
|
610
|
+
return String(word);
|
|
611
|
+
case "labelItalic":
|
|
612
|
+
return word === "italic" || word === "oblique";
|
|
613
|
+
case "curved":
|
|
614
|
+
return !STRAIGHT.has(String(word));
|
|
615
|
+
case "shape":
|
|
616
|
+
return canonEnum("shape", String(word), "cytoscape-js", site) ?? void 0;
|
|
617
|
+
case "borderStyle":
|
|
618
|
+
return canonEnum("borderStyle", String(word), "cytoscape-js", site) ?? void 0;
|
|
619
|
+
case "lineStyle":
|
|
620
|
+
return canonEnum("lineStyle", String(word), "cytoscape-js", site) ?? void 0;
|
|
621
|
+
case "sourceArrow":
|
|
622
|
+
case "targetArrow":
|
|
623
|
+
return canonEnum("arrow", String(word), "cytoscape-js", site) ?? void 0;
|
|
624
|
+
case "labelWeight":
|
|
625
|
+
return canonEnum("weight", String(word), "cytoscape-js", site) ?? void 0;
|
|
626
|
+
default:
|
|
627
|
+
return word;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
function cyjsRendered(target, name, str, site) {
|
|
631
|
+
const spec = cyjsProperties(target).get(cyjsPropertyName(name));
|
|
632
|
+
if (spec === void 0 || typeof str !== "string") {
|
|
633
|
+
return null;
|
|
634
|
+
}
|
|
635
|
+
const v = parseFlat(spec, str, true);
|
|
636
|
+
if (v === null || v === CYJS_THROWS) {
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
return cyjsNeutral(spec, v, site);
|
|
640
|
+
}
|
|
641
|
+
const CYJS_STATES = /* @__PURE__ */ new Set([
|
|
642
|
+
"selected",
|
|
643
|
+
"unselected",
|
|
644
|
+
"selectable",
|
|
645
|
+
"unselectable",
|
|
646
|
+
"locked",
|
|
647
|
+
"unlocked",
|
|
648
|
+
"visible",
|
|
649
|
+
"hidden",
|
|
650
|
+
"transparent",
|
|
651
|
+
"grabbed",
|
|
652
|
+
"free",
|
|
653
|
+
"removed",
|
|
654
|
+
"inside",
|
|
655
|
+
"grabbable",
|
|
656
|
+
"ungrabbable",
|
|
657
|
+
"animated",
|
|
658
|
+
"unanimated",
|
|
659
|
+
"parent",
|
|
660
|
+
"childless",
|
|
661
|
+
"child",
|
|
662
|
+
"orphan",
|
|
663
|
+
"nonorphan",
|
|
664
|
+
"compound",
|
|
665
|
+
"loop",
|
|
666
|
+
"simple",
|
|
667
|
+
"active",
|
|
668
|
+
"inactive",
|
|
669
|
+
"backgrounding",
|
|
670
|
+
"nonbackgrounding"
|
|
671
|
+
]);
|
|
672
|
+
const MAX_SELECTOR_LENGTH = 1 << 22;
|
|
673
|
+
const META = new Set("!\"#$%&'()*+,./:;<=>?@[]^`{|}~");
|
|
674
|
+
const BASE_OPS = ["!=", ">=", "<=", "*=", "^=", "$=", "=", ">", "<"];
|
|
675
|
+
const META_FIELDS = ["indegree", "outdegree", "degree"];
|
|
676
|
+
function isWord(c) {
|
|
677
|
+
if (c === void 0) {
|
|
678
|
+
return false;
|
|
679
|
+
}
|
|
680
|
+
const k = c.codePointAt(0) ?? 0;
|
|
681
|
+
return k >= 48 && k <= 57 || k >= 65 && k <= 90 || k >= 97 && k <= 122 || k === 95;
|
|
682
|
+
}
|
|
683
|
+
function isSpace(c) {
|
|
684
|
+
return c !== void 0 && /\s/.test(c);
|
|
685
|
+
}
|
|
686
|
+
class Cursor {
|
|
687
|
+
constructor(text) {
|
|
688
|
+
this.text = text;
|
|
689
|
+
this.pos = 0;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* The end of a run of whitespace.
|
|
693
|
+
* @param from - where the run starts
|
|
694
|
+
* @returns the first position after it
|
|
695
|
+
*/
|
|
696
|
+
spaceEnd(from) {
|
|
697
|
+
let i = from;
|
|
698
|
+
while (i < this.text.length && isSpace(this.text[i])) {
|
|
699
|
+
i++;
|
|
700
|
+
}
|
|
701
|
+
return i;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* A name at `from`: word characters, `-`, and `.` when `dots` (Cytoscape.js's variable and id tokens), or a
|
|
705
|
+
* backslash before a meta character.
|
|
706
|
+
* @param from - the start
|
|
707
|
+
* @param dots - whether `.` belongs to the name
|
|
708
|
+
* @returns the raw name and its end, or null when there is none
|
|
709
|
+
*/
|
|
710
|
+
name(from, dots) {
|
|
711
|
+
let i = from;
|
|
712
|
+
const t = this.text;
|
|
713
|
+
while (i < t.length) {
|
|
714
|
+
const c = t[i];
|
|
715
|
+
if (isWord(c) || c === "-" || dots && c === ".") {
|
|
716
|
+
i++;
|
|
717
|
+
} else if (c === "\\" && i + 1 < t.length && META.has(t[i + 1])) {
|
|
718
|
+
i += 2;
|
|
719
|
+
} else {
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
return i > from ? { raw: t.slice(from, i), end: i } : null;
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* A number literal at `from` (Cytoscape.js's `[-+]?(\d+|\d*\.\d+)([Ee][+-]?\d+)?`). Both readings of the
|
|
727
|
+
* mantissa are returned, longest first, because the regular expression backtracks to the shorter one.
|
|
728
|
+
* @param from - the start
|
|
729
|
+
* @returns the possible ends, longest first
|
|
730
|
+
*/
|
|
731
|
+
numberEnds(from) {
|
|
732
|
+
const t = this.text;
|
|
733
|
+
let i = from;
|
|
734
|
+
if (t[i] === "+" || t[i] === "-") {
|
|
735
|
+
i++;
|
|
736
|
+
}
|
|
737
|
+
const digits = (k) => {
|
|
738
|
+
let j = k;
|
|
739
|
+
while (j < t.length && t[j] >= "0" && t[j] <= "9") {
|
|
740
|
+
j++;
|
|
741
|
+
}
|
|
742
|
+
return j;
|
|
743
|
+
};
|
|
744
|
+
const mantissas = [];
|
|
745
|
+
const intEnd = digits(i);
|
|
746
|
+
if (intEnd > i) {
|
|
747
|
+
mantissas.push(intEnd);
|
|
748
|
+
}
|
|
749
|
+
if (t[intEnd] === ".") {
|
|
750
|
+
const fracEnd = digits(intEnd + 1);
|
|
751
|
+
if (fracEnd > intEnd + 1) {
|
|
752
|
+
mantissas.unshift(fracEnd);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
const ends = [];
|
|
756
|
+
for (const m of mantissas) {
|
|
757
|
+
if (t[m] === "e" || t[m] === "E") {
|
|
758
|
+
let j = m + 1;
|
|
759
|
+
if (t[j] === "+" || t[j] === "-") {
|
|
760
|
+
j++;
|
|
761
|
+
}
|
|
762
|
+
const expEnd = digits(j);
|
|
763
|
+
if (expEnd > j) {
|
|
764
|
+
ends.push(expEnd);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
ends.push(m);
|
|
768
|
+
}
|
|
769
|
+
return ends;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* The possible ends of a quoted string at `from`: every quote that may close it, longest first (a quote after a
|
|
773
|
+
* backslash may also be escaped; the first quote with no backslash before it must close the string).
|
|
774
|
+
* @param from - the opening quote
|
|
775
|
+
* @returns the possible ends (after the closing quote), longest first
|
|
776
|
+
*/
|
|
777
|
+
stringEnds(from) {
|
|
778
|
+
const t = this.text;
|
|
779
|
+
const q = t[from];
|
|
780
|
+
const ends = [];
|
|
781
|
+
for (let i = from + 1; i < t.length; i++) {
|
|
782
|
+
if (t[i] !== q) {
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
ends.push(i + 1);
|
|
786
|
+
if (t[i - 1] !== "\\" || i - 1 === from) {
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return ends.reverse();
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* A comparison operator at `from`: `!` and `@` flags, then a base operator (`!` before a base that holds `!`
|
|
794
|
+
* is not allowed).
|
|
795
|
+
* @param from - the start
|
|
796
|
+
* @returns the operator text and its end, or null
|
|
797
|
+
*/
|
|
798
|
+
op(from) {
|
|
799
|
+
const t = this.text;
|
|
800
|
+
let i = from;
|
|
801
|
+
let prefix = "";
|
|
802
|
+
if (t[i] === "!" && t[i + 1] !== "=") {
|
|
803
|
+
prefix += "!";
|
|
804
|
+
i++;
|
|
805
|
+
}
|
|
806
|
+
if (t[i] === "@") {
|
|
807
|
+
prefix += "@";
|
|
808
|
+
i++;
|
|
809
|
+
}
|
|
810
|
+
for (const base of BASE_OPS) {
|
|
811
|
+
if (t.startsWith(base, i)) {
|
|
812
|
+
if (prefix.includes("!") && base === "!=") {
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
return { text: prefix + base, end: i + base.length };
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return null;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
function cleanMeta(raw) {
|
|
822
|
+
let out = "";
|
|
823
|
+
let i = 0;
|
|
824
|
+
while (i < raw.length) {
|
|
825
|
+
const escaped = raw[i] === "\\" && i + 1 < raw.length && META.has(raw[i + 1]);
|
|
826
|
+
out += escaped ? raw[i + 1] : raw[i];
|
|
827
|
+
i += escaped ? 2 : 1;
|
|
828
|
+
}
|
|
829
|
+
return out;
|
|
830
|
+
}
|
|
831
|
+
function splitOp(text) {
|
|
832
|
+
let op = text;
|
|
833
|
+
let not = false;
|
|
834
|
+
let ci = false;
|
|
835
|
+
if (op.includes("!")) {
|
|
836
|
+
op = op.replace("!", "");
|
|
837
|
+
not = true;
|
|
838
|
+
}
|
|
839
|
+
if (op.includes("@")) {
|
|
840
|
+
op = op.replace("@", "");
|
|
841
|
+
ci = true;
|
|
842
|
+
}
|
|
843
|
+
return { op, not, ci };
|
|
844
|
+
}
|
|
845
|
+
function replaceLast(b, q) {
|
|
846
|
+
b.queries[b.queries.length - 1] = q;
|
|
847
|
+
}
|
|
848
|
+
function lastQuery(b) {
|
|
849
|
+
return b.queries.at(-1);
|
|
850
|
+
}
|
|
851
|
+
function compoundFill(kind) {
|
|
852
|
+
return (b, query) => {
|
|
853
|
+
if (b.subject === null) {
|
|
854
|
+
const outer2 = { checks: [] };
|
|
855
|
+
const inner2 = { checks: [] };
|
|
856
|
+
const left = lastQuery(b);
|
|
857
|
+
outer2.checks.push(
|
|
858
|
+
kind === "child" ? { type: "child", parent: left, child: inner2 } : { type: "descendant", ancestor: left, descendant: inner2 }
|
|
859
|
+
);
|
|
860
|
+
replaceLast(b, outer2);
|
|
861
|
+
b.compoundCount++;
|
|
862
|
+
return inner2;
|
|
863
|
+
}
|
|
864
|
+
if (b.subject === query) {
|
|
865
|
+
const compound = { checks: [] };
|
|
866
|
+
const left = lastQuery(b);
|
|
867
|
+
const right = { checks: [] };
|
|
868
|
+
const subject = { checks: query.checks };
|
|
869
|
+
const inner2 = { checks: [] };
|
|
870
|
+
const outer2 = { checks: [{ type: "true" }] };
|
|
871
|
+
query.checks = [{ type: "true" }];
|
|
872
|
+
right.checks.push(
|
|
873
|
+
kind === "child" ? { type: "parent", parent: outer2, child: inner2 } : { type: "ancestor", ancestor: outer2, descendant: inner2 }
|
|
874
|
+
);
|
|
875
|
+
compound.checks.push({ type: "split", left, right, subject });
|
|
876
|
+
replaceLast(b, compound);
|
|
877
|
+
b.subject = subject;
|
|
878
|
+
b.compoundCount++;
|
|
879
|
+
return inner2;
|
|
880
|
+
}
|
|
881
|
+
const outer = { checks: query.checks };
|
|
882
|
+
const inner = { checks: [] };
|
|
883
|
+
query.checks = [
|
|
884
|
+
kind === "child" ? { type: "parent", parent: outer, child: inner } : { type: "ancestor", ancestor: outer, descendant: inner }
|
|
885
|
+
];
|
|
886
|
+
b.compoundCount++;
|
|
887
|
+
return inner;
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
function nextToken(c) {
|
|
891
|
+
const ch = c.text[c.pos];
|
|
892
|
+
return groupToken(c) ?? (ch === ":" ? stateToken(c) : null) ?? (ch === "#" || ch === "." ? nameToken(c, ch) : null) ?? (ch === "[" ? dataToken(c, c.pos) : null) ?? separatorToken(c) ?? (ch === "$" ? subjectToken(c) : null);
|
|
893
|
+
}
|
|
894
|
+
function checkToken(end, check) {
|
|
895
|
+
return {
|
|
896
|
+
end,
|
|
897
|
+
fill: (_b, q) => {
|
|
898
|
+
q.checks.push(check);
|
|
899
|
+
return null;
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
function groupToken(c) {
|
|
904
|
+
const i = c.pos;
|
|
905
|
+
for (const [g, value] of [
|
|
906
|
+
["node", "nodes"],
|
|
907
|
+
["edge", "edges"],
|
|
908
|
+
["*", "*"]
|
|
909
|
+
]) {
|
|
910
|
+
if (c.text.startsWith(g, i)) {
|
|
911
|
+
return checkToken(i + g.length, { type: "group", value });
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
return null;
|
|
915
|
+
}
|
|
916
|
+
function stateToken(c) {
|
|
917
|
+
const i = c.pos;
|
|
918
|
+
let best = null;
|
|
919
|
+
for (const s of CYJS_STATES) {
|
|
920
|
+
if (c.text.startsWith(s, i + 1) && (best === null || s.length > best.length)) {
|
|
921
|
+
best = s;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return best === null ? null : checkToken(i + 1 + best.length, { type: "state", value: best });
|
|
925
|
+
}
|
|
926
|
+
function nameToken(c, ch) {
|
|
927
|
+
const n = c.name(c.pos + 1, ch === "#");
|
|
928
|
+
if (n === null) {
|
|
929
|
+
return null;
|
|
930
|
+
}
|
|
931
|
+
return checkToken(n.end, { type: ch === "#" ? "id" : "class", value: cleanMeta(n.raw) });
|
|
932
|
+
}
|
|
933
|
+
function separatorToken(c) {
|
|
934
|
+
const t = c.text;
|
|
935
|
+
const i = c.pos;
|
|
936
|
+
const ws = c.spaceEnd(i);
|
|
937
|
+
if (t[ws] === ",") {
|
|
938
|
+
return { end: c.spaceEnd(ws + 1), fill: nextQuery };
|
|
939
|
+
}
|
|
940
|
+
if (ws === i) {
|
|
941
|
+
return null;
|
|
942
|
+
}
|
|
943
|
+
for (const [sep, kind] of [
|
|
944
|
+
["->", "directed"],
|
|
945
|
+
["<->", "undirected"],
|
|
946
|
+
[">", "child"]
|
|
947
|
+
]) {
|
|
948
|
+
const after = t.startsWith(sep, ws) ? c.spaceEnd(ws + sep.length) : -1;
|
|
949
|
+
if (after > ws + sep.length) {
|
|
950
|
+
return { end: after, fill: kind === "child" ? compoundFill("child") : edgeFill(kind) };
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
return { end: ws, fill: compoundFill("descendant") };
|
|
954
|
+
}
|
|
955
|
+
function nextQuery(b) {
|
|
956
|
+
b.counts.push({ edgeCount: b.edgeCount, compoundCount: b.compoundCount, subject: b.subject });
|
|
957
|
+
b.subject = null;
|
|
958
|
+
b.edgeCount = 0;
|
|
959
|
+
b.compoundCount = 0;
|
|
960
|
+
const next = { checks: [] };
|
|
961
|
+
b.queries.push(next);
|
|
962
|
+
return next;
|
|
963
|
+
}
|
|
964
|
+
function subjectToken(c) {
|
|
965
|
+
return {
|
|
966
|
+
end: c.pos + 1,
|
|
967
|
+
fill: (b, q) => {
|
|
968
|
+
if (b.subject !== null && b.subject !== q) {
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
b.subject = q;
|
|
972
|
+
const top = lastQuery(b);
|
|
973
|
+
const first = top.checks.at(0);
|
|
974
|
+
if (first?.type === "directedEdge") {
|
|
975
|
+
top.checks[0] = { type: "nodeTarget", source: first.source, target: first.target };
|
|
976
|
+
} else if (first?.type === "undirectedEdge") {
|
|
977
|
+
top.checks[0] = { type: "nodeNeighbor", node: first.nodes[1], neighbor: first.nodes[0] };
|
|
978
|
+
}
|
|
979
|
+
return null;
|
|
980
|
+
}
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
function edgeFill(kind) {
|
|
984
|
+
return (b, query) => {
|
|
985
|
+
const target = { checks: [] };
|
|
986
|
+
const outer = { checks: [] };
|
|
987
|
+
if (b.subject === null) {
|
|
988
|
+
outer.checks.push(
|
|
989
|
+
kind === "directed" ? { type: "directedEdge", source: query, target } : { type: "undirectedEdge", nodes: [query, target] }
|
|
990
|
+
);
|
|
991
|
+
replaceLast(b, outer);
|
|
992
|
+
b.edgeCount++;
|
|
993
|
+
return target;
|
|
994
|
+
}
|
|
995
|
+
if (kind === "directed") {
|
|
996
|
+
outer.checks.push({ type: "nodeSource", source: query, target });
|
|
997
|
+
replaceLast(b, outer);
|
|
998
|
+
b.edgeCount++;
|
|
999
|
+
return target;
|
|
1000
|
+
}
|
|
1001
|
+
outer.checks.push({ type: "nodeNeighbor", node: query, neighbor: target });
|
|
1002
|
+
replaceLast(b, outer);
|
|
1003
|
+
return target;
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
function dataToken(c, i) {
|
|
1007
|
+
const inner = c.spaceEnd(i + 1);
|
|
1008
|
+
return compareToken(c, inner) ?? boolToken(c, inner) ?? (c.text[i + 1] === "[" ? metaToken(c, i) : null);
|
|
1009
|
+
}
|
|
1010
|
+
function compareToken(c, inner) {
|
|
1011
|
+
const t = c.text;
|
|
1012
|
+
const v = c.name(inner, true);
|
|
1013
|
+
if (v === null) {
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
const field = cleanMeta(v.raw);
|
|
1017
|
+
const afterName = c.spaceEnd(v.end);
|
|
1018
|
+
if (t[afterName] === "]") {
|
|
1019
|
+
return checkToken(afterName + 1, { type: "exist", field });
|
|
1020
|
+
}
|
|
1021
|
+
const op = c.op(afterName);
|
|
1022
|
+
if (op === null) {
|
|
1023
|
+
return null;
|
|
1024
|
+
}
|
|
1025
|
+
const at = c.spaceEnd(op.end);
|
|
1026
|
+
const quoted = t[at] === '"' || t[at] === "'";
|
|
1027
|
+
const end = (quoted ? c.stringEnds(at) : c.numberEnds(at)).find((x) => t[c.spaceEnd(x)] === "]");
|
|
1028
|
+
if (end === void 0) {
|
|
1029
|
+
return null;
|
|
1030
|
+
}
|
|
1031
|
+
const literal2 = t.slice(at, end);
|
|
1032
|
+
const value = quoted ? literal2.slice(1, -1) : Number.parseFloat(literal2);
|
|
1033
|
+
const { op: base, not, ci } = splitOp(op.text);
|
|
1034
|
+
return checkToken(c.spaceEnd(end) + 1, { type: "compare", field, op: base, not, ci, value });
|
|
1035
|
+
}
|
|
1036
|
+
function boolToken(c, inner) {
|
|
1037
|
+
const t = c.text;
|
|
1038
|
+
const flag = t[inner];
|
|
1039
|
+
if (flag !== "?" && flag !== "!" && flag !== "^") {
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
1042
|
+
const n = c.name(c.spaceEnd(inner + 1), true);
|
|
1043
|
+
const close = n === null ? -1 : c.spaceEnd(n.end);
|
|
1044
|
+
if (n === null || t[close] !== "]") {
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1047
|
+
return checkToken(close + 1, { type: "bool", field: cleanMeta(n.raw), op: flag });
|
|
1048
|
+
}
|
|
1049
|
+
function metaToken(c, i) {
|
|
1050
|
+
const t = c.text;
|
|
1051
|
+
const at = c.spaceEnd(i + 2);
|
|
1052
|
+
const field = META_FIELDS.find((f) => t.startsWith(f, at));
|
|
1053
|
+
const op = field === void 0 ? null : c.op(c.spaceEnd(at + field.length));
|
|
1054
|
+
if (field === void 0 || op === null) {
|
|
1055
|
+
return null;
|
|
1056
|
+
}
|
|
1057
|
+
const numAt = c.spaceEnd(op.end);
|
|
1058
|
+
const end = c.numberEnds(numAt).find((x) => {
|
|
1059
|
+
const close = c.spaceEnd(x);
|
|
1060
|
+
return t[close] === "]" && t[close + 1] === "]";
|
|
1061
|
+
});
|
|
1062
|
+
if (end === void 0) {
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
const value = Number.parseFloat(t.slice(numAt, end));
|
|
1066
|
+
const { op: base, not, ci } = splitOp(op.text);
|
|
1067
|
+
return checkToken(c.spaceEnd(end) + 2, { type: "meta", field, op: base, not, ci, value });
|
|
1068
|
+
}
|
|
1069
|
+
function isBlank(text) {
|
|
1070
|
+
return /^\s*$/.test(text.length > 1024 ? text.slice(0, 1024) : text) && text.trim() === "";
|
|
1071
|
+
}
|
|
1072
|
+
function parseCyjsSelector(text) {
|
|
1073
|
+
if (typeof text !== "string" || isBlank(text)) {
|
|
1074
|
+
return { queries: [], invalid: false };
|
|
1075
|
+
}
|
|
1076
|
+
if (text.length > MAX_SELECTOR_LENGTH) {
|
|
1077
|
+
return { queries: [], invalid: true };
|
|
1078
|
+
}
|
|
1079
|
+
const c = new Cursor(text);
|
|
1080
|
+
const first = { checks: [] };
|
|
1081
|
+
const b = { queries: [first], subject: null, edgeCount: 0, compoundCount: 0, counts: [] };
|
|
1082
|
+
let current = first;
|
|
1083
|
+
c.pos = c.spaceEnd(0);
|
|
1084
|
+
for (; ; ) {
|
|
1085
|
+
const tok = nextToken(c);
|
|
1086
|
+
if (tok === null) {
|
|
1087
|
+
return { queries: b.queries, invalid: true };
|
|
1088
|
+
}
|
|
1089
|
+
const next = tok.fill(b, current);
|
|
1090
|
+
if (next === false) {
|
|
1091
|
+
return { queries: b.queries, invalid: true };
|
|
1092
|
+
}
|
|
1093
|
+
if (next !== null) {
|
|
1094
|
+
current = next;
|
|
1095
|
+
}
|
|
1096
|
+
c.pos = tok.end;
|
|
1097
|
+
if (c.spaceEnd(c.pos) >= text.length) {
|
|
1098
|
+
break;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
b.counts.push({ edgeCount: b.edgeCount, compoundCount: b.compoundCount, subject: b.subject });
|
|
1102
|
+
const invalid = b.counts.some((k) => k.compoundCount > 0 && k.edgeCount > 0 || k.edgeCount > 1);
|
|
1103
|
+
return { queries: b.queries, invalid };
|
|
1104
|
+
}
|
|
1105
|
+
const LINE = /[\n\r\u2028\u2029]/;
|
|
1106
|
+
const SPACE = /\s/;
|
|
1107
|
+
function stripComments(text) {
|
|
1108
|
+
let out = "";
|
|
1109
|
+
let from = 0;
|
|
1110
|
+
for (; ; ) {
|
|
1111
|
+
const open = text.indexOf("/*", from);
|
|
1112
|
+
if (open < 0) {
|
|
1113
|
+
break;
|
|
1114
|
+
}
|
|
1115
|
+
const close = text.indexOf("*/", open + 3);
|
|
1116
|
+
if (close < 0) {
|
|
1117
|
+
break;
|
|
1118
|
+
}
|
|
1119
|
+
out += text.slice(from, open);
|
|
1120
|
+
from = close + 2;
|
|
1121
|
+
}
|
|
1122
|
+
return out + text.slice(from);
|
|
1123
|
+
}
|
|
1124
|
+
function skipSpace(s, i) {
|
|
1125
|
+
let j = i;
|
|
1126
|
+
while (j < s.length && SPACE.test(s[j])) {
|
|
1127
|
+
j++;
|
|
1128
|
+
}
|
|
1129
|
+
return j;
|
|
1130
|
+
}
|
|
1131
|
+
function trimEnd(s) {
|
|
1132
|
+
let e = s.length;
|
|
1133
|
+
while (e > 0 && SPACE.test(s[e - 1])) {
|
|
1134
|
+
e--;
|
|
1135
|
+
}
|
|
1136
|
+
return s.slice(0, e);
|
|
1137
|
+
}
|
|
1138
|
+
function readProperty(block, from, next) {
|
|
1139
|
+
const len = block.length;
|
|
1140
|
+
const lead = next[from];
|
|
1141
|
+
const colon = block.indexOf(":", lead + 1);
|
|
1142
|
+
if (colon < 0) {
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
const name = trimEnd(block.slice(lead, colon));
|
|
1146
|
+
if (name === "" || LINE.test(name)) {
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
const start = next[colon + 1];
|
|
1150
|
+
for (let e = start + 1; e <= len; e++) {
|
|
1151
|
+
if (LINE.test(block[e - 1])) {
|
|
1152
|
+
break;
|
|
1153
|
+
}
|
|
1154
|
+
const nn = next[e];
|
|
1155
|
+
if (nn >= len) {
|
|
1156
|
+
return { name, value: block.slice(start, e), end: len };
|
|
1157
|
+
}
|
|
1158
|
+
if (block[nn] === ";") {
|
|
1159
|
+
return { name, value: block.slice(start, e), end: nn + 1 };
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
if (start >= len) {
|
|
1163
|
+
for (let i = colon + 1; i < len; i++) {
|
|
1164
|
+
if (!LINE.test(block[i])) {
|
|
1165
|
+
return { name, value: block[i], end: len };
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
return null;
|
|
1170
|
+
}
|
|
1171
|
+
function nextNonSpace(s) {
|
|
1172
|
+
const next = new Int32Array(s.length + 1);
|
|
1173
|
+
next[s.length] = s.length;
|
|
1174
|
+
for (let i = s.length - 1; i >= 0; i--) {
|
|
1175
|
+
next[i] = SPACE.test(s[i]) ? next[i + 1] : i;
|
|
1176
|
+
}
|
|
1177
|
+
return next;
|
|
1178
|
+
}
|
|
1179
|
+
function parseCyjsStylesheetText(text) {
|
|
1180
|
+
const s = stripComments(text);
|
|
1181
|
+
const entries = [];
|
|
1182
|
+
let pos = 0;
|
|
1183
|
+
while (skipSpace(s, pos) < s.length) {
|
|
1184
|
+
const lead = skipSpace(s, pos);
|
|
1185
|
+
let open = s.indexOf("{", lead + 1);
|
|
1186
|
+
let selStart = lead;
|
|
1187
|
+
if (s[lead] === "{") {
|
|
1188
|
+
if (lead > pos) {
|
|
1189
|
+
selStart = lead - 1;
|
|
1190
|
+
open = lead;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if (open < 0) {
|
|
1194
|
+
return { entries, stop: "NO_BLOCK" };
|
|
1195
|
+
}
|
|
1196
|
+
const close = s.indexOf("}", open + 2);
|
|
1197
|
+
if (close < 0) {
|
|
1198
|
+
return { entries, stop: "NO_BLOCK" };
|
|
1199
|
+
}
|
|
1200
|
+
const selector = trimEnd(s.slice(selStart, open));
|
|
1201
|
+
const block = s.slice(open + 1, close);
|
|
1202
|
+
pos = close + 1;
|
|
1203
|
+
if (selector !== "core" && parseCyjsSelector(selector).invalid) {
|
|
1204
|
+
continue;
|
|
1205
|
+
}
|
|
1206
|
+
const properties = blockProperties(block);
|
|
1207
|
+
if (properties === null) {
|
|
1208
|
+
return { entries, stop: "BAD_PROPERTY" };
|
|
1209
|
+
}
|
|
1210
|
+
entries.push({ selector, properties, dashOnly: true });
|
|
1211
|
+
}
|
|
1212
|
+
return { entries, stop: null };
|
|
1213
|
+
}
|
|
1214
|
+
function blockProperties(block) {
|
|
1215
|
+
const properties = [];
|
|
1216
|
+
const next = nextNonSpace(block);
|
|
1217
|
+
let from = 0;
|
|
1218
|
+
while (next[from] < block.length) {
|
|
1219
|
+
const p = readProperty(block, from, next);
|
|
1220
|
+
if (p === null) {
|
|
1221
|
+
return null;
|
|
1222
|
+
}
|
|
1223
|
+
properties.push([p.name, p.value]);
|
|
1224
|
+
from = p.end;
|
|
1225
|
+
}
|
|
1226
|
+
return properties;
|
|
1227
|
+
}
|
|
1228
|
+
function isObject(v) {
|
|
1229
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
1230
|
+
}
|
|
1231
|
+
function idText(v) {
|
|
1232
|
+
if (typeof v === "number" && !Number.isNaN(v)) {
|
|
1233
|
+
return String(v);
|
|
1234
|
+
}
|
|
1235
|
+
if (typeof v === "string" && v !== "" && !/^\s+$/.test(v)) {
|
|
1236
|
+
return v;
|
|
1237
|
+
}
|
|
1238
|
+
return null;
|
|
1239
|
+
}
|
|
1240
|
+
function flags(json, edge) {
|
|
1241
|
+
const pannable = json.pannable === void 0 ? edge : Boolean(json.pannable);
|
|
1242
|
+
const grabbable = json.grabbable === void 0 ? true : Boolean(json.grabbable);
|
|
1243
|
+
return {
|
|
1244
|
+
selected: Boolean(json.selected),
|
|
1245
|
+
selectable: json.selectable === void 0 ? true : Boolean(json.selectable),
|
|
1246
|
+
locked: Boolean(json.locked),
|
|
1247
|
+
grabbable: !pannable && grabbable
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
function classSet(v) {
|
|
1251
|
+
const out = /* @__PURE__ */ new Set();
|
|
1252
|
+
let items = [];
|
|
1253
|
+
if (Array.isArray(v)) {
|
|
1254
|
+
items = v;
|
|
1255
|
+
} else if (typeof v === "string") {
|
|
1256
|
+
items = v.split(/\s+/);
|
|
1257
|
+
}
|
|
1258
|
+
for (const c of items) {
|
|
1259
|
+
if (c) {
|
|
1260
|
+
out.add(c);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
return out;
|
|
1264
|
+
}
|
|
1265
|
+
function parentsOf(nodes, ids) {
|
|
1266
|
+
const parent = new Int32Array(nodes.length).fill(-1);
|
|
1267
|
+
const children = nodes.map(() => []);
|
|
1268
|
+
const root = Int32Array.from(nodes, (_n, i) => i);
|
|
1269
|
+
const rootOf = (x) => {
|
|
1270
|
+
while (root[x] !== x) {
|
|
1271
|
+
root[x] = root[root[x]];
|
|
1272
|
+
x = root[x];
|
|
1273
|
+
}
|
|
1274
|
+
return x;
|
|
1275
|
+
};
|
|
1276
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1277
|
+
const raw = nodes[i].data.parent;
|
|
1278
|
+
if (raw === void 0 || raw === null) {
|
|
1279
|
+
continue;
|
|
1280
|
+
}
|
|
1281
|
+
const text = typeof raw === "number" && !Number.isNaN(raw) ? String(raw) : raw;
|
|
1282
|
+
const p = typeof text === "string" ? ids.get(text) : void 0;
|
|
1283
|
+
if (p === void 0 || p < 0) {
|
|
1284
|
+
nodes[i].overrides.set("parent", void 0);
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
if (typeof raw === "number") {
|
|
1288
|
+
nodes[i].overrides.set("parent", text);
|
|
1289
|
+
}
|
|
1290
|
+
if (rootOf(p) === i) {
|
|
1291
|
+
nodes[i].overrides.set("parent", void 0);
|
|
1292
|
+
continue;
|
|
1293
|
+
}
|
|
1294
|
+
parent[i] = p;
|
|
1295
|
+
root[i] = p;
|
|
1296
|
+
children[p].push(i);
|
|
1297
|
+
}
|
|
1298
|
+
return { parent, children };
|
|
1299
|
+
}
|
|
1300
|
+
function cyjsGraph(elements) {
|
|
1301
|
+
const { nodeJson, edgeJson } = elementGroups(elements);
|
|
1302
|
+
const ids = /* @__PURE__ */ new Map();
|
|
1303
|
+
const make = elementMaker(ids);
|
|
1304
|
+
const nodes = [];
|
|
1305
|
+
for (const json of nodeJson) {
|
|
1306
|
+
const e = make(json, false, /* @__PURE__ */ new Map());
|
|
1307
|
+
if (e !== null) {
|
|
1308
|
+
ids.set(e.id, nodes.length);
|
|
1309
|
+
nodes.push(e);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
const edges = [];
|
|
1313
|
+
const src = [];
|
|
1314
|
+
const tgt = [];
|
|
1315
|
+
const edgeIds = /* @__PURE__ */ new Set();
|
|
1316
|
+
for (const json of edgeJson) {
|
|
1317
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
1318
|
+
const e = make(json, true, overrides);
|
|
1319
|
+
const ends = e === null || edgeIds.has(e.id) ? null : edgeEnds(e, ids, overrides);
|
|
1320
|
+
if (e !== null && ends !== null) {
|
|
1321
|
+
edgeIds.add(e.id);
|
|
1322
|
+
edges.push(e);
|
|
1323
|
+
src.push(ends[0]);
|
|
1324
|
+
tgt.push(ends[1]);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
for (const id of edgeIds) {
|
|
1328
|
+
ids.set(id, -1);
|
|
1329
|
+
}
|
|
1330
|
+
const { parent, children } = parentsOf(nodes, ids);
|
|
1331
|
+
const incident = nodes.map(() => []);
|
|
1332
|
+
for (let e = 0; e < edges.length; e++) {
|
|
1333
|
+
incident[src[e]].push(e);
|
|
1334
|
+
if (src[e] !== tgt[e]) {
|
|
1335
|
+
incident[tgt[e]].push(e);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
return {
|
|
1339
|
+
nodes,
|
|
1340
|
+
edges,
|
|
1341
|
+
source: Int32Array.from(src),
|
|
1342
|
+
target: Int32Array.from(tgt),
|
|
1343
|
+
parent,
|
|
1344
|
+
children,
|
|
1345
|
+
incident
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
function elementGroups(elements) {
|
|
1349
|
+
const nodeJson = [];
|
|
1350
|
+
const edgeJson = [];
|
|
1351
|
+
const take = (item, group) => {
|
|
1352
|
+
const g = groupOf(item, group);
|
|
1353
|
+
if (g === "nodes") {
|
|
1354
|
+
nodeJson.push(item);
|
|
1355
|
+
} else if (g === "edges") {
|
|
1356
|
+
edgeJson.push(item);
|
|
1357
|
+
}
|
|
1358
|
+
};
|
|
1359
|
+
if (Array.isArray(elements)) {
|
|
1360
|
+
for (const item of elements) {
|
|
1361
|
+
take(item, void 0);
|
|
1362
|
+
}
|
|
1363
|
+
} else if (isObject(elements)) {
|
|
1364
|
+
for (const item of Array.isArray(elements.nodes) ? elements.nodes : []) {
|
|
1365
|
+
take(item, "nodes");
|
|
1366
|
+
}
|
|
1367
|
+
for (const item of Array.isArray(elements.edges) ? elements.edges : []) {
|
|
1368
|
+
take(item, "edges");
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return { nodeJson, edgeJson };
|
|
1372
|
+
}
|
|
1373
|
+
function groupOf(item, group) {
|
|
1374
|
+
if (!isObject(item)) {
|
|
1375
|
+
return void 0;
|
|
1376
|
+
}
|
|
1377
|
+
const data = item.data ?? {};
|
|
1378
|
+
if (!isObject(data)) {
|
|
1379
|
+
return void 0;
|
|
1380
|
+
}
|
|
1381
|
+
const given = group ?? item.group;
|
|
1382
|
+
if (given !== void 0 && given !== null) {
|
|
1383
|
+
return given;
|
|
1384
|
+
}
|
|
1385
|
+
const ends = data.source !== void 0 && data.source !== null && data.target !== void 0 && data.target !== null;
|
|
1386
|
+
return ends ? "edges" : "nodes";
|
|
1387
|
+
}
|
|
1388
|
+
function elementMaker(ids) {
|
|
1389
|
+
let generated = 0;
|
|
1390
|
+
return (json, edge, overrides) => {
|
|
1391
|
+
const data = isObject(json.data) ? json.data : {};
|
|
1392
|
+
let id;
|
|
1393
|
+
if (data.id === void 0) {
|
|
1394
|
+
id = `${String.fromCodePoint(0)}generated-${String(generated++)}`;
|
|
1395
|
+
overrides.set("id", id);
|
|
1396
|
+
} else {
|
|
1397
|
+
id = idText(data.id);
|
|
1398
|
+
if (id === null || ids.has(id)) {
|
|
1399
|
+
return null;
|
|
1400
|
+
}
|
|
1401
|
+
if (typeof data.id === "number") {
|
|
1402
|
+
overrides.set("id", id);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
return { json, data, overrides, id, classes: classSet(json.classes), ...flags(json, edge) };
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
function edgeEnds(e, ids, overrides) {
|
|
1409
|
+
const ends = [];
|
|
1410
|
+
for (const field of ["source", "target"]) {
|
|
1411
|
+
const raw = e.data[field];
|
|
1412
|
+
const text = typeof raw === "number" && !Number.isNaN(raw) ? String(raw) : raw;
|
|
1413
|
+
if (typeof raw === "number") {
|
|
1414
|
+
overrides.set(field, text);
|
|
1415
|
+
}
|
|
1416
|
+
const at = typeof text === "string" ? ids.get(text) : void 0;
|
|
1417
|
+
if (at !== void 0) {
|
|
1418
|
+
ends.push(at);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
return ends.length === 2 ? [ends[0], ends[1]] : null;
|
|
1422
|
+
}
|
|
1423
|
+
function selectorField(e, field) {
|
|
1424
|
+
if (e.overrides.has(field)) {
|
|
1425
|
+
return e.overrides.get(field);
|
|
1426
|
+
}
|
|
1427
|
+
const direct = e.data[field];
|
|
1428
|
+
if (direct !== void 0 || !field.includes(".")) {
|
|
1429
|
+
return direct;
|
|
1430
|
+
}
|
|
1431
|
+
let v = e.data;
|
|
1432
|
+
const path = field.split(".");
|
|
1433
|
+
let k = 0;
|
|
1434
|
+
while (v !== null && v !== void 0 && k < path.length) {
|
|
1435
|
+
v = v[path[k++]];
|
|
1436
|
+
}
|
|
1437
|
+
return k === path.length ? v : void 0;
|
|
1438
|
+
}
|
|
1439
|
+
function mapperData(e) {
|
|
1440
|
+
if (e.overrides.size === 0) {
|
|
1441
|
+
return e.data;
|
|
1442
|
+
}
|
|
1443
|
+
return new Proxy(e.data, {
|
|
1444
|
+
get: (target, key) => typeof key === "string" && e.overrides.has(key) ? e.overrides.get(key) : target[key]
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
function sheetEntries(style, notes) {
|
|
1448
|
+
if (typeof style === "string") {
|
|
1449
|
+
const { entries, stop } = parseCyjsStylesheetText(style);
|
|
1450
|
+
if (stop !== null) {
|
|
1451
|
+
notes.add(STYLE_ISSUE.UNREADABLE, null, "stylesheet", { sample: stop });
|
|
1452
|
+
}
|
|
1453
|
+
return entries;
|
|
1454
|
+
}
|
|
1455
|
+
if (!Array.isArray(style)) {
|
|
1456
|
+
return [];
|
|
1457
|
+
}
|
|
1458
|
+
const out = [];
|
|
1459
|
+
for (const item of style) {
|
|
1460
|
+
if (!isObject(item)) {
|
|
1461
|
+
continue;
|
|
1462
|
+
}
|
|
1463
|
+
const props = item.style ?? item.css;
|
|
1464
|
+
const properties = [];
|
|
1465
|
+
if (isObject(props)) {
|
|
1466
|
+
for (const name of Object.keys(props)) {
|
|
1467
|
+
properties.push([name, props[name]]);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
out.push({ selector: item.selector, properties, dashOnly: false });
|
|
1471
|
+
}
|
|
1472
|
+
return out;
|
|
1473
|
+
}
|
|
1474
|
+
const MAX_SELECTOR_NESTING = 64;
|
|
1475
|
+
function nesting(q, depth = 0) {
|
|
1476
|
+
if (depth > MAX_SELECTOR_NESTING) {
|
|
1477
|
+
return depth;
|
|
1478
|
+
}
|
|
1479
|
+
let max = depth;
|
|
1480
|
+
for (const c of q.checks) {
|
|
1481
|
+
for (const sub of subQueries(c)) {
|
|
1482
|
+
max = Math.max(max, nesting(sub, depth + 1));
|
|
1483
|
+
if (max > MAX_SELECTOR_NESTING) {
|
|
1484
|
+
return max;
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
return max;
|
|
1489
|
+
}
|
|
1490
|
+
function subQueries(c) {
|
|
1491
|
+
switch (c.type) {
|
|
1492
|
+
case "child":
|
|
1493
|
+
case "parent":
|
|
1494
|
+
return [c.parent, c.child];
|
|
1495
|
+
case "descendant":
|
|
1496
|
+
case "ancestor":
|
|
1497
|
+
return [c.ancestor, c.descendant];
|
|
1498
|
+
case "split":
|
|
1499
|
+
return [c.left, c.right, c.subject];
|
|
1500
|
+
case "directedEdge":
|
|
1501
|
+
case "nodeSource":
|
|
1502
|
+
case "nodeTarget":
|
|
1503
|
+
return [c.source, c.target];
|
|
1504
|
+
case "undirectedEdge":
|
|
1505
|
+
return [c.nodes[0], c.nodes[1]];
|
|
1506
|
+
case "nodeNeighbor":
|
|
1507
|
+
return [c.node, c.neighbor];
|
|
1508
|
+
default:
|
|
1509
|
+
return [];
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
function valCmp(field, op, not, ci, value) {
|
|
1513
|
+
let a = field;
|
|
1514
|
+
let b = value;
|
|
1515
|
+
const isFieldStr = typeof field === "string";
|
|
1516
|
+
const isFieldNum = typeof field === "number" && !Number.isNaN(field);
|
|
1517
|
+
let fs = null;
|
|
1518
|
+
let vs = null;
|
|
1519
|
+
if (isFieldStr || typeof value === "string" || ci) {
|
|
1520
|
+
fs = !isFieldStr && !isFieldNum ? "" : String(field);
|
|
1521
|
+
vs = String(value);
|
|
1522
|
+
}
|
|
1523
|
+
if (ci && fs !== null && vs !== null) {
|
|
1524
|
+
fs = fs.toLowerCase();
|
|
1525
|
+
vs = vs.toLowerCase();
|
|
1526
|
+
a = fs;
|
|
1527
|
+
b = vs;
|
|
1528
|
+
}
|
|
1529
|
+
let m = false;
|
|
1530
|
+
let ineq = false;
|
|
1531
|
+
switch (op) {
|
|
1532
|
+
case "*=":
|
|
1533
|
+
m = fs !== null && vs !== null && fs.includes(vs);
|
|
1534
|
+
break;
|
|
1535
|
+
case "$=":
|
|
1536
|
+
m = fs !== null && vs !== null && fs.endsWith(vs);
|
|
1537
|
+
break;
|
|
1538
|
+
case "^=":
|
|
1539
|
+
m = fs !== null && vs !== null && fs.startsWith(vs);
|
|
1540
|
+
break;
|
|
1541
|
+
case "=":
|
|
1542
|
+
m = a === b;
|
|
1543
|
+
break;
|
|
1544
|
+
case ">":
|
|
1545
|
+
ineq = true;
|
|
1546
|
+
m = a > b;
|
|
1547
|
+
break;
|
|
1548
|
+
case ">=":
|
|
1549
|
+
ineq = true;
|
|
1550
|
+
m = a >= b;
|
|
1551
|
+
break;
|
|
1552
|
+
case "<":
|
|
1553
|
+
ineq = true;
|
|
1554
|
+
m = a < b;
|
|
1555
|
+
break;
|
|
1556
|
+
case "<=":
|
|
1557
|
+
ineq = true;
|
|
1558
|
+
m = a <= b;
|
|
1559
|
+
break;
|
|
1560
|
+
}
|
|
1561
|
+
if (not && (field !== null && field !== void 0 || !ineq)) {
|
|
1562
|
+
m = !m;
|
|
1563
|
+
}
|
|
1564
|
+
return m;
|
|
1565
|
+
}
|
|
1566
|
+
const STRUCTURE_CHECKS = /* @__PURE__ */ new Set([
|
|
1567
|
+
"child",
|
|
1568
|
+
"parent",
|
|
1569
|
+
"descendant",
|
|
1570
|
+
"ancestor",
|
|
1571
|
+
"split",
|
|
1572
|
+
"directedEdge",
|
|
1573
|
+
"undirectedEdge",
|
|
1574
|
+
"nodeSource",
|
|
1575
|
+
"nodeTarget",
|
|
1576
|
+
"nodeNeighbor"
|
|
1577
|
+
]);
|
|
1578
|
+
const RUNTIME_STATES = /* @__PURE__ */ new Set([
|
|
1579
|
+
"active",
|
|
1580
|
+
"inactive",
|
|
1581
|
+
"grabbed",
|
|
1582
|
+
"free",
|
|
1583
|
+
"animated",
|
|
1584
|
+
"unanimated",
|
|
1585
|
+
"visible",
|
|
1586
|
+
"hidden",
|
|
1587
|
+
"transparent",
|
|
1588
|
+
"backgrounding",
|
|
1589
|
+
"nonbackgrounding"
|
|
1590
|
+
]);
|
|
1591
|
+
class BudgetStop extends Error {
|
|
1592
|
+
}
|
|
1593
|
+
const CHECK_EVERY = 4096;
|
|
1594
|
+
class Matcher {
|
|
1595
|
+
constructor(g, notes) {
|
|
1596
|
+
this.g = g;
|
|
1597
|
+
this.notes = notes;
|
|
1598
|
+
this.work = 0;
|
|
1599
|
+
this.#charge = null;
|
|
1600
|
+
this.#charged = 0;
|
|
1601
|
+
this.#memo = { node: /* @__PURE__ */ new Map(), edge: /* @__PURE__ */ new Map() };
|
|
1602
|
+
const n = g.nodes.length;
|
|
1603
|
+
this.degree = new Int32Array(n);
|
|
1604
|
+
this.indegree = new Int32Array(n);
|
|
1605
|
+
this.outdegree = new Int32Array(n);
|
|
1606
|
+
for (let e = 0; e < g.edges.length; e++) {
|
|
1607
|
+
const s = g.source[e];
|
|
1608
|
+
const t = g.target[e];
|
|
1609
|
+
this.degree[s] += s === t ? 2 : 1;
|
|
1610
|
+
if (s !== t) {
|
|
1611
|
+
this.degree[t]++;
|
|
1612
|
+
}
|
|
1613
|
+
this.outdegree[s]++;
|
|
1614
|
+
this.indegree[t]++;
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
#charge;
|
|
1618
|
+
#charged;
|
|
1619
|
+
#memo;
|
|
1620
|
+
/**
|
|
1621
|
+
* Whether an element matches a query.
|
|
1622
|
+
* @param q - the query
|
|
1623
|
+
* @param kind - the element's kind
|
|
1624
|
+
* @param i - the element
|
|
1625
|
+
* @returns true when every check matches
|
|
1626
|
+
*/
|
|
1627
|
+
query(q, kind, i) {
|
|
1628
|
+
for (const c of q.checks) {
|
|
1629
|
+
this.work++;
|
|
1630
|
+
if (this.#charge !== null && this.work - this.#charged >= CHECK_EVERY) {
|
|
1631
|
+
this.settle();
|
|
1632
|
+
}
|
|
1633
|
+
if (!this.check(c, kind, i)) {
|
|
1634
|
+
return false;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
return true;
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Starts one selector match: its work is charged to the budget as it runs, and the sub-query answers are fresh.
|
|
1641
|
+
* @param kind - the target the work is charged to
|
|
1642
|
+
* @param budget - the counted budget
|
|
1643
|
+
* @param signal - cancels the match
|
|
1644
|
+
*/
|
|
1645
|
+
begin(kind, budget, signal) {
|
|
1646
|
+
this.#charge = { kind, budget, signal };
|
|
1647
|
+
this.#charged = this.work;
|
|
1648
|
+
this.#memo.node.clear();
|
|
1649
|
+
this.#memo.edge.clear();
|
|
1650
|
+
}
|
|
1651
|
+
/** Ends a match: its remaining work is charged (never throwing) and its sub-query answers are dropped. */
|
|
1652
|
+
end() {
|
|
1653
|
+
const charge = this.#charge;
|
|
1654
|
+
this.#charge = null;
|
|
1655
|
+
charge?.budget.spend(charge.kind, this.work - this.#charged);
|
|
1656
|
+
this.#charged = this.work;
|
|
1657
|
+
this.#memo.node.clear();
|
|
1658
|
+
this.#memo.edge.clear();
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Charges the work done since the last charge; throws BudgetStop once the budget is exhausted.
|
|
1662
|
+
* @throws BudgetStop - when the target's budget is exhausted
|
|
1663
|
+
*/
|
|
1664
|
+
settle() {
|
|
1665
|
+
const charge = this.#charge;
|
|
1666
|
+
if (charge === null) {
|
|
1667
|
+
return;
|
|
1668
|
+
}
|
|
1669
|
+
charge.budget.spend(charge.kind, this.work - this.#charged);
|
|
1670
|
+
this.#charged = this.work;
|
|
1671
|
+
charge.signal?.throwIfAborted();
|
|
1672
|
+
if (charge.budget.exhausted(charge.kind)) {
|
|
1673
|
+
throw new BudgetStop();
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
/**
|
|
1677
|
+
* Whether an element matches a nested sub-query, remembered for the rest of the match.
|
|
1678
|
+
* @param q - the sub-query
|
|
1679
|
+
* @param kind - the element's kind
|
|
1680
|
+
* @param i - the element
|
|
1681
|
+
* @returns true when every check matches
|
|
1682
|
+
*/
|
|
1683
|
+
sub(q, kind, i) {
|
|
1684
|
+
const memo = this.#memo[kind];
|
|
1685
|
+
let seen = memo.get(q);
|
|
1686
|
+
if (seen === void 0) {
|
|
1687
|
+
seen = new Uint8Array(kind === "node" ? this.g.nodes.length : this.g.edges.length);
|
|
1688
|
+
memo.set(q, seen);
|
|
1689
|
+
}
|
|
1690
|
+
if (seen[i] !== 0) {
|
|
1691
|
+
return seen[i] === 1;
|
|
1692
|
+
}
|
|
1693
|
+
const m = this.query(q, kind, i);
|
|
1694
|
+
seen[i] = m ? 1 : 2;
|
|
1695
|
+
return m;
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* Whether an element matches one check.
|
|
1699
|
+
* @param c - the check
|
|
1700
|
+
* @param kind - the element's kind
|
|
1701
|
+
* @param i - the element
|
|
1702
|
+
* @returns true when it matches
|
|
1703
|
+
*/
|
|
1704
|
+
check(c, kind, i) {
|
|
1705
|
+
return STRUCTURE_CHECKS.has(c.type) ? this.structureCheck(c, kind, i) : this.elementCheck(c, kind, i);
|
|
1706
|
+
}
|
|
1707
|
+
/**
|
|
1708
|
+
* Whether an element matches a check of its own: its group, state, id, classes or data.
|
|
1709
|
+
* @param c - the check
|
|
1710
|
+
* @param kind - the element's kind
|
|
1711
|
+
* @param i - the element
|
|
1712
|
+
* @returns true when it matches
|
|
1713
|
+
*/
|
|
1714
|
+
elementCheck(c, kind, i) {
|
|
1715
|
+
const { g } = this;
|
|
1716
|
+
const e = kind === "node" ? g.nodes[i] : g.edges[i];
|
|
1717
|
+
switch (c.type) {
|
|
1718
|
+
case "group":
|
|
1719
|
+
return c.value === "*" || c.value === `${kind}s`;
|
|
1720
|
+
case "state":
|
|
1721
|
+
return this.state(c.value, kind, i, e);
|
|
1722
|
+
case "id":
|
|
1723
|
+
return e.id === c.value;
|
|
1724
|
+
case "class":
|
|
1725
|
+
return e.classes.has(c.value);
|
|
1726
|
+
case "exist":
|
|
1727
|
+
return selectorField(e, c.field) !== void 0;
|
|
1728
|
+
case "bool": {
|
|
1729
|
+
const v = selectorField(e, c.field);
|
|
1730
|
+
if (c.op === "?") {
|
|
1731
|
+
return Boolean(v);
|
|
1732
|
+
}
|
|
1733
|
+
return c.op === "!" ? !v : v === void 0;
|
|
1734
|
+
}
|
|
1735
|
+
case "compare":
|
|
1736
|
+
return valCmp(selectorField(e, c.field), c.op, c.not, c.ci, c.value);
|
|
1737
|
+
case "meta": {
|
|
1738
|
+
const v = kind === "node" ? this[c.field][i] : void 0;
|
|
1739
|
+
return valCmp(v, c.op, c.not, c.ci, c.value);
|
|
1740
|
+
}
|
|
1741
|
+
case "true":
|
|
1742
|
+
return true;
|
|
1743
|
+
default:
|
|
1744
|
+
return false;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1748
|
+
* Whether an element matches a check of its place in the graph: its parents, children and edges.
|
|
1749
|
+
* @param c - the check
|
|
1750
|
+
* @param kind - the element's kind
|
|
1751
|
+
* @param i - the element
|
|
1752
|
+
* @returns true when it matches
|
|
1753
|
+
*/
|
|
1754
|
+
structureCheck(c, kind, i) {
|
|
1755
|
+
const { g } = this;
|
|
1756
|
+
switch (c.type) {
|
|
1757
|
+
case "child":
|
|
1758
|
+
return this.sub(c.child, kind, i) && kind === "node" && g.parent[i] >= 0 && this.sub(c.parent, "node", g.parent[i]);
|
|
1759
|
+
case "parent":
|
|
1760
|
+
return this.sub(c.parent, kind, i) && kind === "node" && g.children[i].some((k) => this.sub(c.child, "node", k));
|
|
1761
|
+
case "descendant":
|
|
1762
|
+
return this.sub(c.descendant, kind, i) && kind === "node" && this.someAncestor(i, c.ancestor);
|
|
1763
|
+
case "ancestor":
|
|
1764
|
+
return this.sub(c.ancestor, kind, i) && kind === "node" && this.someDescendant(i, c.descendant);
|
|
1765
|
+
case "split":
|
|
1766
|
+
return this.sub(c.subject, kind, i) && this.sub(c.left, kind, i) && this.sub(c.right, kind, i);
|
|
1767
|
+
case "directedEdge":
|
|
1768
|
+
return kind === "edge" && this.sub(c.source, "node", g.source[i]) && this.sub(c.target, "node", g.target[i]);
|
|
1769
|
+
case "undirectedEdge": {
|
|
1770
|
+
if (kind !== "edge") {
|
|
1771
|
+
return false;
|
|
1772
|
+
}
|
|
1773
|
+
const [a, b] = c.nodes;
|
|
1774
|
+
const s = g.source[i];
|
|
1775
|
+
const t = g.target[i];
|
|
1776
|
+
return this.sub(a, "node", s) && this.sub(b, "node", t) || this.sub(b, "node", s) && this.sub(a, "node", t);
|
|
1777
|
+
}
|
|
1778
|
+
case "nodeSource":
|
|
1779
|
+
return kind === "node" && this.sub(c.source, kind, i) && g.incident[i].some((ed) => g.source[ed] === i && this.sub(c.target, "node", g.target[ed]));
|
|
1780
|
+
case "nodeTarget":
|
|
1781
|
+
return kind === "node" && this.sub(c.target, kind, i) && g.incident[i].some((ed) => g.target[ed] === i && this.sub(c.source, "node", g.source[ed]));
|
|
1782
|
+
case "nodeNeighbor":
|
|
1783
|
+
return kind === "node" && this.sub(c.node, kind, i) && g.incident[i].some((ed) => {
|
|
1784
|
+
const other = g.source[ed] === i ? g.target[ed] : g.source[ed];
|
|
1785
|
+
return this.sub(c.neighbor, "node", other);
|
|
1786
|
+
});
|
|
1787
|
+
default:
|
|
1788
|
+
return false;
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
/**
|
|
1792
|
+
* Whether an ancestor of a node matches a query (cycle-safe: parents never form a cycle).
|
|
1793
|
+
* @param i - the node
|
|
1794
|
+
* @param q - the query
|
|
1795
|
+
* @returns true when one does
|
|
1796
|
+
*/
|
|
1797
|
+
someAncestor(i, q) {
|
|
1798
|
+
for (let a = this.g.parent[i]; a >= 0; a = this.g.parent[a]) {
|
|
1799
|
+
if (this.sub(q, "node", a)) {
|
|
1800
|
+
return true;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
return false;
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Whether a descendant of a node matches a query, walked without recursion.
|
|
1807
|
+
* @param i - the node
|
|
1808
|
+
* @param q - the query
|
|
1809
|
+
* @returns true when one does
|
|
1810
|
+
*/
|
|
1811
|
+
someDescendant(i, q) {
|
|
1812
|
+
const stack = [...this.g.children[i]];
|
|
1813
|
+
while (stack.length > 0) {
|
|
1814
|
+
const k = stack.pop();
|
|
1815
|
+
if (this.sub(q, "node", k)) {
|
|
1816
|
+
return true;
|
|
1817
|
+
}
|
|
1818
|
+
for (const c of this.g.children[k]) {
|
|
1819
|
+
stack.push(c);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
return false;
|
|
1823
|
+
}
|
|
1824
|
+
/**
|
|
1825
|
+
* A state selector, evaluated as at load.
|
|
1826
|
+
* @param s - the state
|
|
1827
|
+
* @param kind - the element's kind
|
|
1828
|
+
* @param i - the element
|
|
1829
|
+
* @param e - the element
|
|
1830
|
+
* @returns whether the element is in the state
|
|
1831
|
+
*/
|
|
1832
|
+
state(s, kind, i, e) {
|
|
1833
|
+
const { g } = this;
|
|
1834
|
+
if (RUNTIME_STATES.has(s)) {
|
|
1835
|
+
this.notes.add(STYLE_ISSUE.STATE_ASSUMED, kind, `:${s}`, { sample: `:${s}` });
|
|
1836
|
+
}
|
|
1837
|
+
const node = kind === "node";
|
|
1838
|
+
switch (s) {
|
|
1839
|
+
case "selected":
|
|
1840
|
+
return e.selected;
|
|
1841
|
+
case "unselected":
|
|
1842
|
+
return !e.selected;
|
|
1843
|
+
case "selectable":
|
|
1844
|
+
return e.selectable;
|
|
1845
|
+
case "unselectable":
|
|
1846
|
+
return !e.selectable;
|
|
1847
|
+
case "locked":
|
|
1848
|
+
return e.locked;
|
|
1849
|
+
case "unlocked":
|
|
1850
|
+
return !e.locked;
|
|
1851
|
+
case "grabbable":
|
|
1852
|
+
return e.grabbable;
|
|
1853
|
+
case "ungrabbable":
|
|
1854
|
+
return !e.grabbable;
|
|
1855
|
+
case "free":
|
|
1856
|
+
case "inside":
|
|
1857
|
+
case "unanimated":
|
|
1858
|
+
case "inactive":
|
|
1859
|
+
case "nonbackgrounding":
|
|
1860
|
+
case "visible":
|
|
1861
|
+
return true;
|
|
1862
|
+
case "parent":
|
|
1863
|
+
return node && g.children[i].length > 0;
|
|
1864
|
+
case "childless":
|
|
1865
|
+
return node && g.children[i].length === 0;
|
|
1866
|
+
case "child":
|
|
1867
|
+
case "nonorphan":
|
|
1868
|
+
return node && g.parent[i] >= 0;
|
|
1869
|
+
case "orphan":
|
|
1870
|
+
return node && g.parent[i] < 0;
|
|
1871
|
+
case "compound":
|
|
1872
|
+
return node ? g.children[i].length > 0 : g.children[g.source[i]].length > 0 || g.children[g.target[i]].length > 0;
|
|
1873
|
+
case "loop":
|
|
1874
|
+
return !node && g.source[i] === g.target[i];
|
|
1875
|
+
case "simple":
|
|
1876
|
+
return !node && g.source[i] !== g.target[i];
|
|
1877
|
+
default:
|
|
1878
|
+
return false;
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
class Indexes {
|
|
1883
|
+
constructor(elements, spend) {
|
|
1884
|
+
this.elements = elements;
|
|
1885
|
+
this.spend = spend;
|
|
1886
|
+
this.byClass = /* @__PURE__ */ new Map();
|
|
1887
|
+
this.byId = /* @__PURE__ */ new Map();
|
|
1888
|
+
this.byValue = /* @__PURE__ */ new Map();
|
|
1889
|
+
this.stamp = 0;
|
|
1890
|
+
this.marks = new Int32Array(elements.length);
|
|
1891
|
+
for (let i = 0; i < elements.length; i++) {
|
|
1892
|
+
for (const c of elements[i].classes) {
|
|
1893
|
+
let list = this.byClass.get(c);
|
|
1894
|
+
if (list === void 0) {
|
|
1895
|
+
list = [];
|
|
1896
|
+
this.byClass.set(c, list);
|
|
1897
|
+
}
|
|
1898
|
+
list.push(i);
|
|
1899
|
+
}
|
|
1900
|
+
if (!this.byId.has(elements[i].id)) {
|
|
1901
|
+
this.byId.set(elements[i].id, i);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
spend(elements.length);
|
|
1905
|
+
}
|
|
1906
|
+
/**
|
|
1907
|
+
* The elements whose field is `===` a value.
|
|
1908
|
+
* @param field - the field
|
|
1909
|
+
* @param value - the value
|
|
1910
|
+
* @returns the element indexes
|
|
1911
|
+
*/
|
|
1912
|
+
equal(field, value) {
|
|
1913
|
+
let m = this.byValue.get(field);
|
|
1914
|
+
if (m === void 0) {
|
|
1915
|
+
m = /* @__PURE__ */ new Map();
|
|
1916
|
+
for (let i = 0; i < this.elements.length; i++) {
|
|
1917
|
+
const v = selectorField(this.elements[i], field);
|
|
1918
|
+
if (typeof v !== "string" && typeof v !== "number") {
|
|
1919
|
+
continue;
|
|
1920
|
+
}
|
|
1921
|
+
const k = `${typeof v}:${String(v)}`;
|
|
1922
|
+
let list = m.get(k);
|
|
1923
|
+
if (list === void 0) {
|
|
1924
|
+
list = [];
|
|
1925
|
+
m.set(k, list);
|
|
1926
|
+
}
|
|
1927
|
+
list.push(i);
|
|
1928
|
+
}
|
|
1929
|
+
this.byValue.set(field, m);
|
|
1930
|
+
this.spend(this.elements.length);
|
|
1931
|
+
}
|
|
1932
|
+
if (typeof value === "number" && Number.isNaN(value)) {
|
|
1933
|
+
return [];
|
|
1934
|
+
}
|
|
1935
|
+
return m.get(`${typeof value}:${String(value)}`) ?? [];
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
function candidates(q, kind, ix) {
|
|
1939
|
+
let best = null;
|
|
1940
|
+
for (const c of q.checks) {
|
|
1941
|
+
let list = null;
|
|
1942
|
+
if (c.type === "group" && c.value !== "*" && c.value !== `${kind}s`) {
|
|
1943
|
+
return [];
|
|
1944
|
+
}
|
|
1945
|
+
if (c.type === "class") {
|
|
1946
|
+
list = ix.byClass.get(c.value) ?? [];
|
|
1947
|
+
} else if (c.type === "id") {
|
|
1948
|
+
const at = ix.byId.get(c.value);
|
|
1949
|
+
list = at === void 0 ? [] : [at];
|
|
1950
|
+
} else if (c.type === "compare" && c.op === "=" && !c.not && !c.ci) {
|
|
1951
|
+
list = ix.equal(c.field, c.value);
|
|
1952
|
+
}
|
|
1953
|
+
if (list !== null && (best === null || list.length < best.length)) {
|
|
1954
|
+
best = list;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
return best;
|
|
1958
|
+
}
|
|
1959
|
+
const POSITIONS = /* @__PURE__ */ new Map([
|
|
1960
|
+
["top,left", "top-left"],
|
|
1961
|
+
["top,center", "top"],
|
|
1962
|
+
["top,right", "top-right"],
|
|
1963
|
+
["center,left", "left"],
|
|
1964
|
+
["center,center", "center"],
|
|
1965
|
+
["center,right", "right"],
|
|
1966
|
+
["bottom,left", "bottom-left"],
|
|
1967
|
+
["bottom,center", "bottom"],
|
|
1968
|
+
["bottom,right", "bottom-right"]
|
|
1969
|
+
]);
|
|
1970
|
+
function evaluateCytoscapeJs(input) {
|
|
1971
|
+
const notes = input.notes ?? new StyleNotes();
|
|
1972
|
+
const budget = input.budget ?? new StyleBudget();
|
|
1973
|
+
const graph = cyjsGraph(input.elements);
|
|
1974
|
+
const sheet = [];
|
|
1975
|
+
if (input.toolDefaults !== false) {
|
|
1976
|
+
CYJS_DEFAULT_STYLESHEET.forEach((d, k) => {
|
|
1977
|
+
sheet.push({
|
|
1978
|
+
index: k - CYJS_DEFAULT_STYLESHEET.length,
|
|
1979
|
+
tool: true,
|
|
1980
|
+
text: d.selector,
|
|
1981
|
+
selector: parseCyjsSelector(d.selector),
|
|
1982
|
+
properties: Object.entries(d.style),
|
|
1983
|
+
dashOnly: true
|
|
1984
|
+
});
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1987
|
+
const raw = sheetEntries(input.style, notes);
|
|
1988
|
+
let invalid = 0;
|
|
1989
|
+
let deep = 0;
|
|
1990
|
+
raw.forEach((r, k) => {
|
|
1991
|
+
let selector = parseCyjsSelector(r.selector);
|
|
1992
|
+
if (selector.invalid) {
|
|
1993
|
+
invalid++;
|
|
1994
|
+
}
|
|
1995
|
+
if (selector.queries.some((q) => nesting(q) > MAX_SELECTOR_NESTING)) {
|
|
1996
|
+
deep++;
|
|
1997
|
+
selector = { queries: [], invalid: true };
|
|
1998
|
+
}
|
|
1999
|
+
sheet.push({
|
|
2000
|
+
index: k,
|
|
2001
|
+
tool: false,
|
|
2002
|
+
text: typeof r.selector === "string" ? r.selector : "",
|
|
2003
|
+
selector,
|
|
2004
|
+
properties: r.properties,
|
|
2005
|
+
dashOnly: r.dashOnly
|
|
2006
|
+
});
|
|
2007
|
+
});
|
|
2008
|
+
if (invalid > 0) {
|
|
2009
|
+
notes.add(STYLE_ISSUE.SELECTOR, null, "selector", { count: invalid, sample: "invalid" });
|
|
2010
|
+
}
|
|
2011
|
+
if (deep > 0) {
|
|
2012
|
+
notes.add(STYLE_ISSUE.SELECTOR, null, "selector", { count: deep, sample: "nested too deep" });
|
|
2013
|
+
}
|
|
2014
|
+
const matcher = new Matcher(graph, notes);
|
|
2015
|
+
const node = evaluateTarget("node", graph, sheet, matcher, input, notes, budget);
|
|
2016
|
+
const edge = evaluateTarget("edge", graph, sheet, matcher, input, notes, budget);
|
|
2017
|
+
return { node, edge, graph };
|
|
2018
|
+
}
|
|
2019
|
+
function outputOrder(kind, graph, snapshot, notes) {
|
|
2020
|
+
const els = kind === "node" ? graph.nodes : graph.edges;
|
|
2021
|
+
if (snapshot === void 0) {
|
|
2022
|
+
return Int32Array.from(els, (_e, i) => i);
|
|
2023
|
+
}
|
|
2024
|
+
if (kind === "node") {
|
|
2025
|
+
const order2 = new Int32Array(snapshot.nodeCount).fill(-1);
|
|
2026
|
+
for (let i = 0; i < els.length; i++) {
|
|
2027
|
+
const at = snapshotIndex(snapshot, els[i].id);
|
|
2028
|
+
if (at >= 0 && order2[at] < 0) {
|
|
2029
|
+
order2[at] = i;
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
return order2;
|
|
2033
|
+
}
|
|
2034
|
+
const order = new Int32Array(snapshot.edgeCount).fill(-1);
|
|
2035
|
+
const nodeAt = outputOrder("node", graph, snapshot, notes);
|
|
2036
|
+
const coreToSnap = new Int32Array(graph.nodes.length).fill(-1);
|
|
2037
|
+
nodeAt.forEach((c, s) => {
|
|
2038
|
+
if (c >= 0) {
|
|
2039
|
+
coreToSnap[c] = s;
|
|
2040
|
+
}
|
|
2041
|
+
});
|
|
2042
|
+
let j = 0;
|
|
2043
|
+
for (let e = 0; e < els.length && j < snapshot.edgeCount; e++) {
|
|
2044
|
+
if (coreToSnap[graph.source[e]] === snapshot.edgeSource(j) && coreToSnap[graph.target[e]] === snapshot.edgeTarget(j)) {
|
|
2045
|
+
order[j++] = e;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
if (j < snapshot.edgeCount) {
|
|
2049
|
+
notes.add(STYLE_ISSUE.UNRESOLVED, "edge", "elements", { count: snapshot.edgeCount - j, sample: "edge order" });
|
|
2050
|
+
}
|
|
2051
|
+
return order;
|
|
2052
|
+
}
|
|
2053
|
+
function snapshotIndex(snapshot, id) {
|
|
2054
|
+
if (snapshot.ids.has(id)) {
|
|
2055
|
+
return snapshot.ids.indexOf(id);
|
|
2056
|
+
}
|
|
2057
|
+
const n = Number(id);
|
|
2058
|
+
return id.trim() !== "" && Number.isFinite(n) && snapshot.ids.has(n) ? snapshot.ids.indexOf(n) : -1;
|
|
2059
|
+
}
|
|
2060
|
+
function cellsOf(cells, name, n) {
|
|
2061
|
+
let c = cells.get(name);
|
|
2062
|
+
if (c === void 0) {
|
|
2063
|
+
c = new Array(n);
|
|
2064
|
+
cells.set(name, c);
|
|
2065
|
+
}
|
|
2066
|
+
return c;
|
|
2067
|
+
}
|
|
2068
|
+
function evaluateTarget(kind, graph, sheet, matcher, input, notes, budget) {
|
|
2069
|
+
const els = kind === "node" ? graph.nodes : graph.edges;
|
|
2070
|
+
const spend = (ops) => {
|
|
2071
|
+
budget.spend(kind, ops);
|
|
2072
|
+
};
|
|
2073
|
+
const { cells, applied } = cascade(kind, els, sheet, matcher, input, notes, budget);
|
|
2074
|
+
const order = outputOrder(kind, graph, input.snapshot, notes);
|
|
2075
|
+
const coreToOut = new Int32Array(els.length).fill(-1);
|
|
2076
|
+
order.forEach((c, k) => {
|
|
2077
|
+
if (c >= 0) {
|
|
2078
|
+
coreToOut[c] = k;
|
|
2079
|
+
}
|
|
2080
|
+
});
|
|
2081
|
+
applyBypasses(kind, els, cells, coreToOut, notes);
|
|
2082
|
+
if (kind === "edge") {
|
|
2083
|
+
forceLoopCurves(graph, cells.get("curve-style"));
|
|
2084
|
+
}
|
|
2085
|
+
const drawn = drawnValues(kind, els, cells, order, input.rendered, notes, spend);
|
|
2086
|
+
if (kind === "edge") {
|
|
2087
|
+
straightenUnpairedBeziers(graph, curveStyles(graph, cells, input.rendered), coreToOut, drawn.curved);
|
|
2088
|
+
}
|
|
2089
|
+
const built = buildRules(kind, applied, { els, order, coreToOut }, input, drawn, { matcher, notes, spend });
|
|
2090
|
+
return {
|
|
2091
|
+
n: order.length,
|
|
2092
|
+
values: drawn,
|
|
2093
|
+
rules: built.rules,
|
|
2094
|
+
columns: built.columns,
|
|
2095
|
+
rawColumns: built.rawColumns,
|
|
2096
|
+
elements: Array.from(order, (i) => i >= 0 ? els[i] : null)
|
|
2097
|
+
};
|
|
2098
|
+
}
|
|
2099
|
+
function cascade(kind, els, sheet, matcher, input, notes, budget) {
|
|
2100
|
+
const n = els.length;
|
|
2101
|
+
const specs = cyjsProperties(kind);
|
|
2102
|
+
const spend = (ops) => {
|
|
2103
|
+
budget.spend(kind, ops);
|
|
2104
|
+
};
|
|
2105
|
+
const ix = new Indexes(els, spend);
|
|
2106
|
+
const cells = /* @__PURE__ */ new Map();
|
|
2107
|
+
const notCarried = /* @__PURE__ */ new Map();
|
|
2108
|
+
const applied = [];
|
|
2109
|
+
let stopped = false;
|
|
2110
|
+
for (const entry of sheet) {
|
|
2111
|
+
input.signal?.throwIfAborted();
|
|
2112
|
+
const props = entryProperties(entry, kind, specs, notes, notCarried);
|
|
2113
|
+
if (props.length === 0) {
|
|
2114
|
+
continue;
|
|
2115
|
+
}
|
|
2116
|
+
const list = budget.exhausted(kind) ? null : budgetedMatch(entry.selector, { kind, n }, matcher, ix, input, budget);
|
|
2117
|
+
if (list === null) {
|
|
2118
|
+
stopped = true;
|
|
2119
|
+
break;
|
|
2120
|
+
}
|
|
2121
|
+
spend(list.length);
|
|
2122
|
+
applied.push({ entry, list, props });
|
|
2123
|
+
for (const p of props) {
|
|
2124
|
+
const col = cellsOf(cells, p.name, n);
|
|
2125
|
+
for (const i of list) {
|
|
2126
|
+
col[i] = cellFor(p, els[i]);
|
|
2127
|
+
}
|
|
2128
|
+
spend(list.length);
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
if (stopped) {
|
|
2132
|
+
notes.add(STYLE_ISSUE.BUDGET, kind, null, { sample: "stylesheet" });
|
|
2133
|
+
}
|
|
2134
|
+
for (const [name, count] of notCarried) {
|
|
2135
|
+
notes.add(STYLE_ISSUE.NOT_CARRIED, kind, name, { count, sample: name });
|
|
2136
|
+
}
|
|
2137
|
+
return { cells, applied };
|
|
2138
|
+
}
|
|
2139
|
+
function budgetedMatch(sel, target, matcher, ix, input, budget) {
|
|
2140
|
+
matcher.begin(target.kind, budget, input.signal);
|
|
2141
|
+
try {
|
|
2142
|
+
return matchList(sel, target.kind, target.n, matcher, ix);
|
|
2143
|
+
} catch (error) {
|
|
2144
|
+
if (!(error instanceof BudgetStop)) {
|
|
2145
|
+
throw error;
|
|
2146
|
+
}
|
|
2147
|
+
return null;
|
|
2148
|
+
} finally {
|
|
2149
|
+
matcher.end();
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
function applyBypasses(kind, els, cells, coreToOut, notes) {
|
|
2153
|
+
const specs = cyjsProperties(kind);
|
|
2154
|
+
for (let i = 0; i < els.length; i++) {
|
|
2155
|
+
const { json } = els[i];
|
|
2156
|
+
const bypass = json.style ?? json.css;
|
|
2157
|
+
if (!isObject(bypass)) {
|
|
2158
|
+
continue;
|
|
2159
|
+
}
|
|
2160
|
+
for (const name0 of Object.keys(bypass)) {
|
|
2161
|
+
const name = cyjsPropertyName(name0);
|
|
2162
|
+
const spec = specs.get(name);
|
|
2163
|
+
const value = bypass[name0];
|
|
2164
|
+
if (spec === void 0 || value === "" || value === null) {
|
|
2165
|
+
continue;
|
|
2166
|
+
}
|
|
2167
|
+
const parsed = parseCyjsValue(spec, value, "bypass");
|
|
2168
|
+
if (parsed === null || parsed === CYJS_THROWS || !isFlat(parsed)) {
|
|
2169
|
+
notes.add(STYLE_ISSUE.BAD_VALUE, kind, spec.property, { sample: value, element: coreToOut[i] });
|
|
2170
|
+
continue;
|
|
2171
|
+
}
|
|
2172
|
+
cellsOf(cells, name, els.length)[i] = parsed;
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
function drawnValues(kind, els, cells, order, rendered, notes, spend) {
|
|
2177
|
+
const out = order.length;
|
|
2178
|
+
const values = {};
|
|
2179
|
+
const words = /* @__PURE__ */ new Map();
|
|
2180
|
+
const drawnOf = { kind, els, cells, order, rendered, notes };
|
|
2181
|
+
for (const [name, spec] of cyjsProperties(kind)) {
|
|
2182
|
+
if (!cells.has(name) && rendered === void 0) {
|
|
2183
|
+
continue;
|
|
2184
|
+
}
|
|
2185
|
+
const col = drawnColumn(drawnOf, name, spec);
|
|
2186
|
+
spend(2 * out);
|
|
2187
|
+
if (spec.property.startsWith("_")) {
|
|
2188
|
+
words.set(
|
|
2189
|
+
spec.property,
|
|
2190
|
+
col.map((v) => typeof v === "string" ? v : null)
|
|
2191
|
+
);
|
|
2192
|
+
continue;
|
|
2193
|
+
}
|
|
2194
|
+
values[spec.property] ??= new Array(out).fill(null);
|
|
2195
|
+
const target = values[spec.property];
|
|
2196
|
+
col.forEach((v, k) => {
|
|
2197
|
+
if (v !== null && v !== void 0) {
|
|
2198
|
+
target[k] = v;
|
|
2199
|
+
}
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
combineParts(kind, out, words, values, notes);
|
|
2203
|
+
const drawn = {};
|
|
2204
|
+
for (const [p, col] of Object.entries(values)) {
|
|
2205
|
+
if (col.some((v) => v !== null)) {
|
|
2206
|
+
drawn[p] = col;
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
return drawn;
|
|
2210
|
+
}
|
|
2211
|
+
function drawnColumn(d, name, spec) {
|
|
2212
|
+
const { kind, order, notes, rendered } = d;
|
|
2213
|
+
const out = order.length;
|
|
2214
|
+
const col = new Array(out).fill(null);
|
|
2215
|
+
const cellCol = d.cells.get(name);
|
|
2216
|
+
for (let k = 0; k < out && cellCol !== void 0; k++) {
|
|
2217
|
+
const c = order[k] >= 0 ? cellCol[order[k]] : void 0;
|
|
2218
|
+
if (c !== void 0) {
|
|
2219
|
+
col[k] = neutralOfCell(spec, name, c, { notes, target: kind, property: spec.property, element: k });
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
if (rendered !== void 0) {
|
|
2223
|
+
overrideRendered(d, rendered, name, spec, col);
|
|
2224
|
+
}
|
|
2225
|
+
return col;
|
|
2226
|
+
}
|
|
2227
|
+
function overrideRendered(d, rendered, name, spec, col) {
|
|
2228
|
+
const { kind, order, notes } = d;
|
|
2229
|
+
for (let k = 0; k < order.length; k++) {
|
|
2230
|
+
const r = order[k] >= 0 ? rendered.get(d.els[order[k]].json) : void 0;
|
|
2231
|
+
if (r !== void 0 && Object.hasOwn(r, name)) {
|
|
2232
|
+
const site = { notes, target: kind, property: spec.property, element: k };
|
|
2233
|
+
const v = cyjsRendered(kind, name, r[name], site);
|
|
2234
|
+
col[k] = v === void 0 || v === "" && spec.type === "text" ? null : v;
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
function curveStyles(graph, cells, rendered) {
|
|
2239
|
+
const col = cells.get("curve-style");
|
|
2240
|
+
return graph.edges.map((el, e) => {
|
|
2241
|
+
const r = rendered?.get(el.json);
|
|
2242
|
+
if (r !== void 0 && Object.hasOwn(r, "curve-style")) {
|
|
2243
|
+
return r["curve-style"];
|
|
2244
|
+
}
|
|
2245
|
+
const c = col?.[e];
|
|
2246
|
+
return typeof c === "object" && c.kind === "word" ? c.value : void 0;
|
|
2247
|
+
});
|
|
2248
|
+
}
|
|
2249
|
+
function straightenUnpairedBeziers(graph, styles, coreToOut, curved) {
|
|
2250
|
+
if (curved === void 0) {
|
|
2251
|
+
return;
|
|
2252
|
+
}
|
|
2253
|
+
for (const bundle of bezierBundles(graph, styles)) {
|
|
2254
|
+
const k = bundle.length % 2 === 1 ? coreToOut[bundle[(bundle.length - 1) / 2]] : -1;
|
|
2255
|
+
if (k >= 0) {
|
|
2256
|
+
curved[k] = false;
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
function bezierBundles(graph, styles) {
|
|
2261
|
+
const bundles = /* @__PURE__ */ new Map();
|
|
2262
|
+
for (let e = 0; e < graph.edges.length; e++) {
|
|
2263
|
+
const s = graph.source[e];
|
|
2264
|
+
const t = graph.target[e];
|
|
2265
|
+
if (s === t || styles[e] !== "bezier") {
|
|
2266
|
+
continue;
|
|
2267
|
+
}
|
|
2268
|
+
const key = s < t ? `${s} ${t}` : `${t} ${s}`;
|
|
2269
|
+
const bundle = bundles.get(key);
|
|
2270
|
+
if (bundle === void 0) {
|
|
2271
|
+
bundles.set(key, [e]);
|
|
2272
|
+
} else {
|
|
2273
|
+
bundle.push(e);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
return bundles.values();
|
|
2277
|
+
}
|
|
2278
|
+
function forceLoopCurves(graph, col) {
|
|
2279
|
+
if (col === void 0) {
|
|
2280
|
+
return;
|
|
2281
|
+
}
|
|
2282
|
+
for (let e = 0; e < graph.edges.length; e++) {
|
|
2283
|
+
const c = col[e];
|
|
2284
|
+
if (graph.source[e] === graph.target[e] && typeof c === "object" && c.kind === "word" && c.value !== "bezier" && c.value !== "haystack") {
|
|
2285
|
+
col[e] = { kind: "word", value: "bezier", str: "bezier" };
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
function entryProperties(entry, kind, specs, notes, notCarried) {
|
|
2290
|
+
const out = [];
|
|
2291
|
+
for (const [name0, value] of entry.properties) {
|
|
2292
|
+
const name = entry.dashOnly ? dashOnlyName(name0) : cyjsPropertyName(name0);
|
|
2293
|
+
const spec = specs.get(name);
|
|
2294
|
+
if (spec === void 0) {
|
|
2295
|
+
if (kind === "node" && !CYJS_EDGE_ONLY.has(name) && !entry.tool) {
|
|
2296
|
+
notCarried.set(name, (notCarried.get(name) ?? 0) + 1);
|
|
2297
|
+
}
|
|
2298
|
+
continue;
|
|
2299
|
+
}
|
|
2300
|
+
const parsed = parseCyjsValue(spec, value, "rule");
|
|
2301
|
+
if (parsed === null || parsed === CYJS_THROWS) {
|
|
2302
|
+
if (!entry.tool) {
|
|
2303
|
+
notes.add(STYLE_ISSUE.BAD_VALUE, kind, null, { sample: `${name}: ${String(value)}` });
|
|
2304
|
+
}
|
|
2305
|
+
continue;
|
|
2306
|
+
}
|
|
2307
|
+
out.push({ name, spec, parsed });
|
|
2308
|
+
}
|
|
2309
|
+
return out;
|
|
2310
|
+
}
|
|
2311
|
+
function dashOnlyName(name) {
|
|
2312
|
+
return name === "content" ? "label" : name;
|
|
2313
|
+
}
|
|
2314
|
+
const CYJS_EDGE_ONLY = /* @__PURE__ */ new Set([
|
|
2315
|
+
"line-color",
|
|
2316
|
+
"line-style",
|
|
2317
|
+
"target-arrow-shape",
|
|
2318
|
+
"source-arrow-shape",
|
|
2319
|
+
"target-arrow-color",
|
|
2320
|
+
"source-arrow-color",
|
|
2321
|
+
"curve-style",
|
|
2322
|
+
"arrow-scale",
|
|
2323
|
+
"source-label",
|
|
2324
|
+
"target-label"
|
|
2325
|
+
]);
|
|
2326
|
+
function matchList(sel, kind, n, matcher, ix) {
|
|
2327
|
+
if (sel.queries.length === 0) {
|
|
2328
|
+
return [];
|
|
2329
|
+
}
|
|
2330
|
+
const stamp = ++ix.stamp;
|
|
2331
|
+
const marked = ix.marks;
|
|
2332
|
+
const hits = [];
|
|
2333
|
+
let scanned = false;
|
|
2334
|
+
const visit = (q, i) => {
|
|
2335
|
+
if (marked[i] !== stamp && matcher.query(q, kind, i)) {
|
|
2336
|
+
marked[i] = stamp;
|
|
2337
|
+
hits.push(i);
|
|
2338
|
+
}
|
|
2339
|
+
};
|
|
2340
|
+
for (const q of sel.queries) {
|
|
2341
|
+
const cands = candidates(q, kind, ix);
|
|
2342
|
+
if (cands === null) {
|
|
2343
|
+
scanned = true;
|
|
2344
|
+
for (let i = 0; i < n; i++) {
|
|
2345
|
+
visit(q, i);
|
|
2346
|
+
}
|
|
2347
|
+
} else {
|
|
2348
|
+
matcher.work += cands.length;
|
|
2349
|
+
for (const i of cands) {
|
|
2350
|
+
visit(q, i);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
if (scanned || sel.queries.length > 1) {
|
|
2355
|
+
hits.sort((a, b) => a - b);
|
|
2356
|
+
}
|
|
2357
|
+
matcher.work += hits.length;
|
|
2358
|
+
return hits;
|
|
2359
|
+
}
|
|
2360
|
+
function cellFor(p, e) {
|
|
2361
|
+
const v = p.parsed;
|
|
2362
|
+
if (v.kind === "data" || v.kind === "mapData") {
|
|
2363
|
+
return applyCyjsMapper(p.spec, v, mapperData(e)) ?? "reset";
|
|
2364
|
+
}
|
|
2365
|
+
if (v.kind === "fn") {
|
|
2366
|
+
return "fn";
|
|
2367
|
+
}
|
|
2368
|
+
return v;
|
|
2369
|
+
}
|
|
2370
|
+
const DEFAULT_CELLS = /* @__PURE__ */ new Map();
|
|
2371
|
+
function defaultCell(name, spec) {
|
|
2372
|
+
const key = `${spec.type}|${name}`;
|
|
2373
|
+
if (!DEFAULT_CELLS.has(key)) {
|
|
2374
|
+
const raw = CYJS_PROPERTY_DEFAULTS.get(name);
|
|
2375
|
+
const parsed = raw === void 0 ? null : parseCyjsValue(spec, raw, "flat");
|
|
2376
|
+
DEFAULT_CELLS.set(key, parsed === null || parsed === CYJS_THROWS || !isFlat(parsed) ? null : parsed);
|
|
2377
|
+
}
|
|
2378
|
+
return DEFAULT_CELLS.get(key) ?? null;
|
|
2379
|
+
}
|
|
2380
|
+
function isFlat(v) {
|
|
2381
|
+
return v.kind === "color" || v.kind === "number" || v.kind === "word";
|
|
2382
|
+
}
|
|
2383
|
+
function neutralOfCell(spec, name, c, site) {
|
|
2384
|
+
if (c === CYJS_THROWS) {
|
|
2385
|
+
site.notes.add(STYLE_ISSUE.BAD_VALUE, site.target, site.property, {
|
|
2386
|
+
sample: "unstyleable",
|
|
2387
|
+
element: site.element
|
|
2388
|
+
});
|
|
2389
|
+
return void 0;
|
|
2390
|
+
}
|
|
2391
|
+
if (c === "fn") {
|
|
2392
|
+
site.notes.add(STYLE_ISSUE.LAYER_FLATTENED, site.target, site.property, {
|
|
2393
|
+
sample: "FUNCTION",
|
|
2394
|
+
element: site.element
|
|
2395
|
+
});
|
|
2396
|
+
return void 0;
|
|
2397
|
+
}
|
|
2398
|
+
const flat = c === "reset" ? defaultCell(name, spec) : c;
|
|
2399
|
+
if (flat === null) {
|
|
2400
|
+
return null;
|
|
2401
|
+
}
|
|
2402
|
+
return cyjsNeutral(spec, flat, site);
|
|
2403
|
+
}
|
|
2404
|
+
function combineParts(kind, n, words, values, notes) {
|
|
2405
|
+
const va = words.get("_valign");
|
|
2406
|
+
const ha = words.get("_halign");
|
|
2407
|
+
if (kind === "node" && (va !== void 0 || ha !== void 0)) {
|
|
2408
|
+
values.labelPosition = Array.from(
|
|
2409
|
+
{ length: n },
|
|
2410
|
+
(_, i) => labelPosition(va?.[i] ?? null, ha?.[i] ?? null, (sample) => {
|
|
2411
|
+
notes.add(STYLE_ISSUE.UNKNOWN_VALUE, kind, "labelPosition", { sample, element: i });
|
|
2412
|
+
})
|
|
2413
|
+
);
|
|
2414
|
+
}
|
|
2415
|
+
const vis = words.get("_visibility");
|
|
2416
|
+
const disp = words.get("_display");
|
|
2417
|
+
if (vis !== void 0 || disp !== void 0) {
|
|
2418
|
+
const col = new Array(n).fill(null);
|
|
2419
|
+
for (let i = 0; i < n; i++) {
|
|
2420
|
+
const a = vis?.[i] ?? null;
|
|
2421
|
+
const b = disp?.[i] ?? null;
|
|
2422
|
+
if (a === null && b === null) {
|
|
2423
|
+
continue;
|
|
2424
|
+
}
|
|
2425
|
+
col[i] = a !== "hidden" && b !== "none";
|
|
2426
|
+
}
|
|
2427
|
+
values.visible = col;
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
function labelPosition(v, h, note) {
|
|
2431
|
+
if (v === null && h === null) {
|
|
2432
|
+
return null;
|
|
2433
|
+
}
|
|
2434
|
+
const vv = (v ?? "top").replace("-inside", "");
|
|
2435
|
+
const hh = (h ?? "center").replace("-inside", "");
|
|
2436
|
+
if ((v ?? "").endsWith("-inside") || (h ?? "").endsWith("-inside")) {
|
|
2437
|
+
note(`${v ?? ""} ${h ?? ""}`);
|
|
2438
|
+
}
|
|
2439
|
+
return POSITIONS.get(`${vv},${hh}`) ?? null;
|
|
2440
|
+
}
|
|
2441
|
+
function buildRules(kind, applied, core, input, truth, env) {
|
|
2442
|
+
const { els, order, coreToOut } = core;
|
|
2443
|
+
const { matcher, notes, spend } = env;
|
|
2444
|
+
const out = order.length;
|
|
2445
|
+
const columns = /* @__PURE__ */ new Map();
|
|
2446
|
+
const raw = /* @__PURE__ */ new Set();
|
|
2447
|
+
const ctx = {
|
|
2448
|
+
kind,
|
|
2449
|
+
els,
|
|
2450
|
+
coreToOut,
|
|
2451
|
+
out,
|
|
2452
|
+
snapshot: input.snapshot,
|
|
2453
|
+
truth: input.rendered === void 0 ? null : truth,
|
|
2454
|
+
matcher,
|
|
2455
|
+
notes,
|
|
2456
|
+
spend,
|
|
2457
|
+
columns,
|
|
2458
|
+
raw,
|
|
2459
|
+
members: /* @__PURE__ */ new Map(),
|
|
2460
|
+
faithful: /* @__PURE__ */ new Map(),
|
|
2461
|
+
degrees: /* @__PURE__ */ new Map()
|
|
2462
|
+
};
|
|
2463
|
+
const drafts = [];
|
|
2464
|
+
for (const a of applied) {
|
|
2465
|
+
const props = a.props.filter((p) => !p.spec.property.startsWith("_"));
|
|
2466
|
+
if (props.length === 0 || a.list.length === 0) {
|
|
2467
|
+
continue;
|
|
2468
|
+
}
|
|
2469
|
+
drafts.push(draftOf(ctx, a.entry, a.list, props));
|
|
2470
|
+
}
|
|
2471
|
+
const rules = collapse(ctx, drafts);
|
|
2472
|
+
return { rules, columns, rawColumns: [...raw] };
|
|
2473
|
+
}
|
|
2474
|
+
function draftOf(ctx, entry, list, props) {
|
|
2475
|
+
const setting = /* @__PURE__ */ new Map();
|
|
2476
|
+
const mapping = /* @__PURE__ */ new Map();
|
|
2477
|
+
let flattened = false;
|
|
2478
|
+
const id = entry.tool ? `${ctx.kind}.cytoscape-js.${String(entry.index + CYJS_DEFAULT_STYLESHEET.length)}` : `${ctx.kind}.sheet.${String(entry.index)}`;
|
|
2479
|
+
for (const p of props) {
|
|
2480
|
+
setting.delete(p.spec.property);
|
|
2481
|
+
mapping.delete(p.spec.property);
|
|
2482
|
+
const v = p.parsed;
|
|
2483
|
+
if (v.kind === "fn") {
|
|
2484
|
+
const copied = functionCopy(ctx, entry, list, p.spec.property);
|
|
2485
|
+
if (copied !== null) {
|
|
2486
|
+
mapping.set(p.spec.property, copied);
|
|
2487
|
+
flattened = true;
|
|
2488
|
+
}
|
|
2489
|
+
} else if (isFlat(v)) {
|
|
2490
|
+
const neutral = cyjsNeutral(p.spec, v, {
|
|
2491
|
+
notes: new StyleNotes(),
|
|
2492
|
+
target: ctx.kind,
|
|
2493
|
+
property: p.spec.property
|
|
2494
|
+
});
|
|
2495
|
+
if (neutral !== void 0) {
|
|
2496
|
+
setting.set(p.spec.property, neutral);
|
|
2497
|
+
}
|
|
2498
|
+
} else {
|
|
2499
|
+
mapping.set(p.spec.property, mapperMapping(ctx, entry, list, p));
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
const set = Object.fromEntries(setting);
|
|
2503
|
+
const map = Object.fromEntries(mapping);
|
|
2504
|
+
const hasMap = mapping.size > 0;
|
|
2505
|
+
const rule = () => {
|
|
2506
|
+
const where = predicateOf(ctx, entry, list);
|
|
2507
|
+
return {
|
|
2508
|
+
id,
|
|
2509
|
+
target: ctx.kind,
|
|
2510
|
+
role: roleOf(hasMap, where),
|
|
2511
|
+
origin: entry.tool ? "tool" : "declared",
|
|
2512
|
+
where,
|
|
2513
|
+
...setting.size > 0 ? { set } : {},
|
|
2514
|
+
...hasMap ? { map } : {},
|
|
2515
|
+
facts: flattened ? { elements: list.length, reason: "FUNCTION" } : { elements: list.length }
|
|
2516
|
+
};
|
|
2517
|
+
};
|
|
2518
|
+
return {
|
|
2519
|
+
rule,
|
|
2520
|
+
id,
|
|
2521
|
+
set,
|
|
2522
|
+
tool: entry.tool,
|
|
2523
|
+
single: hasMap || entry.tool ? null : singleTest(entry.selector, ctx.kind),
|
|
2524
|
+
list
|
|
2525
|
+
};
|
|
2526
|
+
}
|
|
2527
|
+
function functionCopy(ctx, entry, list, property) {
|
|
2528
|
+
const drawn = ctx.truth?.[property];
|
|
2529
|
+
if (drawn === void 0) {
|
|
2530
|
+
return null;
|
|
2531
|
+
}
|
|
2532
|
+
const key = `function.${String(entry.index)}.${property}`;
|
|
2533
|
+
const col = new Array(ctx.out).fill(null);
|
|
2534
|
+
for (const i of list) {
|
|
2535
|
+
const k = ctx.coreToOut[i];
|
|
2536
|
+
if (k >= 0) {
|
|
2537
|
+
col[k] = drawn[k];
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
ctx.columns.set(key, col);
|
|
2541
|
+
return { kind: "passthrough", by: { style: key } };
|
|
2542
|
+
}
|
|
2543
|
+
function roleOf(hasMap, where) {
|
|
2544
|
+
if (hasMap) {
|
|
2545
|
+
return "mapping";
|
|
2546
|
+
}
|
|
2547
|
+
return "all" in where ? "defaults" : "group";
|
|
2548
|
+
}
|
|
2549
|
+
function singleTest(sel, kind) {
|
|
2550
|
+
if (sel.invalid || sel.queries.length !== 1) {
|
|
2551
|
+
return null;
|
|
2552
|
+
}
|
|
2553
|
+
const checks = sel.queries[0].checks.filter(
|
|
2554
|
+
(c2) => !(c2.type === "group" && (c2.value === "*" || c2.value === `${kind}s`))
|
|
2555
|
+
);
|
|
2556
|
+
const c = checks.at(-1);
|
|
2557
|
+
if (c === void 0 || checks.slice(0, -1).some((x) => x.type !== "compare" && x.type !== "class")) {
|
|
2558
|
+
return null;
|
|
2559
|
+
}
|
|
2560
|
+
const context = JSON.stringify(checks.slice(0, -1));
|
|
2561
|
+
if (c.type === "class" && typeof c.value === "string") {
|
|
2562
|
+
return { sig: `class\0${context}`, key: c.value };
|
|
2563
|
+
}
|
|
2564
|
+
if (c.type === "id") {
|
|
2565
|
+
return { sig: `id\0${context}`, key: c.value };
|
|
2566
|
+
}
|
|
2567
|
+
if (c.type === "compare" && c.op === "=" && !c.not && !c.ci) {
|
|
2568
|
+
return { sig: `eq\0${context}\0${c.field}`, key: c.value };
|
|
2569
|
+
}
|
|
2570
|
+
return null;
|
|
2571
|
+
}
|
|
2572
|
+
function faithful(ctx, field) {
|
|
2573
|
+
const known = ctx.faithful.get(field);
|
|
2574
|
+
if (known !== void 0) {
|
|
2575
|
+
return known;
|
|
2576
|
+
}
|
|
2577
|
+
let ok = ctx.snapshot !== void 0;
|
|
2578
|
+
const table = ctx.kind === "node" ? ctx.snapshot?.nodes : ctx.snapshot?.edges;
|
|
2579
|
+
const has = table?.names().includes(field) ?? false;
|
|
2580
|
+
for (let c = 0; ok && c < ctx.els.length; c++) {
|
|
2581
|
+
const k = ctx.coreToOut[c];
|
|
2582
|
+
const rv = selectorField(ctx.els[c], field);
|
|
2583
|
+
if (rv === null || rv === false) {
|
|
2584
|
+
ok = false;
|
|
2585
|
+
break;
|
|
2586
|
+
}
|
|
2587
|
+
const gv = k >= 0 && has && table !== void 0 ? plainCell(table.value(field, k)) : null;
|
|
2588
|
+
if (rv === void 0 ? gv !== null : rv !== gv) {
|
|
2589
|
+
ok = false;
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
ctx.spend(ctx.els.length);
|
|
2593
|
+
ctx.faithful.set(field, ok);
|
|
2594
|
+
return ok;
|
|
2595
|
+
}
|
|
2596
|
+
function degreeAgrees(ctx, which) {
|
|
2597
|
+
const known = ctx.degrees.get(which);
|
|
2598
|
+
if (known !== void 0) {
|
|
2599
|
+
return known;
|
|
2600
|
+
}
|
|
2601
|
+
let ok = ctx.snapshot !== void 0 && ctx.kind === "node" && (which === "degree" || ctx.snapshot.directed);
|
|
2602
|
+
if (ok && ctx.snapshot !== void 0) {
|
|
2603
|
+
const mine = degreeValues(ctx.snapshot, which);
|
|
2604
|
+
for (let c = 0; c < ctx.els.length; c++) {
|
|
2605
|
+
const k = ctx.coreToOut[c];
|
|
2606
|
+
if (k < 0 || mine[k] !== ctx.matcher[which][c]) {
|
|
2607
|
+
ok = false;
|
|
2608
|
+
break;
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
ok &&= ctx.els.length === ctx.out;
|
|
2612
|
+
}
|
|
2613
|
+
ctx.degrees.set(which, ok);
|
|
2614
|
+
return ok;
|
|
2615
|
+
}
|
|
2616
|
+
function predicateOf(ctx, entry, list) {
|
|
2617
|
+
const short = shortPredicate(ctx, entry.selector);
|
|
2618
|
+
if (short !== null) {
|
|
2619
|
+
return short;
|
|
2620
|
+
}
|
|
2621
|
+
if (list.length === ctx.els.length && ctx.els.length === ctx.out) {
|
|
2622
|
+
return { all: true };
|
|
2623
|
+
}
|
|
2624
|
+
const sig = `${entry.tool ? "tool" : "file"}\0${entry.text}`;
|
|
2625
|
+
let key = ctx.members.get(sig);
|
|
2626
|
+
if (key === void 0) {
|
|
2627
|
+
key = `member.${String(ctx.members.size + 1)}`;
|
|
2628
|
+
ctx.members.set(sig, key);
|
|
2629
|
+
const col = new Array(ctx.out).fill(null);
|
|
2630
|
+
for (const i of list) {
|
|
2631
|
+
const k = ctx.coreToOut[i];
|
|
2632
|
+
if (k >= 0) {
|
|
2633
|
+
col[k] = true;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
ctx.spend(ctx.out + list.length);
|
|
2637
|
+
ctx.columns.set(key, col);
|
|
2638
|
+
ctx.notes.add(STYLE_ISSUE.SELECTOR_AS_COLUMN, ctx.kind, key, { sample: entry.text });
|
|
2639
|
+
}
|
|
2640
|
+
return { has: { style: key } };
|
|
2641
|
+
}
|
|
2642
|
+
function shortPredicate(ctx, sel) {
|
|
2643
|
+
if (sel.invalid) {
|
|
2644
|
+
return null;
|
|
2645
|
+
}
|
|
2646
|
+
const alts = [];
|
|
2647
|
+
for (const q of sel.queries) {
|
|
2648
|
+
const terms = queryTerms(ctx, q);
|
|
2649
|
+
if (terms === null) {
|
|
2650
|
+
return null;
|
|
2651
|
+
}
|
|
2652
|
+
if (terms !== "never") {
|
|
2653
|
+
alts.push(terms);
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
if (alts.length === 0) {
|
|
2657
|
+
return null;
|
|
2658
|
+
}
|
|
2659
|
+
if (alts.some((t) => t.length === 0)) {
|
|
2660
|
+
return ctx.els.length === ctx.out ? { all: true } : null;
|
|
2661
|
+
}
|
|
2662
|
+
if (alts.length === 1) {
|
|
2663
|
+
const t = alts[0];
|
|
2664
|
+
if (t.length > 8) {
|
|
2665
|
+
return null;
|
|
2666
|
+
}
|
|
2667
|
+
return t.length === 1 ? t[0] : { and: t };
|
|
2668
|
+
}
|
|
2669
|
+
return equalTests(alts);
|
|
2670
|
+
}
|
|
2671
|
+
function queryTerms(ctx, q) {
|
|
2672
|
+
const terms = [];
|
|
2673
|
+
let never = false;
|
|
2674
|
+
for (const c of q.checks) {
|
|
2675
|
+
if (c.type === "group") {
|
|
2676
|
+
never ||= c.value !== "*" && c.value !== `${ctx.kind}s`;
|
|
2677
|
+
continue;
|
|
2678
|
+
}
|
|
2679
|
+
const t = termOf(ctx, c);
|
|
2680
|
+
if (t === null) {
|
|
2681
|
+
return null;
|
|
2682
|
+
}
|
|
2683
|
+
terms.push(t);
|
|
2684
|
+
}
|
|
2685
|
+
return never ? "never" : terms;
|
|
2686
|
+
}
|
|
2687
|
+
function equalTests(alts) {
|
|
2688
|
+
if (alts.length > 8 || !alts.every((t) => t.length === 1 && "eq" in t[0])) {
|
|
2689
|
+
return null;
|
|
2690
|
+
}
|
|
2691
|
+
const by = alts[0][0].eq[0];
|
|
2692
|
+
const values = [];
|
|
2693
|
+
for (const t of alts) {
|
|
2694
|
+
const [r, v] = t[0].eq;
|
|
2695
|
+
if (JSON.stringify(r) !== JSON.stringify(by)) {
|
|
2696
|
+
return null;
|
|
2697
|
+
}
|
|
2698
|
+
values.push(v);
|
|
2699
|
+
}
|
|
2700
|
+
return { in: [by, values] };
|
|
2701
|
+
}
|
|
2702
|
+
function termOf(ctx, c) {
|
|
2703
|
+
switch (c.type) {
|
|
2704
|
+
case "compare":
|
|
2705
|
+
if (c.op !== "=" || c.ci || !faithful(ctx, c.field)) {
|
|
2706
|
+
return null;
|
|
2707
|
+
}
|
|
2708
|
+
return c.not ? { not: { eq: [{ data: c.field }, c.value] } } : { eq: [{ data: c.field }, c.value] };
|
|
2709
|
+
case "exist":
|
|
2710
|
+
return faithful(ctx, c.field) ? { has: { data: c.field } } : null;
|
|
2711
|
+
case "bool":
|
|
2712
|
+
return c.op === "^" && faithful(ctx, c.field) ? { not: { has: { data: c.field } } } : null;
|
|
2713
|
+
case "meta":
|
|
2714
|
+
if (c.ci || !degreeAgrees(ctx, c.field)) {
|
|
2715
|
+
return null;
|
|
2716
|
+
}
|
|
2717
|
+
return degreeTerm(c.field, c.op, c.not, c.value);
|
|
2718
|
+
default:
|
|
2719
|
+
return null;
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
function degreeTerm(field, op, not, value) {
|
|
2723
|
+
const ref = { computed: field };
|
|
2724
|
+
if (op === "=") {
|
|
2725
|
+
return not ? { not: { eq: [ref, value] } } : { eq: [ref, value] };
|
|
2726
|
+
}
|
|
2727
|
+
let below;
|
|
2728
|
+
if (op === ">" || op === "<=") {
|
|
2729
|
+
below = Math.floor(value) + 1;
|
|
2730
|
+
} else if (op === ">=" || op === "<") {
|
|
2731
|
+
below = Math.ceil(value);
|
|
2732
|
+
} else {
|
|
2733
|
+
return null;
|
|
2734
|
+
}
|
|
2735
|
+
if (!Number.isFinite(below) || below < 1 || below > 8) {
|
|
2736
|
+
return null;
|
|
2737
|
+
}
|
|
2738
|
+
const values = Array.from({ length: below }, (_, k) => k);
|
|
2739
|
+
const keeps = op === "<" || op === "<=";
|
|
2740
|
+
const inSet = { in: [ref, values] };
|
|
2741
|
+
return keeps !== not ? inSet : { not: inSet };
|
|
2742
|
+
}
|
|
2743
|
+
function mapperMapping(ctx, entry, list, p) {
|
|
2744
|
+
const v = p.parsed;
|
|
2745
|
+
const want = new Array(list.length);
|
|
2746
|
+
const site = { notes: new StyleNotes(), target: ctx.kind, property: p.spec.property };
|
|
2747
|
+
for (let k = 0; k < list.length; k++) {
|
|
2748
|
+
const c = cellFor(p, ctx.els[list[k]]);
|
|
2749
|
+
const neutral = neutralOfCell(p.spec, p.name, c, site);
|
|
2750
|
+
want[k] = neutral ?? null;
|
|
2751
|
+
}
|
|
2752
|
+
ctx.spend(list.length * 2);
|
|
2753
|
+
const candidate = candidateMapping(ctx, v, p);
|
|
2754
|
+
if (candidate !== null && ctx.snapshot !== void 0) {
|
|
2755
|
+
const exact2 = givesWanted(
|
|
2756
|
+
ctx,
|
|
2757
|
+
ctx.snapshot,
|
|
2758
|
+
candidate,
|
|
2759
|
+
{ field: v.field, property: p.spec.property },
|
|
2760
|
+
list,
|
|
2761
|
+
want
|
|
2762
|
+
);
|
|
2763
|
+
ctx.spend(list.length);
|
|
2764
|
+
if (exact2) {
|
|
2765
|
+
ctx.raw.add(v.field);
|
|
2766
|
+
return candidate;
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
const key = `value.${entry.tool ? "tool" : String(entry.index)}.${p.spec.property}`;
|
|
2770
|
+
const col = new Array(ctx.out).fill(null);
|
|
2771
|
+
for (let k = 0; k < list.length; k++) {
|
|
2772
|
+
const o = ctx.coreToOut[list[k]];
|
|
2773
|
+
if (o >= 0) {
|
|
2774
|
+
col[o] = want[k];
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
ctx.columns.set(key, col);
|
|
2778
|
+
return { kind: "passthrough", by: { style: key } };
|
|
2779
|
+
}
|
|
2780
|
+
function givesWanted(ctx, snapshot, candidate, what, list, want) {
|
|
2781
|
+
const table = ctx.kind === "node" ? snapshot.nodes : snapshot.edges;
|
|
2782
|
+
if (!table.names().includes(what.field)) {
|
|
2783
|
+
return false;
|
|
2784
|
+
}
|
|
2785
|
+
const canon = canonicalFor(ctx.kind, what.property);
|
|
2786
|
+
for (let k = 0; k < list.length; k++) {
|
|
2787
|
+
const o = ctx.coreToOut[list[k]];
|
|
2788
|
+
const cell = o < 0 ? null : plainCell(table.value(what.field, o));
|
|
2789
|
+
let got = null;
|
|
2790
|
+
if (cell !== null && !Array.isArray(cell)) {
|
|
2791
|
+
got = candidate.kind === "passthrough" ? canon(cell) : evalContinuous(candidate.points, numberOf(cell));
|
|
2792
|
+
}
|
|
2793
|
+
if (o >= 0 && got !== want[k]) {
|
|
2794
|
+
return false;
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
return true;
|
|
2798
|
+
}
|
|
2799
|
+
function candidateMapping(ctx, v, p) {
|
|
2800
|
+
if (v.kind === "data") {
|
|
2801
|
+
return { kind: "passthrough", by: { data: v.field } };
|
|
2802
|
+
}
|
|
2803
|
+
if (v.fieldMin === v.fieldMax) {
|
|
2804
|
+
return null;
|
|
2805
|
+
}
|
|
2806
|
+
const site = { notes: new StyleNotes(), target: ctx.kind, property: p.spec.property };
|
|
2807
|
+
const a = cyjsNeutral(p.spec, v.min, site);
|
|
2808
|
+
const b = cyjsNeutral(p.spec, v.max, site);
|
|
2809
|
+
if (a === void 0 || b === void 0) {
|
|
2810
|
+
return null;
|
|
2811
|
+
}
|
|
2812
|
+
const lo = { at: v.fieldMin, below: a, value: a, above: a };
|
|
2813
|
+
const hi = { at: v.fieldMax, below: b, value: b, above: b };
|
|
2814
|
+
return { kind: "continuous", by: { data: v.field }, points: v.fieldMin < v.fieldMax ? [lo, hi] : [hi, lo] };
|
|
2815
|
+
}
|
|
2816
|
+
function collapse(ctx, drafts) {
|
|
2817
|
+
const out = [];
|
|
2818
|
+
let run = 0;
|
|
2819
|
+
let i = 0;
|
|
2820
|
+
while (i < drafts.length) {
|
|
2821
|
+
const sig = drafts[i].single?.sig ?? null;
|
|
2822
|
+
let j = i + 1;
|
|
2823
|
+
while (sig !== null && j < drafts.length && drafts[j].single?.sig === sig) {
|
|
2824
|
+
j++;
|
|
2825
|
+
}
|
|
2826
|
+
if (sig === null || j - i < 3) {
|
|
2827
|
+
for (const d of drafts.slice(i, j)) {
|
|
2828
|
+
const rule = d.rule();
|
|
2829
|
+
if (!(d.tool && "all" in rule.where)) {
|
|
2830
|
+
out.push(rule);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
} else {
|
|
2834
|
+
run++;
|
|
2835
|
+
out.push(runRule(ctx, drafts.slice(i, j), sig, run));
|
|
2836
|
+
}
|
|
2837
|
+
i = j;
|
|
2838
|
+
}
|
|
2839
|
+
return out;
|
|
2840
|
+
}
|
|
2841
|
+
function runRule(ctx, members, sig, run) {
|
|
2842
|
+
const props = new Set(members.flatMap((d) => Object.keys(d.set)));
|
|
2843
|
+
const parts = sig.split("\0");
|
|
2844
|
+
const field = parts[0] === "eq" && parts[1] === "[]" ? parts[2] : null;
|
|
2845
|
+
const map = {};
|
|
2846
|
+
for (const p of props) {
|
|
2847
|
+
map[p] = runMapping(ctx, members, p, { field, key: `winner.${String(run)}.${p}` });
|
|
2848
|
+
}
|
|
2849
|
+
const first = members[0].id.split(".").pop() ?? "";
|
|
2850
|
+
return {
|
|
2851
|
+
id: `${ctx.kind}.sheet.by.${parts[0] === "eq" ? "value" : parts[0]}.${first}`,
|
|
2852
|
+
target: ctx.kind,
|
|
2853
|
+
role: "mapping",
|
|
2854
|
+
origin: "declared",
|
|
2855
|
+
where: { all: true },
|
|
2856
|
+
map,
|
|
2857
|
+
facts: { elements: members.reduce((sum, d) => sum + d.list.length, 0) }
|
|
2858
|
+
};
|
|
2859
|
+
}
|
|
2860
|
+
function runMapping(ctx, members, p, names) {
|
|
2861
|
+
const winner = new Array(ctx.out).fill(null);
|
|
2862
|
+
const table = /* @__PURE__ */ new Map();
|
|
2863
|
+
for (const d of members) {
|
|
2864
|
+
const value = d.set[p];
|
|
2865
|
+
if (value === void 0 || d.single === null) {
|
|
2866
|
+
continue;
|
|
2867
|
+
}
|
|
2868
|
+
const { key } = d.single;
|
|
2869
|
+
table.set(`${typeof key}:${String(key)}`, [key, value]);
|
|
2870
|
+
for (const c of d.list) {
|
|
2871
|
+
const k = ctx.coreToOut[c];
|
|
2872
|
+
if (k >= 0) {
|
|
2873
|
+
winner[k] = key;
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
ctx.spend(d.list.length);
|
|
2877
|
+
}
|
|
2878
|
+
const entries = [...table.values()];
|
|
2879
|
+
const byKey = new Map(entries.map(([k, v]) => [`${typeof k}:${String(k)}`, v]));
|
|
2880
|
+
const { field } = names;
|
|
2881
|
+
if (field !== null && faithful(ctx, field) && sameByData(ctx, field, winner, byKey)) {
|
|
2882
|
+
return { kind: "discrete", by: { data: field }, table: entries };
|
|
2883
|
+
}
|
|
2884
|
+
ctx.columns.set(names.key, winner);
|
|
2885
|
+
return { kind: "discrete", by: { style: names.key }, table: entries };
|
|
2886
|
+
}
|
|
2887
|
+
function sameByData(ctx, field, winner, byKey) {
|
|
2888
|
+
const table = ctx.kind === "node" ? ctx.snapshot?.nodes : ctx.snapshot?.edges;
|
|
2889
|
+
if (!table?.names().includes(field)) {
|
|
2890
|
+
return false;
|
|
2891
|
+
}
|
|
2892
|
+
for (let k = 0; k < ctx.out; k++) {
|
|
2893
|
+
const v = plainCell(table.value(field, k));
|
|
2894
|
+
const viaData = typeof v === "string" || typeof v === "number" ? byKey.get(`${typeof v}:${String(v)}`) ?? null : null;
|
|
2895
|
+
const w = winner[k];
|
|
2896
|
+
const viaWinner = w === null ? null : byKey.get(`${typeof w}:${String(w)}`) ?? null;
|
|
2897
|
+
if (viaData !== viaWinner) {
|
|
2898
|
+
return false;
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
return true;
|
|
2902
|
+
}
|
|
2903
|
+
function cytoscapeJsStyles(input) {
|
|
2904
|
+
const notes = input.notes ?? new StyleNotes();
|
|
2905
|
+
const r = evaluateCytoscapeJs({ ...input, notes });
|
|
2906
|
+
const output = (t) => ({ values: t.values, rules: t.rules, columns: t.columns });
|
|
2907
|
+
return {
|
|
2908
|
+
canonical: true,
|
|
2909
|
+
dialect: "cytoscape-js",
|
|
2910
|
+
tool: "cytoscape-js",
|
|
2911
|
+
units: "px",
|
|
2912
|
+
node: output(r.node),
|
|
2913
|
+
edge: output(r.edge),
|
|
2914
|
+
notes: notes.list()
|
|
2915
|
+
};
|
|
2916
|
+
}
|
|
2917
|
+
const CYTOSCAPE_IMPORT_KEY = "graphty_import";
|
|
2918
|
+
function cytoscapeStyleKey(key) {
|
|
2919
|
+
return `graphty_style_${key.replaceAll(/\W/g, "_")}`;
|
|
2920
|
+
}
|
|
2921
|
+
const PLAIN_NAME = /^[A-Za-z_]\w*$/;
|
|
2922
|
+
const SHAPES_TO_CYJS = /* @__PURE__ */ new Map([
|
|
2923
|
+
["ellipse", "ellipse"],
|
|
2924
|
+
["rectangle", "rectangle"],
|
|
2925
|
+
["round-rectangle", "round-rectangle"],
|
|
2926
|
+
["triangle", "triangle"],
|
|
2927
|
+
["diamond", "diamond"],
|
|
2928
|
+
["pentagon", "pentagon"],
|
|
2929
|
+
["hexagon", "hexagon"],
|
|
2930
|
+
["octagon", "octagon"],
|
|
2931
|
+
["parallelogram", "rhomboid"],
|
|
2932
|
+
["star", "star"],
|
|
2933
|
+
["vee", "vee"]
|
|
2934
|
+
]);
|
|
2935
|
+
const ARROWS_TO_CYJS = /* @__PURE__ */ new Map([
|
|
2936
|
+
["none", "none"],
|
|
2937
|
+
["triangle", "triangle"],
|
|
2938
|
+
["vee", "vee"],
|
|
2939
|
+
["tee", "tee"],
|
|
2940
|
+
["diamond", "diamond"],
|
|
2941
|
+
["circle", "circle"],
|
|
2942
|
+
["square", "square"]
|
|
2943
|
+
]);
|
|
2944
|
+
const ARROWS_NEAREST = /* @__PURE__ */ new Map([
|
|
2945
|
+
["triangle-open", "triangle"],
|
|
2946
|
+
["diamond-open", "diamond"],
|
|
2947
|
+
["circle-open", "circle"],
|
|
2948
|
+
["half", "triangle"],
|
|
2949
|
+
["inverted", "triangle"],
|
|
2950
|
+
["crow", "vee"]
|
|
2951
|
+
]);
|
|
2952
|
+
function toCyjs(target, property, value) {
|
|
2953
|
+
const specs = target === "node" ? CYJS_NODE_PROPERTIES : CYJS_EDGE_PROPERTIES;
|
|
2954
|
+
switch (property) {
|
|
2955
|
+
case "visible":
|
|
2956
|
+
return exact({ display: value === false ? "none" : "element" });
|
|
2957
|
+
case "labelItalic":
|
|
2958
|
+
return exact({ "font-style": value === true ? "italic" : "normal" });
|
|
2959
|
+
case "curved":
|
|
2960
|
+
return exact({ "curve-style": value === true ? "unbundled-bezier" : "straight" });
|
|
2961
|
+
case "labelPosition":
|
|
2962
|
+
return labelPositionToCyjs(String(value));
|
|
2963
|
+
case "shape":
|
|
2964
|
+
return enumToCyjs("shape", String(value), SHAPES_TO_CYJS, specs);
|
|
2965
|
+
case "borderStyle":
|
|
2966
|
+
return borderStyleToCyjs(String(value));
|
|
2967
|
+
case "lineStyle":
|
|
2968
|
+
return lineStyleToCyjs(String(value));
|
|
2969
|
+
case "sourceArrow":
|
|
2970
|
+
case "targetArrow":
|
|
2971
|
+
return arrowToCyjs(
|
|
2972
|
+
property === "sourceArrow" ? "source-arrow-shape" : "target-arrow-shape",
|
|
2973
|
+
String(value),
|
|
2974
|
+
specs
|
|
2975
|
+
);
|
|
2976
|
+
case "labelFont":
|
|
2977
|
+
return isFontFamily(String(value)) ? exact({ "font-family": String(value) }) : null;
|
|
2978
|
+
default:
|
|
2979
|
+
return propertyToCyjs(property, value, specs);
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
function exact(props) {
|
|
2983
|
+
return { props, approximate: false };
|
|
2984
|
+
}
|
|
2985
|
+
function near(props) {
|
|
2986
|
+
return { props, approximate: true };
|
|
2987
|
+
}
|
|
2988
|
+
function labelPositionToCyjs(text) {
|
|
2989
|
+
const v = ["top", "bottom"].find((x) => text.startsWith(x)) ?? "center";
|
|
2990
|
+
const h = ["left", "right"].find((x) => text.endsWith(x)) ?? "center";
|
|
2991
|
+
return exact({ "text-valign": v, "text-halign": h });
|
|
2992
|
+
}
|
|
2993
|
+
function enumToCyjs(name, value, table, specs) {
|
|
2994
|
+
const cy = table.get(value);
|
|
2995
|
+
if (cy !== void 0) {
|
|
2996
|
+
return exact({ [name]: cy });
|
|
2997
|
+
}
|
|
2998
|
+
const other = value.startsWith("other:") ? value.slice(6) : null;
|
|
2999
|
+
return other !== null && specs.get(name)?.enums?.includes(other) === true ? exact({ [name]: other }) : null;
|
|
3000
|
+
}
|
|
3001
|
+
function arrowToCyjs(name, value, specs) {
|
|
3002
|
+
const own = enumToCyjs(name, value, ARROWS_TO_CYJS, specs);
|
|
3003
|
+
if (own !== null) {
|
|
3004
|
+
return own;
|
|
3005
|
+
}
|
|
3006
|
+
const nearest = ARROWS_NEAREST.get(value);
|
|
3007
|
+
return nearest === void 0 ? null : near({ [name]: nearest });
|
|
3008
|
+
}
|
|
3009
|
+
function borderStyleToCyjs(value) {
|
|
3010
|
+
if (value === "dash-dot") {
|
|
3011
|
+
return near({ "border-style": "dashed" });
|
|
3012
|
+
}
|
|
3013
|
+
return ["solid", "dotted", "dashed", "double"].includes(value) ? exact({ "border-style": value }) : null;
|
|
3014
|
+
}
|
|
3015
|
+
function lineStyleToCyjs(value) {
|
|
3016
|
+
if (["solid", "dotted", "dashed"].includes(value)) {
|
|
3017
|
+
return exact({ "line-style": value });
|
|
3018
|
+
}
|
|
3019
|
+
return near({ "line-style": value === "dash-dot" || value === "long-dash" ? "dashed" : "solid" });
|
|
3020
|
+
}
|
|
3021
|
+
function propertyToCyjs(property, value, specs) {
|
|
3022
|
+
const entry = Array.from(specs).find(([, spec2]) => spec2.property === property);
|
|
3023
|
+
if (entry === void 0) {
|
|
3024
|
+
return null;
|
|
3025
|
+
}
|
|
3026
|
+
const [name, spec] = entry;
|
|
3027
|
+
if (spec.type === "positive" && !(typeof value === "number" && value > 0)) {
|
|
3028
|
+
return null;
|
|
3029
|
+
}
|
|
3030
|
+
if (value === "" && /label$/i.test(property)) {
|
|
3031
|
+
return exact({ [name]: " " });
|
|
3032
|
+
}
|
|
3033
|
+
return exact({ [name]: typeof value === "boolean" ? String(value) : value });
|
|
3034
|
+
}
|
|
3035
|
+
function literal(v) {
|
|
3036
|
+
if (typeof v === "number") {
|
|
3037
|
+
return Number.isFinite(v) ? String(v) : null;
|
|
3038
|
+
}
|
|
3039
|
+
if (typeof v !== "string" || v.includes("\\") || /[\n\r\u2028\u2029]/.test(v)) {
|
|
3040
|
+
return null;
|
|
3041
|
+
}
|
|
3042
|
+
if (!v.includes('"')) {
|
|
3043
|
+
return `"${v}"`;
|
|
3044
|
+
}
|
|
3045
|
+
return v.includes("'") ? null : `'${v}'`;
|
|
3046
|
+
}
|
|
3047
|
+
function flatKey(e, target, source) {
|
|
3048
|
+
const known = e.keys[target].get(source);
|
|
3049
|
+
if (known !== void 0) {
|
|
3050
|
+
return { key: known, fresh: false };
|
|
3051
|
+
}
|
|
3052
|
+
let key = cytoscapeStyleKey(source);
|
|
3053
|
+
let k = 2;
|
|
3054
|
+
while (e.used[target].has(key)) {
|
|
3055
|
+
key = `${cytoscapeStyleKey(source)}_${String(k)}`;
|
|
3056
|
+
k++;
|
|
3057
|
+
}
|
|
3058
|
+
e.keys[target].set(source, key);
|
|
3059
|
+
e.used[target].add(key);
|
|
3060
|
+
return { key, fresh: true };
|
|
3061
|
+
}
|
|
3062
|
+
function writeColumn(e, target, key, values) {
|
|
3063
|
+
const rows = e.data[target];
|
|
3064
|
+
for (let i = 0; i < rows.length && i < values.length; i++) {
|
|
3065
|
+
const v = values[i];
|
|
3066
|
+
if (v !== null && v !== void 0 && v !== false) {
|
|
3067
|
+
rows[i][key] = v;
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
function testsOf(e, target, where) {
|
|
3072
|
+
if ("all" in where) {
|
|
3073
|
+
return where.all ? [""] : null;
|
|
3074
|
+
}
|
|
3075
|
+
if ("has" in where) {
|
|
3076
|
+
const k = keyOf(e, target, where.has);
|
|
3077
|
+
return k === null || !("style" in where.has) ? null : [`[${k}]`];
|
|
3078
|
+
}
|
|
3079
|
+
if ("eq" in where) {
|
|
3080
|
+
return equalTest(e, target, where.eq, "=");
|
|
3081
|
+
}
|
|
3082
|
+
if ("in" in where) {
|
|
3083
|
+
const k = keyOf(e, target, where.in[0]);
|
|
3084
|
+
const values = where.in[1].map((x) => literal(x));
|
|
3085
|
+
if (values.length === 0) {
|
|
3086
|
+
return [];
|
|
3087
|
+
}
|
|
3088
|
+
return k === null || values.includes(null) ? null : values.map((v) => `[${k} = ${String(v)}]`);
|
|
3089
|
+
}
|
|
3090
|
+
if ("not" in where) {
|
|
3091
|
+
return notTests(e, target, where.not);
|
|
3092
|
+
}
|
|
3093
|
+
if ("and" in where) {
|
|
3094
|
+
return andTests(e, target, where.and);
|
|
3095
|
+
}
|
|
3096
|
+
if ("or" in where) {
|
|
3097
|
+
return orTests(e, target, where.or);
|
|
3098
|
+
}
|
|
3099
|
+
return null;
|
|
3100
|
+
}
|
|
3101
|
+
function equalTest(e, target, eq, op) {
|
|
3102
|
+
const k = keyOf(e, target, eq[0]);
|
|
3103
|
+
const v = literal(eq[1]);
|
|
3104
|
+
return k === null || v === null ? null : [`[${k} ${op} ${v}]`];
|
|
3105
|
+
}
|
|
3106
|
+
function notTests(e, target, inner) {
|
|
3107
|
+
if ("has" in inner && "style" in inner.has) {
|
|
3108
|
+
const k = keyOf(e, target, inner.has);
|
|
3109
|
+
return k === null ? null : [`[^${k}]`];
|
|
3110
|
+
}
|
|
3111
|
+
return "eq" in inner ? equalTest(e, target, inner.eq, "!=") : null;
|
|
3112
|
+
}
|
|
3113
|
+
function andTests(e, target, parts) {
|
|
3114
|
+
let alts = [""];
|
|
3115
|
+
for (const p of parts) {
|
|
3116
|
+
const t = testsOf(e, target, p);
|
|
3117
|
+
if (t === null) {
|
|
3118
|
+
return null;
|
|
3119
|
+
}
|
|
3120
|
+
alts = alts.flatMap((a) => t.map((b) => a + b));
|
|
3121
|
+
if (alts.length > 8) {
|
|
3122
|
+
return null;
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
return alts;
|
|
3126
|
+
}
|
|
3127
|
+
function orTests(e, target, parts) {
|
|
3128
|
+
const out = [];
|
|
3129
|
+
for (const p of parts) {
|
|
3130
|
+
const t = testsOf(e, target, p);
|
|
3131
|
+
if (t === null) {
|
|
3132
|
+
return null;
|
|
3133
|
+
}
|
|
3134
|
+
out.push(...t);
|
|
3135
|
+
}
|
|
3136
|
+
return out.length > 8 ? null : out;
|
|
3137
|
+
}
|
|
3138
|
+
function keyOf(e, target, ref) {
|
|
3139
|
+
if ("style" in ref) {
|
|
3140
|
+
const col = e.extracted.columns[target].get(ref.style);
|
|
3141
|
+
if (col === void 0) {
|
|
3142
|
+
return null;
|
|
3143
|
+
}
|
|
3144
|
+
const { key, fresh } = flatKey(e, target, ref.style);
|
|
3145
|
+
if (fresh) {
|
|
3146
|
+
writeColumn(e, target, key, col);
|
|
3147
|
+
}
|
|
3148
|
+
return key;
|
|
3149
|
+
}
|
|
3150
|
+
if ("data" in ref && PLAIN_NAME.test(ref.data) && ref.data !== CYTOSCAPE_IMPORT_KEY && !ref.data.startsWith("graphty_")) {
|
|
3151
|
+
return ref.data;
|
|
3152
|
+
}
|
|
3153
|
+
return null;
|
|
3154
|
+
}
|
|
3155
|
+
function selectorsOf(e, rule, index) {
|
|
3156
|
+
const head = `${rule.target}${e.scope}`;
|
|
3157
|
+
const tests = testsOf(e, rule.target, rule.where);
|
|
3158
|
+
if (tests !== null) {
|
|
3159
|
+
return tests.map((t) => head + t);
|
|
3160
|
+
}
|
|
3161
|
+
const src = refSource(
|
|
3162
|
+
rule.target,
|
|
3163
|
+
e.data[rule.target].length,
|
|
3164
|
+
e.extracted.columns[rule.target],
|
|
3165
|
+
e.extracted.features[rule.target]
|
|
3166
|
+
);
|
|
3167
|
+
const { key } = flatKey(e, rule.target, `emit.where.${String(index)}`);
|
|
3168
|
+
const col = new Array(src.n);
|
|
3169
|
+
for (let i = 0; i < src.n; i++) {
|
|
3170
|
+
col[i] = matches(rule.where, src, i) ? true : null;
|
|
3171
|
+
}
|
|
3172
|
+
writeColumn(e, rule.target, key, col);
|
|
3173
|
+
return [`${head}[${key}]`];
|
|
3174
|
+
}
|
|
3175
|
+
function emitRule(e, rule, index) {
|
|
3176
|
+
const { target } = rule;
|
|
3177
|
+
const selectors = selectorsOf(e, rule, index);
|
|
3178
|
+
const constants = {};
|
|
3179
|
+
for (const [p, v] of Object.entries(rule.set ?? {})) {
|
|
3180
|
+
if (v === void 0) {
|
|
3181
|
+
continue;
|
|
3182
|
+
}
|
|
3183
|
+
const w = written(e, target, p, v);
|
|
3184
|
+
if (w !== null) {
|
|
3185
|
+
Object.assign(constants, w);
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
if (Object.keys(constants).length > 0) {
|
|
3189
|
+
for (const sel of selectors) {
|
|
3190
|
+
e.stylesheet.push({ selector: sel, style: constants });
|
|
3191
|
+
if (target === "edge" && constants["curve-style"] === "straight") {
|
|
3192
|
+
e.stylesheet.push({ selector: `${sel}:loop`, style: { "curve-style": "haystack" } });
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
for (const [p, m] of Object.entries(rule.map ?? {})) {
|
|
3197
|
+
if (m !== void 0) {
|
|
3198
|
+
emitMapping(e, rule, index, selectors, p, m);
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
function cyjsHoldsExactly(target, property, value) {
|
|
3203
|
+
const w = toCyjs(target, property, value);
|
|
3204
|
+
return w !== null && !w.approximate;
|
|
3205
|
+
}
|
|
3206
|
+
function written(e, target, property, value) {
|
|
3207
|
+
const w = toCyjs(target, property, value);
|
|
3208
|
+
if (w === null) {
|
|
3209
|
+
e.notes.add(STYLE_ISSUE.NOT_WRITTEN, target, property, { sample: value });
|
|
3210
|
+
return null;
|
|
3211
|
+
}
|
|
3212
|
+
if (w.approximate) {
|
|
3213
|
+
e.notes.add(STYLE_ISSUE.APPROXIMATED, target, property, { sample: value });
|
|
3214
|
+
}
|
|
3215
|
+
return w.props;
|
|
3216
|
+
}
|
|
3217
|
+
function emitMapping(e, rule, index, selectors, property, m) {
|
|
3218
|
+
const { target } = rule;
|
|
3219
|
+
if (m.kind === "discrete") {
|
|
3220
|
+
const key = keyOf(e, target, m.by);
|
|
3221
|
+
const keys = m.table.map(([k]) => literal(k));
|
|
3222
|
+
if (key === null || keys.includes(null)) {
|
|
3223
|
+
emitValues(e, rule, index, selectors, property);
|
|
3224
|
+
return;
|
|
3225
|
+
}
|
|
3226
|
+
m.table.forEach(([, v], j) => {
|
|
3227
|
+
const w = written(e, target, property, v);
|
|
3228
|
+
if (w === null) {
|
|
3229
|
+
return;
|
|
3230
|
+
}
|
|
3231
|
+
for (const sel of selectors) {
|
|
3232
|
+
e.stylesheet.push({ selector: `${sel}[${key} = ${String(keys[j])}]`, style: w });
|
|
3233
|
+
}
|
|
3234
|
+
});
|
|
3235
|
+
return;
|
|
3236
|
+
}
|
|
3237
|
+
if (m.kind === "continuous" && isNumericOutput(target, property)) {
|
|
3238
|
+
const key = numericKey(e, target, m.by, index);
|
|
3239
|
+
if (key !== null) {
|
|
3240
|
+
emitContinuous(e, target, selectors, property, key, m.points);
|
|
3241
|
+
return;
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
emitValues(e, rule, index, selectors, property);
|
|
3245
|
+
}
|
|
3246
|
+
function isNumericOutput(target, property) {
|
|
3247
|
+
const kind = STYLE_PROPERTIES[target].get(property);
|
|
3248
|
+
return kind === "number" || kind === "opacity" || kind === "color";
|
|
3249
|
+
}
|
|
3250
|
+
function numericKey(e, target, by, index) {
|
|
3251
|
+
const src = refSource(target, e.data[target].length, e.extracted.columns[target], e.extracted.features[target]);
|
|
3252
|
+
const col = src.column(by);
|
|
3253
|
+
if (col === null) {
|
|
3254
|
+
return null;
|
|
3255
|
+
}
|
|
3256
|
+
if ("data" in by && PLAIN_NAME.test(by.data) && !by.data.startsWith("graphty_")) {
|
|
3257
|
+
return by.data;
|
|
3258
|
+
}
|
|
3259
|
+
const { key } = flatKey(e, target, `emit.input.${String(index)}`);
|
|
3260
|
+
const values = new Array(src.n);
|
|
3261
|
+
for (let i = 0; i < src.n; i++) {
|
|
3262
|
+
const v = col[i];
|
|
3263
|
+
values[i] = typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
3264
|
+
}
|
|
3265
|
+
writeColumn(e, target, key, values);
|
|
3266
|
+
return key;
|
|
3267
|
+
}
|
|
3268
|
+
function emitContinuous(e, target, selectors, property, key, points) {
|
|
3269
|
+
if (points.length === 0) {
|
|
3270
|
+
return;
|
|
3271
|
+
}
|
|
3272
|
+
const lit = String;
|
|
3273
|
+
const push = (test, style) => {
|
|
3274
|
+
if (style === null) {
|
|
3275
|
+
return;
|
|
3276
|
+
}
|
|
3277
|
+
for (const sel of selectors) {
|
|
3278
|
+
e.stylesheet.push({ selector: `${sel}${test}`, style });
|
|
3279
|
+
}
|
|
3280
|
+
};
|
|
3281
|
+
const first = points[0];
|
|
3282
|
+
const last = points.at(-1) ?? first;
|
|
3283
|
+
push(`[${key} < ${lit(first.at)}]`, written(e, target, property, first.below));
|
|
3284
|
+
for (let k = 0; k + 1 < points.length; k++) {
|
|
3285
|
+
const a = points[k];
|
|
3286
|
+
const b = points[k + 1];
|
|
3287
|
+
const wa = written(e, target, property, a.above);
|
|
3288
|
+
const wb = written(e, target, property, b.below);
|
|
3289
|
+
if (wa === null || wb === null) {
|
|
3290
|
+
continue;
|
|
3291
|
+
}
|
|
3292
|
+
const style = {};
|
|
3293
|
+
for (const name of Object.keys(wa)) {
|
|
3294
|
+
style[name] = `mapData(${key}, ${lit(a.at)}, ${lit(b.at)}, ${String(wa[name])}, ${String(wb[name])})`;
|
|
3295
|
+
}
|
|
3296
|
+
push(`[${key} > ${lit(a.at)}][${key} < ${lit(b.at)}]`, style);
|
|
3297
|
+
}
|
|
3298
|
+
push(`[${key} > ${lit(last.at)}]`, written(e, target, property, last.above));
|
|
3299
|
+
for (const p of points) {
|
|
3300
|
+
push(`[${key} = ${lit(p.at)}]`, written(e, target, property, p.value));
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
function emitValues(e, rule, index, selectors, property) {
|
|
3304
|
+
const { target } = rule;
|
|
3305
|
+
const n = e.data[target].length;
|
|
3306
|
+
const src = refSource(target, n, e.extracted.columns[target], e.extracted.features[target]);
|
|
3307
|
+
const mapping = new Map(Object.entries(rule.map ?? {})).get(property);
|
|
3308
|
+
const only = { ...rule, where: { all: true }, set: void 0, map: { [property]: mapping } };
|
|
3309
|
+
const values = resolveRules([only], target, property, src);
|
|
3310
|
+
const names = /* @__PURE__ */ new Map();
|
|
3311
|
+
for (let i = 0; i < n; i++) {
|
|
3312
|
+
const v = values[i];
|
|
3313
|
+
if (v === null) {
|
|
3314
|
+
continue;
|
|
3315
|
+
}
|
|
3316
|
+
const w = written(e, target, property, v);
|
|
3317
|
+
if (w === null) {
|
|
3318
|
+
continue;
|
|
3319
|
+
}
|
|
3320
|
+
for (const [name, x] of Object.entries(w)) {
|
|
3321
|
+
let col = names.get(name);
|
|
3322
|
+
if (col === void 0) {
|
|
3323
|
+
col = new Array(n).fill(null);
|
|
3324
|
+
names.set(name, col);
|
|
3325
|
+
}
|
|
3326
|
+
col[i] = x;
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
for (const [name, col] of names) {
|
|
3330
|
+
const { key } = flatKey(e, target, `emit.value.${String(index)}.${name}`);
|
|
3331
|
+
writeColumn(e, target, key, col);
|
|
3332
|
+
for (const sel of selectors) {
|
|
3333
|
+
e.stylesheet.push({ selector: `${sel}[${key}]`, style: { [name]: `data(${key})` } });
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
function toCytoscapeStylesheet(extracted, options = {}) {
|
|
3338
|
+
const notes = new StyleNotes();
|
|
3339
|
+
const importId = options.importId?.replaceAll(/["'\\\n\r\u2028\u2029]/g, "_");
|
|
3340
|
+
const { nodes } = extracted.fingerprint;
|
|
3341
|
+
const { edges } = extracted.fingerprint;
|
|
3342
|
+
const e = {
|
|
3343
|
+
extracted,
|
|
3344
|
+
notes,
|
|
3345
|
+
scope: importId === void 0 ? "" : `[${CYTOSCAPE_IMPORT_KEY} = "${importId}"]`,
|
|
3346
|
+
stylesheet: [],
|
|
3347
|
+
data: {
|
|
3348
|
+
node: Array.from({ length: nodes }, () => ({})),
|
|
3349
|
+
edge: Array.from({ length: edges }, () => ({}))
|
|
3350
|
+
},
|
|
3351
|
+
keys: { node: /* @__PURE__ */ new Map(), edge: /* @__PURE__ */ new Map() },
|
|
3352
|
+
// a flat key never takes the name of a data field the elements already hold
|
|
3353
|
+
used: {
|
|
3354
|
+
node: /* @__PURE__ */ new Set([CYTOSCAPE_IMPORT_KEY, ...dataNames(extracted, "node")]),
|
|
3355
|
+
edge: /* @__PURE__ */ new Set([CYTOSCAPE_IMPORT_KEY, ...dataNames(extracted, "edge")])
|
|
3356
|
+
}
|
|
3357
|
+
};
|
|
3358
|
+
if (importId !== void 0) {
|
|
3359
|
+
for (const rows2 of [e.data.node, e.data.edge]) {
|
|
3360
|
+
for (const row of rows2) {
|
|
3361
|
+
row[CYTOSCAPE_IMPORT_KEY] = importId;
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
const rules = extracted.styles.source.tool === "cytoscape-js" ? extracted.styles.rules.filter((r) => r.origin !== "tool") : extracted.styles.rules;
|
|
3366
|
+
rules.forEach((rule, k) => {
|
|
3367
|
+
if (rule.role !== "exceptions") {
|
|
3368
|
+
emitRule(e, rule, k);
|
|
3369
|
+
}
|
|
3370
|
+
});
|
|
3371
|
+
const bypass = exactness(e, rules);
|
|
3372
|
+
for (const sel of e.stylesheet) {
|
|
3373
|
+
if (parseCyjsSelector(sel.selector).invalid) {
|
|
3374
|
+
notes.add(STYLE_ISSUE.NOT_WRITTEN, null, "selector", { sample: sel.selector });
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3377
|
+
const rows = (list) => list.map((r) => Object.keys(r).length > 0 ? r : null);
|
|
3378
|
+
return {
|
|
3379
|
+
stylesheet: e.stylesheet,
|
|
3380
|
+
elementData: { node: rows(e.data.node), edge: rows(e.data.edge) },
|
|
3381
|
+
bypass,
|
|
3382
|
+
notes: notes.list()
|
|
3383
|
+
};
|
|
3384
|
+
}
|
|
3385
|
+
function exactness(e, rules) {
|
|
3386
|
+
const { extracted } = e;
|
|
3387
|
+
const nodes = e.data.node.length;
|
|
3388
|
+
const elements = [];
|
|
3389
|
+
for (let i = 0; i < nodes; i++) {
|
|
3390
|
+
elements.push({
|
|
3391
|
+
group: "nodes",
|
|
3392
|
+
data: { ...dataColumns(extracted, "node", i), ...e.data.node[i], id: `n${String(i)}` }
|
|
3393
|
+
});
|
|
3394
|
+
}
|
|
3395
|
+
const far = nodes > 1 ? "n1" : "n0";
|
|
3396
|
+
for (let i = 0; i < e.data.edge.length && nodes > 0; i++) {
|
|
3397
|
+
elements.push({
|
|
3398
|
+
group: "edges",
|
|
3399
|
+
data: {
|
|
3400
|
+
...dataColumns(extracted, "edge", i),
|
|
3401
|
+
...e.data.edge[i],
|
|
3402
|
+
id: `e${String(i)}`,
|
|
3403
|
+
source: "n0",
|
|
3404
|
+
target: far
|
|
3405
|
+
}
|
|
3406
|
+
});
|
|
3407
|
+
}
|
|
3408
|
+
const drawn = evaluateCytoscapeJs({ elements, style: e.stylesheet, toolDefaults: false });
|
|
3409
|
+
const out = {
|
|
3410
|
+
node: [],
|
|
3411
|
+
edge: []
|
|
3412
|
+
};
|
|
3413
|
+
for (const target of ["node", "edge"]) {
|
|
3414
|
+
const n = e.data[target].length;
|
|
3415
|
+
const src = refSource(target, n, extracted.columns[target], extracted.features[target]);
|
|
3416
|
+
const rows = new Array(n).fill(null);
|
|
3417
|
+
for (const property of STYLE_PROPERTIES[target].keys()) {
|
|
3418
|
+
const want = resolveRules(rules, target, property, src);
|
|
3419
|
+
addBypasses(rows, target, property, want, drawn[target].values[property]);
|
|
3420
|
+
}
|
|
3421
|
+
out[target] = rows;
|
|
3422
|
+
}
|
|
3423
|
+
return out;
|
|
3424
|
+
}
|
|
3425
|
+
function addBypasses(rows, target, property, want, got) {
|
|
3426
|
+
for (let i = 0; i < rows.length; i++) {
|
|
3427
|
+
const w = want[i];
|
|
3428
|
+
const conv = w === null || (got?.[i] ?? null) === w ? null : toCyjs(target, property, w);
|
|
3429
|
+
if (conv !== null && !conv.approximate) {
|
|
3430
|
+
rows[i] = { ...rows[i], ...conv.props };
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
function dataNames(extracted, target) {
|
|
3435
|
+
return extracted.features[target].flatMap((f) => "data" in f.ref ? [f.ref.data] : []);
|
|
3436
|
+
}
|
|
3437
|
+
function dataColumns(extracted, target, i) {
|
|
3438
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
3439
|
+
for (const f of extracted.features[target]) {
|
|
3440
|
+
if ("data" in f.ref && f.values[i] !== null) {
|
|
3441
|
+
out[f.ref.data] = f.values[i];
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
return out;
|
|
3445
|
+
}
|
|
3446
|
+
export {
|
|
3447
|
+
CYTOSCAPE_IMPORT_KEY as C,
|
|
3448
|
+
StyleBudget as S,
|
|
3449
|
+
cyjsHoldsExactly as a,
|
|
3450
|
+
CYJS_EDGE_PROPERTIES as b,
|
|
3451
|
+
cytoscapeJsStyles as c,
|
|
3452
|
+
CYJS_NODE_PROPERTIES as d,
|
|
3453
|
+
evaluateCytoscapeJs as e,
|
|
3454
|
+
toCytoscapeStylesheet as t
|
|
3455
|
+
};
|
|
3456
|
+
//# sourceMappingURL=emit-DZy6JgdA.js.map
|