@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
|
@@ -13,22 +13,26 @@
|
|
|
13
13
|
* bends and other keys stay. The `graphty.styles` block and the per-element values its rules read are keys too,
|
|
14
14
|
* named by the GML writer's rule for names that are not GML keys (`graphty_styles`, `graphty_style_node_<key>`).
|
|
15
15
|
*/
|
|
16
|
-
import { bendsToPoints, canonBends } from "../../styles/canon/bends.js";
|
|
16
|
+
import { bendsToPoints, canonBends, canonNodeOffsets, nodeOffsetsToPoints, } from "../../styles/canon/bends.js";
|
|
17
17
|
import { canonColor, colorOpacity } from "../../styles/canon/color.js";
|
|
18
18
|
import { canonEnum } from "../../styles/canon/enums.js";
|
|
19
|
-
import { canonNumber } from "../../styles/canon/number.js";
|
|
19
|
+
import { canonNumber, canonSigned, num6 } from "../../styles/canon/number.js";
|
|
20
20
|
import { MAX_STYLE_VALUE_LENGTH, noteAt, scalarText } from "../../styles/canon/site.js";
|
|
21
21
|
import { canonText } from "../../styles/canon/text.js";
|
|
22
22
|
import { STYLE_ISSUE } from "../../styles/codes.js";
|
|
23
|
-
import { CYTOSCAPE_LEXICON } from "../../styles/cytoscape/lexicon.js";
|
|
23
|
+
import { CYTOSCAPE_LEXICON, javaFamily } from "../../styles/cytoscape/lexicon.js";
|
|
24
24
|
import { StyleApproximations } from "../../styles/io/approximations.js";
|
|
25
|
-
import {
|
|
25
|
+
import { parseStyleBlock, STYLE_BLOCK_NAME, styleBlockLosses, styleTag, writeStyleBlock, } from "../../styles/io/block.js";
|
|
26
|
+
import { elementValues, takeFromBlock } from "../../styles/io/round-trip.js";
|
|
26
27
|
import { dataRead } from "../../styles/io/writer.js";
|
|
27
28
|
import { StyleNotes } from "../../styles/notes.js";
|
|
28
29
|
import { styleFingerprint } from "../../styles/plan/features.js";
|
|
29
|
-
import { plainCell
|
|
30
|
+
import { plainCell } from "../../styles/plan/resolve.js";
|
|
31
|
+
import { GRAPHVIZ_GLYPH_SHAPES } from "../dot/drawing.js";
|
|
32
|
+
import { graphvizArrowValue, graphvizHasNoOutline, graphvizOutline, graphvizRouteBends, PERIPHERY_GAP, putGlyph, SHAPE_PERIPHERIES, } from "../dot/styles.js";
|
|
30
33
|
import { gephiRules } from "../gexf/styles.js";
|
|
31
|
-
import {
|
|
34
|
+
import { configurationOutline, FONT_STYLES, valueColumns, YED_ARROWS, YED_LINES, YED_SHAPES, yedColor, yedFontName, yedSpelled, yedValue, } from "../graphml/styles-yed.js";
|
|
35
|
+
import { writtenByGv2gml } from "./positions.js";
|
|
32
36
|
import { KEY_MANGLED_CODE, mangleGmlKey } from "./syntax.js";
|
|
33
37
|
/** The writers recognized by their `Creator` text, first match wins. */
|
|
34
38
|
const WRITERS = [
|
|
@@ -55,7 +59,8 @@ const WRITERS = [
|
|
|
55
59
|
vocabulary: "graphlet",
|
|
56
60
|
spelling: "css",
|
|
57
61
|
units: "relative",
|
|
58
|
-
|
|
62
|
+
// Gephi's preview draws node labels as the GEXF reader reads them (formats/gexf/styles.ts)
|
|
63
|
+
labelKey: true,
|
|
59
64
|
},
|
|
60
65
|
],
|
|
61
66
|
[
|
|
@@ -77,6 +82,18 @@ const UNKNOWN_WRITER = {
|
|
|
77
82
|
units: "px",
|
|
78
83
|
labelKey: true,
|
|
79
84
|
};
|
|
85
|
+
/**
|
|
86
|
+
* Graphviz's gv2gml (no `Creator`; `version 2` inside the graph): Graphviz's attribute values (shape names, colors,
|
|
87
|
+
* arrow names, sizes in points, y up) under GML keys, with Graphviz's defaults beneath.
|
|
88
|
+
*/
|
|
89
|
+
const GV2GML_WRITER = {
|
|
90
|
+
dialect: "graphviz",
|
|
91
|
+
tool: "graphviz",
|
|
92
|
+
vocabulary: "graphviz",
|
|
93
|
+
spelling: "graphviz",
|
|
94
|
+
units: "px",
|
|
95
|
+
labelKey: true,
|
|
96
|
+
};
|
|
80
97
|
/** A file graphty wrote: yEd keys, and the `graphty.styles` block gives the rules. */
|
|
81
98
|
const GRAPHTY_WRITER = { ...WRITERS[0][1], tool: null };
|
|
82
99
|
/**
|
|
@@ -113,8 +130,27 @@ function graphText(snapshot, name) {
|
|
|
113
130
|
return typeof v === "number" ? String(v) : null;
|
|
114
131
|
}
|
|
115
132
|
/**
|
|
116
|
-
*
|
|
117
|
-
* the
|
|
133
|
+
* A node label's `anchor` as a label position: yEd's `n`, `s`, `e`, `w` and the corners `nw`, `ne`, `sw`, `se` place it
|
|
134
|
+
* outside the node; `c` and the inside places `t`, `b`, `l`, `r`, `tl`, `tr`, `bl`, `br` keep it inside, which graphty
|
|
135
|
+
* draws centered.
|
|
136
|
+
*/
|
|
137
|
+
const GML_ANCHORS = new Map([
|
|
138
|
+
...["c", "t", "b", "l", "r", "tl", "tr", "bl", "br"].map((a) => [a, "center"]),
|
|
139
|
+
["n", "top"],
|
|
140
|
+
["s", "bottom"],
|
|
141
|
+
["e", "right"],
|
|
142
|
+
["w", "left"],
|
|
143
|
+
["nw", "top-left"],
|
|
144
|
+
["ne", "top-right"],
|
|
145
|
+
["sw", "bottom-left"],
|
|
146
|
+
["se", "bottom-right"],
|
|
147
|
+
]);
|
|
148
|
+
/** Node keys only yEd writes: its group hierarchy. */
|
|
149
|
+
const YED_NODE_KEYS = ["isGroup", "gid"];
|
|
150
|
+
/**
|
|
151
|
+
* Who wrote a GML file: the `Creator` line (top level, or a key of the graph block as Gephi writes it), graphty when
|
|
152
|
+
* the file holds a `graphty.styles` block, or yEd when a file with no `Creator` holds keys only yEd writes (`isGroup`,
|
|
153
|
+
* `gid`, the graph's `hierarchic`).
|
|
118
154
|
* @param snapshot - the graph
|
|
119
155
|
* @returns the writer
|
|
120
156
|
*/
|
|
@@ -128,7 +164,12 @@ function writerOf(snapshot) {
|
|
|
128
164
|
return writer;
|
|
129
165
|
}
|
|
130
166
|
}
|
|
131
|
-
|
|
167
|
+
// keys only yEd writes name it even without a Creator line (BioNetGen writes yEd GML with none)
|
|
168
|
+
if (creator.trim() === "" &&
|
|
169
|
+
(YED_NODE_KEYS.some((k) => snapshot.nodes.has(k)) || snapshot.graph.has("hierarchic"))) {
|
|
170
|
+
return WRITERS[0][1];
|
|
171
|
+
}
|
|
172
|
+
return creator.trim() === "" && writtenByGv2gml(snapshot) ? GV2GML_WRITER : UNKNOWN_WRITER;
|
|
132
173
|
}
|
|
133
174
|
/** The edge's `arrow` key of the GML draft: which ends have an arrow. */
|
|
134
175
|
const ARROW_ENDS = new Map([
|
|
@@ -137,17 +178,63 @@ const ARROW_ENDS = new Map([
|
|
|
137
178
|
["first", ["triangle", "none"]],
|
|
138
179
|
["both", ["triangle", "triangle"]],
|
|
139
180
|
]);
|
|
140
|
-
/**
|
|
181
|
+
/**
|
|
182
|
+
* The node shape names Cytoscape's GML reader knows (NodeShapeVisualProperty, any case, with Cytoscape 2.x's `rect`
|
|
183
|
+
* and `round_rect`); any other name it ignores, so its default style's shape is drawn.
|
|
184
|
+
*/
|
|
185
|
+
const CYTOSCAPE_GML_SHAPES = new Map([
|
|
186
|
+
["ellipse", "ellipse"],
|
|
187
|
+
["round_rectangle", "round-rectangle"],
|
|
188
|
+
["round_rect", "round-rectangle"],
|
|
189
|
+
["rectangle", "rectangle"],
|
|
190
|
+
["rect", "rectangle"],
|
|
191
|
+
["hexagon", "hexagon"],
|
|
192
|
+
["octagon", "octagon"],
|
|
193
|
+
["parallelogram", "parallelogram"],
|
|
194
|
+
["triangle", "triangle"],
|
|
195
|
+
["vee", "vee"],
|
|
196
|
+
["diamond", "diamond"],
|
|
197
|
+
]);
|
|
198
|
+
/** OGDF's stroke types (`stipple`): by number as older OGDF writes them, or by name as GraphIO::writeGML does. */
|
|
141
199
|
const OGDF_STROKES = ["none", "solid", "dashed", "dotted", "dash-dot", "dash-dot"];
|
|
142
|
-
|
|
200
|
+
const OGDF_STROKE_NAMES = new Map([
|
|
201
|
+
["none", "none"],
|
|
202
|
+
["solid", "solid"],
|
|
203
|
+
["dash", "dashed"],
|
|
204
|
+
["dot", "dotted"],
|
|
205
|
+
["dashdot", "dash-dot"],
|
|
206
|
+
["dashdotdot", "dash-dot"],
|
|
207
|
+
]);
|
|
208
|
+
/** OGDF's shape names the common table does not know (an Image node without its image draws as its box). */
|
|
143
209
|
const OGDF_SHAPES = new Map([
|
|
144
210
|
["rect", "rectangle"],
|
|
211
|
+
["roundedrect", "round-rectangle"],
|
|
145
212
|
["rhomb", "diamond"],
|
|
146
|
-
["
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
213
|
+
["image", "rectangle"],
|
|
214
|
+
]);
|
|
215
|
+
/**
|
|
216
|
+
* OGDF's shapes that GraphIO::drawSVG draws as polygons no named shape matches, with their corners as `shapePoints`
|
|
217
|
+
* (fractions of the half width and height, y up), measured in its drawing of
|
|
218
|
+
* graph-io/test/fidelity/specimens/gml/specimen-node-shapes-p5.gml: the triangles, the pentagon, the hexagon and the
|
|
219
|
+
* octagon are regular, their corners on the ellipse of the node's box (so they are drawn where the points say, not
|
|
220
|
+
* stretched to the box: `OGDF_REGULAR`); the trapezes and parallelograms fill the box, their short side half its width.
|
|
221
|
+
*/
|
|
222
|
+
const OGDF_POLYGONS = new Map([
|
|
223
|
+
["triangle", "0,1 0.866,-0.5 -0.866,-0.5"],
|
|
224
|
+
["invtriangle", "0,-1 0.866,0.5 -0.866,0.5"],
|
|
225
|
+
["pentagon", "0,1 0.951,0.309 0.588,-0.809 -0.588,-0.809 -0.951,0.309"],
|
|
226
|
+
["hexagon", "1,0 0.5,0.866 -0.5,0.866 -1,0 -0.5,-0.866 0.5,-0.866"],
|
|
227
|
+
[
|
|
228
|
+
"octagon",
|
|
229
|
+
"0.924,0.383 0.383,0.924 -0.383,0.924 -0.924,0.383 -0.924,-0.383 -0.383,-0.924 0.383,-0.924 0.924,-0.383",
|
|
230
|
+
],
|
|
231
|
+
["trapeze", "-1,-1 1,-1 0.5,1 -0.5,1"],
|
|
232
|
+
["invtrapeze", "-1,1 1,1 0.5,-1 -0.5,-1"],
|
|
233
|
+
["parallelogram", "-1,-1 0.5,-1 1,1 -0.5,1"],
|
|
234
|
+
["invparallelogram", "-1,1 0.5,1 1,-1 -0.5,-1"],
|
|
150
235
|
]);
|
|
236
|
+
/** OGDF's regular polygons, whose corners lie on the ellipse of the node's box rather than reaching its sides. */
|
|
237
|
+
const OGDF_REGULAR = new Set(["triangle", "invtriangle", "pentagon", "hexagon", "octagon"]);
|
|
151
238
|
/** Keys only yEd writes in a label record: its `fill` is the label's background, not the text color. */
|
|
152
239
|
const YED_LABEL_KEYS = [
|
|
153
240
|
"outline",
|
|
@@ -228,15 +315,45 @@ function strokeStyle(raw, kind, writer, at) {
|
|
|
228
315
|
return null;
|
|
229
316
|
}
|
|
230
317
|
if (writer.vocabulary === "ogdf") {
|
|
231
|
-
const stroke =
|
|
232
|
-
if (stroke === undefined
|
|
318
|
+
const stroke = ogdfStroke(raw);
|
|
319
|
+
if (stroke === undefined) {
|
|
233
320
|
noteAt(at, STYLE_ISSUE.UNKNOWN_VALUE, sampleOf(raw));
|
|
234
321
|
return null;
|
|
235
322
|
}
|
|
236
|
-
|
|
323
|
+
// stroke "none" draws no line at all: the callers turn the border or the edge off
|
|
324
|
+
return stroke === "none" ? null : stroke;
|
|
237
325
|
}
|
|
238
326
|
return canonEnum(kind, raw, writer.spelling, at);
|
|
239
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* An OGDF `stipple`: a StrokeType by number or by name.
|
|
330
|
+
* @param raw - the value
|
|
331
|
+
* @returns the line style, "none", or undefined for a value OGDF does not know
|
|
332
|
+
*/
|
|
333
|
+
function ogdfStroke(raw) {
|
|
334
|
+
const text = typeof raw === "string" || typeof raw === "number" ? String(raw).trim() : "";
|
|
335
|
+
return /^\d+$/.test(text) ? OGDF_STROKES[Number(text)] : OGDF_STROKE_NAMES.get(text.toLowerCase());
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Reads an OGDF node `type` (a Shape name): a polygon where OGDF draws one, else the shape it names.
|
|
339
|
+
* @param raw - the value
|
|
340
|
+
* @param writer - the writer
|
|
341
|
+
* @param put - receives the values
|
|
342
|
+
* @param at - the sites
|
|
343
|
+
*/
|
|
344
|
+
function readOgdfShape(raw, writer, put, at) {
|
|
345
|
+
const name = raw.trim().toLowerCase();
|
|
346
|
+
const points = OGDF_POLYGONS.get(name);
|
|
347
|
+
if (points !== undefined) {
|
|
348
|
+
put("shape", "polygon");
|
|
349
|
+
put("shapePoints", points);
|
|
350
|
+
if (OGDF_REGULAR.has(name)) {
|
|
351
|
+
put("shapePointsStretch", false);
|
|
352
|
+
}
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
put("shape", canonEnum("shape", OGDF_SHAPES.get(name) ?? raw, writer.spelling, at("shape")));
|
|
356
|
+
}
|
|
240
357
|
/**
|
|
241
358
|
* Reads one node's `graphics` record.
|
|
242
359
|
* @param g - the record
|
|
@@ -246,18 +363,190 @@ function strokeStyle(raw, kind, writer, at) {
|
|
|
246
363
|
*/
|
|
247
364
|
function readNodeGraphics(g, writer, put, at) {
|
|
248
365
|
const v = writer.vocabulary;
|
|
366
|
+
if (v === "graphviz") {
|
|
367
|
+
readGv2gmlNode(g, writer, put, at);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
249
370
|
readNodeFill(g, writer, put, at);
|
|
250
371
|
readNodeOutline(g, writer, put, at);
|
|
251
372
|
put("borderStyle", strokeStyle(v === "ogdf" ? g.stipple : g.outlineStyle, "borderStyle", writer, at("borderStyle")));
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
373
|
+
if (v === "ogdf" && g.stipple !== undefined && ogdfStroke(g.stipple) === "none") {
|
|
374
|
+
put("borderWidth", 0);
|
|
375
|
+
}
|
|
376
|
+
readNodeSize(g, writer, put, at);
|
|
377
|
+
if (v === "ogdf") {
|
|
378
|
+
readOgdfLabelOffset(g.label, put, at);
|
|
379
|
+
}
|
|
380
|
+
readNodeShape(g, writer, put, at);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Reads a node's size from its `graphics` record.
|
|
384
|
+
* @param g - the record
|
|
385
|
+
* @param writer - the writer
|
|
386
|
+
* @param put - receives the values
|
|
387
|
+
* @param at - the sites
|
|
388
|
+
*/
|
|
389
|
+
function readNodeSize(g, writer, put, at) {
|
|
390
|
+
if (writer.tool === "gephi") {
|
|
391
|
+
// Gephi's w is a node's size, a radius: its disc is twice as wide, and its h is never read
|
|
392
|
+
const size = g.w === undefined ? null : canonNumber(g.w, at("width"));
|
|
393
|
+
put("width", size === null ? null : 2 * size);
|
|
394
|
+
put("height", size === null ? null : 2 * size);
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
put("width", g.w === undefined ? null : canonNumber(g.w, at("width")));
|
|
398
|
+
put("height", g.h === undefined ? null : canonNumber(g.h, at("height")));
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Reads a node's shape from its `graphics` record, in the writer's vocabulary.
|
|
403
|
+
* @param g - the record
|
|
404
|
+
* @param writer - the writer
|
|
405
|
+
* @param put - receives the values
|
|
406
|
+
* @param at - the sites
|
|
407
|
+
*/
|
|
408
|
+
function readNodeShape(g, writer, put, at) {
|
|
409
|
+
const v = writer.vocabulary;
|
|
410
|
+
if (v === "ogdf" && typeof g.type === "string") {
|
|
411
|
+
readOgdfShape(g.type, writer, put, at);
|
|
412
|
+
}
|
|
413
|
+
else if (v === "cytoscape" && g.type !== undefined) {
|
|
414
|
+
const name = scalarText(g.type, at("shape"))?.trim().toLowerCase() ?? "";
|
|
415
|
+
const shape = CYTOSCAPE_GML_SHAPES.get(name);
|
|
416
|
+
if (shape === undefined) {
|
|
417
|
+
noteAt(at("shape"), STYLE_ISSUE.UNKNOWN_VALUE, name.slice(0, MAX_STYLE_VALUE_LENGTH));
|
|
418
|
+
}
|
|
419
|
+
put("shape", shape ?? null);
|
|
420
|
+
}
|
|
421
|
+
else if (g.type !== undefined) {
|
|
422
|
+
put("shape", canonEnum("shape", g.type, writer.spelling, at("shape")));
|
|
257
423
|
}
|
|
258
424
|
else if (v === "yed" && typeof g.customconfiguration === "string") {
|
|
259
425
|
// yEd's flowchart palette keeps a node's shape as a configuration, not a `type`.
|
|
260
|
-
|
|
426
|
+
const outline = configurationOutline(g.customconfiguration);
|
|
427
|
+
put("shape", outline?.shape ?? null);
|
|
428
|
+
if (outline?.points !== undefined) {
|
|
429
|
+
put("shapePoints", outline.points);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Reads where OGDF draws a node's label: GraphIO::writeGML writes the label's center as an offset from the node's
|
|
435
|
+
* center (`graphics [ label [ x y z ] ]`, GraphAttributes::xLabel / yLabel, y down), and GraphIO::drawSVG draws it there.
|
|
436
|
+
* @param label - the graphics record's `label` value
|
|
437
|
+
* @param put - receives the values
|
|
438
|
+
* @param at - the sites
|
|
439
|
+
*/
|
|
440
|
+
function readOgdfLabelOffset(label, put, at) {
|
|
441
|
+
if (typeof label !== "object" || label === null || Array.isArray(label)) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
const { x, y } = label;
|
|
445
|
+
put("labelOffsetX", x === undefined ? null : canonSigned(x, at("labelOffsetX")));
|
|
446
|
+
put("labelOffsetY", y === undefined ? null : canonSigned(y, at("labelOffsetY")));
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Reads one node's `graphics` record as Graphviz's gv2gml writes it (cmd/tools/gv2gml.c emitNodeAttrs): `fill` is the
|
|
450
|
+
* node's `fillcolor` (or its `color`), drawn only where `hasFill 1` says `style=filled`; `outline` its pen color,
|
|
451
|
+
* `width` its pen width, `w` and `H` its size in points, `type` its Graphviz shape, `visible 0` its `style=invis`.
|
|
452
|
+
* @param g - the record
|
|
453
|
+
* @param writer - the writer
|
|
454
|
+
* @param put - receives the values
|
|
455
|
+
* @param at - the sites
|
|
456
|
+
*/
|
|
457
|
+
function readGv2gmlNode(g, writer, put, at) {
|
|
458
|
+
const shape = typeof g.type === "string" ? g.type.trim().toLowerCase() : "";
|
|
459
|
+
if (Number(g.hasFill) === 1 || shape === "point") {
|
|
460
|
+
// filled: the opacity is stated even when opaque, over Graphviz's default of no fill
|
|
461
|
+
const c = canonColor(g.fill ?? "black", writer.spelling, at("fill"), { use: "fill" });
|
|
462
|
+
put("fill", c?.color ?? null);
|
|
463
|
+
put("fillOpacity", c?.alpha ?? null);
|
|
464
|
+
}
|
|
465
|
+
else if (g.fill !== undefined) {
|
|
466
|
+
// Graphviz draws an unfilled node's inside see-through (the tool default), whatever its color
|
|
467
|
+
noteAt(at("fill"), STYLE_ISSUE.UNFILLED, sampleOf(g.fill));
|
|
468
|
+
}
|
|
469
|
+
if (graphvizHasNoOutline(shape)) {
|
|
470
|
+
put("borderWidth", 0);
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
readColor(g.outline, "borderColor", null, writer, put, at);
|
|
474
|
+
put("borderWidth", g.width === undefined ? null : canonNumber(g.width, at("borderWidth")));
|
|
475
|
+
}
|
|
476
|
+
const borderStyle = strokeStyle(g.outlineStyle, "borderStyle", writer, at("borderStyle"));
|
|
477
|
+
put("borderStyle", borderStyle);
|
|
478
|
+
readGv2gmlRings(g, shape, borderStyle, writer, put, at);
|
|
479
|
+
// gv2gml's w and H are the node's outer size: Graphviz draws each further outline PERIPHERY_GAP outside the one
|
|
480
|
+
// within, so graphty's node (the innermost outline, its ring outside it) is that much smaller
|
|
481
|
+
const rings = 2 * PERIPHERY_GAP * ((SHAPE_PERIPHERIES.get(shape) ?? 1) - 1);
|
|
482
|
+
const inner = (raw, property) => {
|
|
483
|
+
const n = raw === undefined ? null : canonNumber(raw, at(property));
|
|
484
|
+
return n === null ? null : Math.max(0, n - rings);
|
|
485
|
+
};
|
|
486
|
+
put("width", inner(g.w, "width"));
|
|
487
|
+
// gv2gml writes the height as H (gv2gml.c emitReal("H", ...)); h where a later edit spelled it as GML does
|
|
488
|
+
put("height", inner(first(g, "H", "h"), "height"));
|
|
489
|
+
if (Number(g.visible) === 0 && g.visible !== undefined) {
|
|
490
|
+
put("visible", false);
|
|
491
|
+
}
|
|
492
|
+
const outline = graphvizOutline(shape);
|
|
493
|
+
if (shape === "polygon") {
|
|
494
|
+
// ponytail: Graphviz's polygon is a box unless its sides, skew or distortion say otherwise; gv2gml copies
|
|
495
|
+
// those as node keys beside graphics, which this record does not see. Read them when a file has them.
|
|
496
|
+
put("shape", "rectangle");
|
|
497
|
+
}
|
|
498
|
+
else if (outline !== undefined) {
|
|
499
|
+
put("shape", "polygon");
|
|
500
|
+
put("shapePoints", outline);
|
|
501
|
+
// a Graphviz polygon's corners are where Graphviz draws them, as the DOT reader reads them
|
|
502
|
+
put("shapePointsStretch", false);
|
|
503
|
+
}
|
|
504
|
+
else if (GRAPHVIZ_GLYPH_SHAPES.has(shape)) {
|
|
505
|
+
const size = (raw, property) => raw === undefined ? null : canonNumber(raw, at(property));
|
|
506
|
+
putGlyph(shape, size(g.w, "width"), size(first(g, "H", "h"), "height"), put, () => {
|
|
507
|
+
const pen = g.width === undefined ? 1 : Number(g.width);
|
|
508
|
+
return Number.isFinite(pen) ? Math.max(0, pen) : 1;
|
|
509
|
+
}, () => canonColor(g.outline ?? "black", writer.spelling, at("outerBorderColor"), { use: "line" })?.color ??
|
|
510
|
+
null);
|
|
511
|
+
}
|
|
512
|
+
else if (g.type !== undefined) {
|
|
513
|
+
put("shape", canonEnum("shape", g.type, "graphviz", at("shape")));
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Reads the second outline Graphviz draws round a `doublecircle`, `doubleoctagon` or `tripleoctagon` (shapes.c):
|
|
518
|
+
* `PERIPHERY_GAP` points outside the first, in its color, width and dashes, as the DOT reader reads it. graphty draws
|
|
519
|
+
* one outer ring, so a third outline is noted as not carried.
|
|
520
|
+
* @param g - the record
|
|
521
|
+
* @param shape - its Graphviz shape, lowercase
|
|
522
|
+
* @param style - its outline's dashes, as read
|
|
523
|
+
* @param writer - the writer
|
|
524
|
+
* @param put - receives the values
|
|
525
|
+
* @param at - the sites
|
|
526
|
+
*/
|
|
527
|
+
function readGv2gmlRings(g, shape, style, writer, put, at) {
|
|
528
|
+
// ponytail: gv2gml copies a `peripheries` attribute as a node key beside graphics, which this record does not
|
|
529
|
+
// see; the shapes' own outlines are read. Read the key when a file sets it.
|
|
530
|
+
const count = SHAPE_PERIPHERIES.get(shape) ?? 1;
|
|
531
|
+
if (count < 2) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const c = canonColor(g.outline ?? "black", writer.spelling, at("outerBorderColor"), { use: "line" });
|
|
535
|
+
if (c !== null && c.alpha === 0) {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
const parsed = g.width === undefined ? 1 : Number(g.width);
|
|
539
|
+
const pen = Number.isFinite(parsed) ? Math.max(0, parsed) : 1;
|
|
540
|
+
put("outerBorderColor", c?.color ?? "#000000");
|
|
541
|
+
put("outerBorderOpacity", c !== null && c.alpha < 1 ? c.alpha : null);
|
|
542
|
+
put("outerBorderWidth", pen);
|
|
543
|
+
// the gap between the outline's outer edge and the ring's inner edge
|
|
544
|
+
put("outerBorderOffset", Math.max(0, PERIPHERY_GAP - pen));
|
|
545
|
+
if (style === "dashed" || style === "dotted") {
|
|
546
|
+
put("outerBorderStyle", style);
|
|
547
|
+
}
|
|
548
|
+
if (count > 2) {
|
|
549
|
+
noteAt(at("outerBorderWidth"), STYLE_ISSUE.NOT_CARRIED, `type ${shape}`);
|
|
261
550
|
}
|
|
262
551
|
}
|
|
263
552
|
/**
|
|
@@ -291,7 +580,8 @@ function readNodeOutline(g, writer, put, at) {
|
|
|
291
580
|
put("borderWidth", 0);
|
|
292
581
|
return;
|
|
293
582
|
}
|
|
294
|
-
|
|
583
|
+
// OGDF's GraphIO::writeGML writes the stroke color as `outline`; older OGDF wrote `line`
|
|
584
|
+
readColor(v === "ogdf" ? first(g, "outline", "line") : g.outline, "borderColor", null, writer, put, at);
|
|
295
585
|
const width = outlineWidthOf(g, v);
|
|
296
586
|
put("borderWidth", width === undefined ? null : canonNumber(width, at("borderWidth")));
|
|
297
587
|
}
|
|
@@ -322,10 +612,31 @@ function outlineWidthOf(g, v) {
|
|
|
322
612
|
*/
|
|
323
613
|
function readEdgeGraphics(g, writer, put, at) {
|
|
324
614
|
const v = writer.vocabulary;
|
|
615
|
+
if (v === "graphviz") {
|
|
616
|
+
readGv2gmlEdge(g, writer, put, at);
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
325
619
|
readColor(g.fill, "color", "opacity", writer, put, at);
|
|
326
620
|
const width = v === "ogdf" ? first(g, "lineWidth", "width") : g.width;
|
|
327
621
|
put("width", width === undefined ? null : canonNumber(width, at("width")));
|
|
328
622
|
put("lineStyle", strokeStyle(v === "ogdf" ? g.stipple : g.style, "lineStyle", writer, at("lineStyle")));
|
|
623
|
+
if (v === "ogdf" && g.stipple !== undefined && ogdfStroke(g.stipple) === "none") {
|
|
624
|
+
put("visible", false);
|
|
625
|
+
}
|
|
626
|
+
readEdgeArrows(g, writer, put, at);
|
|
627
|
+
if (v === "yed") {
|
|
628
|
+
readYedCurve(g, put);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Reads an edge's arrows from its `graphics` record: `arrow` names the ends that have one, and `sourceArrow` and
|
|
633
|
+
* `targetArrow` (or their snake-case spellings) name each end's arrow.
|
|
634
|
+
* @param g - the record
|
|
635
|
+
* @param writer - the writer
|
|
636
|
+
* @param put - receives the values
|
|
637
|
+
* @param at - the sites
|
|
638
|
+
*/
|
|
639
|
+
function readEdgeArrows(g, writer, put, at) {
|
|
329
640
|
if (typeof g.arrow === "string") {
|
|
330
641
|
const ends = ARROW_ENDS.get(g.arrow.trim().toLowerCase());
|
|
331
642
|
if (ends === undefined) {
|
|
@@ -344,13 +655,68 @@ function readEdgeGraphics(g, writer, put, at) {
|
|
|
344
655
|
if (raw === undefined) {
|
|
345
656
|
continue;
|
|
346
657
|
}
|
|
347
|
-
put(property,
|
|
658
|
+
put(property, writer.vocabulary === "cytoscape" && cytoscapeArrow !== undefined
|
|
348
659
|
? cytoscapeArrow(raw, at(property))
|
|
349
660
|
: canonEnum("arrow", raw, writer.spelling, at(property)));
|
|
350
661
|
}
|
|
351
|
-
|
|
352
|
-
|
|
662
|
+
}
|
|
663
|
+
/** gv2gml's `arrow`, from Graphviz's `dir`: `first` is `dir=forward` (the head's arrow), `last` is `dir=back`. */
|
|
664
|
+
const GV2GML_DIRECTIONS = new Map([
|
|
665
|
+
["first", [false, true]],
|
|
666
|
+
["last", [true, false]],
|
|
667
|
+
["both", [true, true]],
|
|
668
|
+
["none", [false, false]],
|
|
669
|
+
]);
|
|
670
|
+
/**
|
|
671
|
+
* Reads one edge's `graphics` record as Graphviz's gv2gml writes it (gv2gml.c emitEdgeAttrs): `fill` its color,
|
|
672
|
+
* `width` its pen width (2 for `style=bold`), `style` its dashes, `visible 0` its `style=invis`, `targetArrow` and
|
|
673
|
+
* `sourceArrow` its `arrowhead` and `arrowtail`, and `arrow` its `dir`. With none of the arrow keys an edge of a
|
|
674
|
+
* directed graph has Graphviz's default arrowhead, and one of an undirected graph none.
|
|
675
|
+
* @param g - the record
|
|
676
|
+
* @param writer - the writer
|
|
677
|
+
* @param put - receives the values
|
|
678
|
+
* @param at - the sites
|
|
679
|
+
*/
|
|
680
|
+
function readGv2gmlEdge(g, writer, put, at) {
|
|
681
|
+
readColor(g.fill, "color", "opacity", writer, put, at);
|
|
682
|
+
put("width", g.width === undefined ? null : canonNumber(g.width, at("width")));
|
|
683
|
+
put("lineStyle", strokeStyle(g.style, "lineStyle", writer, at("lineStyle")));
|
|
684
|
+
if (Number(g.visible) === 0 && g.visible !== undefined) {
|
|
685
|
+
put("visible", false);
|
|
686
|
+
}
|
|
687
|
+
const ends = gv2gmlArrowEnds(g, writer.directed === true);
|
|
688
|
+
if (ends === null) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
for (const [end, raw, on] of [
|
|
692
|
+
["target", g.targetArrow, ends[1]],
|
|
693
|
+
["source", g.sourceArrow, ends[0]],
|
|
694
|
+
]) {
|
|
695
|
+
const name = typeof raw === "string" ? raw : "normal";
|
|
696
|
+
const arrow = on ? graphvizArrowValue(name, at(`${end}Arrow`)) : null;
|
|
697
|
+
put(`${end}Arrow`, arrow === null ? "none" : arrow.value);
|
|
698
|
+
if (arrow?.side !== null && arrow?.side !== undefined) {
|
|
699
|
+
put(`${end}ArrowSide`, arrow.side);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Which ends of a gv2gml edge Graphviz draws an arrow at, as its `dir` says (forward in a directed graph when the
|
|
705
|
+
* record names no arrow), or null for an undirected graph's edge that names none.
|
|
706
|
+
* @param g - the edge's `graphics` record
|
|
707
|
+
* @param directed - whether the graph is directed (its `dir` defaults to forward)
|
|
708
|
+
* @returns [source, target], or null
|
|
709
|
+
*/
|
|
710
|
+
function gv2gmlArrowEnds(g, directed) {
|
|
711
|
+
if (g.arrow === undefined && g.targetArrow === undefined && g.sourceArrow === undefined) {
|
|
712
|
+
// Graphviz's dir is forward in a digraph and its arrowhead normal: gv2gml writes neither when unset
|
|
713
|
+
return directed ? [false, true] : null;
|
|
714
|
+
}
|
|
715
|
+
let dir = directed ? "first" : "none";
|
|
716
|
+
if (typeof g.arrow === "string") {
|
|
717
|
+
dir = g.arrow.trim().toLowerCase();
|
|
353
718
|
}
|
|
719
|
+
return GV2GML_DIRECTIONS.get(dir) ?? null;
|
|
354
720
|
}
|
|
355
721
|
/**
|
|
356
722
|
* Reads whether yEd draws an edge curved: `smoothBends` rounds the bends of its `Line`, whose points run from the
|
|
@@ -368,10 +734,11 @@ function readYedCurve(g, put) {
|
|
|
368
734
|
* Reads an element's label records: the first visible one with text; further visible ones are noted.
|
|
369
735
|
* @param raw - the `LabelGraphics` value (one record or several)
|
|
370
736
|
* @param writer - the writer
|
|
737
|
+
* @param node - whether the label is a node's: its `anchor` places it (`c`, `n`, `t`, `se`, ...)
|
|
371
738
|
* @param put - receives the values
|
|
372
739
|
* @param at - the sites
|
|
373
740
|
*/
|
|
374
|
-
function readLabelGraphics(raw, writer, put, at) {
|
|
741
|
+
function readLabelGraphics(raw, writer, node, put, at) {
|
|
375
742
|
const visible = (Array.isArray(raw) ? raw : [raw]).filter((l) => isRec(l) && Number(l.visible) !== 0);
|
|
376
743
|
const lg = visible.at(0);
|
|
377
744
|
if (lg === undefined) {
|
|
@@ -382,12 +749,13 @@ function readLabelGraphics(raw, writer, put, at) {
|
|
|
382
749
|
noteAt(at("label"), STYLE_ISSUE.EXTRA_LABELS, `${String(extra + 1)} labels`);
|
|
383
750
|
}
|
|
384
751
|
if (lg.text !== undefined) {
|
|
385
|
-
put("label", canonText(lg.text, at("label")));
|
|
752
|
+
put("label", writer.vocabulary === "graphviz" ? graphvizText(lg.text, at("label")) : canonText(lg.text, at("label")));
|
|
386
753
|
}
|
|
387
754
|
// the GML draft's `fill` is the text color; yEd's is the label's background box, its `color` the text color
|
|
388
755
|
const yedLabel = writer.vocabulary === "yed" || YED_LABEL_KEYS.some((k) => Object.hasOwn(lg, k));
|
|
389
|
-
if (lg.color !== undefined) {
|
|
390
|
-
|
|
756
|
+
if (lg.color !== undefined || lg.fontColor !== undefined) {
|
|
757
|
+
// gv2gml writes a label's fontcolor as fontColor (as color with -y); yEd's #RRGGBBAA alpha is the words'
|
|
758
|
+
readColor(lg.color ?? lg.fontColor, "labelColor", "labelOpacity", writer, put, at);
|
|
391
759
|
}
|
|
392
760
|
else if (lg.fill !== undefined && !yedLabel) {
|
|
393
761
|
readColor(lg.fill, "labelColor", null, writer, put, at);
|
|
@@ -395,17 +763,39 @@ function readLabelGraphics(raw, writer, put, at) {
|
|
|
395
763
|
if (lg.fill !== undefined && yedLabel) {
|
|
396
764
|
noteAt(at("label"), STYLE_ISSUE.NOT_CARRIED, "label background");
|
|
397
765
|
}
|
|
398
|
-
|
|
766
|
+
// yEd and Cytoscape are Java programs: a Java logical font (Dialog, SansSerif, ...) is drawn in Java's face for it
|
|
767
|
+
readLabelFont(lg, yedLabel || writer.vocabulary === "cytoscape", put, at);
|
|
768
|
+
if (node && lg.anchor !== undefined) {
|
|
769
|
+
const anchor = scalarText(lg.anchor, at("labelPosition"))?.trim().toLowerCase() ?? "";
|
|
770
|
+
const known = GML_ANCHORS.get(anchor);
|
|
771
|
+
if (known === undefined) {
|
|
772
|
+
noteAt(at("labelPosition"), STYLE_ISSUE.UNKNOWN_VALUE, anchor.slice(0, MAX_STYLE_VALUE_LENGTH));
|
|
773
|
+
}
|
|
774
|
+
put("labelPosition", known ?? null);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* A label's text as Graphviz draws it: gv2gml copies a DOT label as written, so its line breaks are still the escapes
|
|
779
|
+
* `\n`, `\l` and `\r` (centered, left and right lines, drawn here as plain line breaks).
|
|
780
|
+
* @param raw - the text
|
|
781
|
+
* @param at - the site
|
|
782
|
+
* @returns the text
|
|
783
|
+
*/
|
|
784
|
+
function graphvizText(raw, at) {
|
|
785
|
+
const text = canonText(raw, at);
|
|
786
|
+
return text === null ? null : text.replaceAll(/\\[nlr]/g, "\n").replace(/\n$/, "");
|
|
399
787
|
}
|
|
400
788
|
/**
|
|
401
789
|
* Reads a label record's font: its size, name, weight and slant.
|
|
402
790
|
* @param lg - the record
|
|
791
|
+
* @param java - whether a Java program wrote it, whose logical font names are drawn in Java's faces
|
|
403
792
|
* @param put - receives the values
|
|
404
793
|
* @param at - the sites
|
|
405
794
|
*/
|
|
406
|
-
function readLabelFont(lg, put, at) {
|
|
795
|
+
function readLabelFont(lg, java, put, at) {
|
|
407
796
|
put("labelSize", lg.fontSize === undefined ? null : canonNumber(lg.fontSize, at("labelSize")));
|
|
408
|
-
|
|
797
|
+
const font = lg.fontName === undefined ? null : canonText(lg.fontName, at("labelFont"));
|
|
798
|
+
put("labelFont", java && typeof font === "string" ? javaFamily(font) : font);
|
|
409
799
|
const style = scalarText(lg.fontStyle, at("labelWeight"))?.trim().toLowerCase();
|
|
410
800
|
if (style !== undefined) {
|
|
411
801
|
const known = FONT_STYLES.get(style);
|
|
@@ -438,13 +828,81 @@ function readElement(target, g, lg, label, writer, put, at) {
|
|
|
438
828
|
(target === "node" ? readNodeGraphics : readEdgeGraphics)(g, writer, put, at);
|
|
439
829
|
}
|
|
440
830
|
if (lg !== null && lg !== undefined) {
|
|
441
|
-
readLabelGraphics(lg, writer, putLabel, at);
|
|
831
|
+
readLabelGraphics(lg, writer, target === "node", putLabel, at);
|
|
442
832
|
}
|
|
443
833
|
// the GML draft draws the label key; Cytoscape reads it as the node's name, which its default style shows
|
|
444
834
|
const drawn = writer.vocabulary === "cytoscape" ? target === "node" : writer.labelKey && (isRec(g) || lg !== undefined);
|
|
445
835
|
if (!text && drawn && label !== null && label !== undefined) {
|
|
446
|
-
put("label", canonText(label, at("label")));
|
|
836
|
+
put("label", writer.vocabulary === "graphviz" ? graphvizText(label, at("label")) : canonText(label, at("label")));
|
|
837
|
+
// the GML draft names no place for a node's label; a plain GML file's is centered on its node, as OGDF and
|
|
838
|
+
// Cytoscape draw it (yEd's GML keeps its own label models, in LabelGraphics)
|
|
839
|
+
if (target === "node" && writer.tool === null && writer.vocabulary === "graphlet") {
|
|
840
|
+
put("labelPosition", "center");
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
/** The font size GraphIO::drawSVG draws every label in (SVGSettings), by which it sets a cluster's label off its box. */
|
|
845
|
+
const OGDF_SVG_FONT_SIZE = 10;
|
|
846
|
+
/**
|
|
847
|
+
* Places each OGDF cluster's label where GraphIO::drawSVG draws it (SvgPrinter::drawCluster): one font size below the
|
|
848
|
+
* cluster's box where more of the drawing lies below it than above, else above it; starting at the box's left side
|
|
849
|
+
* where more of the drawing lies left of it than right, else ending at its right side. The importer reads a cluster as
|
|
850
|
+
* a group node with the id `cluster<id>`; its box is its center and its `w` and `h`.
|
|
851
|
+
* @param snapshot - the graph
|
|
852
|
+
* @param values - the node values read so far, given the label's place
|
|
853
|
+
*/
|
|
854
|
+
function placeOgdfClusterLabels(snapshot, values) {
|
|
855
|
+
const n = snapshot.nodeCount;
|
|
856
|
+
const boxOf = (i) => {
|
|
857
|
+
const [x, y] = centerOf(snapshot, i);
|
|
858
|
+
const [w, h] = sizeOf(snapshot, i);
|
|
859
|
+
return [x - w / 2, y - h / 2, x + w / 2, y + h / 2];
|
|
860
|
+
};
|
|
861
|
+
// ponytail: drawSVG's bounding box also holds the edges' bends; nodes and clusters decide every sheet so far
|
|
862
|
+
const all = [Infinity, Infinity, -Infinity, -Infinity];
|
|
863
|
+
for (let i = 0; i < n; i++) {
|
|
864
|
+
const b = boxOf(i);
|
|
865
|
+
if (b.every(Number.isFinite)) {
|
|
866
|
+
all[0] = Math.min(all[0], b[0]);
|
|
867
|
+
all[1] = Math.min(all[1], b[1]);
|
|
868
|
+
all[2] = Math.max(all[2], b[2]);
|
|
869
|
+
all[3] = Math.max(all[3], b[3]);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
const put = (property, i, value) => {
|
|
873
|
+
values[property] ?? (values[property] = new Array(n).fill(null));
|
|
874
|
+
values[property][i] = value;
|
|
875
|
+
};
|
|
876
|
+
for (let i = 0; i < n; i++) {
|
|
877
|
+
const id = snapshot.ids.idOf(i);
|
|
878
|
+
const [x0, y0, x1, y1] = boxOf(i);
|
|
879
|
+
if (typeof id !== "string" || !id.startsWith("cluster") || ![x0, y0, x1, y1].every(Number.isFinite)) {
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
const below = all[3] - y1 > y0 - all[1];
|
|
883
|
+
const start = x0 - all[0] > all[2] - x1;
|
|
884
|
+
put("labelPosition", i, "center");
|
|
885
|
+
put("labelOffsetX", i, ((start ? -1 : 1) * (x1 - x0)) / 2);
|
|
886
|
+
put("labelShiftX", i, start ? 0.5 : -0.5);
|
|
887
|
+
put("labelOffsetY", i, (below ? 1 : -1) * ((y1 - y0) / 2 + OGDF_SVG_FONT_SIZE));
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* An element's `label` key. Cytoscape's GML reader names a node by its label and, where the label is empty or
|
|
892
|
+
* missing, by its id, and its default style draws that name.
|
|
893
|
+
* @param snapshot - the graph
|
|
894
|
+
* @param writer - the writer
|
|
895
|
+
* @param target - nodes or edges
|
|
896
|
+
* @param i - the row
|
|
897
|
+
* @returns the label
|
|
898
|
+
*/
|
|
899
|
+
function labelOf(snapshot, writer, target, i) {
|
|
900
|
+
const table = target === "node" ? snapshot.nodes : snapshot.edges;
|
|
901
|
+
const label = cellOf(table, "label", i);
|
|
902
|
+
if (writer.vocabulary === "cytoscape" && target === "node" && (label === undefined || label === "")) {
|
|
903
|
+
return String(snapshot.ids.idOf(i));
|
|
447
904
|
}
|
|
905
|
+
return label;
|
|
448
906
|
}
|
|
449
907
|
/**
|
|
450
908
|
* The value of a column, or undefined when the table has no such column.
|
|
@@ -472,20 +930,180 @@ function centerOf(snapshot, i) {
|
|
|
472
930
|
return v === null ? [Number.NaN, Number.NaN] : [v[0], v[1]];
|
|
473
931
|
}
|
|
474
932
|
/**
|
|
475
|
-
*
|
|
476
|
-
*
|
|
933
|
+
* A node's width and height: its `graphics` `w` and `h`.
|
|
934
|
+
* @param snapshot - the graph
|
|
935
|
+
* @param i - the node's index
|
|
936
|
+
* @returns the size; NaN where the node has none
|
|
937
|
+
*/
|
|
938
|
+
function sizeOf(snapshot, i) {
|
|
939
|
+
const g = cellOf(snapshot.nodes, "graphics", i);
|
|
940
|
+
return isRec(g) ? [Number(g.w ?? Number.NaN), Number(g.h ?? Number.NaN)] : [Number.NaN, Number.NaN];
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* An edge's route from its `graphics` `Line`, whose first and last points are where it attaches to its source and
|
|
944
|
+
* target (its ports: the centers unless yEd moved them) and whose points between are its bends: the bends relative to
|
|
945
|
+
* the two node centers (a self-loop's to its node's size), and each port off its node's center relative to the node.
|
|
946
|
+
* OGDF's `Line` holds the bends alone (GraphIO::writeGML writes no end point).
|
|
477
947
|
* @param snapshot - the graph
|
|
478
948
|
* @param g - the edge's `graphics` value
|
|
479
949
|
* @param e - the edge's row
|
|
480
|
-
* @
|
|
950
|
+
* @param bendsOnly - whether the points are the bends alone (OGDF)
|
|
951
|
+
* @param put - receives the values
|
|
481
952
|
*/
|
|
482
|
-
function
|
|
953
|
+
function readLineRoute(snapshot, g, e, bendsOnly, put) {
|
|
483
954
|
const raw = isRec(g) && isRec(g.Line) ? g.Line.point : undefined;
|
|
484
|
-
|
|
485
|
-
|
|
955
|
+
const list = isRec(raw) ? [raw] : raw;
|
|
956
|
+
if (!Array.isArray(list) || list.length < (bendsOnly ? 1 : 2)) {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
const all = list.map((p) => (isRec(p) ? [Number(p.x), Number(p.y)] : [Number.NaN, 0]));
|
|
960
|
+
const [s, t] = [snapshot.edgeSource(e), snapshot.edgeTarget(e)];
|
|
961
|
+
const points = bendsOnly ? all : all.slice(1, -1);
|
|
962
|
+
const bends = s === t
|
|
963
|
+
? canonNodeOffsets(centerOf(snapshot, s), sizeOf(snapshot, s), points, true)
|
|
964
|
+
: canonBends(centerOf(snapshot, s), centerOf(snapshot, t), points, true);
|
|
965
|
+
if (bends !== null) {
|
|
966
|
+
put("bends", bends);
|
|
967
|
+
}
|
|
968
|
+
if (bendsOnly) {
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
for (const [property, k, end] of [
|
|
972
|
+
["sourcePort", s, all[0]],
|
|
973
|
+
["targetPort", t, all.at(-1) ?? all[0]],
|
|
974
|
+
]) {
|
|
975
|
+
const center = centerOf(snapshot, k);
|
|
976
|
+
const port = end[0] === center[0] && end[1] === center[1]
|
|
977
|
+
? null
|
|
978
|
+
: canonNodeOffsets(center, sizeOf(snapshot, k), [end], true);
|
|
979
|
+
if (port !== null) {
|
|
980
|
+
put(property, port);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* A gv2gml edge's route: its `Line` is the edge's Graphviz `pos`, the B-spline's `3n + 1` control points from the tail
|
|
986
|
+
* to the head (y up), with the arrow tips Graphviz keeps apart (`s,` and `e,`) written as plain first and last points;
|
|
987
|
+
* the points beyond `3n + 1` are those tips (the source's first when there are two or it has the arrow). A route on
|
|
988
|
+
* the line between the centers is the straight edge it looks like and gives no bends.
|
|
989
|
+
* @param snapshot - the graph
|
|
990
|
+
* @param g - the edge's `graphics` value
|
|
991
|
+
* @param e - the edge's row
|
|
992
|
+
* @param put - receives the values
|
|
993
|
+
*/
|
|
994
|
+
function readGv2gmlRoute(snapshot, g, e, put) {
|
|
995
|
+
const raw = isRec(g) && isRec(g.Line) ? g.Line.point : undefined;
|
|
996
|
+
const list = isRec(raw) ? [raw] : raw;
|
|
997
|
+
if (!Array.isArray(list) || !isRec(g)) {
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
let points = list.map((p) => (isRec(p) ? [Number(p.x), Number(p.y)] : [Number.NaN, 0]));
|
|
1001
|
+
const tips = (points.length - 1) % 3;
|
|
1002
|
+
const sourceTip = tips === 2 || (tips === 1 && gv2gmlArrowEnds(g, snapshot.directed)?.[0] === true);
|
|
1003
|
+
points = points.slice(sourceTip ? 1 : 0, points.length - (tips === 2 || (tips === 1 && !sourceTip) ? 1 : 0));
|
|
1004
|
+
const bends = graphvizRouteBends(centerOf(snapshot, snapshot.edgeSource(e)), centerOf(snapshot, snapshot.edgeTarget(e)), [points]);
|
|
1005
|
+
if (bends !== null) {
|
|
1006
|
+
put("bends", bends);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Where graphty-element hangs an edge's label on a route drawn through these points (its centers and bends): the
|
|
1011
|
+
* middle of its middle segment, or the joint between its two middle ones; `labelOffsetX` / `labelOffsetY` move it
|
|
1012
|
+
* from there.
|
|
1013
|
+
* @param points - the route, from the source's center to the target's
|
|
1014
|
+
* @returns the point
|
|
1015
|
+
*/
|
|
1016
|
+
function routeMiddle(points) {
|
|
1017
|
+
const m = points.length - 1;
|
|
1018
|
+
if (m % 2 === 0) {
|
|
1019
|
+
return points[m / 2];
|
|
1020
|
+
}
|
|
1021
|
+
const [a, b] = [points[(m - 1) / 2], points[(m + 1) / 2]];
|
|
1022
|
+
return [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Puts an edge label's offset from where graphty-element hangs it, when the program draws it elsewhere.
|
|
1026
|
+
* @param at - the label's center, in the file's coordinates
|
|
1027
|
+
* @param middle - where graphty-element hangs it, in the same coordinates
|
|
1028
|
+
* @param yUp - whether the file's y grows upward
|
|
1029
|
+
* @param put - receives the values
|
|
1030
|
+
*/
|
|
1031
|
+
function putEdgeLabelOffset(at, middle, yUp, put) {
|
|
1032
|
+
const dx = num6(at[0] - middle[0]);
|
|
1033
|
+
const dy = num6((yUp ? -1 : 1) * (at[1] - middle[1]));
|
|
1034
|
+
if (Number.isFinite(dx) && Number.isFinite(dy) && (dx !== 0 || dy !== 0)) {
|
|
1035
|
+
// moved from the line's middle itself, not from graphty's default place beside the line
|
|
1036
|
+
put("labelPosition", "center");
|
|
1037
|
+
put("labelOffsetX", dx);
|
|
1038
|
+
put("labelOffsetY", dy);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* A gv2gml edge label's place: gv2gml copies Graphviz's `lp` (the label's center, in points, y up) as a plain edge
|
|
1043
|
+
* key, and Graphviz draws the label there, beside its line rather than on it.
|
|
1044
|
+
* @param snapshot - the graph
|
|
1045
|
+
* @param e - the edge's row
|
|
1046
|
+
* @param bent - whether its route has bends
|
|
1047
|
+
* @param put - receives the values
|
|
1048
|
+
*/
|
|
1049
|
+
function readGv2gmlLabelPlace(snapshot, e, bent, put) {
|
|
1050
|
+
const lp = cellOf(snapshot.edges, "lp", e);
|
|
1051
|
+
const m = typeof lp === "string" ? /^\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*$/.exec(lp) : null;
|
|
1052
|
+
// ponytail: a curved route's middle is where graphty-element samples its curve; only a straight one is placed
|
|
1053
|
+
if (m === null || bent) {
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
const [s, t] = [centerOf(snapshot, snapshot.edgeSource(e)), centerOf(snapshot, snapshot.edgeTarget(e))];
|
|
1057
|
+
putEdgeLabelOffset([Number(m[1]), Number(m[2])], routeMiddle([s, t]), true, put);
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* An OGDF edge label's place: GraphIO::drawSVG (SvgPrinter::drawEdge) draws it at the middle of the route's first
|
|
1061
|
+
* segment, from the source's center to its first bend, not at the route's middle.
|
|
1062
|
+
* @param snapshot - the graph
|
|
1063
|
+
* @param g - the edge's `graphics` value
|
|
1064
|
+
* @param e - the edge's row
|
|
1065
|
+
* @param put - receives the values
|
|
1066
|
+
*/
|
|
1067
|
+
function readOgdfLabelPlace(snapshot, g, e, put) {
|
|
1068
|
+
const raw = isRec(g) && isRec(g.Line) ? g.Line.point : undefined;
|
|
1069
|
+
const list = isRec(raw) ? [raw] : raw;
|
|
1070
|
+
const [s, t] = [centerOf(snapshot, snapshot.edgeSource(e)), centerOf(snapshot, snapshot.edgeTarget(e))];
|
|
1071
|
+
if (!Array.isArray(list) || snapshot.edgeSource(e) === snapshot.edgeTarget(e)) {
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
const same = (a, b) => Math.hypot(a[0] - b[0], a[1] - b[1]) < 1e-6;
|
|
1075
|
+
// the Line OGDF writes may start and end at the centers
|
|
1076
|
+
const bends = list
|
|
1077
|
+
.map((p) => (isRec(p) ? [Number(p.x), Number(p.y)] : [Number.NaN, 0]))
|
|
1078
|
+
.filter((p) => !same(p, s) && !same(p, t));
|
|
1079
|
+
if (bends.length === 0) {
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
const route = [s, ...bends, t];
|
|
1083
|
+
putEdgeLabelOffset([(route[0][0] + route[1][0]) / 2, (route[0][1] + route[1][1]) / 2], routeMiddle(route), false, put);
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Hides the edges Gephi's own GML importer leaves out: an edge whose `directed` key disagrees with the graph's
|
|
1087
|
+
* `directed` header (Gephi 0.11 loads 4 of `specimen-arrows-p6`'s 5 edges). A file with no header is read as mixed and
|
|
1088
|
+
* every edge is loaded. The edge and its data stay; Gephi draws nothing there, so graphty draws nothing.
|
|
1089
|
+
* @param snapshot - the graph
|
|
1090
|
+
* @param values - the edge values read so far, given `visible`
|
|
1091
|
+
*/
|
|
1092
|
+
function hideGephiDroppedEdges(snapshot, values) {
|
|
1093
|
+
const header = snapshot.meta.extra.gml?.directed;
|
|
1094
|
+
const directed = snapshot.edges.byRole("directed");
|
|
1095
|
+
// with no `directed` header Gephi reads a mixed graph and loads every edge (Gephi Toolkit 0.11.3, checked)
|
|
1096
|
+
if (directed === null || header === undefined) {
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
const graphDirected = Number(header) === 1;
|
|
1100
|
+
for (let e = 0; e < snapshot.edgeCount; e++) {
|
|
1101
|
+
const v = plainCell(directed.value(e));
|
|
1102
|
+
if (typeof v === "boolean" && v !== graphDirected) {
|
|
1103
|
+
values.visible ?? (values.visible = new Array(snapshot.edgeCount).fill(null));
|
|
1104
|
+
values.visible[e] = false;
|
|
1105
|
+
}
|
|
486
1106
|
}
|
|
487
|
-
const points = raw.slice(1, -1).map((p) => (isRec(p) ? [Number(p.x), Number(p.y)] : [Number.NaN, 0]));
|
|
488
|
-
return canonBends(centerOf(snapshot, snapshot.edgeSource(e)), centerOf(snapshot, snapshot.edgeTarget(e)), points, true);
|
|
489
1107
|
}
|
|
490
1108
|
/**
|
|
491
1109
|
* Every element's values, read with a writer's vocabulary.
|
|
@@ -507,18 +1125,33 @@ function readValues(snapshot, writer, notes, context) {
|
|
|
507
1125
|
for (let i = 0; i < n; i++) {
|
|
508
1126
|
context.budget.spend(target, 1);
|
|
509
1127
|
const at = (property) => ({ notes, target, property, element: i, budget: context.budget });
|
|
510
|
-
readElement(target, cellOf(table, "graphics", i), cellOf(table, "LabelGraphics", i),
|
|
1128
|
+
readElement(target, cellOf(table, "graphics", i), cellOf(table, "LabelGraphics", i), labelOf(snapshot, writer, target, i), writer, (property, value) => {
|
|
511
1129
|
if (value !== null) {
|
|
512
1130
|
found = true;
|
|
513
1131
|
out.put(i, property, value);
|
|
514
1132
|
}
|
|
515
1133
|
}, at);
|
|
516
|
-
if (target === "edge") {
|
|
517
|
-
|
|
518
|
-
|
|
1134
|
+
if (target === "edge" && writer.vocabulary === "graphviz") {
|
|
1135
|
+
let bent = false;
|
|
1136
|
+
readGv2gmlRoute(snapshot, cellOf(table, "graphics", i), i, (property, value) => {
|
|
519
1137
|
found = true;
|
|
520
|
-
|
|
521
|
-
|
|
1138
|
+
bent || (bent = property === "bends");
|
|
1139
|
+
out.put(i, property, value);
|
|
1140
|
+
});
|
|
1141
|
+
readGv2gmlLabelPlace(snapshot, i, bent, (property, value) => {
|
|
1142
|
+
out.put(i, property, value);
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
else if (target === "edge" && writer.vocabulary === "ogdf") {
|
|
1146
|
+
readOgdfLabelPlace(snapshot, cellOf(table, "graphics", i), i, (property, value) => {
|
|
1147
|
+
out.put(i, property, value);
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
if (target === "edge" && writer.vocabulary !== "graphviz") {
|
|
1151
|
+
readLineRoute(snapshot, cellOf(table, "graphics", i), i, writer.vocabulary === "ogdf", (property, value) => {
|
|
1152
|
+
found = true;
|
|
1153
|
+
out.put(i, property, value);
|
|
1154
|
+
});
|
|
522
1155
|
}
|
|
523
1156
|
}
|
|
524
1157
|
return out.values;
|
|
@@ -589,8 +1222,11 @@ function styleColumns(table) {
|
|
|
589
1222
|
*/
|
|
590
1223
|
export function gmlStyles(snapshot, context) {
|
|
591
1224
|
const notes = new StyleNotes();
|
|
592
|
-
const writer = writerOf(snapshot);
|
|
1225
|
+
const writer = { ...writerOf(snapshot), directed: snapshot.directed };
|
|
593
1226
|
const values = readValues(snapshot, writer, notes, context);
|
|
1227
|
+
if (writer.vocabulary === "ogdf") {
|
|
1228
|
+
placeOgdfClusterLabels(snapshot, values.node);
|
|
1229
|
+
}
|
|
594
1230
|
const blockText = graphText(snapshot, GML_STYLE_BLOCK_KEY);
|
|
595
1231
|
const block = blockText === null ? null : blockWithValues(snapshot, blockText);
|
|
596
1232
|
if (block !== null) {
|
|
@@ -599,16 +1235,33 @@ export function gmlStyles(snapshot, context) {
|
|
|
599
1235
|
if (writer.tool === null && !values.found && block === null) {
|
|
600
1236
|
return null;
|
|
601
1237
|
}
|
|
1238
|
+
if (writer.tool === "gephi" && block === null) {
|
|
1239
|
+
// Gephi draws every edge in its end nodes' mixed color (EdgeColor MIXED), whatever its own
|
|
1240
|
+
delete values.edge.color;
|
|
1241
|
+
// and as thick as its weight, the `value` Gephi writes, also where the reader kept `value` as plain data
|
|
1242
|
+
if (snapshot.edges.byRole("weight") === null && snapshot.edges.has("value")) {
|
|
1243
|
+
values.edge.width = Array.from({ length: snapshot.edgeCount }, (_, e) => {
|
|
1244
|
+
const w = cellOf(snapshot.edges, "value", e);
|
|
1245
|
+
if (typeof w !== "number" || !Number.isFinite(w)) {
|
|
1246
|
+
return null;
|
|
1247
|
+
}
|
|
1248
|
+
// a weight of 0 or below is drawn 1 wide, so the edge stays visible
|
|
1249
|
+
return w > 0 ? w : 1;
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
hideGephiDroppedEdges(snapshot, values.edge);
|
|
1253
|
+
}
|
|
1254
|
+
const none = { rules: [], columns: new Map() };
|
|
602
1255
|
const gephi = writer.tool === "gephi"
|
|
603
|
-
? gephiRules(snapshot, values.node.fill, values.
|
|
604
|
-
: {
|
|
1256
|
+
? gephiRules(snapshot, { fill: values.node.fill, width: values.node.width }, { color: values.edge.color, width: values.edge.width }, context.budget)
|
|
1257
|
+
: { node: none, edge: none };
|
|
605
1258
|
return {
|
|
606
1259
|
canonical: true,
|
|
607
1260
|
dialect: writer.dialect,
|
|
608
1261
|
tool: writer.tool,
|
|
609
1262
|
units: writer.units,
|
|
610
|
-
node: { values: values.node },
|
|
611
|
-
edge: { values: values.edge,
|
|
1263
|
+
node: { values: values.node, ...gephi.node },
|
|
1264
|
+
edge: { values: values.edge, ...gephi.edge },
|
|
612
1265
|
notes: notes.list(),
|
|
613
1266
|
opacityInColor: true,
|
|
614
1267
|
block,
|
|
@@ -623,6 +1276,7 @@ export function gmlStyles(snapshot, context) {
|
|
|
623
1276
|
* @category Built-in formats
|
|
624
1277
|
*/
|
|
625
1278
|
export const GML_STYLE_CAPABILITIES = Object.freeze({
|
|
1279
|
+
tool: "yed",
|
|
626
1280
|
node: Object.freeze([
|
|
627
1281
|
"fill",
|
|
628
1282
|
"fillOpacity",
|
|
@@ -648,6 +1302,8 @@ export const GML_STYLE_CAPABILITIES = Object.freeze({
|
|
|
648
1302
|
"targetArrow",
|
|
649
1303
|
"curved",
|
|
650
1304
|
"bends",
|
|
1305
|
+
"sourcePort",
|
|
1306
|
+
"targetPort",
|
|
651
1307
|
"label",
|
|
652
1308
|
"labelColor",
|
|
653
1309
|
"labelSize",
|
|
@@ -797,7 +1453,8 @@ function labelGraphics(get) {
|
|
|
797
1453
|
}
|
|
798
1454
|
const font = get("labelFont");
|
|
799
1455
|
if (typeof font === "string") {
|
|
800
|
-
|
|
1456
|
+
// a Java face is written back as the logical font yEd draws in it
|
|
1457
|
+
lg.fontName = yedFontName(font);
|
|
801
1458
|
}
|
|
802
1459
|
const weight = get("labelWeight");
|
|
803
1460
|
const italic = get("labelItalic");
|
|
@@ -841,19 +1498,6 @@ function mergedLabels(old, written) {
|
|
|
841
1498
|
}
|
|
842
1499
|
return head === undefined ? rest : [head, ...rest];
|
|
843
1500
|
}
|
|
844
|
-
/**
|
|
845
|
-
* Each element's values of the properties the writer writes, as a getter per element.
|
|
846
|
-
* @param picture - each element's value of a property
|
|
847
|
-
* @param target - nodes or edges
|
|
848
|
-
* @returns the getter
|
|
849
|
-
*/
|
|
850
|
-
function getter(picture, target) {
|
|
851
|
-
const columns = new Map();
|
|
852
|
-
for (const p of GML_STYLE_CAPABILITIES[target]) {
|
|
853
|
-
columns.set(p, picture(target, p));
|
|
854
|
-
}
|
|
855
|
-
return (i) => (property) => columns.get(property)?.[i] ?? null;
|
|
856
|
-
}
|
|
857
1501
|
/**
|
|
858
1502
|
* For a file graphty wrote: where a value read from the graphics is what the writer writes for the block's own value
|
|
859
1503
|
* (a pentagon written as a rectangle, an opacity rounded to 255 steps), the block's exact value is the truth, so a
|
|
@@ -865,29 +1509,16 @@ function getter(picture, target) {
|
|
|
865
1509
|
* @param read.edge - the edge values
|
|
866
1510
|
*/
|
|
867
1511
|
function exactFromBlock(snapshot, text, read) {
|
|
868
|
-
const parsed = parseStyleBlock(text, styleFingerprint(snapshot));
|
|
869
|
-
const ex = parsed.ok ? blockStyles(parsed.block, snapshot, "gml") : null;
|
|
870
|
-
if (ex === null) {
|
|
871
|
-
return;
|
|
872
|
-
}
|
|
873
1512
|
const notes = new StyleNotes();
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
const want = get(i);
|
|
1513
|
+
takeFromBlock(snapshot, text, "gml", (target) => ({
|
|
1514
|
+
values: read[target],
|
|
1515
|
+
properties: GML_STYLE_CAPABILITIES[target],
|
|
1516
|
+
writes: GML_STYLE_CAPABILITIES[target],
|
|
1517
|
+
readBack: (_i, want) => {
|
|
880
1518
|
const back = writtenAndReadBack(target, want, notes);
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
if (native !== w && native === (back.get(property) ?? null)) {
|
|
885
|
-
values[property] ?? (values[property] = new Array(n).fill(null));
|
|
886
|
-
values[property][i] = w;
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
}
|
|
1519
|
+
return (property) => back.get(property) ?? null;
|
|
1520
|
+
},
|
|
1521
|
+
}));
|
|
891
1522
|
}
|
|
892
1523
|
/**
|
|
893
1524
|
* An element's values written as the writer writes them and read back as the reader reads them.
|
|
@@ -968,13 +1599,18 @@ function writeGraphicsColumns(snapshot, input, target, table, approximated) {
|
|
|
968
1599
|
const approximate = (property, value) => {
|
|
969
1600
|
approximated.add(target, property, value);
|
|
970
1601
|
};
|
|
971
|
-
const get =
|
|
1602
|
+
const get = elementValues((t, p) => input.picture(t, p), target, GML_STYLE_CAPABILITIES[target]);
|
|
1603
|
+
const getNode = elementValues((t, p) => input.picture(t, p), "node", GML_STYLE_CAPABILITIES.node);
|
|
1604
|
+
const size = (k) => {
|
|
1605
|
+
const [w, h] = [getNode(k)("width"), getNode(k)("height")];
|
|
1606
|
+
return typeof w === "number" && typeof h === "number" ? [w, h] : sizeOf(snapshot, k);
|
|
1607
|
+
};
|
|
972
1608
|
const graphics = [];
|
|
973
1609
|
const labels = [];
|
|
974
1610
|
for (let i = 0; i < n; i++) {
|
|
975
1611
|
const g = target === "node" ? nodeGraphics(get(i), approximate) : edgeGraphics(get(i), approximate);
|
|
976
1612
|
if (target === "edge") {
|
|
977
|
-
const line =
|
|
1613
|
+
const line = routeLine(snapshot, get(i), i, size);
|
|
978
1614
|
if (line !== null) {
|
|
979
1615
|
g.Line = line;
|
|
980
1616
|
}
|
|
@@ -995,21 +1631,38 @@ function writeGraphicsColumns(snapshot, input, target, table, approximated) {
|
|
|
995
1631
|
}
|
|
996
1632
|
}
|
|
997
1633
|
/**
|
|
998
|
-
* An edge's `Line` from its `bends`
|
|
999
|
-
*
|
|
1634
|
+
* An edge's `Line` from its `bends`, `sourcePort` and `targetPort` values: from its source port (the node's center
|
|
1635
|
+
* without one) through the bends placed between the node centers (a self-loop's around its node) to its target port,
|
|
1636
|
+
* so the route reads back as written.
|
|
1000
1637
|
* @param snapshot - the graph handed to the exporter
|
|
1001
|
-
* @param
|
|
1638
|
+
* @param get - the edge's values
|
|
1002
1639
|
* @param e - the edge's row
|
|
1640
|
+
* @param size - each node's written width and height
|
|
1003
1641
|
* @returns the `Line` record, or null without a value or without both centers
|
|
1004
1642
|
*/
|
|
1005
|
-
function
|
|
1006
|
-
const
|
|
1007
|
-
const
|
|
1008
|
-
const
|
|
1009
|
-
if (
|
|
1643
|
+
function routeLine(snapshot, get, e, size) {
|
|
1644
|
+
const [s, t] = [snapshot.edgeSource(e), snapshot.edgeTarget(e)];
|
|
1645
|
+
const source = centerOf(snapshot, s);
|
|
1646
|
+
const target = centerOf(snapshot, t);
|
|
1647
|
+
if (![...source, ...target].every(Number.isFinite)) {
|
|
1648
|
+
return null;
|
|
1649
|
+
}
|
|
1650
|
+
const bends = get("bends");
|
|
1651
|
+
let points = null;
|
|
1652
|
+
if (typeof bends === "string") {
|
|
1653
|
+
points =
|
|
1654
|
+
s === t ? nodeOffsetsToPoints(source, size(s), bends, true) : bendsToPoints(source, target, bends, true);
|
|
1655
|
+
}
|
|
1656
|
+
const port = (property, k, center) => {
|
|
1657
|
+
const value = get(property);
|
|
1658
|
+
return typeof value === "string" ? (nodeOffsetsToPoints(center, size(k), value, true)?.[0] ?? null) : null;
|
|
1659
|
+
};
|
|
1660
|
+
const from = port("sourcePort", s, source);
|
|
1661
|
+
const to = port("targetPort", t, target);
|
|
1662
|
+
if (points === null && from === null && to === null) {
|
|
1010
1663
|
return null;
|
|
1011
1664
|
}
|
|
1012
|
-
return { point: [source, ...points, target].map(([x, y]) => ({ x, y })) };
|
|
1665
|
+
return { point: [from ?? source, ...(points ?? []), to ?? target].map(([x, y]) => ({ x, y })) };
|
|
1013
1666
|
}
|
|
1014
1667
|
/**
|
|
1015
1668
|
* Writes a data column under a name out of the keys the style values take.
|