@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,1025 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Neutral style rules back to a Cytoscape visual style, for the CX, CX2 and session writers: rules over every element
|
|
3
|
+
* become defaults and mappings, everything Cytoscape cannot say as a rule (a rule over a group of elements, a second
|
|
4
|
+
* mapping of one property, a value written per element) becomes per-element bypasses, so what Cytoscape draws is
|
|
5
|
+
* what the rules give. Every value the style cannot hold is a coded note.
|
|
6
|
+
*/
|
|
7
|
+
import { escapeXmlAttribute } from "../../common/escape.js";
|
|
8
|
+
import { num6 } from "../canon/number.js";
|
|
9
|
+
import { STYLE_ISSUE } from "../codes.js";
|
|
10
|
+
import { StyleNotes } from "../notes.js";
|
|
11
|
+
import { canonicalFor, degreeValues, refSource, resolveRules } from "../plan/resolve.js";
|
|
12
|
+
import { STYLE_PROPERTIES } from "../vocabulary.js";
|
|
13
|
+
import { JAVA_FONTS } from "./lexicon.js";
|
|
14
|
+
import { emptyCytoscapeStyle, } from "./mappings.js";
|
|
15
|
+
/**
|
|
16
|
+
* `#RRGGBB`.
|
|
17
|
+
* @param v - a canonical color
|
|
18
|
+
* @returns the color as Cytoscape writes it
|
|
19
|
+
*/
|
|
20
|
+
const colorOut = (v) => String(v).toUpperCase();
|
|
21
|
+
/**
|
|
22
|
+
* A writer of an enumeration.
|
|
23
|
+
* @param table - canonical value to the dialect's spelling
|
|
24
|
+
* @param near - canonical value to the nearest spelling, for values the dialect does not have
|
|
25
|
+
* @param upper - whether an `other:` value is written uppercase with underscores
|
|
26
|
+
* @param cytoscape - the `other:` values (lowercase, hyphenated) that are Cytoscape's own names, written as they
|
|
27
|
+
* are; any other `other:` value (another program's, such as Graphviz's `invtrapezium`) is no Cytoscape value and
|
|
28
|
+
* is written as its nearest
|
|
29
|
+
* @returns the writer
|
|
30
|
+
*/
|
|
31
|
+
function enumOut(table, near, upper, cytoscape = new Set()) {
|
|
32
|
+
return (v, approx) => {
|
|
33
|
+
const s = String(v);
|
|
34
|
+
if (Object.hasOwn(table, s)) {
|
|
35
|
+
return table[s];
|
|
36
|
+
}
|
|
37
|
+
if (s.startsWith("other:") && cytoscape.has(s.slice("other:".length).toLowerCase().replaceAll("_", "-"))) {
|
|
38
|
+
const raw = s.slice("other:".length);
|
|
39
|
+
const out = upper ? raw.toUpperCase().replaceAll("-", "_") : raw;
|
|
40
|
+
if (out !== raw) {
|
|
41
|
+
// read back in Cytoscape's spelling, which is another value
|
|
42
|
+
approx();
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
approx();
|
|
47
|
+
return Object.hasOwn(near, s) ? near[s] : Object.values(table)[0];
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const DESKTOP_SHAPES = {
|
|
51
|
+
ellipse: "ELLIPSE",
|
|
52
|
+
rectangle: "RECTANGLE",
|
|
53
|
+
"round-rectangle": "ROUND_RECTANGLE",
|
|
54
|
+
triangle: "TRIANGLE",
|
|
55
|
+
diamond: "DIAMOND",
|
|
56
|
+
hexagon: "HEXAGON",
|
|
57
|
+
octagon: "OCTAGON",
|
|
58
|
+
parallelogram: "PARALLELOGRAM",
|
|
59
|
+
vee: "V",
|
|
60
|
+
};
|
|
61
|
+
const NEAR_SHAPES = {
|
|
62
|
+
pentagon: "hexagon",
|
|
63
|
+
star: "octagon",
|
|
64
|
+
trapezoid: "parallelogram",
|
|
65
|
+
none: "ellipse",
|
|
66
|
+
// Graphviz shapes no canonical shape names
|
|
67
|
+
"other:invtrapezium": "parallelogram",
|
|
68
|
+
"other:house": "hexagon",
|
|
69
|
+
"other:invhouse": "hexagon",
|
|
70
|
+
};
|
|
71
|
+
const lower = (t) => Object.fromEntries(Object.entries(t).map(([k, v]) => [k, v === "V" ? "vee" : v.toLowerCase()]));
|
|
72
|
+
const nearIn = (t, near) => Object.fromEntries(Object.entries(near).map(([k, v]) => [k, t[v]]));
|
|
73
|
+
const DESKTOP_BORDERS = {
|
|
74
|
+
solid: "SOLID",
|
|
75
|
+
dashed: "EQUAL_DASH",
|
|
76
|
+
dotted: "DOT",
|
|
77
|
+
"dash-dot": "DASH_DOT",
|
|
78
|
+
double: "PARALLEL_LINES",
|
|
79
|
+
};
|
|
80
|
+
// LONG_DASH is read as dashed (CX2 has no long dash), so long-dash is written as its nearest, EQUAL_DASH
|
|
81
|
+
const DESKTOP_LINES = { ...DESKTOP_BORDERS, zigzag: "ZIGZAG", sinewave: "SINEWAVE" };
|
|
82
|
+
const CX2_LINES = { solid: "solid", dashed: "dashed", dotted: "dotted", double: "double" };
|
|
83
|
+
const NEAR_LINES = { "dash-dot": "dashed", "long-dash": "dashed", zigzag: "solid", sinewave: "solid" };
|
|
84
|
+
const DESKTOP_ARROWS = {
|
|
85
|
+
none: "NONE",
|
|
86
|
+
triangle: "DELTA",
|
|
87
|
+
vee: "ARROW",
|
|
88
|
+
tee: "T",
|
|
89
|
+
diamond: "DIAMOND",
|
|
90
|
+
circle: "CIRCLE",
|
|
91
|
+
square: "SQUARE",
|
|
92
|
+
"triangle-open": "OPEN_DELTA",
|
|
93
|
+
"diamond-open": "OPEN_DIAMOND",
|
|
94
|
+
"circle-open": "OPEN_CIRCLE",
|
|
95
|
+
half: "HALF_TOP",
|
|
96
|
+
};
|
|
97
|
+
const CX2_ARROWS = {
|
|
98
|
+
none: "none",
|
|
99
|
+
triangle: "triangle",
|
|
100
|
+
vee: "vee",
|
|
101
|
+
tee: "tee",
|
|
102
|
+
diamond: "diamond",
|
|
103
|
+
circle: "circle",
|
|
104
|
+
square: "square",
|
|
105
|
+
"triangle-open": "open-triangle",
|
|
106
|
+
"diamond-open": "open-diamond",
|
|
107
|
+
"circle-open": "open-circle",
|
|
108
|
+
half: "half-top",
|
|
109
|
+
};
|
|
110
|
+
const NEAR_ARROWS = { crow: "vee", inverted: "triangle" };
|
|
111
|
+
/** The Cytoscape arrow names no canonical arrow names, which Cytoscape's readers keep as `other:` values. */
|
|
112
|
+
const CY_OTHER_ARROWS = new Set(["open-square", "open-half-circle", "half-circle"]);
|
|
113
|
+
/** The Cytoscape line types no canonical line style names. */
|
|
114
|
+
const CY_OTHER_LINES = new Set([
|
|
115
|
+
"backward-slash",
|
|
116
|
+
"forward-slash",
|
|
117
|
+
"vertical-slash",
|
|
118
|
+
"separate-arrow",
|
|
119
|
+
"contiguous-arrow",
|
|
120
|
+
]);
|
|
121
|
+
/** The Cytoscape line types a border can take that no canonical border style names. */
|
|
122
|
+
const CY_OTHER_BORDERS = new Set([...CY_OTHER_LINES, "zigzag", "sinewave"]);
|
|
123
|
+
/** A label position: the node's anchor and the label's opposite anchor. */
|
|
124
|
+
const DESKTOP_POSITIONS = {
|
|
125
|
+
center: "C,C,c,0.00,0.00",
|
|
126
|
+
top: "N,S,c,0.00,0.00",
|
|
127
|
+
bottom: "S,N,c,0.00,0.00",
|
|
128
|
+
left: "W,E,c,0.00,0.00",
|
|
129
|
+
right: "E,W,c,0.00,0.00",
|
|
130
|
+
"top-left": "NW,SE,c,0.00,0.00",
|
|
131
|
+
"top-right": "NE,SW,c,0.00,0.00",
|
|
132
|
+
"bottom-left": "SW,NE,c,0.00,0.00",
|
|
133
|
+
"bottom-right": "SE,NW,c,0.00,0.00",
|
|
134
|
+
};
|
|
135
|
+
const CX2_ANCHORS = {
|
|
136
|
+
center: ["center", "center"],
|
|
137
|
+
top: ["center", "top"],
|
|
138
|
+
bottom: ["center", "bottom"],
|
|
139
|
+
left: ["left", "center"],
|
|
140
|
+
right: ["right", "center"],
|
|
141
|
+
"top-left": ["left", "top"],
|
|
142
|
+
"top-right": ["right", "top"],
|
|
143
|
+
"bottom-left": ["left", "bottom"],
|
|
144
|
+
"bottom-right": ["right", "bottom"],
|
|
145
|
+
};
|
|
146
|
+
const desktopNumber = String;
|
|
147
|
+
const cx2Number = (v) => v;
|
|
148
|
+
const textOut = String;
|
|
149
|
+
const desktopBool = (v) => String(v === true);
|
|
150
|
+
const opacity255 = (v, approx) => {
|
|
151
|
+
const b = Math.round(Number(v) * 255);
|
|
152
|
+
if (num6(b / 255) !== v) {
|
|
153
|
+
approx();
|
|
154
|
+
}
|
|
155
|
+
return String(b);
|
|
156
|
+
};
|
|
157
|
+
/** The writers of each dialect, per target and property. */
|
|
158
|
+
const WRITERS = {
|
|
159
|
+
desktop: {
|
|
160
|
+
node: new Map([
|
|
161
|
+
["fill", { vp: "NODE_FILL_COLOR", write: colorOut }],
|
|
162
|
+
["fillOpacity", { vp: "NODE_TRANSPARENCY", write: opacity255 }],
|
|
163
|
+
["borderColor", { vp: "NODE_BORDER_PAINT", write: colorOut }],
|
|
164
|
+
["borderWidth", { vp: "NODE_BORDER_WIDTH", write: desktopNumber }],
|
|
165
|
+
[
|
|
166
|
+
"borderStyle",
|
|
167
|
+
{
|
|
168
|
+
vp: "NODE_BORDER_LINE_TYPE",
|
|
169
|
+
write: enumOut(DESKTOP_BORDERS, nearIn(DESKTOP_BORDERS, NEAR_LINES), true, CY_OTHER_BORDERS),
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
["shape", { vp: "NODE_SHAPE", write: enumOut(DESKTOP_SHAPES, nearIn(DESKTOP_SHAPES, NEAR_SHAPES), true) }],
|
|
173
|
+
["width", { vp: "NODE_WIDTH", write: desktopNumber }],
|
|
174
|
+
["height", { vp: "NODE_HEIGHT", write: desktopNumber }],
|
|
175
|
+
["label", { vp: "NODE_LABEL", write: textOut }],
|
|
176
|
+
["labelColor", { vp: "NODE_LABEL_COLOR", write: colorOut }],
|
|
177
|
+
["labelSize", { vp: "NODE_LABEL_FONT_SIZE", write: desktopNumber }],
|
|
178
|
+
["labelPosition", { vp: "NODE_LABEL_POSITION", write: enumOut(DESKTOP_POSITIONS, {}, false) }],
|
|
179
|
+
["tooltip", { vp: "NODE_TOOLTIP", write: textOut }],
|
|
180
|
+
["visible", { vp: "NODE_VISIBLE", write: desktopBool }],
|
|
181
|
+
]),
|
|
182
|
+
edge: new Map([
|
|
183
|
+
["color", { vp: "EDGE_STROKE_UNSELECTED_PAINT", write: colorOut }],
|
|
184
|
+
["opacity", { vp: "EDGE_TRANSPARENCY", write: opacity255 }],
|
|
185
|
+
["width", { vp: "EDGE_WIDTH", write: desktopNumber }],
|
|
186
|
+
[
|
|
187
|
+
"lineStyle",
|
|
188
|
+
{
|
|
189
|
+
vp: "EDGE_LINE_TYPE",
|
|
190
|
+
write: enumOut(DESKTOP_LINES, nearIn(DESKTOP_LINES, NEAR_LINES), true, CY_OTHER_LINES),
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
[
|
|
194
|
+
"sourceArrow",
|
|
195
|
+
{
|
|
196
|
+
vp: "EDGE_SOURCE_ARROW_SHAPE",
|
|
197
|
+
write: enumOut(DESKTOP_ARROWS, nearIn(DESKTOP_ARROWS, NEAR_ARROWS), true, CY_OTHER_ARROWS),
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
[
|
|
201
|
+
"targetArrow",
|
|
202
|
+
{
|
|
203
|
+
vp: "EDGE_TARGET_ARROW_SHAPE",
|
|
204
|
+
write: enumOut(DESKTOP_ARROWS, nearIn(DESKTOP_ARROWS, NEAR_ARROWS), true, CY_OTHER_ARROWS),
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
["sourceArrowColor", { vp: "EDGE_SOURCE_ARROW_UNSELECTED_PAINT", write: colorOut }],
|
|
208
|
+
["targetArrowColor", { vp: "EDGE_TARGET_ARROW_UNSELECTED_PAINT", write: colorOut }],
|
|
209
|
+
["curved", { vp: "EDGE_CURVED", write: desktopBool }],
|
|
210
|
+
["label", { vp: "EDGE_LABEL", write: textOut }],
|
|
211
|
+
["labelColor", { vp: "EDGE_LABEL_COLOR", write: colorOut }],
|
|
212
|
+
["labelSize", { vp: "EDGE_LABEL_FONT_SIZE", write: desktopNumber }],
|
|
213
|
+
["tooltip", { vp: "EDGE_TOOLTIP", write: textOut }],
|
|
214
|
+
["visible", { vp: "EDGE_VISIBLE", write: desktopBool }],
|
|
215
|
+
]),
|
|
216
|
+
},
|
|
217
|
+
cx2: {
|
|
218
|
+
node: new Map([
|
|
219
|
+
["fill", { vp: "NODE_BACKGROUND_COLOR", write: colorOut }],
|
|
220
|
+
["fillOpacity", { vp: "NODE_BACKGROUND_OPACITY", write: cx2Number }],
|
|
221
|
+
["borderColor", { vp: "NODE_BORDER_COLOR", write: colorOut }],
|
|
222
|
+
["borderWidth", { vp: "NODE_BORDER_WIDTH", write: cx2Number }],
|
|
223
|
+
[
|
|
224
|
+
"borderStyle",
|
|
225
|
+
{
|
|
226
|
+
vp: "NODE_BORDER_STYLE",
|
|
227
|
+
write: enumOut(CX2_LINES, nearIn(CX2_LINES, NEAR_LINES), false, CY_OTHER_BORDERS),
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
[
|
|
231
|
+
"shape",
|
|
232
|
+
{
|
|
233
|
+
vp: "NODE_SHAPE",
|
|
234
|
+
write: enumOut(lower(DESKTOP_SHAPES), nearIn(lower(DESKTOP_SHAPES), NEAR_SHAPES), false),
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
["width", { vp: "NODE_WIDTH", write: cx2Number }],
|
|
238
|
+
["height", { vp: "NODE_HEIGHT", write: cx2Number }],
|
|
239
|
+
["label", { vp: "NODE_LABEL", write: textOut }],
|
|
240
|
+
["labelColor", { vp: "NODE_LABEL_COLOR", write: colorOut }],
|
|
241
|
+
["labelSize", { vp: "NODE_LABEL_FONT_SIZE", write: cx2Number }],
|
|
242
|
+
["labelPosition", { vp: "NODE_LABEL_POSITION", write: cx2Position }],
|
|
243
|
+
["visible", { vp: "NODE_VISIBILITY", write: (v) => (v === true ? "element" : "none") }],
|
|
244
|
+
]),
|
|
245
|
+
edge: new Map([
|
|
246
|
+
["color", { vp: "EDGE_LINE_COLOR", write: colorOut }],
|
|
247
|
+
["opacity", { vp: "EDGE_OPACITY", write: cx2Number }],
|
|
248
|
+
["width", { vp: "EDGE_WIDTH", write: cx2Number }],
|
|
249
|
+
[
|
|
250
|
+
"lineStyle",
|
|
251
|
+
{
|
|
252
|
+
vp: "EDGE_LINE_STYLE",
|
|
253
|
+
write: enumOut(CX2_LINES, nearIn(CX2_LINES, NEAR_LINES), false, CY_OTHER_LINES),
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
[
|
|
257
|
+
"sourceArrow",
|
|
258
|
+
{
|
|
259
|
+
vp: "EDGE_SOURCE_ARROW_SHAPE",
|
|
260
|
+
write: enumOut(CX2_ARROWS, nearIn(CX2_ARROWS, NEAR_ARROWS), false, CY_OTHER_ARROWS),
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
[
|
|
264
|
+
"targetArrow",
|
|
265
|
+
{
|
|
266
|
+
vp: "EDGE_TARGET_ARROW_SHAPE",
|
|
267
|
+
write: enumOut(CX2_ARROWS, nearIn(CX2_ARROWS, NEAR_ARROWS), false, CY_OTHER_ARROWS),
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
["sourceArrowColor", { vp: "EDGE_SOURCE_ARROW_COLOR", write: colorOut }],
|
|
271
|
+
["targetArrowColor", { vp: "EDGE_TARGET_ARROW_COLOR", write: colorOut }],
|
|
272
|
+
["curved", { vp: "EDGE_CURVED", write: (v) => v === true }],
|
|
273
|
+
["label", { vp: "EDGE_LABEL", write: textOut }],
|
|
274
|
+
["labelColor", { vp: "EDGE_LABEL_COLOR", write: colorOut }],
|
|
275
|
+
["labelSize", { vp: "EDGE_LABEL_FONT_SIZE", write: cx2Number }],
|
|
276
|
+
["visible", { vp: "EDGE_VISIBILITY", write: (v) => (v === true ? "element" : "none") }],
|
|
277
|
+
]),
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* CX2's label position object.
|
|
282
|
+
* @param v - a canonical position
|
|
283
|
+
* @returns the object
|
|
284
|
+
*/
|
|
285
|
+
function cx2Position(v) {
|
|
286
|
+
const [h, vert] = Object.hasOwn(CX2_ANCHORS, String(v)) ? CX2_ANCHORS[String(v)] : ["center", "center"];
|
|
287
|
+
return {
|
|
288
|
+
HORIZONTAL_ALIGN: "center",
|
|
289
|
+
VERTICAL_ALIGN: "center",
|
|
290
|
+
HORIZONTAL_ANCHOR: h,
|
|
291
|
+
VERTICAL_ANCHOR: vert,
|
|
292
|
+
MARGIN_X: 0,
|
|
293
|
+
MARGIN_Y: 0,
|
|
294
|
+
JUSTIFICATION: "center",
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/** The font properties, written together into one font face. */
|
|
298
|
+
const FONT_PROPS = ["labelFont", "labelWeight", "labelItalic"];
|
|
299
|
+
const FONT_VP = { node: "NODE_LABEL_FONT_FACE", edge: "EDGE_LABEL_FONT_FACE" };
|
|
300
|
+
const CSS_TO_JAVA = {
|
|
301
|
+
"sans-serif": "SansSerif",
|
|
302
|
+
serif: "Serif",
|
|
303
|
+
monospace: "Monospaced",
|
|
304
|
+
};
|
|
305
|
+
/**
|
|
306
|
+
* A font face in a dialect's spelling.
|
|
307
|
+
* @param dialect - the dialect
|
|
308
|
+
* @param family - the family, or null
|
|
309
|
+
* @param weight - the weight, or null
|
|
310
|
+
* @param italic - whether italic, or null
|
|
311
|
+
* @param approx - called when the family had to be shortened
|
|
312
|
+
* @returns the face
|
|
313
|
+
*/
|
|
314
|
+
function fontOut(dialect, family, weight, italic, approx) {
|
|
315
|
+
const bold = weight === "bold";
|
|
316
|
+
const it = italic === true;
|
|
317
|
+
const fam = family === null ? "sans-serif" : String(family);
|
|
318
|
+
if (dialect === "cx2") {
|
|
319
|
+
if (fontReadsAs(fam) !== fam) {
|
|
320
|
+
approx();
|
|
321
|
+
}
|
|
322
|
+
return { FONT_FAMILY: fam, FONT_STYLE: it ? "italic" : "normal", FONT_WEIGHT: bold ? "bold" : "normal" };
|
|
323
|
+
}
|
|
324
|
+
const first = fam.includes(",") ? fam.split(",")[0].trim() : fam;
|
|
325
|
+
const java = Object.hasOwn(CSS_TO_JAVA, first) ? CSS_TO_JAVA[first] : first;
|
|
326
|
+
if (fontReadsAs(java) !== fam) {
|
|
327
|
+
approx();
|
|
328
|
+
}
|
|
329
|
+
return `${java},${javaFontStyle(bold, it)},12`;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The style part of a Java font face.
|
|
333
|
+
* @param bold - whether bold
|
|
334
|
+
* @param italic - whether italic
|
|
335
|
+
* @returns `plain`, `bold`, `italic` or `bolditalic`
|
|
336
|
+
*/
|
|
337
|
+
function javaFontStyle(bold, italic) {
|
|
338
|
+
if (!bold && !italic) {
|
|
339
|
+
return "plain";
|
|
340
|
+
}
|
|
341
|
+
return (bold ? "bold" : "") + (italic ? "italic" : "");
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* The family a font face reads back as: the reader drops a face suffix (Dialog.plain is Dialog) and reads a Java
|
|
345
|
+
* logical name as the family Cytoscape draws it with (Dialog as sans-serif).
|
|
346
|
+
* @param name - the face
|
|
347
|
+
* @returns the family
|
|
348
|
+
*/
|
|
349
|
+
function fontReadsAs(name) {
|
|
350
|
+
const family = name.replace(/\.(?:bold|italic|plain|bolditalic)$/i, "");
|
|
351
|
+
return JAVA_FONTS.get(family.toLowerCase()) ?? family;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* The default name of the column a mapping over a non-data column reads.
|
|
355
|
+
* @param target - nodes or edges
|
|
356
|
+
* @param ref - the column
|
|
357
|
+
* @returns the name
|
|
358
|
+
*/
|
|
359
|
+
function defaultColumnName(target, ref) {
|
|
360
|
+
if ("style" in ref) {
|
|
361
|
+
return `graphty.style.${target}.${ref.style}`;
|
|
362
|
+
}
|
|
363
|
+
return `graphty.style.${target}.${"computed" in ref ? ref.computed : ref.data}`;
|
|
364
|
+
}
|
|
365
|
+
/** The kinds of value a Cytoscape passthrough reads the same way the neutral reading does. */
|
|
366
|
+
const PASSTHROUGH_SAFE = new Set(["color", "number", "text", "boolean"]);
|
|
367
|
+
/**
|
|
368
|
+
* Turns neutral rules into a Cytoscape visual style. Rules over every element become defaults (a constant) and
|
|
369
|
+
* mappings (one per visual property: the topmost wins); a passthrough of a value Cytoscape spells differently (an
|
|
370
|
+
* opacity, a shape) becomes a discrete table over the values the graph holds. Every element whose value under the
|
|
371
|
+
* rules differs from what that style gives gets a bypass, so Cytoscape draws exactly what the rules give; each rule
|
|
372
|
+
* written that way is noted as `W_STYLE_LAYER_FLATTENED`. A property Cytoscape has no visual property for is noted as
|
|
373
|
+
* `W_STYLE_NOT_WRITTEN`, a value changed to the nearest Cytoscape has as `W_STYLE_APPROXIMATED`.
|
|
374
|
+
* @param extracted - the styles, for this graph
|
|
375
|
+
* @param snapshot - the graph
|
|
376
|
+
* @param options - the dialect, notes and column names
|
|
377
|
+
* @returns the style, the bypasses and the columns the writer adds
|
|
378
|
+
* @category Styles
|
|
379
|
+
*/
|
|
380
|
+
export function emitCytoscapeStyle(extracted, snapshot, options) {
|
|
381
|
+
const notes = options.notes ?? new StyleNotes();
|
|
382
|
+
const style = emptyCytoscapeStyle();
|
|
383
|
+
const bypasses = {
|
|
384
|
+
node: new Array(snapshot.nodeCount).fill(null),
|
|
385
|
+
edge: new Array(snapshot.edgeCount).fill(null),
|
|
386
|
+
};
|
|
387
|
+
const columns = {
|
|
388
|
+
node: new Map(),
|
|
389
|
+
edge: new Map(),
|
|
390
|
+
};
|
|
391
|
+
for (const target of ["node", "edge"]) {
|
|
392
|
+
emitTarget(targetEmit(target, extracted, snapshot, options, notes), style, bypasses[target], columns[target]);
|
|
393
|
+
}
|
|
394
|
+
const bg = extracted.styles.graph.background;
|
|
395
|
+
if (bg !== undefined) {
|
|
396
|
+
style.network.defaults.set(options.dialect === "cx2" ? "NETWORK_BACKGROUND_COLOR" : "NETWORK_BACKGROUND_PAINT", bg.toUpperCase());
|
|
397
|
+
}
|
|
398
|
+
return { style, bypasses, columns };
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* What emitting one target reads, worked out once.
|
|
402
|
+
* @param target - nodes or edges
|
|
403
|
+
* @param extracted - the styles
|
|
404
|
+
* @param snapshot - the graph
|
|
405
|
+
* @param options - the options
|
|
406
|
+
* @param notes - where losses are noted
|
|
407
|
+
* @returns the target's emission
|
|
408
|
+
*/
|
|
409
|
+
function targetEmit(target, extracted, snapshot, options, notes) {
|
|
410
|
+
const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
|
|
411
|
+
const src = refSource(target, n, extracted.columns[target], extracted.features[target], snapshot);
|
|
412
|
+
const rules = extracted.styles.rules.filter((r) => r.target === target);
|
|
413
|
+
const written = new Set(rules.flatMap((r) => [...Object.keys(r.set ?? {}), ...Object.keys(r.map ?? {})]));
|
|
414
|
+
const truth = new Map(Array.from(written, (p) => [p, resolveRules(rules, target, p, src)]));
|
|
415
|
+
return {
|
|
416
|
+
target,
|
|
417
|
+
extracted,
|
|
418
|
+
snapshot,
|
|
419
|
+
options,
|
|
420
|
+
notes,
|
|
421
|
+
n,
|
|
422
|
+
src,
|
|
423
|
+
rules,
|
|
424
|
+
truth,
|
|
425
|
+
approx: (p) => () => {
|
|
426
|
+
notes.add(STYLE_ISSUE.APPROXIMATED, target, p);
|
|
427
|
+
},
|
|
428
|
+
// a default written as an approximation changes every element that draws it
|
|
429
|
+
approxDefault: (p, value) => () => {
|
|
430
|
+
const count = (truth.get(p) ?? []).filter((v) => v === value).length;
|
|
431
|
+
notes.add(STYLE_ISSUE.APPROXIMATED, target, p, { count: Math.max(count, 1) });
|
|
432
|
+
},
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Emits one target.
|
|
437
|
+
* @param e - the target's emission
|
|
438
|
+
* @param style - the style being written
|
|
439
|
+
* @param bypasses - the target's bypasses, filled in
|
|
440
|
+
* @param columns - the target's added columns, filled in
|
|
441
|
+
*/
|
|
442
|
+
function emitTarget(e, style, bypasses, columns) {
|
|
443
|
+
const { target, notes, truth } = e;
|
|
444
|
+
const writers = WRITERS[e.options.dialect][target];
|
|
445
|
+
for (const [p, values] of truth) {
|
|
446
|
+
if (!writers.has(p) && !FONT_PROPS.includes(p)) {
|
|
447
|
+
const count = values.filter((v) => v !== null).length;
|
|
448
|
+
notes.add(STYLE_ISSUE.NOT_WRITTEN, target, p, { count: Math.max(count, 1) });
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
// a rule written as per-element values is noted with the elements that carry one, once per property
|
|
452
|
+
const counted = new Set();
|
|
453
|
+
const carrying = (p) => {
|
|
454
|
+
if (counted.has(p)) {
|
|
455
|
+
return 0;
|
|
456
|
+
}
|
|
457
|
+
counted.add(p);
|
|
458
|
+
return Math.max((truth.get(p) ?? []).filter((v) => v !== null).length, 1);
|
|
459
|
+
};
|
|
460
|
+
const model = buildModel(target, e.rules, writers, notes, carrying);
|
|
461
|
+
const s = style[target];
|
|
462
|
+
s.dependencies.set(target === "node" ? "nodeSizeLocked" : "arrowColorMatchesEdge", false);
|
|
463
|
+
for (const [p, w] of writers) {
|
|
464
|
+
if (truth.has(p)) {
|
|
465
|
+
emitProperty(e, s, model, p, w, columns, carrying);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
addBypasses(e, model, writers, bypasses);
|
|
469
|
+
emitFont(e, model, s, bypasses);
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Emits one property the rules write: its default, and its mapping, or the mapping noted as flattened when
|
|
473
|
+
* Cytoscape cannot read the column it needs.
|
|
474
|
+
* @param e - the target's emission
|
|
475
|
+
* @param s - the target's style
|
|
476
|
+
* @param model - the model; a mapping not written is removed
|
|
477
|
+
* @param p - the property
|
|
478
|
+
* @param w - its writer
|
|
479
|
+
* @param columns - where added columns go
|
|
480
|
+
* @param carrying - how many elements carry a value of a property, once
|
|
481
|
+
*/
|
|
482
|
+
function emitProperty(e, s, model, p, w, columns, carrying) {
|
|
483
|
+
const set = model.set.get(p);
|
|
484
|
+
if (set !== undefined) {
|
|
485
|
+
s.defaults.set(w.vp, w.write(set, e.approxDefault(p, set)));
|
|
486
|
+
}
|
|
487
|
+
let m = model.map.get(p);
|
|
488
|
+
if (m === undefined) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
if (e.options.dialect === "cx2" && m.kind === "continuous") {
|
|
492
|
+
m = cx2Points(m, e.approx(p));
|
|
493
|
+
model.map.set(p, m);
|
|
494
|
+
}
|
|
495
|
+
const cm = cytoscapeMapping(e, p, m, w, columns);
|
|
496
|
+
if (cm === null) {
|
|
497
|
+
e.notes.add(STYLE_ISSUE.LAYER_FLATTENED, e.target, p, { sample: model.mappedBy.get(p), count: carrying(p) });
|
|
498
|
+
model.map.delete(p);
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
s.mappings.set(w.vp, cm);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* A bypass for every element the written style draws differently from the rules.
|
|
506
|
+
* @param e - the target's emission
|
|
507
|
+
* @param model - the defaults and mappings written
|
|
508
|
+
* @param writers - the dialect's writers
|
|
509
|
+
* @param bypasses - the bypasses, filled in
|
|
510
|
+
*/
|
|
511
|
+
function addBypasses(e, model, writers, bypasses) {
|
|
512
|
+
const { target } = e;
|
|
513
|
+
const modelRules = [
|
|
514
|
+
{
|
|
515
|
+
id: "defaults",
|
|
516
|
+
target,
|
|
517
|
+
role: "defaults",
|
|
518
|
+
origin: "declared",
|
|
519
|
+
where: { all: true },
|
|
520
|
+
set: Object.fromEntries(model.set),
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
id: "mappings",
|
|
524
|
+
target,
|
|
525
|
+
role: "mapping",
|
|
526
|
+
origin: "declared",
|
|
527
|
+
where: { all: true },
|
|
528
|
+
map: Object.fromEntries(model.map),
|
|
529
|
+
},
|
|
530
|
+
];
|
|
531
|
+
for (const [p, w] of writers) {
|
|
532
|
+
const want = e.truth.get(p);
|
|
533
|
+
if (want === undefined) {
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
const drawn = resolveRules(modelRules, target, p, e.src);
|
|
537
|
+
for (let i = 0; i < e.n; i++) {
|
|
538
|
+
const v = want[i];
|
|
539
|
+
if (v !== null && v !== drawn[i]) {
|
|
540
|
+
bypasses[i] ?? (bypasses[i] = new Map());
|
|
541
|
+
bypasses[i]?.set(w.vp, w.write(v, e.approx(p)));
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* The defaults and mappings of one target: rules over every element, bottom to top. A constant over every element
|
|
548
|
+
* hides everything beneath it; of two mappings of one property only the topmost is kept. Every rule that cannot be
|
|
549
|
+
* kept whole is noted as `W_STYLE_LAYER_FLATTENED`.
|
|
550
|
+
* @param target - nodes or edges
|
|
551
|
+
* @param rules - the target's rules
|
|
552
|
+
* @param writers - the dialect's writers
|
|
553
|
+
* @param notes - where flattened rules are noted
|
|
554
|
+
* @param carrying - how many elements carry a value of a property
|
|
555
|
+
* @returns the model
|
|
556
|
+
*/
|
|
557
|
+
function buildModel(target, rules, writers, notes, carrying) {
|
|
558
|
+
const model = { set: new Map(), map: new Map(), mappedBy: new Map() };
|
|
559
|
+
const flatten = (p, id) => {
|
|
560
|
+
notes.add(STYLE_ISSUE.LAYER_FLATTENED, target, p, { sample: id, count: carrying(p) });
|
|
561
|
+
};
|
|
562
|
+
const holds = (p) => writers.has(p) || FONT_PROPS.includes(p);
|
|
563
|
+
const applySet = (r, all) => {
|
|
564
|
+
for (const [p, v] of Object.entries(r.set ?? {})) {
|
|
565
|
+
if (v === undefined || !holds(p)) {
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
if (!all) {
|
|
569
|
+
flatten(p, r.id);
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
model.set.set(p, v);
|
|
573
|
+
model.map.delete(p);
|
|
574
|
+
model.mappedBy.delete(p);
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
const applyMap = (r, all) => {
|
|
578
|
+
for (const [p, m] of Object.entries(r.map ?? {})) {
|
|
579
|
+
if (m === undefined || !holds(p)) {
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
if (!all || FONT_PROPS.includes(p)) {
|
|
583
|
+
flatten(p, r.id);
|
|
584
|
+
continue;
|
|
585
|
+
}
|
|
586
|
+
const below = model.mappedBy.get(p);
|
|
587
|
+
if (below !== undefined) {
|
|
588
|
+
flatten(p, below);
|
|
589
|
+
}
|
|
590
|
+
model.map.set(p, m);
|
|
591
|
+
model.mappedBy.set(p, r.id);
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
for (const r of rules) {
|
|
595
|
+
const all = "all" in r.where && r.where.all;
|
|
596
|
+
applySet(r, all);
|
|
597
|
+
applyMap(r, all);
|
|
598
|
+
}
|
|
599
|
+
return model;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* One neutral mapping as a Cytoscape mapping.
|
|
603
|
+
* @param e - the target's emission
|
|
604
|
+
* @param p - the property
|
|
605
|
+
* @param m - the mapping
|
|
606
|
+
* @param w - the property's writer
|
|
607
|
+
* @param columns - where added columns go
|
|
608
|
+
* @returns the mapping, or null when Cytoscape cannot read the column it needs
|
|
609
|
+
*/
|
|
610
|
+
function cytoscapeMapping(e, p, m, w, columns) {
|
|
611
|
+
const column = mappingColumn(e, m.by, columns);
|
|
612
|
+
if (column === null) {
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
615
|
+
const approx = e.approx(p);
|
|
616
|
+
const write = (v) => w.write(v, approx);
|
|
617
|
+
if (m.kind === "passthrough") {
|
|
618
|
+
return passthroughMapping(e, p, m.by, column, write);
|
|
619
|
+
}
|
|
620
|
+
if (m.kind === "discrete") {
|
|
621
|
+
return {
|
|
622
|
+
kind: "discrete",
|
|
623
|
+
column,
|
|
624
|
+
type: typeOf(m.table.map(([k]) => k)),
|
|
625
|
+
table: m.table.map(([k, v]) => [k, write(v)]),
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
if (m.kind === "continuous") {
|
|
629
|
+
const points = m.points.map((pt) => ({
|
|
630
|
+
at: pt.at,
|
|
631
|
+
below: write(pt.below),
|
|
632
|
+
value: write(pt.value),
|
|
633
|
+
above: write(pt.above),
|
|
634
|
+
}));
|
|
635
|
+
return { kind: "continuous", column, type: "double", points };
|
|
636
|
+
}
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* The column a mapping reads, by its name in the file: a data column's own, else an added column of the style
|
|
641
|
+
* column's or the degree's values.
|
|
642
|
+
* @param e - the target's emission
|
|
643
|
+
* @param ref - the column
|
|
644
|
+
* @param columns - where added columns go
|
|
645
|
+
* @returns the name, or null when the values cannot be written (a degree of an edge)
|
|
646
|
+
*/
|
|
647
|
+
function mappingColumn(e, ref, columns) {
|
|
648
|
+
if ("data" in ref) {
|
|
649
|
+
return ref.data;
|
|
650
|
+
}
|
|
651
|
+
const { target } = e;
|
|
652
|
+
const column = (e.options.columnName ?? defaultColumnName)(target, ref);
|
|
653
|
+
let values = null;
|
|
654
|
+
if ("style" in ref) {
|
|
655
|
+
values = e.extracted.columns[target].get(ref.style) ?? null;
|
|
656
|
+
}
|
|
657
|
+
else if ("computed" in ref && target === "node") {
|
|
658
|
+
values = degreeValues(e.snapshot, ref.computed);
|
|
659
|
+
}
|
|
660
|
+
if (values === null) {
|
|
661
|
+
return null;
|
|
662
|
+
}
|
|
663
|
+
columns.set(column, values);
|
|
664
|
+
return column;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* A passthrough as Cytoscape reads it: a passthrough where Cytoscape reads the values as the neutral reading does,
|
|
668
|
+
* else a table over the values the graph holds, in Cytoscape's spelling.
|
|
669
|
+
* @param e - the target's emission
|
|
670
|
+
* @param p - the property
|
|
671
|
+
* @param by - the column
|
|
672
|
+
* @param column - its name in the file
|
|
673
|
+
* @param write - a value in Cytoscape's spelling
|
|
674
|
+
* @returns the mapping
|
|
675
|
+
*/
|
|
676
|
+
function passthroughMapping(e, p, by, column, write) {
|
|
677
|
+
const { target } = e;
|
|
678
|
+
const kind = STYLE_PROPERTIES[target].get(p) ?? "";
|
|
679
|
+
const cells = e.src.column(by) ?? [];
|
|
680
|
+
if (PASSTHROUGH_SAFE.has(kind)) {
|
|
681
|
+
return { kind: "passthrough", column, type: typeOf(Array.from(cells)) };
|
|
682
|
+
}
|
|
683
|
+
const read = "style" in by ? (v) => (isScalar(v) ? v : null) : canonicalFor(target, p);
|
|
684
|
+
const seen = new Map();
|
|
685
|
+
for (let i = 0; i < cells.length; i++) {
|
|
686
|
+
const raw = cells[i];
|
|
687
|
+
const v = isScalar(raw) && !seen.has(raw) ? read(raw) : null;
|
|
688
|
+
if (v !== null) {
|
|
689
|
+
seen.set(raw, write(v));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
const table = Array.from(seen);
|
|
693
|
+
return { kind: "discrete", column, type: typeOf(table.map(([k]) => k)), table };
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* A continuous mapping as CX2 holds it: CX2's intervals give the value exactly at a point only as the value just
|
|
697
|
+
* below or just above it, so a third value becomes the one below (noted; the elements exactly at it get bypasses).
|
|
698
|
+
* @param m - the mapping
|
|
699
|
+
* @param approx - called when a point changes
|
|
700
|
+
* @returns the mapping CX2 reads back
|
|
701
|
+
*/
|
|
702
|
+
function cx2Points(m, approx) {
|
|
703
|
+
let changed = false;
|
|
704
|
+
const points = m.points.map((pt) => {
|
|
705
|
+
if (pt.value === pt.below || pt.value === pt.above) {
|
|
706
|
+
return pt;
|
|
707
|
+
}
|
|
708
|
+
changed = true;
|
|
709
|
+
return { ...pt, value: pt.below };
|
|
710
|
+
});
|
|
711
|
+
if (!changed) {
|
|
712
|
+
return m;
|
|
713
|
+
}
|
|
714
|
+
approx();
|
|
715
|
+
return { ...m, points };
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Whether a value is a scalar.
|
|
719
|
+
* @param v - the value
|
|
720
|
+
* @returns true for a string, a finite number or a boolean
|
|
721
|
+
*/
|
|
722
|
+
function isScalar(v) {
|
|
723
|
+
return typeof v === "string" || typeof v === "boolean" || (typeof v === "number" && Number.isFinite(v));
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Cytoscape's attribute type of a set of values: `integer`, `double`, `boolean` or `string`.
|
|
727
|
+
* @param values - the values
|
|
728
|
+
* @returns the type
|
|
729
|
+
*/
|
|
730
|
+
function typeOf(values) {
|
|
731
|
+
let numbers = 0;
|
|
732
|
+
let integers = 0;
|
|
733
|
+
let booleans = 0;
|
|
734
|
+
let all = 0;
|
|
735
|
+
for (const v of values) {
|
|
736
|
+
if (v === null || v === undefined) {
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
all++;
|
|
740
|
+
if (typeof v === "number") {
|
|
741
|
+
numbers++;
|
|
742
|
+
if (Number.isInteger(v)) {
|
|
743
|
+
integers++;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
else if (typeof v === "boolean") {
|
|
747
|
+
booleans++;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
if (all > 0 && numbers === all) {
|
|
751
|
+
return integers === all ? "integer" : "double";
|
|
752
|
+
}
|
|
753
|
+
if (all > 0 && booleans === all) {
|
|
754
|
+
return "boolean";
|
|
755
|
+
}
|
|
756
|
+
return "string";
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* The font face: a default from the constant font properties, and a bypass for every element whose family, weight
|
|
760
|
+
* or italic differs from it.
|
|
761
|
+
* @param e - the target's emission
|
|
762
|
+
* @param model - the model
|
|
763
|
+
* @param s - the target's style
|
|
764
|
+
* @param bypasses - the bypasses
|
|
765
|
+
*/
|
|
766
|
+
function emitFont(e, model, s, bypasses) {
|
|
767
|
+
const { target, truth, n, approx, approxDefault } = e;
|
|
768
|
+
const { dialect } = e.options;
|
|
769
|
+
if (!FONT_PROPS.some((p) => truth.has(p))) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const [fd, wd, id] = FONT_PROPS.map((p) => model.set.get(p) ?? null);
|
|
773
|
+
const vp = FONT_VP[target];
|
|
774
|
+
if (fd !== null || wd !== null || id !== null) {
|
|
775
|
+
s.defaults.set(vp, fontOut(dialect, fd, wd, id, fd === null ? approx("labelFont") : approxDefault("labelFont", fd)));
|
|
776
|
+
}
|
|
777
|
+
const [ft, wt, it] = FONT_PROPS.map((p) => truth.get(p) ?? null);
|
|
778
|
+
for (let i = 0; i < n; i++) {
|
|
779
|
+
const f = ft?.[i] ?? null;
|
|
780
|
+
const w = wt?.[i] ?? null;
|
|
781
|
+
const t = it?.[i] ?? null;
|
|
782
|
+
const differs = (f !== null && f !== fd) || (w !== null && w !== wd) || (t !== null && t !== id);
|
|
783
|
+
if (differs) {
|
|
784
|
+
bypasses[i] ?? (bypasses[i] = new Map());
|
|
785
|
+
bypasses[i]?.set(vp, fontOut(dialect, f ?? fd, w ?? wd, t ?? id, approx("labelFont")));
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
// ------------------------------------------------------------------ the file forms
|
|
790
|
+
/**
|
|
791
|
+
* A raw value as text: `,` doubled inside a CX version 1 definition.
|
|
792
|
+
* @param v - the value
|
|
793
|
+
* @returns the text
|
|
794
|
+
*/
|
|
795
|
+
function defText(v) {
|
|
796
|
+
return String(v).replaceAll(",", ",,");
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* A mapping as a CX version 1 definition string.
|
|
800
|
+
* @param m - the mapping
|
|
801
|
+
* @returns the definition
|
|
802
|
+
* @category Styles
|
|
803
|
+
*/
|
|
804
|
+
export function cx1Definition(m) {
|
|
805
|
+
const parts = [`COL=${defText(m.column)}`, `T=${m.type ?? "string"}`];
|
|
806
|
+
if (m.kind === "discrete") {
|
|
807
|
+
m.table.forEach(([k, v], i) => {
|
|
808
|
+
parts.push(`K=${i}=${defText(k)}`, `V=${i}=${defText(v)}`);
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
else if (m.kind === "continuous") {
|
|
812
|
+
m.points.forEach((p, i) => {
|
|
813
|
+
parts.push(`L=${i}=${defText(p.below)}`, `E=${i}=${defText(p.value)}`, `G=${i}=${defText(p.above)}`, `OV=${i}=${p.at}`);
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
return parts.join(",");
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* A record of a Map with text keys.
|
|
820
|
+
* @param map - the map
|
|
821
|
+
* @param value - how each value is written
|
|
822
|
+
* @returns the record
|
|
823
|
+
*/
|
|
824
|
+
function recordOf(map, value) {
|
|
825
|
+
const out = {};
|
|
826
|
+
for (const [k, v] of map) {
|
|
827
|
+
Object.defineProperty(out, k, { value: value(v), enumerable: true, writable: true, configurable: true });
|
|
828
|
+
}
|
|
829
|
+
return out;
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* A style (in the desktop dialect) as the default entries of a CX version 1 `cyVisualProperties` aspect: `network`,
|
|
833
|
+
* `nodes:default` and `edges:default`, with every value as text and every mapping as a definition string. The
|
|
834
|
+
* writer adds each element's bypasses as `nodes` / `edges` entries.
|
|
835
|
+
* @param style - the style
|
|
836
|
+
* @returns the entries
|
|
837
|
+
* @category Styles
|
|
838
|
+
*/
|
|
839
|
+
export function cytoscapeCxAspect(style) {
|
|
840
|
+
const entry = (of, t) => ({
|
|
841
|
+
properties_of: of,
|
|
842
|
+
properties: recordOf(t.defaults, String),
|
|
843
|
+
dependencies: recordOf(t.dependencies, String),
|
|
844
|
+
mappings: recordOf(t.mappings, (m) => ({ type: m.kind.toUpperCase(), definition: cx1Definition(m) })),
|
|
845
|
+
});
|
|
846
|
+
return [
|
|
847
|
+
{ properties_of: "network", properties: recordOf(style.network.defaults, String) },
|
|
848
|
+
entry("nodes:default", style.node),
|
|
849
|
+
entry("edges:default", style.edge),
|
|
850
|
+
];
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* A continuous mapping's points as CX2 intervals: below the first point, between each two, above the last. The
|
|
854
|
+
* value exactly at a point is the interval that includes it.
|
|
855
|
+
* @param points - the points
|
|
856
|
+
* @returns the intervals
|
|
857
|
+
*/
|
|
858
|
+
function cx2Intervals(points) {
|
|
859
|
+
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
860
|
+
const out = [];
|
|
861
|
+
for (let i = 0; i <= points.length; i++) {
|
|
862
|
+
const lo = points.at(i - 1);
|
|
863
|
+
const hi = points.at(i);
|
|
864
|
+
const iv = {};
|
|
865
|
+
if (i > 0 && lo !== undefined) {
|
|
866
|
+
iv.min = lo.at;
|
|
867
|
+
iv.minVPValue = lo.above;
|
|
868
|
+
iv.includeMin = same(lo.value, lo.above);
|
|
869
|
+
}
|
|
870
|
+
if (i < points.length && hi !== undefined) {
|
|
871
|
+
iv.max = hi.at;
|
|
872
|
+
iv.maxVPValue = hi.below;
|
|
873
|
+
iv.includeMax = !same(hi.value, hi.above) && same(hi.value, hi.below);
|
|
874
|
+
}
|
|
875
|
+
out.push(iv);
|
|
876
|
+
}
|
|
877
|
+
return out;
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* A style (in the CX2 dialect) as CX2's `visualProperties` and `visualEditorProperties` aspects. The writer adds the
|
|
881
|
+
* bypasses as `nodeBypasses` / `edgeBypasses`.
|
|
882
|
+
* @param style - the style
|
|
883
|
+
* @returns the two aspects
|
|
884
|
+
* @category Styles
|
|
885
|
+
*/
|
|
886
|
+
export function cytoscapeCx2Aspects(style) {
|
|
887
|
+
const mapping = (m) => {
|
|
888
|
+
if (m.kind === "passthrough") {
|
|
889
|
+
return { type: "PASSTHROUGH", definition: { attribute: m.column } };
|
|
890
|
+
}
|
|
891
|
+
if (m.kind === "discrete") {
|
|
892
|
+
return {
|
|
893
|
+
type: "DISCRETE",
|
|
894
|
+
definition: { attribute: m.column, map: m.table.map(([v, vp]) => ({ v, vp })) },
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
return { type: "CONTINUOUS", definition: { attribute: m.column, map: cx2Intervals(m.points) } };
|
|
898
|
+
};
|
|
899
|
+
const id = (v) => v;
|
|
900
|
+
return {
|
|
901
|
+
visualProperties: [
|
|
902
|
+
{
|
|
903
|
+
default: {
|
|
904
|
+
network: recordOf(style.network.defaults, id),
|
|
905
|
+
node: recordOf(style.node.defaults, id),
|
|
906
|
+
edge: recordOf(style.edge.defaults, id),
|
|
907
|
+
},
|
|
908
|
+
nodeMapping: recordOf(style.node.mappings, mapping),
|
|
909
|
+
edgeMapping: recordOf(style.edge.mappings, mapping),
|
|
910
|
+
},
|
|
911
|
+
],
|
|
912
|
+
visualEditorProperties: [
|
|
913
|
+
{
|
|
914
|
+
properties: {
|
|
915
|
+
nodeSizeLocked: style.node.dependencies.get("nodeSizeLocked") === true,
|
|
916
|
+
arrowColorMatchesEdge: style.edge.dependencies.get("arrowColorMatchesEdge") === true,
|
|
917
|
+
},
|
|
918
|
+
},
|
|
919
|
+
],
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* An attribute pair.
|
|
924
|
+
* @param name - the attribute
|
|
925
|
+
* @param value - its value
|
|
926
|
+
* @returns ` name="value"`, escaped
|
|
927
|
+
*/
|
|
928
|
+
function attr(name, value) {
|
|
929
|
+
return ` ${name}="${escapeXmlAttribute(String(value))}"`;
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* A style (in the desktop dialect) as one `<visualStyle>` element of a session's `session_vizmap.xml`.
|
|
933
|
+
* @param style - the style
|
|
934
|
+
* @param name - the style's name
|
|
935
|
+
* @returns the element's XML
|
|
936
|
+
* @category Styles
|
|
937
|
+
*/
|
|
938
|
+
export function cytoscapeVizmapXml(style, name) {
|
|
939
|
+
const lines = [`<visualStyle${attr("name", name)}>`];
|
|
940
|
+
const section = (tag, defaults, t) => {
|
|
941
|
+
lines.push(` <${tag}>`);
|
|
942
|
+
for (const [dep, on] of t?.dependencies ?? []) {
|
|
943
|
+
lines.push(` <dependency${attr("name", dep)}${attr("value", on)}/>`);
|
|
944
|
+
}
|
|
945
|
+
const vps = new Set([...defaults.keys(), ...(t?.mappings.keys() ?? [])]);
|
|
946
|
+
for (const vp of vps) {
|
|
947
|
+
const d = defaults.has(vp) ? attr("default", defaults.get(vp)) : "";
|
|
948
|
+
const m = t?.mappings.get(vp);
|
|
949
|
+
if (m === undefined) {
|
|
950
|
+
lines.push(` <visualProperty${attr("name", vp)}${d}/>`);
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
lines.push(` <visualProperty${attr("name", vp)}${d}>`, ...mappingXml(m), " </visualProperty>");
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
lines.push(` </${tag}>`);
|
|
957
|
+
};
|
|
958
|
+
section("network", style.network.defaults);
|
|
959
|
+
section("node", style.node.defaults, style.node);
|
|
960
|
+
section("edge", style.edge.defaults, style.edge);
|
|
961
|
+
lines.push("</visualStyle>");
|
|
962
|
+
return lines.join("\n");
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* A mapping as the lines of its `session_vizmap.xml` element.
|
|
966
|
+
* @param m - the mapping
|
|
967
|
+
* @returns the lines
|
|
968
|
+
*/
|
|
969
|
+
function mappingXml(m) {
|
|
970
|
+
const head = `${attr("attributeName", m.column)}${attr("attributeType", m.kind === "continuous" ? "float" : (m.type ?? "string"))}`;
|
|
971
|
+
if (m.kind === "passthrough") {
|
|
972
|
+
return [` <passthroughMapping${head}/>`];
|
|
973
|
+
}
|
|
974
|
+
if (m.kind === "discrete") {
|
|
975
|
+
return [
|
|
976
|
+
` <discreteMapping${head}>`,
|
|
977
|
+
...m.table.map(([k, v]) => ` <discreteMappingEntry${attr("attributeValue", k)}${attr("value", v)}/>`),
|
|
978
|
+
" </discreteMapping>",
|
|
979
|
+
];
|
|
980
|
+
}
|
|
981
|
+
return [
|
|
982
|
+
` <continuousMapping${head}>`,
|
|
983
|
+
...m.points.map((p) => ` <continuousMappingPoint${attr("attrValue", p.at)}${attr("lesserValue", p.below)}${attr("equalValue", p.value)}${attr("greaterValue", p.above)}/>`),
|
|
984
|
+
" </continuousMapping>",
|
|
985
|
+
];
|
|
986
|
+
}
|
|
987
|
+
// ------------------------------------------------------------------ per-element values
|
|
988
|
+
/**
|
|
989
|
+
* The neutral properties a Cytoscape dialect holds per element: what a writer of resolved per-element values (XGMML
|
|
990
|
+
* graphics, a session view's bypasses) can write.
|
|
991
|
+
* @param target - nodes or edges
|
|
992
|
+
* @param dialect - the spelling
|
|
993
|
+
* @returns the properties
|
|
994
|
+
*/
|
|
995
|
+
export function cytoscapeWritableProperties(target, dialect) {
|
|
996
|
+
return [...WRITERS[dialect][target].keys(), ...FONT_PROPS];
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* One element's values as Cytoscape visual properties in a dialect's spelling, for a writer of per-element values.
|
|
1000
|
+
* The label font, weight and italic are written together as one font face.
|
|
1001
|
+
* @param target - nodes or edges
|
|
1002
|
+
* @param value - the element's value of a neutral property, or null
|
|
1003
|
+
* @param dialect - the spelling
|
|
1004
|
+
* @param approx - called with the property when a value is written as its nearest
|
|
1005
|
+
* @returns visual property name to raw value
|
|
1006
|
+
*/
|
|
1007
|
+
export function cytoscapeElementProperties(target, value, dialect, approx) {
|
|
1008
|
+
const out = new Map();
|
|
1009
|
+
for (const [p, w] of WRITERS[dialect][target]) {
|
|
1010
|
+
const v = value(p);
|
|
1011
|
+
if (v !== null) {
|
|
1012
|
+
out.set(w.vp, w.write(v, () => {
|
|
1013
|
+
approx(p);
|
|
1014
|
+
}));
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
const [f, wt, it] = FONT_PROPS.map((p) => value(p));
|
|
1018
|
+
if (f !== null || wt !== null || it !== null) {
|
|
1019
|
+
out.set(FONT_VP[target], fontOut(dialect, f, wt, it, () => {
|
|
1020
|
+
approx("labelFont");
|
|
1021
|
+
}));
|
|
1022
|
+
}
|
|
1023
|
+
return out;
|
|
1024
|
+
}
|
|
1025
|
+
//# sourceMappingURL=emit.js.map
|