@graphty/graph-io 0.3.47 → 0.3.49
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-wWjCRzKj.js → approximations-Bzn3L-je.js} +2 -2
- package/dist/chunks/{approximations-wWjCRzKj.js.map → approximations-Bzn3L-je.js.map} +1 -1
- package/dist/chunks/bends-BGXjv_U4.js +129 -0
- package/dist/chunks/bends-BGXjv_U4.js.map +1 -0
- package/dist/chunks/{block-DiGq58c3.js → block-iptrlMBb.js} +947 -134
- package/dist/chunks/block-iptrlMBb.js.map +1 -0
- package/dist/chunks/choose-CczZJaX_.js +717 -0
- package/dist/chunks/choose-CczZJaX_.js.map +1 -0
- package/dist/chunks/codes-BE2xir2k.js +157 -0
- package/dist/chunks/codes-BE2xir2k.js.map +1 -0
- package/dist/chunks/{constants-BKwqelYD.js → constants-CKkYLPtt.js} +2 -2
- package/dist/chunks/{constants-BKwqelYD.js.map → constants-CKkYLPtt.js.map} +1 -1
- package/dist/chunks/context-C3p0RQxR.js +664 -0
- package/dist/chunks/context-C3p0RQxR.js.map +1 -0
- package/dist/chunks/{convert-BcQ8_jMo.js → convert-Ct2zelbQ.js} +7 -2
- package/dist/chunks/convert-Ct2zelbQ.js.map +1 -0
- package/dist/chunks/credentials-DXHx7nwR.js +349 -0
- package/dist/chunks/credentials-DXHx7nwR.js.map +1 -0
- package/dist/chunks/cx-export-Bt6NoqTQ.js +259 -0
- package/dist/chunks/cx-export-Bt6NoqTQ.js.map +1 -0
- package/dist/chunks/descriptor-B28U25x4.js +60 -0
- package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
- package/dist/chunks/descriptor-C-YDhtsn.js +48 -0
- package/dist/chunks/descriptor-C-YDhtsn.js.map +1 -0
- package/dist/chunks/descriptor-DLA5kINx.js +142 -0
- package/dist/chunks/descriptor-DLA5kINx.js.map +1 -0
- package/dist/chunks/{emit-CwU8cUmG.js → emit-BwHQkZle.js} +1690 -103
- package/dist/chunks/emit-BwHQkZle.js.map +1 -0
- package/dist/chunks/{escape-CgzxiYPg.js → escape-CuCIzNMB.js} +12 -12
- package/dist/chunks/{escape-CgzxiYPg.js.map → escape-CuCIzNMB.js.map} +1 -1
- package/dist/chunks/{export-BvqAXCKh.js → export-Cha4dRFz.js} +48 -1780
- package/dist/chunks/export-Cha4dRFz.js.map +1 -0
- package/dist/chunks/{exporter--Mk9gXCJ.js → exporter-BP6otMO6.js} +6 -4
- package/dist/chunks/{exporter--Mk9gXCJ.js.map → exporter-BP6otMO6.js.map} +1 -1
- package/dist/chunks/{exporter-CrDWIyiq.js → exporter-D2CETOMK.js} +1222 -154
- package/dist/chunks/exporter-D2CETOMK.js.map +1 -0
- package/dist/chunks/{exporter-DndFlGSa.js → exporter-D9yMtocA.js} +7 -6
- package/dist/chunks/{exporter-DndFlGSa.js.map → exporter-D9yMtocA.js.map} +1 -1
- package/dist/chunks/exporter-_jrBTnos.js +1009 -0
- package/dist/chunks/exporter-_jrBTnos.js.map +1 -0
- package/dist/chunks/{exporter-CJgfhF-l.js → exporter-nDfxIK5D.js} +9 -7
- package/dist/chunks/{exporter-CJgfhF-l.js.map → exporter-nDfxIK5D.js.map} +1 -1
- package/dist/chunks/format-BXiAb-1h.js +408 -0
- package/dist/chunks/format-BXiAb-1h.js.map +1 -0
- package/dist/chunks/{generic-Dq1ntt9q.js → generic-ymWCETAJ.js} +387 -31
- package/dist/chunks/generic-ymWCETAJ.js.map +1 -0
- package/dist/chunks/{importer-CMmeMWlC.js → importer-B92x1xY5.js} +15 -263
- package/dist/chunks/importer-B92x1xY5.js.map +1 -0
- package/dist/chunks/{importer-DiZRmOQG.js → importer-CT9mJ1nn.js} +328 -90
- package/dist/chunks/importer-CT9mJ1nn.js.map +1 -0
- package/dist/chunks/{importer-COTK9Tsl.js → importer-DaLTjbds.js} +116 -1099
- package/dist/chunks/importer-DaLTjbds.js.map +1 -0
- package/dist/chunks/{importer-iFYPEKaJ.js → importer-GREKMdIf.js} +28 -16
- package/dist/chunks/importer-GREKMdIf.js.map +1 -0
- package/dist/chunks/{importer-BSvfrX_h.js → importer-PqaaKKnY.js} +23 -1016
- package/dist/chunks/importer-PqaaKKnY.js.map +1 -0
- package/dist/chunks/{importer-yh_aBCU6.js → importer-Vn5QvmmJ.js} +66 -12
- package/dist/chunks/importer-Vn5QvmmJ.js.map +1 -0
- package/dist/chunks/{importer-e6LGpqHB.js → importer-vRq4h3j5.js} +1470 -354
- package/dist/chunks/importer-vRq4h3j5.js.map +1 -0
- package/dist/chunks/input-CAxt_aV-.js +1397 -0
- package/dist/chunks/input-CAxt_aV-.js.map +1 -0
- package/dist/chunks/{json-elements-DJZRZ6jd.js → json-elements-Cq76WjnZ.js} +4 -4
- package/dist/chunks/{json-elements-DJZRZ6jd.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
- package/dist/chunks/{lexicon-CT69Kd87.js → lexicon-Clf4QIyl.js} +299 -77
- package/dist/chunks/lexicon-Clf4QIyl.js.map +1 -0
- package/dist/chunks/{ontology-export-G4MqRdux.js → ontology-export-OMo91mb0.js} +4 -3
- package/dist/chunks/{ontology-export-G4MqRdux.js.map → ontology-export-OMo91mb0.js.map} +1 -1
- package/dist/chunks/{records-CiaWZrFH.js → records-NJiYvekn.js} +2 -2
- package/dist/chunks/{records-CiaWZrFH.js.map → records-NJiYvekn.js.map} +1 -1
- package/dist/chunks/{format-BpQBx8MZ.js → report-CwMfYa9J.js} +70 -127
- package/dist/chunks/report-CwMfYa9J.js.map +1 -0
- package/dist/chunks/round-trip-Zm3_ivgq.js +79 -0
- package/dist/chunks/round-trip-Zm3_ivgq.js.map +1 -0
- package/dist/chunks/sigv4-EokFic1V.js +247 -0
- package/dist/chunks/sigv4-EokFic1V.js.map +1 -0
- package/dist/chunks/{styles-BQnsga7p.js → styles-CCs214_3.js} +1300 -168
- package/dist/chunks/styles-CCs214_3.js.map +1 -0
- package/dist/chunks/styles-Cm62yyQX.js +2812 -0
- package/dist/chunks/styles-Cm62yyQX.js.map +1 -0
- package/dist/chunks/styles-DPQQIig4.js +1928 -0
- package/dist/chunks/styles-DPQQIig4.js.map +1 -0
- package/dist/chunks/styles-yed-UMFdNqze.js +1213 -0
- package/dist/chunks/styles-yed-UMFdNqze.js.map +1 -0
- package/dist/chunks/{text-CzJNFOS9.js → text-ystE2bYi.js} +2 -2
- package/dist/chunks/{text-CzJNFOS9.js.map → text-ystE2bYi.js.map} +1 -1
- package/dist/csv.js +7 -5
- package/dist/csv.js.map +1 -1
- package/dist/cx.js +5 -4
- package/dist/cx.js.map +1 -1
- package/dist/cx2.js +2 -2
- package/dist/cys.js +1 -1
- package/dist/dot.js +5 -4
- package/dist/dot.js.map +1 -1
- package/dist/gexf.js +42 -10
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +850 -193
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +1189 -220
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +3 -3
- package/dist/json.js +3 -2
- package/dist/neo4j.js +6 -4
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/positions.js +45 -3
- package/dist/positions.js.map +1 -1
- package/dist/sources-cypher.d.ts +1 -0
- package/dist/sources-cypher.js +1351 -0
- package/dist/sources-cypher.js.map +1 -0
- package/dist/sources-ndex.d.ts +1 -0
- package/dist/sources-ndex.js +278 -0
- package/dist/sources-ndex.js.map +1 -0
- package/dist/sources-rest.d.ts +1 -0
- package/dist/sources-rest.js +1377 -0
- package/dist/sources-rest.js.map +1 -0
- package/dist/sources-sparql.d.ts +1 -0
- package/dist/sources-sparql.js +405 -0
- package/dist/sources-sparql.js.map +1 -0
- package/dist/src/common/report.d.ts +6 -3
- package/dist/src/common/report.d.ts.map +1 -1
- package/dist/src/common/report.js +15 -9
- package/dist/src/common/report.js.map +1 -1
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +5 -1
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx/styles.d.ts +24 -1
- package/dist/src/formats/cx/styles.d.ts.map +1 -1
- package/dist/src/formats/cx/styles.js +118 -11
- package/dist/src/formats/cx/styles.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +1 -0
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/cx2/styles.d.ts.map +1 -1
- package/dist/src/formats/cx2/styles.js +3 -1
- package/dist/src/formats/cx2/styles.js.map +1 -1
- package/dist/src/formats/cys/importer.d.ts.map +1 -1
- package/dist/src/formats/cys/importer.js +1 -0
- package/dist/src/formats/cys/importer.js.map +1 -1
- package/dist/src/formats/cys/styles.d.ts +2 -0
- package/dist/src/formats/cys/styles.d.ts.map +1 -1
- package/dist/src/formats/cys/styles.js +15 -7
- package/dist/src/formats/cys/styles.js.map +1 -1
- package/dist/src/formats/dot/drawing.d.ts +98 -0
- package/dist/src/formats/dot/drawing.d.ts.map +1 -0
- package/dist/src/formats/dot/drawing.js +734 -0
- package/dist/src/formats/dot/drawing.js.map +1 -0
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +108 -31
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/label-places.d.ts +34 -0
- package/dist/src/formats/dot/label-places.d.ts.map +1 -0
- package/dist/src/formats/dot/label-places.js +179 -0
- package/dist/src/formats/dot/label-places.js.map +1 -0
- package/dist/src/formats/dot/record.d.ts +50 -0
- package/dist/src/formats/dot/record.d.ts.map +1 -0
- package/dist/src/formats/dot/record.js +275 -0
- package/dist/src/formats/dot/record.js.map +1 -0
- package/dist/src/formats/dot/styles.d.ts +62 -2
- package/dist/src/formats/dot/styles.d.ts.map +1 -1
- package/dist/src/formats/dot/styles.js +1457 -120
- package/dist/src/formats/dot/styles.js.map +1 -1
- package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
- package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
- package/dist/src/formats/gexf/dialog-metrics.js +59 -0
- package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
- package/dist/src/formats/gexf/importer.d.ts +7 -0
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +41 -5
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/preview.d.ts +77 -0
- package/dist/src/formats/gexf/preview.d.ts.map +1 -0
- package/dist/src/formats/gexf/preview.js +191 -0
- package/dist/src/formats/gexf/preview.js.map +1 -0
- package/dist/src/formats/gexf/schema.d.ts.map +1 -1
- package/dist/src/formats/gexf/schema.js +2 -1
- package/dist/src/formats/gexf/schema.js.map +1 -1
- package/dist/src/formats/gexf/styles.d.ts +60 -16
- package/dist/src/formats/gexf/styles.d.ts.map +1 -1
- package/dist/src/formats/gexf/styles.js +883 -131
- package/dist/src/formats/gexf/styles.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts +5 -2
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +258 -71
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/index.d.ts +1 -1
- package/dist/src/formats/gml/index.d.ts.map +1 -1
- package/dist/src/formats/gml/index.js +1 -1
- package/dist/src/formats/gml/index.js.map +1 -1
- package/dist/src/formats/gml/positions.d.ts +7 -0
- package/dist/src/formats/gml/positions.d.ts.map +1 -1
- package/dist/src/formats/gml/positions.js +29 -7
- package/dist/src/formats/gml/positions.js.map +1 -1
- package/dist/src/formats/gml/styles.d.ts.map +1 -1
- package/dist/src/formats/gml/styles.js +756 -103
- package/dist/src/formats/gml/styles.js.map +1 -1
- package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-plain.js +8 -12
- package/dist/src/formats/graphml/styles-plain.js.map +1 -1
- package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
- package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-yed.js +749 -148
- package/dist/src/formats/graphml/styles-yed.js.map +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.js +429 -64
- package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts +3 -3
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +16 -6
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/dialect.d.ts +3 -2
- package/dist/src/formats/json/dialect.d.ts.map +1 -1
- package/dist/src/formats/json/dialect.js +39 -5
- package/dist/src/formats/json/dialect.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts +13 -2
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +42 -6
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/index.d.ts +1 -1
- package/dist/src/formats/json/index.d.ts.map +1 -1
- package/dist/src/formats/json/index.js +1 -1
- package/dist/src/formats/json/index.js.map +1 -1
- package/dist/src/formats/json/positions.d.ts +5 -2
- package/dist/src/formats/json/positions.d.ts.map +1 -1
- package/dist/src/formats/json/positions.js +20 -4
- package/dist/src/formats/json/positions.js.map +1 -1
- package/dist/src/formats/json/styles.d.ts +12 -1
- package/dist/src/formats/json/styles.d.ts.map +1 -1
- package/dist/src/formats/json/styles.js +1755 -136
- package/dist/src/formats/json/styles.js.map +1 -1
- package/dist/src/formats/pajek/draw.d.ts +96 -0
- package/dist/src/formats/pajek/draw.d.ts.map +1 -0
- package/dist/src/formats/pajek/draw.js +372 -0
- package/dist/src/formats/pajek/draw.js.map +1 -0
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +70 -51
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts +9 -0
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +233 -102
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/index.d.ts +1 -0
- package/dist/src/formats/pajek/index.d.ts.map +1 -1
- package/dist/src/formats/pajek/index.js.map +1 -1
- package/dist/src/formats/pajek/styles.d.ts +15 -7
- package/dist/src/formats/pajek/styles.d.ts.map +1 -1
- package/dist/src/formats/pajek/styles.js +1279 -114
- package/dist/src/formats/pajek/styles.js.map +1 -1
- package/dist/src/formats/pajek/syntax.d.ts +10 -1
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +26 -2
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts +1 -0
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +65 -5
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/styles.d.ts +23 -3
- package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
- package/dist/src/formats/xgmml/styles.js +278 -60
- package/dist/src/formats/xgmml/styles.js.map +1 -1
- package/dist/src/index.d.ts +10 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +11 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/positions/convert.d.ts.map +1 -1
- package/dist/src/positions/convert.js +11 -1
- package/dist/src/positions/convert.js.map +1 -1
- package/dist/src/positions/extract.d.ts.map +1 -1
- package/dist/src/positions/extract.js +53 -1
- package/dist/src/positions/extract.js.map +1 -1
- package/dist/src/positions/index.d.ts +1 -1
- package/dist/src/positions/index.d.ts.map +1 -1
- package/dist/src/positions/types.d.ts +59 -0
- package/dist/src/positions/types.d.ts.map +1 -1
- package/dist/src/registry.d.ts +173 -1
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +196 -1
- package/dist/src/registry.js.map +1 -1
- package/dist/src/sources/builtins.d.ts +11 -0
- package/dist/src/sources/builtins.d.ts.map +1 -0
- package/dist/src/sources/builtins.js +53 -0
- package/dist/src/sources/builtins.js.map +1 -0
- package/dist/src/sources/codes.d.ts +230 -0
- package/dist/src/sources/codes.d.ts.map +1 -0
- package/dist/src/sources/codes.js +58 -0
- package/dist/src/sources/codes.js.map +1 -0
- package/dist/src/sources/context.d.ts +112 -0
- package/dist/src/sources/context.d.ts.map +1 -0
- package/dist/src/sources/context.js +740 -0
- package/dist/src/sources/context.js.map +1 -0
- package/dist/src/sources/credentials.d.ts +179 -0
- package/dist/src/sources/credentials.d.ts.map +1 -0
- package/dist/src/sources/credentials.js +301 -0
- package/dist/src/sources/credentials.js.map +1 -0
- package/dist/src/sources/cypher/descriptor.d.ts +21 -0
- package/dist/src/sources/cypher/descriptor.d.ts.map +1 -0
- package/dist/src/sources/cypher/descriptor.js +124 -0
- package/dist/src/sources/cypher/descriptor.js.map +1 -0
- package/dist/src/sources/cypher/flatten.d.ts +72 -0
- package/dist/src/sources/cypher/flatten.d.ts.map +1 -0
- package/dist/src/sources/cypher/flatten.js +279 -0
- package/dist/src/sources/cypher/flatten.js.map +1 -0
- package/dist/src/sources/cypher/index.d.ts +33 -0
- package/dist/src/sources/cypher/index.d.ts.map +1 -0
- package/dist/src/sources/cypher/index.js +511 -0
- package/dist/src/sources/cypher/index.js.map +1 -0
- package/dist/src/sources/cypher/params.d.ts +40 -0
- package/dist/src/sources/cypher/params.d.ts.map +1 -0
- package/dist/src/sources/cypher/params.js +6 -0
- package/dist/src/sources/cypher/params.js.map +1 -0
- package/dist/src/sources/cypher/profiles.d.ts +44 -0
- package/dist/src/sources/cypher/profiles.d.ts.map +1 -0
- package/dist/src/sources/cypher/profiles.js +61 -0
- package/dist/src/sources/cypher/profiles.js.map +1 -0
- package/dist/src/sources/cypher/query-builder.d.ts +123 -0
- package/dist/src/sources/cypher/query-builder.d.ts.map +1 -0
- package/dist/src/sources/cypher/query-builder.js +267 -0
- package/dist/src/sources/cypher/query-builder.js.map +1 -0
- package/dist/src/sources/cypher/transports/bolt.d.ts +21 -0
- package/dist/src/sources/cypher/transports/bolt.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/bolt.js +185 -0
- package/dist/src/sources/cypher/transports/bolt.js.map +1 -0
- package/dist/src/sources/cypher/transports/neptune-analytics.d.ts +15 -0
- package/dist/src/sources/cypher/transports/neptune-analytics.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/neptune-analytics.js +38 -0
- package/dist/src/sources/cypher/transports/neptune-analytics.js.map +1 -0
- package/dist/src/sources/cypher/transports/neptune-https.d.ts +31 -0
- package/dist/src/sources/cypher/transports/neptune-https.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/neptune-https.js +104 -0
- package/dist/src/sources/cypher/transports/neptune-https.js.map +1 -0
- package/dist/src/sources/cypher/transports/query-api.d.ts +14 -0
- package/dist/src/sources/cypher/transports/query-api.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/query-api.js +80 -0
- package/dist/src/sources/cypher/transports/query-api.js.map +1 -0
- package/dist/src/sources/cypher/transports/transport.d.ts +78 -0
- package/dist/src/sources/cypher/transports/transport.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/transport.js +77 -0
- package/dist/src/sources/cypher/transports/transport.js.map +1 -0
- package/dist/src/sources/cypher/types-map.d.ts +91 -0
- package/dist/src/sources/cypher/types-map.d.ts.map +1 -0
- package/dist/src/sources/cypher/types-map.js +306 -0
- package/dist/src/sources/cypher/types-map.js.map +1 -0
- package/dist/src/sources/define.d.ts +47 -0
- package/dist/src/sources/define.d.ts.map +1 -0
- package/dist/src/sources/define.js +173 -0
- package/dist/src/sources/define.js.map +1 -0
- package/dist/src/sources/fail.d.ts +33 -0
- package/dist/src/sources/fail.d.ts.map +1 -0
- package/dist/src/sources/fail.js +49 -0
- package/dist/src/sources/fail.js.map +1 -0
- package/dist/src/sources/ids.d.ts +69 -0
- package/dist/src/sources/ids.d.ts.map +1 -0
- package/dist/src/sources/ids.js +69 -0
- package/dist/src/sources/ids.js.map +1 -0
- package/dist/src/sources/ndex/client.d.ts +31 -0
- package/dist/src/sources/ndex/client.d.ts.map +1 -0
- package/dist/src/sources/ndex/client.js +90 -0
- package/dist/src/sources/ndex/client.js.map +1 -0
- package/dist/src/sources/ndex/descriptor.d.ts +10 -0
- package/dist/src/sources/ndex/descriptor.d.ts.map +1 -0
- package/dist/src/sources/ndex/descriptor.js +55 -0
- package/dist/src/sources/ndex/descriptor.js.map +1 -0
- package/dist/src/sources/ndex/expand.d.ts +20 -0
- package/dist/src/sources/ndex/expand.d.ts.map +1 -0
- package/dist/src/sources/ndex/expand.js +87 -0
- package/dist/src/sources/ndex/expand.js.map +1 -0
- package/dist/src/sources/ndex/index.d.ts +25 -0
- package/dist/src/sources/ndex/index.d.ts.map +1 -0
- package/dist/src/sources/ndex/index.js +191 -0
- package/dist/src/sources/ndex/index.js.map +1 -0
- package/dist/src/sources/ndex/params.d.ts +17 -0
- package/dist/src/sources/ndex/params.d.ts.map +1 -0
- package/dist/src/sources/ndex/params.js +6 -0
- package/dist/src/sources/ndex/params.js.map +1 -0
- package/dist/src/sources/ndex/share-url.d.ts +40 -0
- package/dist/src/sources/ndex/share-url.d.ts.map +1 -0
- package/dist/src/sources/ndex/share-url.js +64 -0
- package/dist/src/sources/ndex/share-url.js.map +1 -0
- package/dist/src/sources/params.d.ts +31 -0
- package/dist/src/sources/params.d.ts.map +1 -0
- package/dist/src/sources/params.js +6 -0
- package/dist/src/sources/params.js.map +1 -0
- package/dist/src/sources/registry.d.ts +118 -0
- package/dist/src/sources/registry.d.ts.map +1 -0
- package/dist/src/sources/registry.js +193 -0
- package/dist/src/sources/registry.js.map +1 -0
- package/dist/src/sources/rest/descriptor.d.ts +16 -0
- package/dist/src/sources/rest/descriptor.d.ts.map +1 -0
- package/dist/src/sources/rest/descriptor.js +76 -0
- package/dist/src/sources/rest/descriptor.js.map +1 -0
- package/dist/src/sources/rest/index.d.ts +14 -0
- package/dist/src/sources/rest/index.d.ts.map +1 -0
- package/dist/src/sources/rest/index.js +13 -0
- package/dist/src/sources/rest/index.js.map +1 -0
- package/dist/src/sources/rest/mapping.d.ts +30 -0
- package/dist/src/sources/rest/mapping.d.ts.map +1 -0
- package/dist/src/sources/rest/mapping.js +362 -0
- package/dist/src/sources/rest/mapping.js.map +1 -0
- package/dist/src/sources/rest/openalex.d.ts +27 -0
- package/dist/src/sources/rest/openalex.d.ts.map +1 -0
- package/dist/src/sources/rest/openalex.js +269 -0
- package/dist/src/sources/rest/openalex.js.map +1 -0
- package/dist/src/sources/rest/paging.d.ts +53 -0
- package/dist/src/sources/rest/paging.d.ts.map +1 -0
- package/dist/src/sources/rest/paging.js +138 -0
- package/dist/src/sources/rest/paging.js.map +1 -0
- package/dist/src/sources/rest/params.d.ts +216 -0
- package/dist/src/sources/rest/params.d.ts.map +1 -0
- package/dist/src/sources/rest/params.js +7 -0
- package/dist/src/sources/rest/params.js.map +1 -0
- package/dist/src/sources/rest/records.d.ts +41 -0
- package/dist/src/sources/rest/records.d.ts.map +1 -0
- package/dist/src/sources/rest/records.js +240 -0
- package/dist/src/sources/rest/records.js.map +1 -0
- package/dist/src/sources/rest/samples/deps-dev.d.ts +10 -0
- package/dist/src/sources/rest/samples/deps-dev.d.ts.map +1 -0
- package/dist/src/sources/rest/samples/deps-dev.js +47 -0
- package/dist/src/sources/rest/samples/deps-dev.js.map +1 -0
- package/dist/src/sources/rest/samples/string.d.ts +9 -0
- package/dist/src/sources/rest/samples/string.d.ts.map +1 -0
- package/dist/src/sources/rest/samples/string.js +42 -0
- package/dist/src/sources/rest/samples/string.js.map +1 -0
- package/dist/src/sources/rest/selectors.d.ts +41 -0
- package/dist/src/sources/rest/selectors.d.ts.map +1 -0
- package/dist/src/sources/rest/selectors.js +81 -0
- package/dist/src/sources/rest/selectors.js.map +1 -0
- package/dist/src/sources/rest/source.d.ts +67 -0
- package/dist/src/sources/rest/source.d.ts.map +1 -0
- package/dist/src/sources/rest/source.js +650 -0
- package/dist/src/sources/rest/source.js.map +1 -0
- package/dist/src/sources/rest/templates.d.ts +38 -0
- package/dist/src/sources/rest/templates.d.ts.map +1 -0
- package/dist/src/sources/rest/templates.js +125 -0
- package/dist/src/sources/rest/templates.js.map +1 -0
- package/dist/src/sources/run.d.ts +93 -0
- package/dist/src/sources/run.d.ts.map +1 -0
- package/dist/src/sources/run.js +673 -0
- package/dist/src/sources/run.js.map +1 -0
- package/dist/src/sources/sha256.d.ts +12 -0
- package/dist/src/sources/sha256.d.ts.map +1 -0
- package/dist/src/sources/sha256.js +95 -0
- package/dist/src/sources/sha256.js.map +1 -0
- package/dist/src/sources/sigv4.d.ts +26 -0
- package/dist/src/sources/sigv4.d.ts.map +1 -0
- package/dist/src/sources/sigv4.js +184 -0
- package/dist/src/sources/sigv4.js.map +1 -0
- package/dist/src/sources/sparql/descriptor.d.ts +10 -0
- package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
- package/dist/src/sources/sparql/descriptor.js +64 -0
- package/dist/src/sources/sparql/descriptor.js.map +1 -0
- package/dist/src/sources/sparql/index.d.ts +28 -0
- package/dist/src/sources/sparql/index.d.ts.map +1 -0
- package/dist/src/sources/sparql/index.js +314 -0
- package/dist/src/sources/sparql/index.js.map +1 -0
- package/dist/src/sources/sparql/ntriples.d.ts +69 -0
- package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
- package/dist/src/sources/sparql/ntriples.js +180 -0
- package/dist/src/sources/sparql/ntriples.js.map +1 -0
- package/dist/src/sources/sparql/params.d.ts +27 -0
- package/dist/src/sources/sparql/params.d.ts.map +1 -0
- package/dist/src/sources/sparql/params.js +5 -0
- package/dist/src/sources/sparql/params.js.map +1 -0
- package/dist/src/sources/sparql/query.d.ts +72 -0
- package/dist/src/sources/sparql/query.d.ts.map +1 -0
- package/dist/src/sources/sparql/query.js +113 -0
- package/dist/src/sources/sparql/query.js.map +1 -0
- package/dist/src/sources/testing.d.ts +96 -0
- package/dist/src/sources/testing.d.ts.map +1 -0
- package/dist/src/sources/testing.js +138 -0
- package/dist/src/sources/testing.js.map +1 -0
- package/dist/src/sources/types.d.ts +696 -0
- package/dist/src/sources/types.d.ts.map +1 -0
- package/dist/src/sources/types.js +10 -0
- package/dist/src/sources/types.js.map +1 -0
- package/dist/src/styles/annotations.d.ts +61 -5
- package/dist/src/styles/annotations.d.ts.map +1 -1
- package/dist/src/styles/annotations.js +130 -22
- package/dist/src/styles/annotations.js.map +1 -1
- package/dist/src/styles/canon/bends.d.ts +46 -0
- package/dist/src/styles/canon/bends.d.ts.map +1 -1
- package/dist/src/styles/canon/bends.js +123 -0
- package/dist/src/styles/canon/bends.js.map +1 -1
- package/dist/src/styles/canon/color-tables.d.ts +6 -1
- package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
- package/dist/src/styles/canon/color-tables.js +10 -4
- package/dist/src/styles/canon/color-tables.js.map +1 -1
- package/dist/src/styles/canon/color.d.ts +3 -1
- package/dist/src/styles/canon/color.d.ts.map +1 -1
- package/dist/src/styles/canon/color.js +103 -3
- package/dist/src/styles/canon/color.js.map +1 -1
- package/dist/src/styles/canon/enums.d.ts +2 -2
- package/dist/src/styles/canon/enums.d.ts.map +1 -1
- package/dist/src/styles/canon/enums.js +82 -7
- package/dist/src/styles/canon/enums.js.map +1 -1
- package/dist/src/styles/canon/graphviz.d.ts +12 -3
- package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
- package/dist/src/styles/canon/graphviz.js +57 -9
- package/dist/src/styles/canon/graphviz.js.map +1 -1
- package/dist/src/styles/canon/number.d.ts +8 -0
- package/dist/src/styles/canon/number.d.ts.map +1 -1
- package/dist/src/styles/canon/number.js +18 -0
- package/dist/src/styles/canon/number.js.map +1 -1
- package/dist/src/styles/canon/text.d.ts +29 -2
- package/dist/src/styles/canon/text.d.ts.map +1 -1
- package/dist/src/styles/canon/text.js +156 -16
- package/dist/src/styles/canon/text.js.map +1 -1
- package/dist/src/styles/codes.d.ts +2 -0
- package/dist/src/styles/codes.d.ts.map +1 -1
- package/dist/src/styles/codes.js +2 -0
- package/dist/src/styles/codes.js.map +1 -1
- package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
- package/dist/src/styles/cyjs/cascade.js +1037 -35
- package/dist/src/styles/cyjs/cascade.js.map +1 -1
- package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
- package/dist/src/styles/cyjs/defaults-table.js +5 -0
- package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
- package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
- package/dist/src/styles/cyjs/emit.js +216 -12
- package/dist/src/styles/cyjs/emit.js.map +1 -1
- package/dist/src/styles/cyjs/face.d.ts +20 -0
- package/dist/src/styles/cyjs/face.d.ts.map +1 -0
- package/dist/src/styles/cyjs/face.js +332 -0
- package/dist/src/styles/cyjs/face.js.map +1 -0
- package/dist/src/styles/cyjs/mappers.d.ts +48 -2
- package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
- package/dist/src/styles/cyjs/mappers.js +463 -26
- package/dist/src/styles/cyjs/mappers.js.map +1 -1
- package/dist/src/styles/cyjs/routes.d.ts +53 -0
- package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
- package/dist/src/styles/cyjs/routes.js +360 -0
- package/dist/src/styles/cyjs/routes.js.map +1 -0
- package/dist/src/styles/cytoscape/charts.d.ts +23 -0
- package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/charts.js +560 -0
- package/dist/src/styles/cytoscape/charts.js.map +1 -0
- package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/emit.js +204 -44
- package/dist/src/styles/cytoscape/emit.js.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.d.ts +97 -3
- package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.js +413 -79
- package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
- package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
- package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/mappings.js +92 -0
- package/dist/src/styles/cytoscape/mappings.js.map +1 -1
- package/dist/src/styles/cytoscape/resolve.d.ts +46 -3
- package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/resolve.js +632 -22
- package/dist/src/styles/cytoscape/resolve.js.map +1 -1
- package/dist/src/styles/cytoscape/translate.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/translate.js +10 -10
- package/dist/src/styles/cytoscape/translate.js.map +1 -1
- package/dist/src/styles/defaults.d.ts +50 -0
- package/dist/src/styles/defaults.d.ts.map +1 -1
- package/dist/src/styles/defaults.js +315 -37
- package/dist/src/styles/defaults.js.map +1 -1
- package/dist/src/styles/index.d.ts +4 -3
- package/dist/src/styles/index.d.ts.map +1 -1
- package/dist/src/styles/index.js +3 -2
- package/dist/src/styles/index.js.map +1 -1
- package/dist/src/styles/internal.d.ts +1 -0
- package/dist/src/styles/internal.d.ts.map +1 -1
- package/dist/src/styles/internal.js +1 -0
- package/dist/src/styles/internal.js.map +1 -1
- package/dist/src/styles/io/block.d.ts.map +1 -1
- package/dist/src/styles/io/block.js +9 -0
- package/dist/src/styles/io/block.js.map +1 -1
- package/dist/src/styles/io/generic.d.ts.map +1 -1
- package/dist/src/styles/io/generic.js +56 -16
- package/dist/src/styles/io/generic.js.map +1 -1
- package/dist/src/styles/io/round-trip.d.ts +56 -0
- package/dist/src/styles/io/round-trip.d.ts.map +1 -0
- package/dist/src/styles/io/round-trip.js +138 -0
- package/dist/src/styles/io/round-trip.js.map +1 -0
- package/dist/src/styles/io/writer.d.ts.map +1 -1
- package/dist/src/styles/io/writer.js +13 -4
- package/dist/src/styles/io/writer.js.map +1 -1
- package/dist/src/styles/notes.d.ts.map +1 -1
- package/dist/src/styles/notes.js +1 -0
- package/dist/src/styles/notes.js.map +1 -1
- package/dist/src/styles/plan/features.d.ts +1 -1
- package/dist/src/styles/plan/features.d.ts.map +1 -1
- package/dist/src/styles/plan/features.js +22 -2
- package/dist/src/styles/plan/features.js.map +1 -1
- package/dist/src/styles/plan/index.d.ts +1 -1
- package/dist/src/styles/plan/index.d.ts.map +1 -1
- package/dist/src/styles/plan/index.js +1 -1
- package/dist/src/styles/plan/index.js.map +1 -1
- package/dist/src/styles/plan/plan.d.ts.map +1 -1
- package/dist/src/styles/plan/plan.js +61 -4
- package/dist/src/styles/plan/plan.js.map +1 -1
- package/dist/src/styles/plan/resolve.d.ts +13 -1
- package/dist/src/styles/plan/resolve.d.ts.map +1 -1
- package/dist/src/styles/plan/resolve.js +53 -6
- package/dist/src/styles/plan/resolve.js.map +1 -1
- package/dist/src/styles/slots.d.ts +14 -0
- package/dist/src/styles/slots.d.ts.map +1 -0
- package/dist/src/styles/slots.js +20 -0
- package/dist/src/styles/slots.js.map +1 -0
- package/dist/src/styles/types.d.ts +638 -5
- package/dist/src/styles/types.d.ts.map +1 -1
- package/dist/src/styles/vocabulary.d.ts +3 -2
- package/dist/src/styles/vocabulary.d.ts.map +1 -1
- package/dist/src/styles/vocabulary.js +218 -1
- package/dist/src/styles/vocabulary.js.map +1 -1
- package/dist/src/types.d.ts +19 -5
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/styles.js +29 -238
- package/dist/styles.js.map +1 -1
- package/dist/xgmml.js +3 -3
- package/docs/samples/people.json +6 -0
- package/package.json +53 -8
- package/src/common/report.ts +27 -7
- package/src/formats/cx/importer.ts +6 -1
- package/src/formats/cx/styles.ts +144 -9
- package/src/formats/cx2/importer.ts +1 -0
- package/src/formats/cx2/styles.ts +3 -1
- package/src/formats/cys/importer.ts +1 -0
- package/src/formats/cys/styles.ts +27 -5
- package/src/formats/dot/drawing.ts +799 -0
- package/src/formats/dot/importer.ts +120 -35
- package/src/formats/dot/label-places.ts +228 -0
- package/src/formats/dot/record.ts +336 -0
- package/src/formats/dot/styles.ts +1657 -154
- package/src/formats/gexf/dialog-metrics.ts +61 -0
- package/src/formats/gexf/importer.ts +50 -5
- package/src/formats/gexf/preview.ts +217 -0
- package/src/formats/gexf/schema.ts +2 -1
- package/src/formats/gexf/styles.ts +1144 -142
- package/src/formats/gml/importer.ts +291 -76
- package/src/formats/gml/index.ts +1 -1
- package/src/formats/gml/positions.ts +29 -7
- package/src/formats/gml/styles.ts +854 -111
- package/src/formats/graphml/styles-plain.ts +8 -23
- package/src/formats/graphml/styles-yed.ts +821 -159
- package/src/formats/graphml/styles-yfiles3.ts +485 -63
- package/src/formats/graphml/yfiles.ts +19 -6
- package/src/formats/json/dialect.ts +41 -5
- package/src/formats/json/importer.ts +59 -7
- package/src/formats/json/index.ts +1 -0
- package/src/formats/json/positions.ts +22 -5
- package/src/formats/json/styles.ts +2041 -185
- package/src/formats/pajek/draw.ts +458 -0
- package/src/formats/pajek/exporter.ts +81 -49
- package/src/formats/pajek/importer.ts +278 -103
- package/src/formats/pajek/index.ts +1 -0
- package/src/formats/pajek/styles.ts +1382 -133
- package/src/formats/pajek/syntax.ts +27 -2
- package/src/formats/xgmml/emit.ts +73 -5
- package/src/formats/xgmml/styles.ts +331 -71
- package/src/index.ts +94 -0
- package/src/positions/convert.ts +12 -1
- package/src/positions/extract.ts +55 -1
- package/src/positions/index.ts +1 -0
- package/src/positions/types.ts +60 -0
- package/src/registry.ts +326 -1
- package/src/sources/builtins.ts +63 -0
- package/src/sources/codes.ts +235 -0
- package/src/sources/context.ts +894 -0
- package/src/sources/credentials.ts +409 -0
- package/src/sources/cypher/descriptor.ts +131 -0
- package/src/sources/cypher/flatten.ts +323 -0
- package/src/sources/cypher/index.ts +628 -0
- package/src/sources/cypher/params.ts +41 -0
- package/src/sources/cypher/profiles.ts +78 -0
- package/src/sources/cypher/query-builder.ts +327 -0
- package/src/sources/cypher/transports/bolt.ts +228 -0
- package/src/sources/cypher/transports/neptune-analytics.ts +41 -0
- package/src/sources/cypher/transports/neptune-https.ts +122 -0
- package/src/sources/cypher/transports/query-api.ts +100 -0
- package/src/sources/cypher/transports/transport.ts +139 -0
- package/src/sources/cypher/types-map.ts +418 -0
- package/src/sources/define.ts +195 -0
- package/src/sources/fail.ts +70 -0
- package/src/sources/ids.ts +80 -0
- package/src/sources/ndex/client.ts +102 -0
- package/src/sources/ndex/descriptor.ts +64 -0
- package/src/sources/ndex/expand.ts +100 -0
- package/src/sources/ndex/index.ts +235 -0
- package/src/sources/ndex/params.ts +17 -0
- package/src/sources/ndex/share-url.ts +84 -0
- package/src/sources/params.ts +32 -0
- package/src/sources/registry.ts +325 -0
- package/src/sources/rest/descriptor.ts +79 -0
- package/src/sources/rest/index.ts +22 -0
- package/src/sources/rest/mapping.ts +401 -0
- package/src/sources/rest/openalex.ts +288 -0
- package/src/sources/rest/paging.ts +180 -0
- package/src/sources/rest/params.ts +243 -0
- package/src/sources/rest/records.ts +289 -0
- package/src/sources/rest/samples/deps-dev.ts +49 -0
- package/src/sources/rest/samples/string.ts +44 -0
- package/src/sources/rest/selectors.ts +91 -0
- package/src/sources/rest/source.ts +776 -0
- package/src/sources/rest/templates.ts +151 -0
- package/src/sources/run.ts +793 -0
- package/src/sources/sha256.ts +99 -0
- package/src/sources/sigv4.ts +209 -0
- package/src/sources/sparql/descriptor.ts +67 -0
- package/src/sources/sparql/index.ts +356 -0
- package/src/sources/sparql/ntriples.ts +219 -0
- package/src/sources/sparql/params.ts +28 -0
- package/src/sources/sparql/query.ts +162 -0
- package/src/sources/testing.ts +210 -0
- package/src/sources/types.ts +776 -0
- package/src/styles/annotations.ts +201 -27
- package/src/styles/canon/bends.ts +137 -0
- package/src/styles/canon/color-tables.ts +10 -4
- package/src/styles/canon/color.ts +105 -3
- package/src/styles/canon/enums.ts +99 -8
- package/src/styles/canon/graphviz.ts +71 -10
- package/src/styles/canon/number.ts +19 -0
- package/src/styles/canon/text.ts +187 -16
- package/src/styles/codes.ts +2 -0
- package/src/styles/cyjs/cascade.ts +1193 -38
- package/src/styles/cyjs/defaults-table.ts +5 -0
- package/src/styles/cyjs/emit.ts +247 -16
- package/src/styles/cyjs/face.ts +372 -0
- package/src/styles/cyjs/mappers.ts +498 -28
- package/src/styles/cyjs/routes.ts +432 -0
- package/src/styles/cytoscape/charts.ts +684 -0
- package/src/styles/cytoscape/emit.ts +220 -44
- package/src/styles/cytoscape/lexicon.ts +459 -80
- package/src/styles/cytoscape/mappings.ts +108 -0
- package/src/styles/cytoscape/resolve.ts +763 -23
- package/src/styles/cytoscape/translate.ts +11 -11
- package/src/styles/defaults.ts +436 -38
- package/src/styles/index.ts +5 -0
- package/src/styles/internal.ts +1 -0
- package/src/styles/io/block.ts +10 -0
- package/src/styles/io/generic.ts +79 -23
- package/src/styles/io/round-trip.ts +202 -0
- package/src/styles/io/writer.ts +14 -4
- package/src/styles/notes.ts +1 -0
- package/src/styles/plan/features.ts +23 -2
- package/src/styles/plan/index.ts +1 -1
- package/src/styles/plan/plan.ts +69 -5
- package/src/styles/plan/resolve.ts +61 -6
- package/src/styles/slots.ts +25 -0
- package/src/styles/types.ts +658 -4
- package/src/styles/vocabulary.ts +226 -3
- package/src/types.ts +19 -5
- package/dist/chunks/block-DiGq58c3.js.map +0 -1
- package/dist/chunks/choose--jM0yYCo.js +0 -57
- package/dist/chunks/choose--jM0yYCo.js.map +0 -1
- package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
- package/dist/chunks/emit-CwU8cUmG.js.map +0 -1
- package/dist/chunks/export-BvqAXCKh.js.map +0 -1
- package/dist/chunks/exporter-CrDWIyiq.js.map +0 -1
- package/dist/chunks/format-BpQBx8MZ.js.map +0 -1
- package/dist/chunks/generic-Dq1ntt9q.js.map +0 -1
- package/dist/chunks/importer-BSvfrX_h.js.map +0 -1
- package/dist/chunks/importer-CMmeMWlC.js.map +0 -1
- package/dist/chunks/importer-COTK9Tsl.js.map +0 -1
- package/dist/chunks/importer-DiZRmOQG.js.map +0 -1
- package/dist/chunks/importer-e6LGpqHB.js.map +0 -1
- package/dist/chunks/importer-iFYPEKaJ.js.map +0 -1
- package/dist/chunks/importer-yh_aBCU6.js.map +0 -1
- package/dist/chunks/lexicon-CT69Kd87.js.map +0 -1
- package/dist/chunks/styles-BQnsga7p.js.map +0 -1
- package/dist/chunks/styles-D3fRphrO.js +0 -690
- package/dist/chunks/styles-D3fRphrO.js.map +0 -1
- package/dist/chunks/styles-yed-BF5x3_Y5.js +0 -842
- package/dist/chunks/styles-yed-BF5x3_Y5.js.map +0 -1
- package/dist/chunks/writer-DMKvthQE.js +0 -448
- package/dist/chunks/writer-DMKvthQE.js.map +0 -1
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* of elements plus the size of the style, and spends from the extraction's one budget.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type { GraphSnapshot } from "@graphty/graph-format";
|
|
9
|
+
|
|
10
|
+
import { num6 } from "../canon/number.js";
|
|
11
|
+
import { type CanonSite, noteAt } from "../canon/site.js";
|
|
9
12
|
import { STYLE_ISSUE } from "../codes.js";
|
|
10
13
|
import { toolDefaults } from "../defaults.js";
|
|
11
14
|
import { StyleNotes } from "../notes.js";
|
|
@@ -21,13 +24,24 @@ import type {
|
|
|
21
24
|
StyleWorkBudget,
|
|
22
25
|
} from "../types.js";
|
|
23
26
|
import { isStyleValue } from "../vocabulary.js";
|
|
27
|
+
import { readCytoscapeCharts } from "./charts.js";
|
|
24
28
|
import {
|
|
29
|
+
arrowGap,
|
|
30
|
+
arrowProportion,
|
|
31
|
+
arrowSizeParser,
|
|
25
32
|
colorParser,
|
|
26
33
|
CYTOSCAPE_LEXICON,
|
|
34
|
+
cytoscapeLabelBase,
|
|
35
|
+
cytoscapeLabelMove,
|
|
36
|
+
type CytoscapeLabelPlace,
|
|
37
|
+
cytoscapeLabelPlace,
|
|
27
38
|
type CytoscapeValueParser,
|
|
39
|
+
halfBack,
|
|
28
40
|
isUncarriedVp,
|
|
29
41
|
NODE_SIZE_VP,
|
|
42
|
+
opacityParser,
|
|
30
43
|
sizeParser,
|
|
44
|
+
vpStep,
|
|
31
45
|
} from "./lexicon.js";
|
|
32
46
|
import {
|
|
33
47
|
type CytoscapeContinuousPoint,
|
|
@@ -59,6 +73,27 @@ export interface CytoscapeElements {
|
|
|
59
73
|
value(column: string, i: number): unknown;
|
|
60
74
|
/** Each element's bypasses, by element index. */
|
|
61
75
|
readonly bypasses?: readonly CytoscapeBypass[];
|
|
76
|
+
/**
|
|
77
|
+
* Edges only: each edge's source and target node index, in the order Cytoscape created the edges. With them,
|
|
78
|
+
* the edges Cytoscape desktop fans apart (parallel edges without bends) are marked curved; with `nodeSize` too
|
|
79
|
+
* (each node's larger drawn side, by node index, as `fanNodeSizes()` reads it), they are given the `fanSpacing`
|
|
80
|
+
* desktop spaces them by. With `nodeBox` (each node's width, height and border width, by node index), each
|
|
81
|
+
* self-loop without bends is given the two handles desktop draws it round.
|
|
82
|
+
*/
|
|
83
|
+
readonly ends?: {
|
|
84
|
+
readonly source: ArrayLike<number>;
|
|
85
|
+
readonly target: ArrayLike<number>;
|
|
86
|
+
readonly nodeSize?: ArrayLike<number | null>;
|
|
87
|
+
readonly nodeBox?: ArrayLike<readonly [width: number, height: number, border: number] | null>;
|
|
88
|
+
/** Each node's center on screen, x right and y down, by node index: what an edge's label is placed by. */
|
|
89
|
+
readonly nodeAt?: ArrayLike<readonly [x: number, y: number] | null>;
|
|
90
|
+
/**
|
|
91
|
+
* The order Cytoscape desktop creates the file's nodes and edges in, when it is not the file's (its CX reader
|
|
92
|
+
* creates them in hash order): each element's rank, lower first, by index. With it, `nodeAt` and `nodeSize`,
|
|
93
|
+
* each fanned edge is given desktop's own anchor as its bend, so it bows to the side desktop draws it on.
|
|
94
|
+
*/
|
|
95
|
+
readonly created?: { readonly node: ArrayLike<number>; readonly edge: ArrayLike<number> };
|
|
96
|
+
};
|
|
62
97
|
}
|
|
63
98
|
|
|
64
99
|
/**
|
|
@@ -76,11 +111,101 @@ export interface CytoscapeResolveOptions {
|
|
|
76
111
|
* element the style says nothing about is null. Defaults to null.
|
|
77
112
|
*/
|
|
78
113
|
readonly defaults?: StyleTool | null;
|
|
114
|
+
/** `resolveCytoscapeBypasses()` only: the edges' ends, as `CytoscapeElements.ends`. */
|
|
115
|
+
readonly ends?: CytoscapeElements["ends"];
|
|
116
|
+
/**
|
|
117
|
+
* `resolveCytoscapeBypasses()` only: an element's value of an attribute column, as `CytoscapeElements.value`,
|
|
118
|
+
* for what is drawn from the element's data (a chart's values); without it no element has any.
|
|
119
|
+
*/
|
|
120
|
+
readonly value?: CytoscapeElements["value"];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** How closely desktop stacks the edges it fans, 0..1: its anchors are twice this times the node size apart. */
|
|
124
|
+
const EDGE_STACKING_DENSITY_VP = "EDGE_STACKING_DENSITY";
|
|
125
|
+
/** How desktop draws parallel edges: AUTO_BEND (the default) fans them, HAYSTACK draws them straight. */
|
|
126
|
+
const EDGE_STACKING_VP = "EDGE_STACKING";
|
|
127
|
+
/** Whether an edge's label is turned along its line. */
|
|
128
|
+
const AUTOROTATE_VP = "EDGE_LABEL_AUTOROTATE";
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A map without one key.
|
|
132
|
+
* @param m - the map
|
|
133
|
+
* @param key - the key left out
|
|
134
|
+
* @returns a copy without it
|
|
135
|
+
*/
|
|
136
|
+
function withoutKey(m: ReadonlyMap<string, unknown>, key: string): ReadonlyMap<string, unknown> {
|
|
137
|
+
return new Map([...m].filter(([k]) => k !== key));
|
|
138
|
+
}
|
|
139
|
+
/** Desktop's `EDGE_STACKING_DENSITY` default. */
|
|
140
|
+
const EDGE_STACKING_DENSITY_DEFAULT = 0.5;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* A graph's edge ends for `CytoscapeElements.ends`, with each node's larger side from the nodes' resolved `width`
|
|
144
|
+
* and `height`: what desktop spaces the edges it fans between two nodes by.
|
|
145
|
+
* @param snapshot - the graph
|
|
146
|
+
* @param nodes - the nodes' values per property
|
|
147
|
+
* @returns the ends
|
|
148
|
+
*/
|
|
149
|
+
export function edgeEnds(
|
|
150
|
+
snapshot: GraphSnapshot,
|
|
151
|
+
nodes: Partial<Record<string, StyleColumn>>,
|
|
152
|
+
): NonNullable<CytoscapeElements["ends"]> {
|
|
153
|
+
const nodeSize = Array.from({ length: snapshot.nodeCount }, (_, i) => {
|
|
154
|
+
const sides = [nodes.width?.[i], nodes.height?.[i]].filter((v): v is number => typeof v === "number");
|
|
155
|
+
return sides.length === 0 ? null : Math.max(...sides);
|
|
156
|
+
});
|
|
157
|
+
const nodeBox = Array.from({ length: snapshot.nodeCount }, (_, i) => {
|
|
158
|
+
const [w, h, b] = [nodes.width?.[i], nodes.height?.[i], nodes.borderWidth?.[i]];
|
|
159
|
+
return typeof w === "number" && typeof h === "number" ? ([w, h, typeof b === "number" ? b : 0] as const) : null;
|
|
160
|
+
});
|
|
161
|
+
const position = snapshot.nodes.byRole("position");
|
|
162
|
+
// stored y up unless the column says otherwise; the label places are worked out y down, as Cytoscape draws
|
|
163
|
+
const down = (position?.meta.extra as { yAxis?: string } | undefined)?.yAxis === "down";
|
|
164
|
+
const nodeAt = Array.from({ length: snapshot.nodeCount }, (_, i) => {
|
|
165
|
+
const v = position?.isSet(i) === true ? (position.value(i) as ArrayLike<number>) : null;
|
|
166
|
+
return v === null ? null : ([v[0], down ? v[1] : -v[1]] as const);
|
|
167
|
+
});
|
|
168
|
+
const { src, dst } = snapshot.edgeList();
|
|
169
|
+
return { source: src, target: dst, nodeSize, nodeBox, nodeAt };
|
|
79
170
|
}
|
|
80
171
|
|
|
81
172
|
/** Locked node sizes with no `NODE_SIZE` anywhere draw at Cytoscape's lexicon default. */
|
|
82
173
|
const NODE_SIZE_FALLBACK = 50;
|
|
83
174
|
|
|
175
|
+
/**
|
|
176
|
+
* The visual property whose bypass each one takes when an element does not bypass it itself: Cytoscape desktop locks
|
|
177
|
+
* a bypassed parent's children too, so a session's `NODE_PAINT` bypass paints the fill and the border, a `NODE_SIZE`
|
|
178
|
+
* bypass sizes the node whatever `nodeSizeLocked` says, and an `EDGE_PAINT` or `EDGE_UNSELECTED_PAINT` bypass paints
|
|
179
|
+
* the line and its arrows (Cytoscape 3.10.5's SVG of the session specimen sheets `node-fills-borders`,
|
|
180
|
+
* `node-sizes-opacity` and `edges-lines`).
|
|
181
|
+
*/
|
|
182
|
+
const LOCK_PARENT: ReadonlyMap<string, string> = new Map([
|
|
183
|
+
["NODE_FILL_COLOR", "NODE_PAINT"],
|
|
184
|
+
["NODE_BORDER_PAINT", "NODE_PAINT"],
|
|
185
|
+
["NODE_WIDTH", "NODE_SIZE"],
|
|
186
|
+
["NODE_HEIGHT", "NODE_SIZE"],
|
|
187
|
+
["EDGE_UNSELECTED_PAINT", "EDGE_PAINT"],
|
|
188
|
+
["EDGE_STROKE_UNSELECTED_PAINT", "EDGE_UNSELECTED_PAINT"],
|
|
189
|
+
["EDGE_SOURCE_ARROW_UNSELECTED_PAINT", "EDGE_UNSELECTED_PAINT"],
|
|
190
|
+
["EDGE_TARGET_ARROW_UNSELECTED_PAINT", "EDGE_UNSELECTED_PAINT"],
|
|
191
|
+
]);
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* An element's bypass of a visual property: its own, else the nearest bypassed parent's (`LOCK_PARENT`).
|
|
195
|
+
* @param b - the element's bypasses
|
|
196
|
+
* @param vp - the visual property
|
|
197
|
+
* @returns the bypass value, or undefined
|
|
198
|
+
*/
|
|
199
|
+
function lockedValue(b: NonNullable<CytoscapeBypass>, vp: string): unknown {
|
|
200
|
+
for (let p: string | undefined = vp; p !== undefined; p = LOCK_PARENT.get(p)) {
|
|
201
|
+
const v = b.get(p);
|
|
202
|
+
if (v !== undefined && v !== null) {
|
|
203
|
+
return v;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
|
|
84
209
|
/** A visual property and the parser that reads it for one neutral property. */
|
|
85
210
|
type VpChoice = readonly [vp: string, parse: CytoscapeValueParser];
|
|
86
211
|
|
|
@@ -107,6 +232,12 @@ export function vpUsage(
|
|
|
107
232
|
bypassed.add(to);
|
|
108
233
|
}
|
|
109
234
|
}
|
|
235
|
+
// a bypassed parent bypasses its children (LOCK_PARENT lists a parent's own entry before its children's)
|
|
236
|
+
for (const [child, parent] of LOCK_PARENT) {
|
|
237
|
+
if (bypassed.has(parent)) {
|
|
238
|
+
bypassed.add(child);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
110
241
|
const used = new Set([...style.defaults.keys(), ...style.mappings.keys(), ...bypassed]);
|
|
111
242
|
return { used, bypassed };
|
|
112
243
|
}
|
|
@@ -136,7 +267,8 @@ export function chooseVps(
|
|
|
136
267
|
chosen.delete("height");
|
|
137
268
|
}
|
|
138
269
|
if (target === "edge" && style.dependencies.get("arrowColorMatchesEdge") === true) {
|
|
139
|
-
|
|
270
|
+
// the line is EDGE_UNSELECTED_PAINT's, not the stroke's, even where the style sets only the stroke
|
|
271
|
+
if (used.has("EDGE_UNSELECTED_PAINT") || used.has("EDGE_STROKE_UNSELECTED_PAINT")) {
|
|
140
272
|
chosen.set("color", ["EDGE_UNSELECTED_PAINT", colorParser]);
|
|
141
273
|
}
|
|
142
274
|
chosen.delete("sourceArrowColor");
|
|
@@ -152,7 +284,13 @@ export function chooseVps(
|
|
|
152
284
|
export type ParsedMapping =
|
|
153
285
|
| { readonly kind: "passthrough"; readonly column: string }
|
|
154
286
|
| { readonly kind: "discrete"; readonly column: string; readonly table: readonly (readonly [Scalar, StyleValue])[] }
|
|
155
|
-
| {
|
|
287
|
+
| {
|
|
288
|
+
readonly kind: "continuous";
|
|
289
|
+
readonly column: string;
|
|
290
|
+
readonly points: readonly ContinuousPoint[];
|
|
291
|
+
/** The step Cytoscape rounds a value to, for an integer visual property. */
|
|
292
|
+
readonly step?: number;
|
|
293
|
+
};
|
|
156
294
|
|
|
157
295
|
/**
|
|
158
296
|
* Reads a mapping's raw values with a property's parser: table entries and points whose values do not parse are
|
|
@@ -160,9 +298,15 @@ export type ParsedMapping =
|
|
|
160
298
|
* @param m - the mapping
|
|
161
299
|
* @param parse - the property's parser
|
|
162
300
|
* @param site - where problems are noted
|
|
301
|
+
* @param vp - the visual property it sets, whose type decides whether an interpolated value is rounded
|
|
163
302
|
* @returns the mapping with canonical values
|
|
164
303
|
*/
|
|
165
|
-
export function parseMapping(
|
|
304
|
+
export function parseMapping(
|
|
305
|
+
m: CytoscapeMapping,
|
|
306
|
+
parse: CytoscapeValueParser,
|
|
307
|
+
site: CanonSite,
|
|
308
|
+
vp: string,
|
|
309
|
+
): ParsedMapping {
|
|
166
310
|
switch (m.kind) {
|
|
167
311
|
case "passthrough":
|
|
168
312
|
return { kind: "passthrough", column: m.column };
|
|
@@ -176,8 +320,11 @@ export function parseMapping(m: CytoscapeMapping, parse: CytoscapeValueParser, s
|
|
|
176
320
|
}
|
|
177
321
|
return { kind: "discrete", column: m.column, table };
|
|
178
322
|
}
|
|
179
|
-
default:
|
|
180
|
-
|
|
323
|
+
default: {
|
|
324
|
+
const step = vpStep(vp);
|
|
325
|
+
const points = parsePoints(m.points, parse, site);
|
|
326
|
+
return { kind: "continuous", column: m.column, points, ...(step === undefined ? {} : { step }) };
|
|
327
|
+
}
|
|
181
328
|
}
|
|
182
329
|
}
|
|
183
330
|
|
|
@@ -240,7 +387,7 @@ function evalMapping(
|
|
|
240
387
|
return j < 0 ? null : m.table[j][1];
|
|
241
388
|
}
|
|
242
389
|
default:
|
|
243
|
-
return evalContinuous(m.points, numberOf(value));
|
|
390
|
+
return evalContinuous(m.points, numberOf(value), m.step);
|
|
244
391
|
}
|
|
245
392
|
}
|
|
246
393
|
|
|
@@ -283,7 +430,7 @@ function resolver(
|
|
|
283
430
|
return b.get(from);
|
|
284
431
|
}
|
|
285
432
|
}
|
|
286
|
-
return
|
|
433
|
+
return lockedValue(b, vp);
|
|
287
434
|
};
|
|
288
435
|
// a mapping parsed once per visual property and neutral property
|
|
289
436
|
const mappingOf = (vp: string, parse: CytoscapeValueParser, property: string): ParsedMapping | undefined => {
|
|
@@ -296,7 +443,7 @@ function resolver(
|
|
|
296
443
|
if (m === undefined) {
|
|
297
444
|
const entries = raw.kind === "discrete" ? raw.table.length : 0;
|
|
298
445
|
budget?.spend(target, 1 + entries + (raw.kind === "continuous" ? raw.points.length : 0));
|
|
299
|
-
m = parseMapping(raw, parse, ruleSite(property));
|
|
446
|
+
m = parseMapping(raw, parse, ruleSite(property), vp);
|
|
300
447
|
parsed.set(key, m);
|
|
301
448
|
}
|
|
302
449
|
return m;
|
|
@@ -321,7 +468,7 @@ function resolver(
|
|
|
321
468
|
/**
|
|
322
469
|
* Every element's value per neutral property under a Cytoscape style, the way Cytoscape draws it: per visual
|
|
323
470
|
* property a bypass, else the mapping's value, else the default; `nodeSizeLocked` and `arrowColorMatchesEdge`
|
|
324
|
-
* applied. `EDGE_CURVED` only rounds an edge's bends, so an edge without bends is `curved: false
|
|
471
|
+
* applied (under `nodeSizeLocked` a node's own `NODE_WIDTH` or `NODE_HEIGHT` bypass still sets that dimension). `EDGE_CURVED` only rounds an edge's bends, so an edge without bends is `curved: false` unless desktop fans it out of a bundle of parallel edges (given `elements.ends`). Visual properties
|
|
325
472
|
* no neutral property carries are noted as `W_STYLE_NOT_CARRIED`.
|
|
326
473
|
* @param target - nodes or edges
|
|
327
474
|
* @param style - the style
|
|
@@ -341,7 +488,7 @@ export function resolveCytoscape(
|
|
|
341
488
|
const n = elements.count;
|
|
342
489
|
const { used, bypassed } = vpUsage(s, elements.bypasses ?? []);
|
|
343
490
|
const chosen = chooseVps(target, s, used);
|
|
344
|
-
const { one } = resolver(target, s, elements, notes, options.budget);
|
|
491
|
+
const { one, bypass } = resolver(target, s, elements, notes, options.budget);
|
|
345
492
|
const out: Partial<Record<string, StyleColumn>> = {};
|
|
346
493
|
const column = (vp: string, parse: CytoscapeValueParser, property: string): (StyleValue | null)[] => {
|
|
347
494
|
options.budget?.spend(target, n);
|
|
@@ -355,31 +502,581 @@ export function resolveCytoscape(
|
|
|
355
502
|
out[prop] = column(vp, parse, prop);
|
|
356
503
|
}
|
|
357
504
|
if (target === "node" && s.dependencies.get("nodeSizeLocked") === true) {
|
|
505
|
+
// a node's own width or height still wins over the locked size: Cytoscape draws it
|
|
358
506
|
const size = column(NODE_SIZE_VP, sizeParser, "width").map((v) => v ?? NODE_SIZE_FALLBACK);
|
|
359
|
-
|
|
360
|
-
|
|
507
|
+
const own = (vp: string, property: string): StyleColumn =>
|
|
508
|
+
size.map((v, i) => {
|
|
509
|
+
const b = bypass(i, vp);
|
|
510
|
+
const parsed =
|
|
511
|
+
b === undefined || b === null ? null : sizeParser(b, { notes, target, property, element: i });
|
|
512
|
+
return parsed ?? v;
|
|
513
|
+
});
|
|
514
|
+
out.width = own("NODE_WIDTH", "width");
|
|
515
|
+
out.height = own("NODE_HEIGHT", "height");
|
|
516
|
+
}
|
|
517
|
+
labelDress(target, out, one, n, elements.ends);
|
|
518
|
+
if (target === "node") {
|
|
519
|
+
squashHexagons(out);
|
|
520
|
+
// the value as written: a chart is text, or an object in CX2; a size a number or its text
|
|
521
|
+
const raw: CytoscapeValueParser = (v) => {
|
|
522
|
+
if (typeof v === "string" || typeof v === "number") {
|
|
523
|
+
return String(v);
|
|
524
|
+
}
|
|
525
|
+
return typeof v === "object" && v !== null ? JSON.stringify(v) : null;
|
|
526
|
+
};
|
|
527
|
+
readCytoscapeCharts(
|
|
528
|
+
out,
|
|
529
|
+
n,
|
|
530
|
+
(slot, i) => {
|
|
531
|
+
const v = one(slot, raw, "pieColors", i);
|
|
532
|
+
return typeof v === "string" && v.startsWith("{") ? (JSON.parse(v) as unknown) : v;
|
|
533
|
+
},
|
|
534
|
+
(column, i) => elements.value(column, i),
|
|
535
|
+
s.dependencies.get("nodeCustomGraphicsSizeSync") !== false,
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
if (
|
|
539
|
+
target === "edge" &&
|
|
540
|
+
s.dependencies.get("arrowColorMatchesEdge") === true &&
|
|
541
|
+
!used.has("EDGE_UNSELECTED_PAINT") &&
|
|
542
|
+
used.has("EDGE_STROKE_UNSELECTED_PAINT")
|
|
543
|
+
) {
|
|
544
|
+
// the dependency draws the line and the arrows in EDGE_UNSELECTED_PAINT, Cytoscape's own when the style has
|
|
545
|
+
// none: the stroke's default and its mapping are not drawn, only an element's own bypass of the stroke (below;
|
|
546
|
+
// Cytoscape 3.10.5 on specimen-mappings-bypass draws a passthrough of the stroke #404040, as its XGMML says)
|
|
547
|
+
const paint = (toolDefaults("cytoscape-fallbacks")?.edge.color?.value ?? null) as StyleValue | null;
|
|
548
|
+
out.color = Array.from({ length: n }, (_, i) => one("EDGE_UNSELECTED_PAINT", colorParser, "color", i) ?? paint);
|
|
361
549
|
}
|
|
362
550
|
if (target === "edge" && s.dependencies.get("arrowColorMatchesEdge") === true && out.color !== undefined) {
|
|
363
|
-
|
|
364
|
-
out
|
|
551
|
+
// CX2's EDGE_LINE_COLOR bypass is the stroke's alone (its writer spells a desktop EDGE_UNSELECTED_PAINT
|
|
552
|
+
// bypass out as the line and both arrow colors): the arrows keep the style's line color (Cytoscape 3.10.5's
|
|
553
|
+
// SVG of the CX2 specimen-mappings-bypass, bypass-over-edge-passthrough, draws its arrow #505050)
|
|
554
|
+
const lineVp = chosen.get("color")?.[0];
|
|
555
|
+
const unbypassed = resolver(target, s, { ...elements, bypasses: [] }, notes, options.budget).one;
|
|
556
|
+
const arrows =
|
|
557
|
+
lineVp === "EDGE_LINE_COLOR"
|
|
558
|
+
? Array.from({ length: n }, (_, i) => unbypassed(lineVp, colorParser, "color", i))
|
|
559
|
+
: out.color;
|
|
560
|
+
out.sourceArrowColor = arrows.slice();
|
|
561
|
+
out.targetArrowColor = arrows.slice();
|
|
562
|
+
// the dependency sets the line and the arrows from EDGE_UNSELECTED_PAINT; an element's own bypass of one of
|
|
563
|
+
// them still wins for that one (Cytoscape draws a bypassed EDGE_STROKE_UNSELECTED_PAINT line in its color)
|
|
564
|
+
const own: readonly [string, string][] = [
|
|
565
|
+
["color", "EDGE_STROKE_UNSELECTED_PAINT"],
|
|
566
|
+
["sourceArrowColor", "EDGE_SOURCE_ARROW_UNSELECTED_PAINT"],
|
|
567
|
+
["targetArrowColor", "EDGE_TARGET_ARROW_UNSELECTED_PAINT"],
|
|
568
|
+
["sourceArrowColor", "EDGE_SOURCE_ARROW_COLOR"],
|
|
569
|
+
["targetArrowColor", "EDGE_TARGET_ARROW_COLOR"],
|
|
570
|
+
];
|
|
571
|
+
for (const [prop, vp] of own) {
|
|
572
|
+
out[prop] = (out[prop] ?? []).map((v, i) => {
|
|
573
|
+
const b = bypass(i, vp);
|
|
574
|
+
const site = { notes, target, property: prop, element: i };
|
|
575
|
+
return (b === undefined || b === null ? null : colorParser(b, site)) ?? v;
|
|
576
|
+
});
|
|
577
|
+
}
|
|
365
578
|
}
|
|
366
579
|
noteUncarried(target, s, used, bypassed, notes);
|
|
367
|
-
fillToolDefaults(target, out, n, options.defaults ?? null);
|
|
368
580
|
if (target === "edge") {
|
|
369
|
-
|
|
581
|
+
const bends = column(EDGE_BEND_VP, bendsParser, "bends");
|
|
582
|
+
if (bends.some((v) => v !== null)) {
|
|
583
|
+
out.bends = bends;
|
|
584
|
+
}
|
|
585
|
+
// before the tool's defaults: an edge the style leaves unset is curved as Cytoscape's EDGE_CURVED default is
|
|
586
|
+
const curvedAsSet = out.curved?.slice();
|
|
587
|
+
straightenBendless(out, one, n, elements.ends);
|
|
588
|
+
loopHandles(out, one, curvedAsSet, elements.ends);
|
|
589
|
+
arrowProportions(out, column);
|
|
370
590
|
}
|
|
591
|
+
fillToolDefaults(target, out, n, options.defaults ?? null);
|
|
371
592
|
return out;
|
|
372
593
|
}
|
|
373
594
|
|
|
374
595
|
/**
|
|
375
|
-
*
|
|
596
|
+
* A visual property's value as written, a CX2 object as its JSON.
|
|
597
|
+
* @param v - the value
|
|
598
|
+
* @returns its text, or null
|
|
599
|
+
*/
|
|
600
|
+
const rawText: CytoscapeValueParser = (v) => {
|
|
601
|
+
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
|
|
602
|
+
return String(v);
|
|
603
|
+
}
|
|
604
|
+
return typeof v === "object" && v !== null ? JSON.stringify(v) : null;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Reads what Cytoscape draws of each element's label beyond its words, font and color: the box behind it (drawn only
|
|
609
|
+
* with a `*_LABEL_BACKGROUND_SHAPE` other than NONE, the default, in its color and transparency), where it is placed
|
|
610
|
+
* (`*_LABEL_POSITION` read whole: which point of the label's box is pinned to which point of the node, or of the
|
|
611
|
+
* edge's line, and the offset) and how its lines are justified. Each column is kept only where some element needs it;
|
|
612
|
+
* an edge's place is kept whenever it has one, since Cytoscape centers an edge's label on its line.
|
|
613
|
+
* @param target - nodes or edges
|
|
614
|
+
* @param out - the values per property, changed in place
|
|
615
|
+
* @param one - reads one visual property of one element
|
|
616
|
+
* @param n - the element count
|
|
617
|
+
* @param ends - the edges' ends and their nodes' centers, when known
|
|
618
|
+
*/
|
|
619
|
+
function labelDress(
|
|
620
|
+
target: StyleTarget,
|
|
621
|
+
out: Partial<Record<string, StyleColumn>>,
|
|
622
|
+
one: Resolver["one"],
|
|
623
|
+
n: number,
|
|
624
|
+
ends: CytoscapeElements["ends"],
|
|
625
|
+
): void {
|
|
626
|
+
const vp = (name: string): string => `${target === "node" ? "NODE" : "EDGE"}_LABEL_${name}`;
|
|
627
|
+
const columns: Record<string, (StyleValue | null)[]> = {};
|
|
628
|
+
const put = (property: string, i: number, v: StyleValue | null): void => {
|
|
629
|
+
let column = columns[property];
|
|
630
|
+
if (column === undefined) {
|
|
631
|
+
column = new Array<StyleValue | null>(n).fill(null);
|
|
632
|
+
columns[property] = column;
|
|
633
|
+
}
|
|
634
|
+
column[i] = v;
|
|
635
|
+
};
|
|
636
|
+
for (let i = 0; i < n; i++) {
|
|
637
|
+
labelBox(vp, one, i, put);
|
|
638
|
+
// read whole, quietly (the lexicon's reading of the same value notes a bad one), under a name of its own: a
|
|
639
|
+
// mapping is parsed once per visual property and neutral property
|
|
640
|
+
const placed = one(vp("POSITION"), rawText, "labelPlace", i);
|
|
641
|
+
const raw = typeof placed === "string" && placed.startsWith("{") ? (JSON.parse(placed) as unknown) : placed;
|
|
642
|
+
const place = cytoscapeLabelPlace(raw, { notes: new StyleNotes(), target, property: "labelPosition" });
|
|
643
|
+
if (place !== null) {
|
|
644
|
+
placeLabel(target, place, i, out, put, ends);
|
|
645
|
+
}
|
|
646
|
+
if (target === "edge") {
|
|
647
|
+
autorotate(one, i, out, n, ends);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
const kept = (property: string, v: StyleValue | null): boolean =>
|
|
651
|
+
v !== null && v !== 0 && (v !== "center" || (property === "labelPosition" && target === "edge"));
|
|
652
|
+
for (const [property, values] of Object.entries(columns)) {
|
|
653
|
+
if (values.some((v) => kept(property, v))) {
|
|
654
|
+
out[property] = values;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* The box Cytoscape draws behind one label, when its shape is not NONE: its color (`#B6B6B6` unset, the lexicon's
|
|
661
|
+
* default), its opacity, and for ROUND_RECTANGLE its corners, rounded an eighth of the box's height: 1.455 on the
|
|
662
|
+
* 11.64-tall box of a 10 px label (xgmml-specimen-labels.svg, label-background-shape-round-rectangle), so 0.1455 of the
|
|
663
|
+
* label's size. ponytail: one line's height; a box of several lines is rounded as one line's.
|
|
664
|
+
* @param vp - names a label visual property of the target
|
|
665
|
+
* @param one - reads one visual property of one element
|
|
666
|
+
* @param i - the element
|
|
667
|
+
* @param put - sets one element's value of a property
|
|
668
|
+
*/
|
|
669
|
+
function labelBox(
|
|
670
|
+
vp: (name: string) => string,
|
|
671
|
+
one: Resolver["one"],
|
|
672
|
+
i: number,
|
|
673
|
+
put: (property: string, i: number, v: StyleValue | null) => void,
|
|
674
|
+
): void {
|
|
675
|
+
const shape = one(vp("BACKGROUND_SHAPE"), rawText, "labelBackgroundShape", i);
|
|
676
|
+
if (typeof shape !== "string" || shape.trim().toUpperCase() === "NONE") {
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
put("labelBackground", i, one(vp("BACKGROUND_COLOR"), colorParser, "labelBackground", i) ?? "#b6b6b6");
|
|
680
|
+
const [t, o] = [vp("BACKGROUND_TRANSPARENCY"), vp("BACKGROUND_OPACITY")];
|
|
681
|
+
const opacity =
|
|
682
|
+
one(t, opacityParser(t), "labelBackgroundOpacity", i) ?? one(o, opacityParser(o), "labelBackgroundOpacity", i);
|
|
683
|
+
put("labelBackgroundOpacity", i, opacity ?? 1);
|
|
684
|
+
// CX2 spells it round-rectangle
|
|
685
|
+
if (shape.trim().toUpperCase().replace("-", "_") === "ROUND_RECTANGLE") {
|
|
686
|
+
const size = one(vp("FONT_SIZE"), sizeParser, "labelSize", i);
|
|
687
|
+
// desktop's default label sizes: 12 on a node, 10 on an edge
|
|
688
|
+
const defaultSize = vp("FONT_SIZE").startsWith("EDGE") ? 10 : 12;
|
|
689
|
+
put("labelCornerRadius", i, num6(LABEL_CORNER_PER_SIZE * (typeof size === "number" ? size : defaultSize)));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/** How far Cytoscape rounds a ROUND_RECTANGLE label box's corners, as a fraction of the label's font size. */
|
|
694
|
+
const LABEL_CORNER_PER_SIZE = 0.1455;
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Where one label is placed, from its Cytoscape label position: its neutral `labelPosition`, offsets, shifts and
|
|
698
|
+
* line justification. A node's label is pinned against the node's box. An edge's is pinned to a point of its drawn
|
|
699
|
+
* line, the middle unless the anchor's horizontal letter names an end (W the source's, E the target's; its vertical
|
|
700
|
+
* letter changes nothing, measured on Cytoscape 3.10.5's SVG), from the line's middle, where it is centered.
|
|
701
|
+
* @param target - nodes or edges
|
|
702
|
+
* @param place - the label position
|
|
703
|
+
* @param i - the element
|
|
704
|
+
* @param out - the values per property (the node sizes are read)
|
|
705
|
+
* @param put - sets one element's value of a property
|
|
706
|
+
* @param ends - the edges' ends and their nodes' centers, when known
|
|
707
|
+
*/
|
|
708
|
+
function placeLabel(
|
|
709
|
+
target: StyleTarget,
|
|
710
|
+
place: CytoscapeLabelPlace,
|
|
711
|
+
i: number,
|
|
712
|
+
out: Partial<Record<string, StyleColumn>>,
|
|
713
|
+
put: (property: string, i: number, v: StyleValue | null) => void,
|
|
714
|
+
ends: CytoscapeElements["ends"],
|
|
715
|
+
): void {
|
|
716
|
+
let move: ReturnType<typeof cytoscapeLabelMove>;
|
|
717
|
+
if (target === "node") {
|
|
718
|
+
const [w, h] = [out.width?.[i], out.height?.[i]];
|
|
719
|
+
move = cytoscapeLabelMove(place, typeof w === "number" ? w : 0, typeof h === "number" ? h : 0);
|
|
720
|
+
put("labelPosition", i, cytoscapeLabelBase(place));
|
|
721
|
+
} else {
|
|
722
|
+
const [ax, ay] = lineEnd(ends, i, place.node[0]);
|
|
723
|
+
move = {
|
|
724
|
+
offset: [ax + place.offset[0], ay + place.offset[1]],
|
|
725
|
+
shift: [halfBack(place.label[0]), halfBack(place.label[1])],
|
|
726
|
+
};
|
|
727
|
+
put("labelPosition", i, "center");
|
|
728
|
+
}
|
|
729
|
+
put("labelOffsetX", i, num6(move.offset[0]));
|
|
730
|
+
put("labelOffsetY", i, num6(move.offset[1]));
|
|
731
|
+
put("labelShiftX", i, move.shift[0]);
|
|
732
|
+
put("labelShiftY", i, move.shift[1]);
|
|
733
|
+
put("labelTextAlign", i, place.justify);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Turns an edge's label along its line under `EDGE_LABEL_AUTOROTATE`, as Cytoscape draws it: the line's angle from
|
|
738
|
+
* its source's center to its target's (kept between -90 and 90 so the words read left to right), plus its
|
|
739
|
+
* `EDGE_LABEL_ROTATION`.
|
|
740
|
+
* ponytail: the angle is the file's node places at import; a layout that moves the nodes leaves it as it was, until
|
|
741
|
+
* the neutral styles can say "along the line"
|
|
742
|
+
* @param one - reads one visual property of one element
|
|
743
|
+
* @param e - the edge
|
|
744
|
+
* @param out - the values per property, changed in place
|
|
745
|
+
* @param n - the edge count
|
|
746
|
+
* @param ends - the edges' ends and their nodes' centers
|
|
747
|
+
*/
|
|
748
|
+
function autorotate(
|
|
749
|
+
one: Resolver["one"],
|
|
750
|
+
e: number,
|
|
751
|
+
out: Partial<Record<string, StyleColumn>>,
|
|
752
|
+
n: number,
|
|
753
|
+
ends: CytoscapeElements["ends"],
|
|
754
|
+
): void {
|
|
755
|
+
const on = one(AUTOROTATE_VP, rawText, "labelRotation", e);
|
|
756
|
+
const [si, ti] = [ends?.source[e], ends?.target[e]];
|
|
757
|
+
const [s, t] = [si === undefined ? null : ends?.nodeAt?.[si], ti === undefined ? null : ends?.nodeAt?.[ti]];
|
|
758
|
+
if (String(on).toLowerCase() !== "true" || !s || !t || (s[0] === t[0] && s[1] === t[1])) {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
const a = (Math.atan2(t[1] - s[1], t[0] - s[0]) * 180) / Math.PI;
|
|
762
|
+
let upright = a;
|
|
763
|
+
if (a > 90) {
|
|
764
|
+
upright = a - 180;
|
|
765
|
+
} else if (a <= -90) {
|
|
766
|
+
upright = a + 180;
|
|
767
|
+
}
|
|
768
|
+
out.labelRotation ??= new Array<StyleValue | null>(n).fill(null);
|
|
769
|
+
const column = out.labelRotation as (StyleValue | null)[];
|
|
770
|
+
const own = column[e];
|
|
771
|
+
column[e] = num6((((upright + (typeof own === "number" ? own : 0)) % 360) + 360) % 360);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* How far from the middle of an edge's drawn line one of its ends is, on screen (y down): the line between its two
|
|
776
|
+
* nodes' centers, cut where it meets each node's ellipse; 0 for the middle, or where the centers are not known.
|
|
777
|
+
* @param ends - the edges' ends, their nodes' centers and boxes
|
|
778
|
+
* @param e - the edge
|
|
779
|
+
* @param side - -1 for the source's end, 1 for the target's, 0 for the middle
|
|
780
|
+
* @returns the offset from the line's middle
|
|
781
|
+
*/
|
|
782
|
+
function lineEnd(ends: CytoscapeElements["ends"], e: number, side: number): readonly [number, number] {
|
|
783
|
+
const [si, ti] = [ends?.source[e], ends?.target[e]];
|
|
784
|
+
const [s, t] = [si === undefined ? null : ends?.nodeAt?.[si], ti === undefined ? null : ends?.nodeAt?.[ti]];
|
|
785
|
+
if (side === 0 || s === null || s === undefined || t === null || t === undefined) {
|
|
786
|
+
return [0, 0];
|
|
787
|
+
}
|
|
788
|
+
const length = Math.hypot(t[0] - s[0], t[1] - s[1]);
|
|
789
|
+
if (length === 0) {
|
|
790
|
+
return [0, 0];
|
|
791
|
+
}
|
|
792
|
+
const [ux, uy] = [(t[0] - s[0]) / length, (t[1] - s[1]) / length];
|
|
793
|
+
// where the line leaves a node's ellipse, along it from the center
|
|
794
|
+
const reach = (node: number | undefined): number => {
|
|
795
|
+
const box = node === undefined ? null : ends?.nodeBox?.[node];
|
|
796
|
+
if (box === null || box === undefined) {
|
|
797
|
+
return 0;
|
|
798
|
+
}
|
|
799
|
+
const [a, b] = [box[0] / 2, box[1] / 2];
|
|
800
|
+
return a === 0 || b === 0 ? 0 : (a * b) / Math.hypot(b * ux, a * uy);
|
|
801
|
+
};
|
|
802
|
+
const from = reach(si);
|
|
803
|
+
const to = length - reach(ti);
|
|
804
|
+
// the drawn line's middle and the end asked for, both measured along the line from the source's center
|
|
805
|
+
const along = (side < 0 ? from : to) - (from + to) / 2;
|
|
806
|
+
return [ux * along, uy * along];
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/** How tall a regular hexagon is for its width. */
|
|
810
|
+
const HEXAGON_ASPECT = Math.sqrt(3) / 2;
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Gives every hexagon node the height Cytoscape desktop draws it at. Its HEXAGON is a regular hexagon squashed to
|
|
814
|
+
* the node's box rather than one filling it: the corners reach the box's sides, the flat top and bottom only
|
|
815
|
+
* `sqrt(3) / 2` of the way up and down, so a 40 x 40 node with a border of 1 is a 39 x 33.8 path (its border is
|
|
816
|
+
* inside its size, `borderPosition` inside). The neutral hexagon fills its box, so the node is that much shorter.
|
|
817
|
+
* @param out - the node values per property, changed in place
|
|
818
|
+
*/
|
|
819
|
+
function squashHexagons(out: Partial<Record<string, StyleColumn>>): void {
|
|
820
|
+
const { shape, height } = out;
|
|
821
|
+
if (shape === undefined || height === undefined || !shape.includes("hexagon")) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
const border = out.borderWidth;
|
|
825
|
+
out.height = height.map((h, i) => {
|
|
826
|
+
if (shape[i] !== "hexagon" || typeof h !== "number") {
|
|
827
|
+
return h;
|
|
828
|
+
}
|
|
829
|
+
const b = border?.[i];
|
|
830
|
+
const w = typeof b === "number" ? Math.min(b, h) : 0;
|
|
831
|
+
return (h - w) * HEXAGON_ASPECT + w;
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* What Cytoscape draws of each end's arrow beyond its shape and the one neutral `arrowSize`: the source end's own
|
|
837
|
+
* size where it differs from the target's (an unset size is Cytoscape's 6), and the length and width of the short and
|
|
838
|
+
* crossed arrows against their neutral shape's, and how far off its node each arrow stands. Each is kept only where
|
|
839
|
+
* some edge needs it.
|
|
840
|
+
* @param out - the values per property, changed in place
|
|
841
|
+
* @param column - reads one visual property of every element
|
|
842
|
+
*/
|
|
843
|
+
function arrowProportions(
|
|
844
|
+
out: Partial<Record<string, StyleColumn>>,
|
|
845
|
+
column: (vp: string, parse: CytoscapeValueParser, property: string) => (StyleValue | null)[],
|
|
846
|
+
): void {
|
|
847
|
+
const size = out.arrowSize;
|
|
848
|
+
const own = column("EDGE_SOURCE_ARROW_SIZE", arrowSizeParser, "sourceArrowSize").map((v) => v ?? 1);
|
|
849
|
+
if (own.some((v, i) => v !== (size?.[i] ?? 1))) {
|
|
850
|
+
out.sourceArrowSize = own;
|
|
851
|
+
}
|
|
852
|
+
for (const [prop, vp, side] of [
|
|
853
|
+
["sourceArrowLength", "EDGE_SOURCE_ARROW_SHAPE", "length"],
|
|
854
|
+
["targetArrowLength", "EDGE_TARGET_ARROW_SHAPE", "length"],
|
|
855
|
+
["sourceArrowWidth", "EDGE_SOURCE_ARROW_SHAPE", "width"],
|
|
856
|
+
["targetArrowWidth", "EDGE_TARGET_ARROW_SHAPE", "width"],
|
|
857
|
+
] as const) {
|
|
858
|
+
const values = column(vp, arrowProportion(side), prop).map((v) => (v === 1 ? null : v));
|
|
859
|
+
if (values.some((v) => v !== null)) {
|
|
860
|
+
out[prop] = values;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
// the arrows desktop draws standing off their node (T, the half circles, HALF_TOP, the squares)
|
|
864
|
+
for (const [prop, vp] of [
|
|
865
|
+
["sourceArrowGap", "EDGE_SOURCE_ARROW_SHAPE"],
|
|
866
|
+
["targetArrowGap", "EDGE_TARGET_ARROW_SHAPE"],
|
|
867
|
+
] as const) {
|
|
868
|
+
const values = column(vp, arrowGap, prop).map((v) => (v === 0 ? null : v));
|
|
869
|
+
if (values.some((v) => v !== null)) {
|
|
870
|
+
out[prop] = values;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Marks straight every curved edge without bends, except where Cytoscape desktop fans it: `EDGE_CURVED` only
|
|
877
|
+
* rounds the bends an edge has, and the bends Cytoscape adds itself. Among the edges joining the same two nodes
|
|
878
|
+
* (either way round, not loops), it draws the last it created straight and bends each earlier one without bends
|
|
879
|
+
* of its own round an anchor beside the line (`DEdgeDetails.getAnchors`, `EDGE_STACKING` `AUTO_BEND`, the default;
|
|
880
|
+
* it walks the pair's edges newest first, measured on Cytoscape 3.10.5's SVG of edges joining two nodes both ways)
|
|
881
|
+
* -- unless the last has bends, when every anchor falls on the line. Its anchors are the larger side of the two
|
|
882
|
+
* nodes times twice `EDGE_STACKING_DENSITY` apart, so the curves' middles half that: each fanned edge's
|
|
883
|
+
* `fanSpacing`, when the node sizes are known. A fanned edge is drawn curved even under `EDGE_CURVED` false, and an
|
|
884
|
+
* edge whose `EDGE_STACKING` is HAYSTACK is neither fanned nor counted: desktop draws it straight (both measured on
|
|
885
|
+
* Cytoscape 3.10.5's SVG of the edges-lines specimen sheet).
|
|
886
|
+
* @param out - the values per property, changed in place
|
|
887
|
+
* @param one - reads one visual property of one element
|
|
888
|
+
* @param n - the edge count
|
|
889
|
+
* @param ends - each edge's source and target node index, in creation order, when known
|
|
890
|
+
*/
|
|
891
|
+
function straightenBendless(
|
|
892
|
+
out: Partial<Record<string, StyleColumn>>,
|
|
893
|
+
one: Resolver["one"],
|
|
894
|
+
n: number,
|
|
895
|
+
ends: CytoscapeElements["ends"],
|
|
896
|
+
): void {
|
|
897
|
+
// an edge the style leaves unset takes EDGE_CURVED's default, true
|
|
898
|
+
const curved = out.curved ?? new Array<StyleValue | null>(n).fill(null);
|
|
899
|
+
const bent = (i: number): boolean => one(EDGE_BEND_VP, bendParser, "curved", i) === true;
|
|
900
|
+
const haystack = (i: number): boolean =>
|
|
901
|
+
String(one(EDGE_STACKING_VP, rawText, "fanned", i) ?? "").toUpperCase() === "HAYSTACK";
|
|
902
|
+
// each fanned edge's place in its pair's walk (1 for the first fanned)
|
|
903
|
+
const place = ends === undefined ? new Map<number, number>() : fanPlaces(ends, curved.length, bent, haystack);
|
|
904
|
+
const fanned = new Set(place.keys());
|
|
905
|
+
const rounds = (i: number): boolean => fanned.has(i) || bent(i);
|
|
906
|
+
const rounded = curved.map((c, i) => {
|
|
907
|
+
if (c === null) {
|
|
908
|
+
return rounds(i) ? true : null;
|
|
909
|
+
}
|
|
910
|
+
return c === true || fanned.has(i) ? rounds(i) : c;
|
|
911
|
+
});
|
|
912
|
+
if (out.curved !== undefined || rounded.includes(true)) {
|
|
913
|
+
out.curved = rounded;
|
|
914
|
+
}
|
|
915
|
+
if (ends?.nodeSize === undefined || fanned.size === 0) {
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
const { source, target, nodeSize } = ends;
|
|
919
|
+
out.fanSpacing = curved.map((_, i) => {
|
|
920
|
+
const size = Math.max(nodeSize[source[i]] ?? Number.NaN, nodeSize[target[i]] ?? Number.NaN);
|
|
921
|
+
if (out.curved?.[i] !== true || !fanned.has(i) || bent(i) || !Number.isFinite(size)) {
|
|
922
|
+
return null;
|
|
923
|
+
}
|
|
924
|
+
const read = one(EDGE_STACKING_DENSITY_VP, sizeParser, "fanSpacing", i);
|
|
925
|
+
const density = Math.min(1, typeof read === "number" ? read : EDGE_STACKING_DENSITY_DEFAULT);
|
|
926
|
+
return size * density;
|
|
927
|
+
});
|
|
928
|
+
fanAnchors(out, ends, place);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* The edges desktop fans, each with its place in its node pair's walk (1 for the first fanned). Desktop walks a node
|
|
933
|
+
* pair's edges newest first (its adjacency lists take each new edge at the head); the first it meets is drawn
|
|
934
|
+
* straight, and each later one fanned unless that first one has bends. Loops and haystack edges are left out.
|
|
935
|
+
* @param ends - each edge's source and target node index, and the order they were created in
|
|
936
|
+
* @param count - the edge count
|
|
937
|
+
* @param bent - whether an edge has bends of its own
|
|
938
|
+
* @param haystack - whether an edge is a haystack edge
|
|
939
|
+
* @returns each fanned edge's place, in walk order
|
|
940
|
+
*/
|
|
941
|
+
function fanPlaces(
|
|
942
|
+
ends: NonNullable<CytoscapeElements["ends"]>,
|
|
943
|
+
count: number,
|
|
944
|
+
bent: (i: number) => boolean,
|
|
945
|
+
haystack: (i: number) => boolean,
|
|
946
|
+
): Map<number, number> {
|
|
947
|
+
const place = new Map<number, number>();
|
|
948
|
+
const first = new Map<string, { f: number; k: number }>();
|
|
949
|
+
for (const i of newestFirst(count, ends.created?.edge)) {
|
|
950
|
+
const [s, t] = [ends.source[i], ends.target[i]];
|
|
951
|
+
if (s === t || haystack(i)) {
|
|
952
|
+
continue;
|
|
953
|
+
}
|
|
954
|
+
const key = `${Math.min(s, t)},${Math.max(s, t)}`;
|
|
955
|
+
const f = first.get(key);
|
|
956
|
+
if (f === undefined) {
|
|
957
|
+
first.set(key, { f: i, k: 0 });
|
|
958
|
+
} else if (!bent(f.f)) {
|
|
959
|
+
f.k++;
|
|
960
|
+
place.set(i, f.k);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
return place;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* The edges newest first: by the order they were created in when it is known, else last index first.
|
|
968
|
+
* @param count - the edge count
|
|
969
|
+
* @param created - each edge's place in the creation order, when known
|
|
970
|
+
* @returns the edge indices in that order
|
|
971
|
+
*/
|
|
972
|
+
function newestFirst(count: number, created: ArrayLike<number> | undefined): number[] {
|
|
973
|
+
const walk = Array.from({ length: count }, (_, i) => i);
|
|
974
|
+
walk.sort(created === undefined ? (a, b) => b - a : (a, b) => created[b] - created[a]);
|
|
975
|
+
return walk;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/**
|
|
979
|
+
* Gives each fanned edge its place in desktop's fan as a bend, when the order desktop created the nodes in is known:
|
|
980
|
+
* the fan's side is then desktop's, not graphty's. Desktop measures each pair's fan from the node whose view it made
|
|
981
|
+
* first, and it makes views newest node first (`DEdgeDetails.getAnchors`: the pair's lower view SUID is its source;
|
|
982
|
+
* `SimpleNetwork.getNodeList` lists the newest node first); the `k`-th fanned edge bows `ceil(k / 2)` fan spacings
|
|
983
|
+
* off the middle of the line, to the right of the fan's direction (y down) for odd `k`, to the left for even. The
|
|
984
|
+
* bend is the control point of a quadratic Bezier whose middle lies there, twice as far off.
|
|
985
|
+
* @param out - the values per property, with `fanSpacing` set; changed in place
|
|
986
|
+
* @param ends - the edges' ends, their nodes' centers and creation order
|
|
987
|
+
* @param place - each fanned edge's place in its pair's walk, from 1
|
|
988
|
+
*/
|
|
989
|
+
function fanAnchors(
|
|
990
|
+
out: Partial<Record<string, StyleColumn>>,
|
|
991
|
+
ends: NonNullable<CytoscapeElements["ends"]>,
|
|
992
|
+
place: ReadonlyMap<number, number>,
|
|
993
|
+
): void {
|
|
994
|
+
const { created, nodeAt, source, target } = ends;
|
|
995
|
+
const spacing = out.fanSpacing?.slice();
|
|
996
|
+
if (created === undefined || nodeAt === undefined || spacing === undefined) {
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
const bends = out.bends?.slice() ?? new Array<StyleValue | null>(source.length).fill(null);
|
|
1000
|
+
const bendCurve = out.bendCurve?.slice() ?? new Array<StyleValue | null>(source.length).fill(null);
|
|
1001
|
+
let changed = false;
|
|
1002
|
+
for (const [i, k] of place) {
|
|
1003
|
+
const [s, t] = [source[i], target[i]];
|
|
1004
|
+
const [ps, pt, f] = [nodeAt[s], nodeAt[t], spacing[i]];
|
|
1005
|
+
if (ps === null || ps === undefined || pt === null || pt === undefined || typeof f !== "number") {
|
|
1006
|
+
continue;
|
|
1007
|
+
}
|
|
1008
|
+
const len = Math.hypot(pt[0] - ps[0], pt[1] - ps[1]);
|
|
1009
|
+
if (len === 0) {
|
|
1010
|
+
continue;
|
|
1011
|
+
}
|
|
1012
|
+
// the fan's direction: from the node desktop made a view of first, the one created last
|
|
1013
|
+
const sign = created.node[s] > created.node[t] ? 1 : -1;
|
|
1014
|
+
const [nx, ny] = [(sign * (pt[0] - ps[0])) / len, (sign * (pt[1] - ps[1])) / len];
|
|
1015
|
+
const offset = Math.ceil(k / 2) * (k % 2 === 0 ? 1 : -1) * 2 * f;
|
|
1016
|
+
const [vx, vy] = [offset * ny, -offset * nx];
|
|
1017
|
+
// to the left of source -> target, y up, as a fraction of the length
|
|
1018
|
+
const across = (vx * (pt[1] - ps[1]) - vy * (pt[0] - ps[0])) / (len * len);
|
|
1019
|
+
bends[i] = `0.5,${String(Math.round(across * 1e6) / 1e6 || 0)}`;
|
|
1020
|
+
bendCurve[i] = "bezier";
|
|
1021
|
+
spacing[i] = null;
|
|
1022
|
+
changed = true;
|
|
1023
|
+
}
|
|
1024
|
+
if (changed) {
|
|
1025
|
+
out.bends = bends;
|
|
1026
|
+
out.bendCurve = bendCurve;
|
|
1027
|
+
out.fanSpacing = spacing;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Gives each self-loop without bends of its own the two handles Cytoscape desktop draws it round
|
|
1033
|
+
* (`DEdgeDetails.getAnchors`): one left of the node's center and one above it, each `(i + 3) / 2` of the node's
|
|
1034
|
+
* size times twice `EDGE_STACKING_DENSITY` away, where the size is the larger side of the node with its border
|
|
1035
|
+
* (its extents in desktop's spatial index) and `i` counts the node's earlier loops without bends, newest first as
|
|
1036
|
+
* desktop walks them. A loop is curved through them unless `EDGE_CURVED` says false. Measured on Cytoscape
|
|
1037
|
+
* 3.10.5's SVG of the edges-lines specimen sheet (within 0.3 px of its loops).
|
|
376
1038
|
* @param out - the values per property, changed in place
|
|
377
1039
|
* @param one - reads one visual property of one element
|
|
1040
|
+
* @param curvedAsSet - each edge's `curved` as the style set it, before bendless edges were straightened
|
|
1041
|
+
* @param ends - each edge's source and target node index, in creation order, and each node's box, when known
|
|
378
1042
|
*/
|
|
379
|
-
function
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
1043
|
+
function loopHandles(
|
|
1044
|
+
out: Partial<Record<string, StyleColumn>>,
|
|
1045
|
+
one: Resolver["one"],
|
|
1046
|
+
curvedAsSet: readonly (StyleValue | null)[] | undefined,
|
|
1047
|
+
ends: CytoscapeElements["ends"],
|
|
1048
|
+
): void {
|
|
1049
|
+
const box = ends?.nodeBox;
|
|
1050
|
+
if (ends === undefined || box === undefined) {
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
const bends = out.bends?.slice() ?? new Array<StyleValue | null>(ends.source.length).fill(null);
|
|
1054
|
+
const curved = out.curved?.slice() ?? new Array<StyleValue | null>(ends.source.length).fill(null);
|
|
1055
|
+
const earlier = new Map<number, number>();
|
|
1056
|
+
const fraction = (v: number): string => String(Math.round(v * 1e4) / 1e4 || 0);
|
|
1057
|
+
let changed = false;
|
|
1058
|
+
for (let i = ends.source.length - 1; i >= 0; i--) {
|
|
1059
|
+
const node = ends.source[i];
|
|
1060
|
+
const b = box[node];
|
|
1061
|
+
if (node !== ends.target[i] || bends[i] !== null) {
|
|
1062
|
+
continue;
|
|
1063
|
+
}
|
|
1064
|
+
const rank = earlier.get(node) ?? 0;
|
|
1065
|
+
earlier.set(node, rank + 1);
|
|
1066
|
+
if (b === null || b === undefined || b[0] <= 0 || b[1] <= 0) {
|
|
1067
|
+
continue;
|
|
1068
|
+
}
|
|
1069
|
+
const read = one(EDGE_STACKING_DENSITY_VP, sizeParser, "fanSpacing", i);
|
|
1070
|
+
const density = Math.min(1, typeof read === "number" ? read : EDGE_STACKING_DENSITY_DEFAULT);
|
|
1071
|
+
const reach = (((rank + 3) * (Math.max(b[0], b[1]) + b[2])) / 2) * 2 * density;
|
|
1072
|
+
// as `x,y` fractions of the node's half width and half height, y up: left of the center, then above it
|
|
1073
|
+
bends[i] = `${fraction(-reach / (b[0] / 2))},0 0,${fraction(reach / (b[1] / 2))}`;
|
|
1074
|
+
curved[i] = curvedAsSet?.[i] !== false;
|
|
1075
|
+
changed = true;
|
|
1076
|
+
}
|
|
1077
|
+
if (changed) {
|
|
1078
|
+
out.bends = bends;
|
|
1079
|
+
out.curved = curved;
|
|
383
1080
|
}
|
|
384
1081
|
}
|
|
385
1082
|
|
|
@@ -399,6 +1096,41 @@ export const bendParser: CytoscapeValueParser = (raw) => {
|
|
|
399
1096
|
return Array.isArray(raw) ? raw.length > 0 : raw !== null && raw !== undefined && typeof raw === "object";
|
|
400
1097
|
};
|
|
401
1098
|
|
|
1099
|
+
/**
|
|
1100
|
+
* An `EDGE_BEND` value as the neutral `bends`: Cytoscape keeps each handle as `cos,sin,ratio`, the handle at the
|
|
1101
|
+
* source center plus `ratio` times the source-to-target vector turned by the angle (y down), handles separated by
|
|
1102
|
+
* `|`. Relative to the same line, y up, that is `ratio * cos` along it and `-ratio * sin` across it.
|
|
1103
|
+
* @param input - the value: an `EDGE_BEND` text, or CX2's `EDGE_CONTROL_POINTS` objects
|
|
1104
|
+
* @param site - where it was read
|
|
1105
|
+
* @returns the bends, or null for an edge without handles or a value that is not handles
|
|
1106
|
+
*/
|
|
1107
|
+
const bendsParser: CytoscapeValueParser = (input, site) => {
|
|
1108
|
+
// CX2's EDGE_CONTROL_POINTS: one object per handle, whose `sin` Cytoscape fills with EDGE_BEND's first number and
|
|
1109
|
+
// `cos` with its second (it reads them back the same way: specimen-edges-lines bend-one-handle bends)
|
|
1110
|
+
const raw = Array.isArray(input)
|
|
1111
|
+
? input
|
|
1112
|
+
.map((h: unknown) => {
|
|
1113
|
+
const o = (h ?? {}) as Record<string, unknown>;
|
|
1114
|
+
return `${Number(o.sin)},${Number(o.cos)},${Number(o.ratio)}`;
|
|
1115
|
+
})
|
|
1116
|
+
.join("|")
|
|
1117
|
+
: input;
|
|
1118
|
+
if (typeof raw !== "string" || !bendParser(raw, site)) {
|
|
1119
|
+
return null;
|
|
1120
|
+
}
|
|
1121
|
+
const points: string[] = [];
|
|
1122
|
+
for (const handle of raw.trim().split("|")) {
|
|
1123
|
+
const [c, sin, ratio] = handle.split(",").map((t) => Number(t.trim()));
|
|
1124
|
+
if (![c, sin, ratio].every((v) => Number.isFinite(v))) {
|
|
1125
|
+
noteAt(site, STYLE_ISSUE.BAD_VALUE, raw.slice(0, 64));
|
|
1126
|
+
return null;
|
|
1127
|
+
}
|
|
1128
|
+
const fraction = (v: number): string => String(Math.round(v * 1e4) / 1e4 || 0);
|
|
1129
|
+
points.push(`${fraction(ratio * c)},${fraction(-ratio * sin)}`);
|
|
1130
|
+
}
|
|
1131
|
+
return points.join(" ");
|
|
1132
|
+
};
|
|
1133
|
+
|
|
402
1134
|
/** Default values that mean "nothing drawn": a VP left at one of these is not worth a note. */
|
|
403
1135
|
const INERT_DEFAULT = /NullCustomGraphics|^255$|^0(?:\.0+)?$|^$|^C,C,c,0\.00,0\.00$|^false$/;
|
|
404
1136
|
|
|
@@ -494,7 +1226,15 @@ export function resolveCytoscapeBypasses(
|
|
|
494
1226
|
): Partial<Record<string, StyleColumn>> {
|
|
495
1227
|
const notes = options.notes ?? new StyleNotes();
|
|
496
1228
|
const style = emptyCytoscapeStyle();
|
|
497
|
-
const elements: CytoscapeElements = {
|
|
1229
|
+
const elements: CytoscapeElements = {
|
|
1230
|
+
count: maps.length,
|
|
1231
|
+
value: options.value ?? (() => null),
|
|
1232
|
+
// Cytoscape 3.10.5 draws an XGMML edge's EDGE_LABEL_AUTOROTATE true level, where it turns the same edge read
|
|
1233
|
+
// from CX, CX2 or a session along its line (the label-autorotate-true edge of the edge-labels and
|
|
1234
|
+
// mappings-bypass-p13 sheets in its SVG): its XGMML reader does not apply it, so neither does graph-io
|
|
1235
|
+
bypasses: maps.map((m) => (m?.has(AUTOROTATE_VP) === true ? withoutKey(m, AUTOROTATE_VP) : m)),
|
|
1236
|
+
ends: options.ends,
|
|
1237
|
+
};
|
|
498
1238
|
const out = resolveCytoscape(target, style, elements, { notes, budget: options.budget });
|
|
499
1239
|
if (target === "node" && out.width === undefined) {
|
|
500
1240
|
const size = maps.map((m) => {
|