@graphty/graph-io 0.3.48 → 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-C2riR4NT.js → approximations-Bzn3L-je.js} +2 -2
- package/dist/chunks/{approximations-C2riR4NT.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-Cu22ewuS.js → block-iptrlMBb.js} +906 -164
- 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-CV_Bhcyi.js → codes-BE2xir2k.js} +6 -2
- package/dist/chunks/codes-BE2xir2k.js.map +1 -0
- package/dist/chunks/{constants-D0LqcsLJ.js → constants-CKkYLPtt.js} +2 -2
- package/dist/chunks/{constants-D0LqcsLJ.js.map → constants-CKkYLPtt.js.map} +1 -1
- package/dist/chunks/{context-cgmmOxZ2.js → context-C3p0RQxR.js} +5 -4
- package/dist/chunks/{context-cgmmOxZ2.js.map → context-C3p0RQxR.js.map} +1 -1
- 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-BiQsnMTb.js → credentials-DXHx7nwR.js} +16 -14
- package/dist/chunks/credentials-DXHx7nwR.js.map +1 -0
- package/dist/chunks/{cx-export-BEeF6ymo.js → cx-export-Bt6NoqTQ.js} +3 -3
- package/dist/chunks/{cx-export-BEeF6ymo.js.map → cx-export-Bt6NoqTQ.js.map} +1 -1
- package/dist/chunks/descriptor-B28U25x4.js +60 -0
- package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
- package/dist/chunks/{descriptor-BJ-W0Jd-.js → descriptor-DLA5kINx.js} +7 -2
- package/dist/chunks/descriptor-DLA5kINx.js.map +1 -0
- package/dist/chunks/{emit-CD8xnY8s.js → emit-BwHQkZle.js} +1660 -133
- package/dist/chunks/emit-BwHQkZle.js.map +1 -0
- package/dist/chunks/{escape-DH2Egt-l.js → escape-CuCIzNMB.js} +8 -8
- package/dist/chunks/{escape-DH2Egt-l.js.map → escape-CuCIzNMB.js.map} +1 -1
- package/dist/chunks/{export-CZ7VRm4I.js → export-Cha4dRFz.js} +45 -387
- package/dist/chunks/export-Cha4dRFz.js.map +1 -0
- package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
- package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
- package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-D2CETOMK.js} +1222 -156
- package/dist/chunks/exporter-D2CETOMK.js.map +1 -0
- package/dist/chunks/{exporter-BIdaoIgh.js → exporter-D9yMtocA.js} +7 -7
- package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-D9yMtocA.js.map} +1 -1
- package/dist/chunks/{exporter-DtVU80Fa.js → exporter-_jrBTnos.js} +9 -8
- package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-_jrBTnos.js.map} +1 -1
- package/dist/chunks/{exporter-ChjL5fmP.js → exporter-nDfxIK5D.js} +9 -8
- package/dist/chunks/{exporter-ChjL5fmP.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-CP6YD34u.js → generic-ymWCETAJ.js} +387 -31
- package/dist/chunks/generic-ymWCETAJ.js.map +1 -0
- package/dist/chunks/{importer-e3huMZbm.js → importer-B92x1xY5.js} +14 -10
- package/dist/chunks/importer-B92x1xY5.js.map +1 -0
- package/dist/chunks/{importer-B87_fmVx.js → importer-CT9mJ1nn.js} +326 -84
- package/dist/chunks/importer-CT9mJ1nn.js.map +1 -0
- package/dist/chunks/{importer-CB_zV5_L.js → importer-DaLTjbds.js} +116 -1102
- package/dist/chunks/importer-DaLTjbds.js.map +1 -0
- package/dist/chunks/{importer-DPZDN40-.js → importer-GREKMdIf.js} +25 -17
- package/dist/chunks/importer-GREKMdIf.js.map +1 -0
- package/dist/chunks/{importer-Bji2MeWr.js → importer-PqaaKKnY.js} +13 -10
- package/dist/chunks/{importer-Bji2MeWr.js.map → importer-PqaaKKnY.js.map} +1 -1
- package/dist/chunks/{importer-Cyy6UseH.js → importer-Vn5QvmmJ.js} +66 -13
- package/dist/chunks/importer-Vn5QvmmJ.js.map +1 -0
- package/dist/chunks/{importer-CVT-JyDE.js → importer-vRq4h3j5.js} +1469 -356
- package/dist/chunks/importer-vRq4h3j5.js.map +1 -0
- package/dist/chunks/{input-Ccg9I22A.js → input-CAxt_aV-.js} +4 -4
- package/dist/chunks/{input-Ccg9I22A.js.map → input-CAxt_aV-.js.map} +1 -1
- package/dist/chunks/{json-elements-By172SVq.js → json-elements-Cq76WjnZ.js} +4 -4
- package/dist/chunks/{json-elements-By172SVq.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
- package/dist/chunks/{lexicon-u2SI5xcx.js → lexicon-Clf4QIyl.js} +282 -74
- package/dist/chunks/lexicon-Clf4QIyl.js.map +1 -0
- package/dist/chunks/{ontology-export-BwgMyuF0.js → ontology-export-OMo91mb0.js} +4 -4
- package/dist/chunks/{ontology-export-BwgMyuF0.js.map → ontology-export-OMo91mb0.js.map} +1 -1
- package/dist/chunks/{records-Cgvxz-Vx.js → records-NJiYvekn.js} +2 -2
- package/dist/chunks/{records-Cgvxz-Vx.js.map → records-NJiYvekn.js.map} +1 -1
- package/dist/chunks/{report-CgdsL9Hb.js → report-CwMfYa9J.js} +23 -23
- package/dist/chunks/{report-CgdsL9Hb.js.map → report-CwMfYa9J.js.map} +1 -1
- 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-LkAzsLAu.js → sigv4-EokFic1V.js} +5 -5
- package/dist/chunks/sigv4-EokFic1V.js.map +1 -0
- package/dist/chunks/{styles-CaABMoO1.js → styles-CCs214_3.js} +1237 -138
- 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-Cs1nmrjn.js → styles-yed-UMFdNqze.js} +503 -172
- package/dist/chunks/styles-yed-UMFdNqze.js.map +1 -0
- package/dist/chunks/{text-BuKQVMz2.js → text-ystE2bYi.js} +2 -2
- package/dist/chunks/{text-BuKQVMz2.js.map → text-ystE2bYi.js.map} +1 -1
- package/dist/csv.js +7 -7
- package/dist/cx.js +2 -2
- 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 -12
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +847 -193
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +232 -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 -6
- 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.js +138 -23
- package/dist/sources-cypher.js.map +1 -1
- package/dist/sources-ndex.js +2 -2
- package/dist/sources-rest.js +16 -6
- package/dist/sources-rest.js.map +1 -1
- 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/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 +117 -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 +1454 -119
- 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 +58 -31
- package/dist/src/formats/gexf/styles.d.ts.map +1 -1
- package/dist/src/formats/gexf/styles.js +848 -225
- 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 +753 -101
- 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 +6 -10
- 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 +692 -161
- 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 +1278 -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 +277 -60
- package/dist/src/formats/xgmml/styles.js.map +1 -1
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -3
- 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/sources/builtins.d.ts +1 -1
- package/dist/src/sources/builtins.d.ts.map +1 -1
- package/dist/src/sources/builtins.js +8 -2
- package/dist/src/sources/builtins.js.map +1 -1
- package/dist/src/sources/context.d.ts.map +1 -1
- package/dist/src/sources/context.js +1 -0
- package/dist/src/sources/context.js.map +1 -1
- package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
- package/dist/src/sources/cypher/descriptor.js +5 -0
- package/dist/src/sources/cypher/descriptor.js.map +1 -1
- package/dist/src/sources/cypher/index.d.ts.map +1 -1
- package/dist/src/sources/cypher/index.js +124 -18
- package/dist/src/sources/cypher/index.js.map +1 -1
- package/dist/src/sources/cypher/params.d.ts +1 -1
- package/dist/src/sources/cypher/params.d.ts.map +1 -1
- package/dist/src/sources/cypher/query-builder.d.ts +17 -0
- package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
- package/dist/src/sources/cypher/query-builder.js +31 -0
- package/dist/src/sources/cypher/query-builder.js.map +1 -1
- package/dist/src/sources/ids.d.ts +5 -0
- package/dist/src/sources/ids.d.ts.map +1 -1
- package/dist/src/sources/ids.js +5 -0
- package/dist/src/sources/ids.js.map +1 -1
- package/dist/src/sources/params.d.ts +3 -0
- package/dist/src/sources/params.d.ts.map +1 -1
- package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
- package/dist/src/sources/rest/descriptor.js +5 -0
- package/dist/src/sources/rest/descriptor.js.map +1 -1
- package/dist/src/sources/rest/source.d.ts.map +1 -1
- package/dist/src/sources/rest/source.js +15 -0
- package/dist/src/sources/rest/source.js.map +1 -1
- package/dist/src/sources/sigv4.d.ts +5 -3
- package/dist/src/sources/sigv4.d.ts.map +1 -1
- package/dist/src/sources/sigv4.js +6 -4
- package/dist/src/sources/sigv4.js.map +1 -1
- 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/types.d.ts +31 -0
- package/dist/src/sources/types.d.ts.map +1 -1
- 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 +81 -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 +1015 -79
- 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 +3 -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 +202 -9
- 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 +44 -1
- package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
- package/dist/src/styles/cyjs/mappers.js +461 -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 +156 -48
- package/dist/src/styles/cytoscape/emit.js.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
- package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.js +387 -77
- 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 +42 -2
- package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/resolve.js +623 -17
- package/dist/src/styles/cytoscape/resolve.js.map +1 -1
- package/dist/src/styles/defaults.d.ts +46 -26
- package/dist/src/styles/defaults.d.ts.map +1 -1
- package/dist/src/styles/defaults.js +308 -71
- 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/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 +6 -1
- 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 +11 -0
- package/dist/src/styles/plan/resolve.d.ts.map +1 -1
- package/dist/src/styles/plan/resolve.js +40 -4
- 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 +622 -6
- 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 +203 -0
- package/dist/src/styles/vocabulary.js.map +1 -1
- package/dist/styles.js +30 -239
- package/dist/styles.js.map +1 -1
- package/dist/xgmml.js +3 -3
- package/package.json +27 -7
- package/src/formats/cx/importer.ts +6 -1
- package/src/formats/cx/styles.ts +143 -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 +1654 -153
- 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 +1099 -245
- 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 +851 -109
- package/src/formats/graphml/styles-plain.ts +6 -15
- package/src/formats/graphml/styles-yed.ts +762 -173
- 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 +1381 -133
- package/src/formats/pajek/syntax.ts +27 -2
- package/src/formats/xgmml/emit.ts +73 -5
- package/src/formats/xgmml/styles.ts +330 -71
- package/src/index.ts +5 -1
- 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/sources/builtins.ts +8 -1
- package/src/sources/context.ts +1 -0
- package/src/sources/cypher/descriptor.ts +7 -1
- package/src/sources/cypher/index.ts +148 -18
- package/src/sources/cypher/params.ts +1 -1
- package/src/sources/cypher/query-builder.ts +33 -0
- package/src/sources/ids.ts +6 -0
- package/src/sources/params.ts +3 -0
- package/src/sources/rest/descriptor.ts +5 -0
- package/src/sources/rest/source.ts +16 -0
- package/src/sources/sigv4.ts +6 -4
- 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/types.ts +35 -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 +98 -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 +1160 -84
- package/src/styles/cyjs/defaults-table.ts +3 -0
- package/src/styles/cyjs/emit.ts +233 -13
- package/src/styles/cyjs/face.ts +372 -0
- package/src/styles/cyjs/mappers.ts +492 -27
- package/src/styles/cyjs/routes.ts +432 -0
- package/src/styles/cytoscape/charts.ts +684 -0
- package/src/styles/cytoscape/emit.ts +170 -48
- package/src/styles/cytoscape/lexicon.ts +431 -78
- package/src/styles/cytoscape/mappings.ts +108 -0
- package/src/styles/cytoscape/resolve.ts +741 -17
- package/src/styles/defaults.ts +417 -108
- package/src/styles/index.ts +5 -0
- package/src/styles/internal.ts +1 -0
- package/src/styles/io/generic.ts +79 -23
- package/src/styles/io/round-trip.ts +202 -0
- package/src/styles/io/writer.ts +6 -1
- 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 +47 -4
- package/src/styles/slots.ts +25 -0
- package/src/styles/types.ts +633 -5
- package/src/styles/vocabulary.ts +211 -2
- package/dist/chunks/block-Cu22ewuS.js.map +0 -1
- package/dist/chunks/choose-Cdx6Enl2.js +0 -57
- package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
- package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
- package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
- package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
- package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
- package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
- package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
- package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
- package/dist/chunks/format-BMS-1Nxb.js +0 -64
- package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
- package/dist/chunks/generic-CP6YD34u.js.map +0 -1
- package/dist/chunks/importer-B87_fmVx.js.map +0 -1
- package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
- package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
- package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
- package/dist/chunks/importer-DPZDN40-.js.map +0 -1
- package/dist/chunks/importer-e3huMZbm.js.map +0 -1
- package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
- package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
- package/dist/chunks/styles-CaABMoO1.js.map +0 -1
- package/dist/chunks/styles-P_gmFAOi.js +0 -770
- package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
- package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
- package/dist/chunks/writer-DvHTl36J.js +0 -449
- package/dist/chunks/writer-DvHTl36J.js.map +0 -1
|
@@ -7,14 +7,17 @@
|
|
|
7
7
|
* The tree helpers here are shared with the yFiles 3 reader.
|
|
8
8
|
*/
|
|
9
9
|
import { toFilePositions, toNeutral } from "../../positions/convert.js";
|
|
10
|
-
import { bendsToPoints, canonBends } from "../../styles/canon/bends.js";
|
|
10
|
+
import { bendsToPoints, canonBends, canonNodeOffsets, flattenCubic, flattenQuadSpline, nodeOffsetsToPoints, } from "../../styles/canon/bends.js";
|
|
11
11
|
import { canonColor, colorOpacity } from "../../styles/canon/color.js";
|
|
12
12
|
import { canonEnum } from "../../styles/canon/enums.js";
|
|
13
|
-
import { canonNumber } from "../../styles/canon/number.js";
|
|
13
|
+
import { canonNumber, canonSigned } from "../../styles/canon/number.js";
|
|
14
14
|
import { MAX_STYLE_VALUE_LENGTH, noteAt } from "../../styles/canon/site.js";
|
|
15
15
|
import { canonText } from "../../styles/canon/text.js";
|
|
16
16
|
import { STYLE_ISSUE } from "../../styles/codes.js";
|
|
17
|
+
import { JAVA_MONO, JAVA_SANS, JAVA_SERIF, javaFamily } from "../../styles/cytoscape/lexicon.js";
|
|
17
18
|
import { StyleApproximations } from "../../styles/io/approximations.js";
|
|
19
|
+
import { elementValues, takeFromBlock } from "../../styles/io/round-trip.js";
|
|
20
|
+
import { StyleNotes } from "../../styles/notes.js";
|
|
18
21
|
import { plainCell } from "../../styles/plan/resolve.js";
|
|
19
22
|
/**
|
|
20
23
|
* Whether a value is a tree object.
|
|
@@ -197,32 +200,167 @@ function activeRealizer(proxy) {
|
|
|
197
200
|
return all[Number.isInteger(active) && active >= 0 && active < all.length ? active : 0] ?? null;
|
|
198
201
|
}
|
|
199
202
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
203
|
+
* Points along an elliptical arc, as `x,y` text: center (cx, cy), radii (rx, ry), from angle `from` to `to` (radians,
|
|
204
|
+
* counter-clockwise, y up), both ends included.
|
|
205
|
+
* @param cx - center x
|
|
206
|
+
* @param cy - center y
|
|
207
|
+
* @param rx - x radius
|
|
208
|
+
* @param ry - y radius
|
|
209
|
+
* @param from - first angle
|
|
210
|
+
* @param to - last angle
|
|
211
|
+
* @param steps - segments
|
|
212
|
+
* @returns the points
|
|
202
213
|
*/
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
214
|
+
function arcPoints(cx, cy, rx, ry, from, to, steps = 12) {
|
|
215
|
+
return Array.from({ length: steps + 1 }, (_, i) => {
|
|
216
|
+
const t = from + ((to - from) * i) / steps;
|
|
217
|
+
return pointText(cx + rx * Math.cos(t), cy + ry * Math.sin(t));
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Points along a wave y = y0 + amp * sin(pi * x), x from `x0` to `x1`.
|
|
222
|
+
* @param y0 - the wave's middle
|
|
223
|
+
* @param amp - its height
|
|
224
|
+
* @param x0 - first x
|
|
225
|
+
* @param x1 - last x
|
|
226
|
+
* @returns the points
|
|
227
|
+
*/
|
|
228
|
+
function wavePoints(y0, amp, x0, x1) {
|
|
229
|
+
const steps = 16;
|
|
230
|
+
return Array.from({ length: steps + 1 }, (_, i) => {
|
|
231
|
+
const x = x0 + ((x1 - x0) * i) / steps;
|
|
232
|
+
return pointText(x, y0 + amp * Math.sin(Math.PI * x));
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* One corner as `x,y`, rounded to three decimals.
|
|
237
|
+
* @param x - x
|
|
238
|
+
* @param y - y
|
|
239
|
+
* @returns the text
|
|
240
|
+
*/
|
|
241
|
+
function pointText(x, y) {
|
|
242
|
+
const r = (v) => String(Math.round(v * 1000) / 1000 + 0);
|
|
243
|
+
return `${r(x)},${r(y)}`;
|
|
244
|
+
}
|
|
245
|
+
const HALF_PI = Math.PI / 2;
|
|
246
|
+
/** A cloud: a circle of bumps, stretched to the box. */
|
|
247
|
+
const CLOUD = Array.from({ length: 72 }, (_, i) => {
|
|
248
|
+
const t = (2 * Math.PI * i) / 72;
|
|
249
|
+
const r = 0.86 + 0.14 * Math.abs(Math.cos(4 * t));
|
|
250
|
+
return pointText(r * Math.cos(t), r * Math.sin(t));
|
|
251
|
+
}).join(" ");
|
|
252
|
+
/** A stadium: a box whose ends are half circles (a pill). */
|
|
253
|
+
const STADIUM = [
|
|
254
|
+
...arcPoints(0.5, 0, 0.5, 1, -HALF_PI, HALF_PI),
|
|
255
|
+
...arcPoints(-0.5, 0, 0.5, 1, HALF_PI, 3 * HALF_PI),
|
|
256
|
+
].join(" ");
|
|
257
|
+
/**
|
|
258
|
+
* The shape each configuration of yEd's GenericNode palettes draws (flowchart, entity relationship, BPMN, SBGN), by
|
|
259
|
+
* its name after `com.yworks.` without a `.withShadow` suffix, lowercase. Matched whole, before the words below:
|
|
260
|
+
* "data" is a parallelogram, but "storedData" and "directData" are not. A shape no neutral one names is the polygon
|
|
261
|
+
* yEd draws it as (curves as short segments); the lines some draw inside (predefined process, internal storage) are
|
|
262
|
+
* not drawn. Left out until a drawing by yEd itself shows them (ISSUES.md): the BPMN artifact, whose `type` property
|
|
263
|
+
* picks among a data object, a data store, a message and others, and the SBGN nucleic acid feature and perturbing
|
|
264
|
+
* agent, which draw.io, the stand-in, draws as plain boxes.
|
|
265
|
+
*/
|
|
266
|
+
const YED_CONFIGURATIONS = new Map([
|
|
267
|
+
["flowchart.process", { shape: "rectangle" }],
|
|
268
|
+
["flowchart.predefinedprocess", { shape: "rectangle" }],
|
|
269
|
+
["flowchart.internalstorage", { shape: "rectangle" }],
|
|
270
|
+
["flowchart.decision", { shape: "diamond" }],
|
|
271
|
+
["flowchart.terminator", { shape: "round-rectangle" }],
|
|
272
|
+
["flowchart.start1", { shape: "ellipse" }],
|
|
273
|
+
["flowchart.start2", { shape: "ellipse" }],
|
|
274
|
+
["flowchart.onpagereference", { shape: "ellipse" }],
|
|
275
|
+
["flowchart.sequentialdata", { shape: "ellipse" }],
|
|
276
|
+
["flowchart.data", { shape: "parallelogram" }],
|
|
277
|
+
["flowchart.preparation", { shape: "hexagon" }],
|
|
278
|
+
["flowchart.database", { shape: "other:database" }],
|
|
279
|
+
["flowchart.looplimit", { shape: "polygon", points: "-1,-1 1,-1 1,0.5 0.8,1 -0.8,1 -1,0.5" }],
|
|
280
|
+
["flowchart.looplimitend", { shape: "polygon", points: "-1,1 -1,-0.5 -0.8,-1 0.8,-1 1,-0.5 1,1" }],
|
|
281
|
+
["flowchart.manualinput", { shape: "polygon", points: "-1,-1 1,-1 1,1 -1,0.4" }],
|
|
282
|
+
["flowchart.card", { shape: "polygon", points: "-1,-1 1,-1 1,1 -0.6,1 -1,0.6" }],
|
|
283
|
+
["flowchart.manualoperation", { shape: "polygon", points: "-1,1 -0.7,-1 0.7,-1 1,1" }],
|
|
284
|
+
["flowchart.offpagereference", { shape: "polygon", points: "-1,1 -1,0 0,-1 1,0 1,1" }],
|
|
285
|
+
["flowchart.usermessage", { shape: "polygon", points: "-1,1 -1,-1 0.6,-1 1,0 0.6,1" }],
|
|
286
|
+
["flowchart.networkmessage", { shape: "polygon", points: "-1,1 -0.6,0 -1,-1 1,-1 1,1" }],
|
|
287
|
+
["flowchart.document", { shape: "polygon", points: ["-1,1", ...wavePoints(-0.75, 0.2, -1, 1), "1,1"].join(" ") }],
|
|
288
|
+
[
|
|
289
|
+
"flowchart.papertype",
|
|
290
|
+
{
|
|
291
|
+
shape: "polygon",
|
|
292
|
+
points: [...wavePoints(-0.8, 0.2, -1, 1), ...wavePoints(0.8, 0.2, 1, -1)].join(" "),
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
[
|
|
296
|
+
"flowchart.delay",
|
|
297
|
+
{ shape: "polygon", points: ["-1,-1", ...arcPoints(0, 0, 1, 1, -HALF_PI, HALF_PI), "-1,1"].join(" ") },
|
|
298
|
+
],
|
|
299
|
+
[
|
|
300
|
+
"flowchart.display",
|
|
301
|
+
{
|
|
302
|
+
shape: "polygon",
|
|
303
|
+
points: ["-1,0", "-0.6,-1", ...arcPoints(0.6, 0, 0.4, 1, -HALF_PI, HALF_PI), "-0.6,1"].join(" "),
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
[
|
|
307
|
+
"flowchart.storeddata",
|
|
308
|
+
{
|
|
309
|
+
shape: "polygon",
|
|
310
|
+
points: [
|
|
311
|
+
...arcPoints(1, 0, -0.2, 1, -HALF_PI, HALF_PI),
|
|
312
|
+
...arcPoints(-0.8, 0, 0.2, 1, HALF_PI, 3 * HALF_PI),
|
|
313
|
+
].join(" "),
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
[
|
|
317
|
+
"flowchart.directdata",
|
|
318
|
+
{
|
|
319
|
+
shape: "polygon",
|
|
320
|
+
points: [
|
|
321
|
+
...arcPoints(0.8, 0, 0.2, 1, -HALF_PI, HALF_PI),
|
|
322
|
+
...arcPoints(-0.8, 0, 0.2, 1, HALF_PI, 3 * HALF_PI),
|
|
323
|
+
].join(" "),
|
|
324
|
+
},
|
|
325
|
+
],
|
|
326
|
+
["flowchart.cloud", { shape: "polygon", points: CLOUD }],
|
|
327
|
+
["entityrelationship.relationship", { shape: "diamond" }],
|
|
328
|
+
["entityrelationship.attribute", { shape: "ellipse" }],
|
|
329
|
+
["bpmn.conversation", { shape: "hexagon" }],
|
|
330
|
+
["sbgn.unspecifiedentity", { shape: "ellipse" }],
|
|
331
|
+
["sbgn.simplechemical", { shape: "ellipse" }],
|
|
332
|
+
["sbgn.emptyset", { shape: "ellipse" }],
|
|
333
|
+
["sbgn.operator", { shape: "ellipse" }],
|
|
334
|
+
["sbgn.macromolecule", { shape: "round-rectangle" }],
|
|
335
|
+
["sbgn.phenotype", { shape: "hexagon" }],
|
|
336
|
+
["sbgn.process", { shape: "rectangle" }],
|
|
337
|
+
["sbgn.submap", { shape: "rectangle" }],
|
|
338
|
+
["sbgn.unitofinformation", { shape: "rectangle" }],
|
|
339
|
+
["sbgn.statevariable", { shape: "polygon", points: STADIUM }],
|
|
340
|
+
["sbgn.tag", { shape: "polygon", points: "-1,1 -1,-1 0.6,-1 1,0 0.6,1" }],
|
|
211
341
|
]);
|
|
212
|
-
const FLOWCHART_PREFIX = "com.yworks.flowchart.";
|
|
213
342
|
/**
|
|
214
|
-
* The shape a yEd
|
|
343
|
+
* The shape a yEd GenericNode configuration draws: a GraphML GenericNode's `configuration`, or a yEd GML node's
|
|
215
344
|
* `customconfiguration`.
|
|
216
345
|
* @param configuration - the configuration
|
|
217
|
-
* @returns the
|
|
346
|
+
* @returns the shape, with its corners where it is a polygon, or null for a configuration not known here
|
|
218
347
|
*/
|
|
219
|
-
export function
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
348
|
+
export function configurationOutline(configuration) {
|
|
349
|
+
const key = configuration
|
|
350
|
+
.slice(0, MAX_STYLE_VALUE_LENGTH)
|
|
351
|
+
.toLowerCase()
|
|
352
|
+
.replace(/^com\.yworks\./, "")
|
|
353
|
+
.replace(/\.withshadow$/, "");
|
|
354
|
+
return YED_CONFIGURATIONS.get(key) ?? null;
|
|
223
355
|
}
|
|
224
356
|
/** GenericNode configurations, by a word they contain, to the shape they draw; the first match wins. */
|
|
225
357
|
const GENERIC_SHAPES = [
|
|
358
|
+
// yEd's BPMN and entity-relationship palettes: a task is a rounded box, an event a circle, a
|
|
359
|
+
// gateway a diamond, an attribute an ellipse
|
|
360
|
+
["bpmn.activity", "round-rectangle"],
|
|
361
|
+
["bpmn.event", "ellipse"],
|
|
362
|
+
["bpmn.gateway", "diamond"],
|
|
363
|
+
["entityrelationship.attribute", "ellipse"],
|
|
226
364
|
["ellipse", "ellipse"],
|
|
227
365
|
["circle", "ellipse"],
|
|
228
366
|
["oval", "ellipse"],
|
|
@@ -292,8 +430,9 @@ function readColor(raw, property, opacity, put, at) {
|
|
|
292
430
|
* @param node - whether they are node labels (which have a position)
|
|
293
431
|
* @param put - receives the values
|
|
294
432
|
* @param at - the sites
|
|
433
|
+
* @param geometry - a node label's node `y:Geometry`, which places the label inside or outside the node
|
|
295
434
|
*/
|
|
296
|
-
function readLabels(labels, node, put, at) {
|
|
435
|
+
function readLabels(labels, node, put, at, geometry) {
|
|
297
436
|
let label = undefined;
|
|
298
437
|
let text = "";
|
|
299
438
|
let extra = 0;
|
|
@@ -317,19 +456,32 @@ function readLabels(labels, node, put, at) {
|
|
|
317
456
|
noteAt(at("label"), STYLE_ISSUE.EXTRA_LABELS, `${String(extra + 1)} labels`);
|
|
318
457
|
}
|
|
319
458
|
put("label", canonText(text, at("label")));
|
|
320
|
-
readLabelLook(label, node, put, at);
|
|
459
|
+
readLabelLook(label, node, put, at, geometry);
|
|
321
460
|
}
|
|
322
461
|
/**
|
|
323
|
-
* Reads a label's look: its color, font and, for a node label, its position.
|
|
462
|
+
* Reads a label's look: its color, background box and its border, font and, for a node label, its position.
|
|
324
463
|
* @param label - the label element
|
|
325
464
|
* @param node - whether it is a node label
|
|
326
465
|
* @param put - receives the values
|
|
327
466
|
* @param at - the sites
|
|
467
|
+
* @param geometry - a node label's node `y:Geometry`
|
|
328
468
|
*/
|
|
329
|
-
function readLabelLook(label, node, put, at) {
|
|
469
|
+
function readLabelLook(label, node, put, at, geometry) {
|
|
330
470
|
readColor(treeAttr(label, "textColor"), "labelColor", null, put, at);
|
|
471
|
+
// yEd draws a box behind the words in `backgroundColor` unless `hasBackgroundColor` is false
|
|
472
|
+
if (treeAttr(label, "hasBackgroundColor") !== "false") {
|
|
473
|
+
readColor(treeAttr(label, "backgroundColor"), "labelBackground", null, put, at);
|
|
474
|
+
}
|
|
475
|
+
// and a one-pixel line round that box in `lineColor` unless `hasLineColor` is false
|
|
476
|
+
if (treeAttr(label, "hasLineColor") !== "false" && treeAttr(label, "lineColor") !== undefined) {
|
|
477
|
+
readColor(treeAttr(label, "lineColor"), "labelBorderColor", null, put, at);
|
|
478
|
+
put("labelBorderWidth", 1);
|
|
479
|
+
}
|
|
331
480
|
put("labelSize", canonNumber(treeAttr(label, "fontSize"), at("labelSize")));
|
|
332
|
-
|
|
481
|
+
// yEd is a Java program: its logical fonts (Dialog, SansSerif, Monospaced, ...) are drawn in the faces Java gives
|
|
482
|
+
// them, and a font it does not have in Dialog's
|
|
483
|
+
const font = canonText(treeAttr(label, "fontFamily"), at("labelFont"));
|
|
484
|
+
put("labelFont", font === null ? null : javaFamily(font));
|
|
333
485
|
const style = treeAttr(label, "fontStyle");
|
|
334
486
|
if (style !== undefined) {
|
|
335
487
|
const known = FONT_STYLES.get(style.trim().toLowerCase());
|
|
@@ -341,38 +493,152 @@ function readLabelLook(label, node, put, at) {
|
|
|
341
493
|
put("labelItalic", known[1]);
|
|
342
494
|
}
|
|
343
495
|
}
|
|
496
|
+
readRotation(label, put, at);
|
|
344
497
|
if (node) {
|
|
345
|
-
|
|
498
|
+
const position = nodeLabelPosition(label, geometry, at);
|
|
499
|
+
put("labelPosition", position);
|
|
500
|
+
readInsideInset(label, geometry, position, put);
|
|
501
|
+
readOutsideOffset(label, geometry, position, put);
|
|
346
502
|
}
|
|
347
503
|
}
|
|
348
504
|
/**
|
|
349
|
-
* Reads a
|
|
350
|
-
* `
|
|
505
|
+
* Reads a label's `rotationAngle`: yEd is a Java2D program, whose angles turn clockwise on screen (y down), as the
|
|
506
|
+
* neutral `labelRotation` does.
|
|
351
507
|
* @param label - the label element
|
|
352
508
|
* @param put - receives the values
|
|
353
509
|
* @param at - the sites
|
|
354
510
|
*/
|
|
355
|
-
function
|
|
356
|
-
const
|
|
357
|
-
if (
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
511
|
+
function readRotation(label, put, at) {
|
|
512
|
+
const angle = canonSigned(treeAttr(label, "rotationAngle"), at("labelRotation"));
|
|
513
|
+
if (angle === null) {
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
const turn = ((angle % 360) + 360) % 360;
|
|
517
|
+
put("labelRotation", turn === 0 ? null : turn);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* How far from where its position puts it a label outside its node, or placed freely, is drawn: yEd writes every
|
|
521
|
+
* label's box as it draws it, so an outside label keeps its model's distance from the node (4 by default) and a
|
|
522
|
+
* free label its offset. Across the side it is beside, the label is moved by the gap between the node and its box;
|
|
523
|
+
* along that side (and on both axes for a free label over the node), by how far its box's middle is from the node's.
|
|
524
|
+
* A turned label's box is not its words' box, so it is left where its position puts it.
|
|
525
|
+
* @param label - the label element
|
|
526
|
+
* @param geometry - the node's `y:Geometry`
|
|
527
|
+
* @param position - where the label is placed
|
|
528
|
+
* @param put - receives the values
|
|
529
|
+
*/
|
|
530
|
+
function readOutsideOffset(label, geometry, position, put) {
|
|
531
|
+
const model = treeAttr(label, "modelName");
|
|
532
|
+
const free = position === "center" && model !== undefined && model !== "internal";
|
|
533
|
+
if (position === null || position.startsWith("inside-") || (position === "center" && !free)) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (Number(treeAttr(label, "rotationAngle") ?? 0) % 360 !== 0) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const num = (o, k) => Number(treeAttr(o, k) ?? Number.NaN);
|
|
540
|
+
const [x, y, w, h] = ["x", "y", "width", "height"].map((k) => num(label, k));
|
|
541
|
+
const [nw, nh] = [num(geometry, "width"), num(geometry, "height")];
|
|
542
|
+
if (![x, y, w, h, nw, nh].every(Number.isFinite)) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
const signed = (value) => {
|
|
546
|
+
const r = Math.round(value * 1000) / 1000;
|
|
547
|
+
return r === 0 ? null : r;
|
|
548
|
+
};
|
|
549
|
+
// across a side: the gap between the node and the box; along it: the box's middle against the node's
|
|
550
|
+
const offset = (lo, size, extent, before, after) => {
|
|
551
|
+
if (before) {
|
|
552
|
+
return signed(lo + size);
|
|
362
553
|
}
|
|
363
|
-
|
|
554
|
+
return after ? signed(lo - extent) : signed(lo + size / 2 - extent / 2);
|
|
555
|
+
};
|
|
556
|
+
put("labelOffsetX", offset(x, w, nw, position.includes("left"), position.includes("right")));
|
|
557
|
+
put("labelOffsetY", offset(y, h, nh, position.includes("top"), position.includes("bottom")));
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* How far in from the sides it is drawn against yEd puts a label inside its node (its internal model's insets, 4 by
|
|
561
|
+
* default), from the label's stored box, for a label sized to its words: the label is moved that far right of a left side, left of a right side, down
|
|
562
|
+
* from the top and up from the bottom.
|
|
563
|
+
* @param label - the label element
|
|
564
|
+
* @param geometry - the node's `y:Geometry`
|
|
565
|
+
* @param position - where the label is placed
|
|
566
|
+
* @param put - receives the values
|
|
567
|
+
*/
|
|
568
|
+
function readInsideInset(label, geometry, position, put) {
|
|
569
|
+
// a label sized to its node (a group's header band) has a box that is not its words'
|
|
570
|
+
const sized = treeAttr(label, "autoSizePolicy")?.startsWith("node_") === true;
|
|
571
|
+
if (position?.startsWith("inside-") !== true || sized) {
|
|
364
572
|
return;
|
|
365
573
|
}
|
|
574
|
+
const num = (o, k) => Number(treeAttr(o, k) ?? Number.NaN);
|
|
575
|
+
const [x, y, w, h] = ["x", "y", "width", "height"].map((k) => num(label, k));
|
|
576
|
+
const [nw, nh] = [num(geometry, "width"), num(geometry, "height")];
|
|
577
|
+
const inset = (value) => Number.isFinite(value) && value > 0 ? Math.round(value * 1000) / 1000 : null;
|
|
578
|
+
if (position.includes("left")) {
|
|
579
|
+
put("labelOffsetX", inset(x));
|
|
580
|
+
}
|
|
581
|
+
else if (position.includes("right")) {
|
|
582
|
+
const gap = inset(nw - x - w);
|
|
583
|
+
put("labelOffsetX", gap === null ? null : -gap);
|
|
584
|
+
}
|
|
585
|
+
if (position.includes("top")) {
|
|
586
|
+
put("labelOffsetY", inset(y));
|
|
587
|
+
}
|
|
588
|
+
else if (position.includes("bottom")) {
|
|
589
|
+
const gap = inset(nh - y - h);
|
|
590
|
+
put("labelOffsetY", gap === null ? null : -gap);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Where yEd draws a node label: from the label's box, which every model yEd writes stores relative to the node's
|
|
595
|
+
* top-left corner (a label entirely beside the node is outside it on that side), else from its model. A label inside
|
|
596
|
+
* the node is placed by its model: yEd's `internal` model puts it against a side or in a corner (`t`, `bl`, ...), or
|
|
597
|
+
* in the middle (`c`); any other model's label inside the node is in its middle.
|
|
598
|
+
* @param label - the label element
|
|
599
|
+
* @param geometry - the node's `y:Geometry`
|
|
600
|
+
* @param at - the sites
|
|
601
|
+
* @returns the position, or null
|
|
602
|
+
*/
|
|
603
|
+
function nodeLabelPosition(label, geometry, at) {
|
|
604
|
+
const outside = boxPosition(label, geometry);
|
|
605
|
+
if (outside !== null && outside !== "center") {
|
|
606
|
+
return outside;
|
|
607
|
+
}
|
|
366
608
|
const position = treeAttr(label, "modelPosition");
|
|
367
|
-
|
|
368
|
-
|
|
609
|
+
const model = treeAttr(label, "modelName");
|
|
610
|
+
if (model === "internal") {
|
|
611
|
+
return insidePosition(label, position);
|
|
612
|
+
}
|
|
613
|
+
if (model === "custom") {
|
|
614
|
+
return customPosition(label, outside, at);
|
|
615
|
+
}
|
|
616
|
+
if (outside !== null || position === undefined) {
|
|
617
|
+
return outside;
|
|
369
618
|
}
|
|
370
|
-
const
|
|
371
|
-
const known = model === "internal" && key === "t" ? "inside-top" : YED_POSITIONS.get(key);
|
|
619
|
+
const known = YED_POSITIONS.get(position.trim().toLowerCase());
|
|
372
620
|
if (known === undefined) {
|
|
373
621
|
noteAt(at("labelPosition"), STYLE_ISSUE.UNKNOWN_VALUE, position.slice(0, MAX_STYLE_VALUE_LENGTH));
|
|
374
622
|
}
|
|
375
|
-
|
|
623
|
+
return known ?? null;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Where a SmartNodeLabelModel (`custom`) label is drawn: where its stored box puts it, as for any other model, and
|
|
627
|
+
* where its ratios put it when the file stores no box (a label hung from the node's top edge into it is a header
|
|
628
|
+
* along its top). A box beside the node is handled before this.
|
|
629
|
+
* @param label - the label element
|
|
630
|
+
* @param outside - the box's position against the node, `center` or null
|
|
631
|
+
* @param at - the sites
|
|
632
|
+
* @returns the position, or null
|
|
633
|
+
*/
|
|
634
|
+
function customPosition(label, outside, at) {
|
|
635
|
+
const smart = treeChild(treeChild(label, "ModelParameter"), "SmartNodeLabelModelParameter");
|
|
636
|
+
if (smart === undefined) {
|
|
637
|
+
noteAt(at("labelPosition"), STYLE_ISSUE.UNKNOWN_VALUE, "custom");
|
|
638
|
+
return outside;
|
|
639
|
+
}
|
|
640
|
+
// the stored box is where yEd drew the label; the ratios place it only when the file stores no box
|
|
641
|
+
return outside ?? smartPosition(smart);
|
|
376
642
|
}
|
|
377
643
|
/**
|
|
378
644
|
* The nearest neutral position of a SmartNodeLabelModel placement. yEd puts the point `labelRatio` of the label
|
|
@@ -411,6 +677,59 @@ function sideOf(ratio, low, high) {
|
|
|
411
677
|
}
|
|
412
678
|
return ratio > 0 ? high : "";
|
|
413
679
|
}
|
|
680
|
+
/**
|
|
681
|
+
* Where a label's box lies against its node: beside a side or a corner, or `center` when it overlaps the node.
|
|
682
|
+
* @param label - the label element
|
|
683
|
+
* @param geometry - the node's `y:Geometry`
|
|
684
|
+
* @returns the position, or null when the label or the node has no box
|
|
685
|
+
*/
|
|
686
|
+
function boxPosition(label, geometry) {
|
|
687
|
+
const num = (o, k) => Number(treeAttr(o, k) ?? Number.NaN);
|
|
688
|
+
const [x, y, w, h] = ["x", "y", "width", "height"].map((k) => num(label, k));
|
|
689
|
+
const [nw, nh] = [num(geometry, "width"), num(geometry, "height")];
|
|
690
|
+
if (![x, y, w, h, nw, nh].every(Number.isFinite)) {
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
const side = (lo, size, extent) => {
|
|
694
|
+
if (lo + size <= 0) {
|
|
695
|
+
return -1;
|
|
696
|
+
}
|
|
697
|
+
return lo >= extent ? 1 : 0;
|
|
698
|
+
};
|
|
699
|
+
return BOX_POSITIONS[side(y, h, nh) + 1][side(x, w, nw) + 1];
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Where yEd's internal model draws a label: in the middle, or inside the node against the side or in the corner its
|
|
703
|
+
* `modelPosition` names. A label as wide as its node (a group's header) is drawn against the side its `alignment`
|
|
704
|
+
* names, so a right-aligned header along the top is in the top-right corner.
|
|
705
|
+
* @param label - the label element
|
|
706
|
+
* @param position - its `modelPosition`
|
|
707
|
+
* @returns the position
|
|
708
|
+
*/
|
|
709
|
+
function insidePosition(label, position) {
|
|
710
|
+
const inside = INTERNAL_POSITIONS.get((position ?? "c").trim().toLowerCase()) ?? "center";
|
|
711
|
+
const align = treeAttr(label, "alignment");
|
|
712
|
+
const across = treeAttr(label, "autoSizePolicy") === "node_width" && (align === "left" || align === "right");
|
|
713
|
+
return across && (inside === "inside-top" || inside === "inside-bottom") ? `${inside}-${align}` : inside;
|
|
714
|
+
}
|
|
715
|
+
/** yEd's internal label model positions, as the neutral position inside the node. */
|
|
716
|
+
const INTERNAL_POSITIONS = new Map([
|
|
717
|
+
["c", "center"],
|
|
718
|
+
["t", "inside-top"],
|
|
719
|
+
["b", "inside-bottom"],
|
|
720
|
+
["l", "inside-left"],
|
|
721
|
+
["r", "inside-right"],
|
|
722
|
+
["tl", "inside-top-left"],
|
|
723
|
+
["tr", "inside-top-right"],
|
|
724
|
+
["bl", "inside-bottom-left"],
|
|
725
|
+
["br", "inside-bottom-right"],
|
|
726
|
+
]);
|
|
727
|
+
/** A label's position by the side of the node it lies on: rows above, level, below; columns left, level, right. */
|
|
728
|
+
const BOX_POSITIONS = [
|
|
729
|
+
["top-left", "top", "top-right"],
|
|
730
|
+
["left", "center", "right"],
|
|
731
|
+
["bottom-left", "bottom", "bottom-right"],
|
|
732
|
+
];
|
|
414
733
|
/**
|
|
415
734
|
* The shape of a node realizer: its `y:Shape` where it has one, a GenericNode's configuration, or the realizer
|
|
416
735
|
* type itself for one that draws an image (SVG, image, table, UML).
|
|
@@ -426,11 +745,15 @@ function realizerShape(real, at) {
|
|
|
426
745
|
if (real.type === "ShapeNode" || real.type === "GroupNode" || real.type === "GenericGroupNode") {
|
|
427
746
|
return null;
|
|
428
747
|
}
|
|
748
|
+
if (real.type === "TableNode") {
|
|
749
|
+
// a yEd table or pool is a rectangle of bands
|
|
750
|
+
return canonEnum("shape", "rectangle", "yed", at("shape"));
|
|
751
|
+
}
|
|
429
752
|
if (real.type === "GenericNode") {
|
|
430
753
|
const conf = treeAttr(real.r, "configuration") ?? "";
|
|
431
|
-
const
|
|
432
|
-
if (
|
|
433
|
-
return
|
|
754
|
+
const known = configurationOutline(conf);
|
|
755
|
+
if (known !== null) {
|
|
756
|
+
return known.shape;
|
|
434
757
|
}
|
|
435
758
|
const lower = conf.slice(0, MAX_STYLE_VALUE_LENGTH).toLowerCase();
|
|
436
759
|
for (const [word, value] of GENERIC_SHAPES) {
|
|
@@ -447,28 +770,161 @@ function realizerShape(real, at) {
|
|
|
447
770
|
noteAt(at("shape"), STYLE_ISSUE.UNKNOWN_VALUE, real.type);
|
|
448
771
|
return `other:${real.type}`;
|
|
449
772
|
}
|
|
773
|
+
/** yEd's gradient: from the fill color at a node's top-left corner to `color2` at its bottom-right one. */
|
|
774
|
+
const YED_GRADIENT_ANGLE = 45;
|
|
450
775
|
/**
|
|
451
|
-
* Reads
|
|
776
|
+
* Reads a node realizer's fill: its color, and a gradient into `color2`. yEd paints no fill where the fill has no
|
|
777
|
+
* color or is transparent.
|
|
452
778
|
* @param real - the realizer
|
|
453
779
|
* @param put - receives the values
|
|
454
780
|
* @param at - the sites
|
|
455
781
|
*/
|
|
456
|
-
function
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
782
|
+
function readFill(real, put, at) {
|
|
783
|
+
const fill = treeChild(real.r, "Fill");
|
|
784
|
+
if (fill === undefined) {
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
if (treeAttr(fill, "hasColor") === "false" || treeAttr(fill, "transparent") === "true") {
|
|
788
|
+
noteAt(at("fill"), STYLE_ISSUE.NO_FILL, "transparent");
|
|
789
|
+
put("fillOpacity", 0);
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
readColor(treeAttr(fill, "color"), "fill", "fillOpacity", put, at);
|
|
793
|
+
const second = canonColor(treeAttr(fill, "color2"), "yed", at("fillGradient"));
|
|
794
|
+
if (second !== null) {
|
|
795
|
+
put("fillGradient", second.color);
|
|
796
|
+
put("fillGradientAngle", YED_GRADIENT_ANGLE);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* A `y:TableNode`'s `yed.table.*` style property, as a color.
|
|
801
|
+
* @param real - the table realizer
|
|
802
|
+
* @param name - the property's name
|
|
803
|
+
* @param at - the sites
|
|
804
|
+
* @returns the `#rrggbb` color, or null when the table does not set it
|
|
805
|
+
*/
|
|
806
|
+
function tableColor(real, name, at) {
|
|
807
|
+
const props = treeChildren(treeChild(real.r, "StyleProperties"), "Property");
|
|
808
|
+
const prop = props.find((p) => treeAttr(p, "name") === name);
|
|
809
|
+
return prop === undefined ? null : (canonColor(treeAttr(prop, "value"), "yed", at("stripeColors"))?.color ?? null);
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Reads a `y:TableNode` (a yEd table or BPMN pool) as bands over the node: its header (the table's top inset, or
|
|
813
|
+
* its left one for columns side by side) in `yed.table.header.color.main`, then its rows top to bottom (or its
|
|
814
|
+
* columns left to right) in `yed.table.lane.color.main` and `.alternating` by turns, then the opposite inset. A
|
|
815
|
+
* color the table does not set is the node's fill. The lines between the lanes and the row and column headers
|
|
816
|
+
* (`yed.table.header.color.alternating`) are not drawn.
|
|
817
|
+
* @param real - the realizer
|
|
818
|
+
* @param put - receives the values
|
|
819
|
+
* @param at - the sites
|
|
820
|
+
*/
|
|
821
|
+
function readTable(real, put, at) {
|
|
822
|
+
const table = treeChild(real.r, "Table");
|
|
823
|
+
const rows = treeChildren(treeChild(table, "Rows"), "Row");
|
|
824
|
+
const columns = treeChildren(treeChild(table, "Columns"), "Column");
|
|
825
|
+
const across = columns.length > 1 && rows.length <= 1;
|
|
826
|
+
const lanes = (across ? columns : rows).map((l) => Number(treeAttr(l, across ? "width" : "height")));
|
|
827
|
+
const insets = treeChild(table, "Insets");
|
|
828
|
+
const inset = (side) => Math.max(0, Number(treeAttr(insets, side) ?? 0) || 0);
|
|
829
|
+
const [head, tail] = across ? [inset("left"), inset("right")] : [inset("top"), inset("bottom")];
|
|
830
|
+
const sizes = [head, ...lanes, tail];
|
|
831
|
+
const total = sizes.reduce((a, b) => a + b, 0);
|
|
832
|
+
if (lanes.length === 0 || !sizes.every(Number.isFinite) || total <= 0) {
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
const fill = canonColor(treeAttr(treeChild(real.r, "Fill"), "color"), "yed", at("stripeColors"))?.color ?? "#ffffff";
|
|
836
|
+
const main = tableColor(real, "yed.table.lane.color.main", at) ?? fill;
|
|
837
|
+
const alternating = tableColor(real, "yed.table.lane.color.alternating", at) ?? main;
|
|
838
|
+
const header = tableColor(real, "yed.table.header.color.main", at) ?? fill;
|
|
839
|
+
const bands = [[head, header], ...lanes.map((size, i) => [size, i % 2 === 0 ? main : alternating]), [tail, fill]].filter(([size]) => size > 0);
|
|
840
|
+
put("stripeColors", bands.map(([, color]) => color).join(" "));
|
|
841
|
+
put("stripeSizes", bands.map(([size]) => String(Number((size / total).toFixed(6)))).join(" "));
|
|
842
|
+
if (across) {
|
|
843
|
+
put("stripeDirection", "right");
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* yEd's shared pictures (`<y:Resources>` on the graph): each resource's id to the picture as a URL, an SVG's text as
|
|
848
|
+
* a `data:image/svg+xml` URL and a `java.awt.image.BufferedImage` (base64 PNG) as a `data:image/png` one.
|
|
849
|
+
* @param snapshot - the graph
|
|
850
|
+
* @returns the pictures by id
|
|
851
|
+
*/
|
|
852
|
+
function yedResources(snapshot) {
|
|
853
|
+
const out = new Map();
|
|
854
|
+
for (const col of snapshot.graph) {
|
|
855
|
+
if (col.dtype !== "json" || col.meta.origin?.namespace !== "yfiles") {
|
|
856
|
+
continue;
|
|
463
857
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
858
|
+
addYedResources(plainCell(snapshot.graph.value(col.meta.name, 0)), out);
|
|
859
|
+
}
|
|
860
|
+
return out;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Adds the pictures of one yFiles graph value's `<y:Resources>`; an id already there keeps its picture.
|
|
864
|
+
* @param root - the graph's yFiles value
|
|
865
|
+
* @param out - the pictures by id, added to
|
|
866
|
+
*/
|
|
867
|
+
function addYedResources(root, out) {
|
|
868
|
+
for (const resources of treeChildren(root, "Resources")) {
|
|
869
|
+
for (const r of treeChildren(resources, "Resource")) {
|
|
870
|
+
const id = treeAttr(r, "id");
|
|
871
|
+
const url = id === undefined || out.has(id) ? null : yedResourceUrl(r);
|
|
872
|
+
if (id !== undefined && url !== null) {
|
|
873
|
+
out.set(id, url);
|
|
469
874
|
}
|
|
470
875
|
}
|
|
471
876
|
}
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* One `<y:Resource>` as a picture URL: a `java.awt.image.BufferedImage` (base64 PNG) as a `data:image/png` URL and
|
|
880
|
+
* an SVG's text as a `data:image/svg+xml` one.
|
|
881
|
+
* @param r - the resource element
|
|
882
|
+
* @returns the URL, or null for an empty resource or one that is no picture
|
|
883
|
+
*/
|
|
884
|
+
function yedResourceUrl(r) {
|
|
885
|
+
const text = treeText(r)?.trim() ?? "";
|
|
886
|
+
if (text === "") {
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
const type = treeAttr(r, "type") ?? "";
|
|
890
|
+
if (type.endsWith("BufferedImage")) {
|
|
891
|
+
return `data:image/png;base64,${text.replaceAll(/\s+/g, "")}`;
|
|
892
|
+
}
|
|
893
|
+
if (text.includes("<svg")) {
|
|
894
|
+
return `data:image/svg+xml;utf8,${encodeURIComponent(text)}`;
|
|
895
|
+
}
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* The picture an image or SVG node realizer draws (`y:Image refid`, `y:SVGModel/y:SVGContent refid`), stretched over
|
|
900
|
+
* the node's box, as yEd draws `y:ImageNode` and `y:SVGNode`. The realizer's own fill and border are kept beneath it:
|
|
901
|
+
* whether yEd paints them under the picture waits for a drawing by yEd itself (ISSUES.md).
|
|
902
|
+
* @param real - the realizer
|
|
903
|
+
* @param resources - the graph's shared pictures
|
|
904
|
+
* @param put - receives the values
|
|
905
|
+
*/
|
|
906
|
+
function readPicture(real, resources, put) {
|
|
907
|
+
const ref = real.type === "ImageNode"
|
|
908
|
+
? treeAttr(treeChild(real.r, "Image"), "refid")
|
|
909
|
+
: treeAttr(treeChild(treeChild(real.r, "SVGModel"), "SVGContent"), "refid");
|
|
910
|
+
const src = ref === undefined ? undefined : resources.get(ref);
|
|
911
|
+
if (src === undefined) {
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
put("image", src);
|
|
915
|
+
put("imageFit", "fill");
|
|
916
|
+
put("imageClip", "none");
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* Reads one node realizer.
|
|
920
|
+
* @param real - the realizer
|
|
921
|
+
* @param put - receives the values
|
|
922
|
+
* @param at - the sites
|
|
923
|
+
* @param resources - the graph's shared pictures, for image and SVG nodes
|
|
924
|
+
*/
|
|
925
|
+
function readNode(real, put, at, resources) {
|
|
926
|
+
const { r } = real;
|
|
927
|
+
readFill(real, put, at);
|
|
472
928
|
const border = treeChild(r, "BorderStyle");
|
|
473
929
|
if (border !== undefined) {
|
|
474
930
|
if (treeAttr(border, "hasColor") === "false") {
|
|
@@ -484,7 +940,17 @@ function readNode(real, put, at) {
|
|
|
484
940
|
put("width", canonNumber(treeAttr(geometry, "width"), at("width")));
|
|
485
941
|
put("height", canonNumber(treeAttr(geometry, "height"), at("height")));
|
|
486
942
|
put("shape", realizerShape(real, at));
|
|
487
|
-
|
|
943
|
+
const points = real.type === "GenericNode" ? configurationOutline(treeAttr(r, "configuration") ?? "")?.points : undefined;
|
|
944
|
+
if (points !== undefined) {
|
|
945
|
+
put("shapePoints", points);
|
|
946
|
+
}
|
|
947
|
+
if (real.type === "TableNode") {
|
|
948
|
+
readTable(real, put, at);
|
|
949
|
+
}
|
|
950
|
+
if (resources !== undefined && (real.type === "ImageNode" || real.type === "SVGNode")) {
|
|
951
|
+
readPicture(real, resources, put);
|
|
952
|
+
}
|
|
953
|
+
readLabels(treeChildren(r, "NodeLabel"), true, put, at, geometry);
|
|
488
954
|
}
|
|
489
955
|
/**
|
|
490
956
|
* Reads one edge realizer.
|
|
@@ -506,11 +972,20 @@ function readEdge(real, put, at) {
|
|
|
506
972
|
put("targetArrow", canonEnum("arrow", treeAttr(arrows, "target"), "yed", at("targetArrow")));
|
|
507
973
|
}
|
|
508
974
|
put("curved", edgeCurved(real));
|
|
975
|
+
if (real.type === "ArcEdge") {
|
|
976
|
+
// the bend yEd saves is the arc's apex, `y:Arc height` from the line between the ends (every yEd-saved arc
|
|
977
|
+
// in the corpus: scala-collection-mutable, Animatron__player__flow), so the arc is the circle through it
|
|
978
|
+
put("bendCurve", "arc");
|
|
979
|
+
}
|
|
509
980
|
readLabels(treeChildren(r, "EdgeLabel"), false, put, at);
|
|
510
981
|
}
|
|
511
982
|
/**
|
|
512
|
-
* Whether
|
|
513
|
-
*
|
|
983
|
+
* Whether an edge is drawn curved through its bends: an arc always; a spline only through its control points (with
|
|
984
|
+
* none it is a straight line); a polyline, and a generic edge (a framed or styled polyline), only when it smooths
|
|
985
|
+
* bends it has. A quad curve edge never, nor a Bezier edge of whole cubic pieces (two control points, five, ...): its
|
|
986
|
+
* curve is flattened into points on it (`readEdgeRoute`), drawn straight from one to the next, as a Graphviz spline
|
|
987
|
+
* is; rounding their corners cut inside the curve (a quad curve of straightness 1, whose points are its control
|
|
988
|
+
* polygon, was drawn bowed).
|
|
514
989
|
* @param real - the edge realizer
|
|
515
990
|
* @returns true when curved, null when a polyline does not say whether it smooths
|
|
516
991
|
*/
|
|
@@ -518,30 +993,61 @@ function edgeCurved(real) {
|
|
|
518
993
|
if (real.type === "ArcEdge") {
|
|
519
994
|
return true;
|
|
520
995
|
}
|
|
521
|
-
const
|
|
522
|
-
if (real.type
|
|
996
|
+
const points = treeChildren(treeChild(real.r, "Path"), "Point").length;
|
|
997
|
+
if (real.type === "QuadCurveEdge") {
|
|
998
|
+
return false;
|
|
999
|
+
}
|
|
1000
|
+
if (real.type === "BezierEdge") {
|
|
1001
|
+
// a count of control points no run of cubic pieces takes is not flattened: its corners are rounded
|
|
1002
|
+
return points > 0 && (points + 1) % 3 !== 0;
|
|
1003
|
+
}
|
|
1004
|
+
const bent = points > 0;
|
|
1005
|
+
if (real.type !== "PolyLineEdge" && real.type !== "GenericEdge") {
|
|
523
1006
|
return bent;
|
|
524
1007
|
}
|
|
525
1008
|
const smoothed = treeAttr(treeChild(real.r, "BendStyle"), "smoothed");
|
|
526
1009
|
return smoothed === undefined ? null : smoothed === "true" && bent;
|
|
527
1010
|
}
|
|
528
1011
|
/**
|
|
529
|
-
* An edge's
|
|
530
|
-
*
|
|
1012
|
+
* An edge's route from its `y:Path`: the ports its ends attach at (`sx sy`, `tx ty`: offsets from the node centers),
|
|
1013
|
+
* relative to each node's size, and its bends, relative to the centers of its two nodes (a self-loop's to its node's
|
|
1014
|
+
* size). yEd draws a polyline, an arc or a spline through the points; a Bezier or quad curve edge takes them as
|
|
1015
|
+
* control points its curve does not pass through, so its curve is flattened into the points it does pass through.
|
|
531
1016
|
* @param real - the edge realizer
|
|
532
|
-
* @param
|
|
1017
|
+
* @param nodes - each node's center x and y, width and height
|
|
533
1018
|
* @param source - the source node's index
|
|
534
1019
|
* @param target - the target node's index
|
|
535
|
-
* @
|
|
1020
|
+
* @param put - receives the values
|
|
536
1021
|
*/
|
|
537
|
-
function
|
|
538
|
-
const
|
|
1022
|
+
function readEdgeRoute(real, nodes, source, target, put) {
|
|
1023
|
+
const path = treeChild(real.r, "Path");
|
|
1024
|
+
const at = (k) => [nodes[4 * k], nodes[4 * k + 1]];
|
|
1025
|
+
const size = (k) => [nodes[4 * k + 2], nodes[4 * k + 3]];
|
|
1026
|
+
const offset = (key) => Number(treeAttr(path, key) ?? 0) || 0;
|
|
1027
|
+
const ends = [
|
|
1028
|
+
[at(source)[0] + offset("sx"), at(source)[1] + offset("sy")],
|
|
1029
|
+
[at(target)[0] + offset("tx"), at(target)[1] + offset("ty")],
|
|
1030
|
+
];
|
|
1031
|
+
const port = (k, end) => end[0] === at(k)[0] && end[1] === at(k)[1] ? null : canonNodeOffsets(at(k), size(k), [end], true);
|
|
1032
|
+
put("sourcePort", port(source, ends[0]));
|
|
1033
|
+
put("targetPort", port(target, ends[1]));
|
|
1034
|
+
let points = treeChildren(path, "Point").map((p) => [
|
|
539
1035
|
Number(treeAttr(p, "x")),
|
|
540
1036
|
Number(treeAttr(p, "y")),
|
|
541
1037
|
]);
|
|
542
|
-
|
|
543
|
-
|
|
1038
|
+
if (points.length > 0 && (real.type === "BezierEdge" || real.type === "QuadCurveEdge")) {
|
|
1039
|
+
const controls = [ends[0], ...points, ends[1]];
|
|
1040
|
+
const curve = real.type === "BezierEdge"
|
|
1041
|
+
? flattenCubic(controls)
|
|
1042
|
+
: flattenQuadSpline(controls, Number(treeAttr(real.r, "straightness") ?? YED_STRAIGHTNESS));
|
|
1043
|
+
points = (curve ?? controls).slice(1, -1);
|
|
1044
|
+
}
|
|
1045
|
+
put("bends", source === target
|
|
1046
|
+
? canonNodeOffsets(at(source), size(source), points, true)
|
|
1047
|
+
: canonBends(at(source), at(target), points, true));
|
|
544
1048
|
}
|
|
1049
|
+
/** yEd's quad curve straightness when a file gives none. */
|
|
1050
|
+
const YED_STRAIGHTNESS = 0.1;
|
|
545
1051
|
/**
|
|
546
1052
|
* A collector of canonical values for one target.
|
|
547
1053
|
* @param n - the element count
|
|
@@ -568,8 +1074,9 @@ export function valueColumns(n) {
|
|
|
568
1074
|
*/
|
|
569
1075
|
export function readYedStyles(snapshot, notes, budget) {
|
|
570
1076
|
let found = false;
|
|
571
|
-
|
|
572
|
-
|
|
1077
|
+
const resources = yedResources(snapshot);
|
|
1078
|
+
// each node's center, width and height, read with the node, for its edges' routes; NaN without yEd graphics
|
|
1079
|
+
const boxes = new Float64Array(4 * snapshot.nodeCount).fill(Number.NaN);
|
|
573
1080
|
const read = (target) => {
|
|
574
1081
|
const table = target === "node" ? snapshot.nodes : snapshot.edges;
|
|
575
1082
|
const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
|
|
@@ -594,14 +1101,14 @@ export function readYedStyles(snapshot, notes, budget) {
|
|
|
594
1101
|
out.put(i, property, value);
|
|
595
1102
|
};
|
|
596
1103
|
if (target === "node") {
|
|
597
|
-
readNode(real, put, at);
|
|
1104
|
+
readNode(real, put, at, resources);
|
|
598
1105
|
const geometry = treeChild(real.r, "Geometry");
|
|
599
|
-
|
|
600
|
-
|
|
1106
|
+
const [w, h] = [Number(treeAttr(geometry, "width")), Number(treeAttr(geometry, "height"))];
|
|
1107
|
+
boxes.set([Number(treeAttr(geometry, "x")) + w / 2, Number(treeAttr(geometry, "y")) + h / 2, w, h], 4 * i);
|
|
601
1108
|
}
|
|
602
1109
|
else {
|
|
603
1110
|
readEdge(real, put, at);
|
|
604
|
-
|
|
1111
|
+
readEdgeRoute(real, boxes, snapshot.edgeSource(i), snapshot.edgeTarget(i), put);
|
|
605
1112
|
}
|
|
606
1113
|
}
|
|
607
1114
|
return out.values;
|
|
@@ -621,6 +1128,8 @@ export const GRAPHML_STYLE_CAPABILITIES = Object.freeze({
|
|
|
621
1128
|
node: Object.freeze([
|
|
622
1129
|
"fill",
|
|
623
1130
|
"fillOpacity",
|
|
1131
|
+
"fillGradient",
|
|
1132
|
+
"fillGradientAngle",
|
|
624
1133
|
"borderColor",
|
|
625
1134
|
"borderWidth",
|
|
626
1135
|
"borderStyle",
|
|
@@ -644,6 +1153,8 @@ export const GRAPHML_STYLE_CAPABILITIES = Object.freeze({
|
|
|
644
1153
|
"targetArrow",
|
|
645
1154
|
"curved",
|
|
646
1155
|
"bends",
|
|
1156
|
+
"sourcePort",
|
|
1157
|
+
"targetPort",
|
|
647
1158
|
"label",
|
|
648
1159
|
"labelColor",
|
|
649
1160
|
"labelSize",
|
|
@@ -687,21 +1198,18 @@ export const YED_ARROWS = new Map([
|
|
|
687
1198
|
["square", "skewed_dash"],
|
|
688
1199
|
["crow", "crows_foot_many"],
|
|
689
1200
|
]);
|
|
690
|
-
/**
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
*/
|
|
1201
|
+
/** yEd's internal label model positions by neutral position: the center, and against a side or in a corner inside. */
|
|
1202
|
+
const INTERNAL_MODEL_POSITIONS = new Map([...INTERNAL_POSITIONS].map(([model, position]) => [position, model]));
|
|
1203
|
+
/** yEd's eight-position label model positions by neutral position, all outside the node. */
|
|
694
1204
|
const YED_MODEL_POSITIONS = new Map([
|
|
695
|
-
["
|
|
696
|
-
["
|
|
697
|
-
["
|
|
698
|
-
["
|
|
699
|
-
["left",
|
|
700
|
-
["right",
|
|
701
|
-
["
|
|
702
|
-
["
|
|
703
|
-
["bottom-left", ["eight_pos", "sw"]],
|
|
704
|
-
["bottom-right", ["eight_pos", "se"]],
|
|
1205
|
+
["top", "n"],
|
|
1206
|
+
["bottom", "s"],
|
|
1207
|
+
["left", "w"],
|
|
1208
|
+
["right", "e"],
|
|
1209
|
+
["top-left", "nw"],
|
|
1210
|
+
["top-right", "ne"],
|
|
1211
|
+
["bottom-left", "sw"],
|
|
1212
|
+
["bottom-right", "se"],
|
|
705
1213
|
]);
|
|
706
1214
|
/**
|
|
707
1215
|
* A value of a table, or the nearest value the table has.
|
|
@@ -751,22 +1259,30 @@ export function yedSpelled(table, value, nearest, property, approximate) {
|
|
|
751
1259
|
}
|
|
752
1260
|
return w.value;
|
|
753
1261
|
}
|
|
1262
|
+
/** The Java logical font each family the reader gives one is written back as. */
|
|
1263
|
+
const JAVA_LOGICAL = {
|
|
1264
|
+
[JAVA_SANS]: "Dialog",
|
|
1265
|
+
[JAVA_SERIF]: "Serif",
|
|
1266
|
+
[JAVA_MONO]: "Monospaced",
|
|
1267
|
+
};
|
|
754
1268
|
/**
|
|
755
|
-
*
|
|
1269
|
+
* A CSS family as the one font name yEd reads: a Java logical font's family as that font, else the list's first name.
|
|
1270
|
+
* @param family - the CSS family or family list
|
|
1271
|
+
* @returns the font name
|
|
1272
|
+
*/
|
|
1273
|
+
export function yedFontName(family) {
|
|
1274
|
+
return Object.hasOwn(JAVA_LOGICAL, family) ? JAVA_LOGICAL[family] : family.split(",")[0].trim();
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* A label's font attributes: family, size and style.
|
|
756
1278
|
* @param get - the element's values
|
|
757
|
-
* @
|
|
758
|
-
* @param approximate - records approximations
|
|
759
|
-
* @returns the label element, or null when the element has no label text
|
|
1279
|
+
* @returns the label element holding them
|
|
760
1280
|
*/
|
|
761
|
-
function
|
|
762
|
-
const text = get("label");
|
|
763
|
-
if (typeof text !== "string" || text.trim().length === 0) {
|
|
764
|
-
return null;
|
|
765
|
-
}
|
|
1281
|
+
function labelFontTree(get) {
|
|
766
1282
|
const label = {};
|
|
767
1283
|
const font = get("labelFont");
|
|
768
1284
|
if (typeof font === "string") {
|
|
769
|
-
label["@_fontFamily"] = font;
|
|
1285
|
+
label["@_fontFamily"] = yedFontName(font);
|
|
770
1286
|
}
|
|
771
1287
|
const size = get("labelSize");
|
|
772
1288
|
if (typeof size === "number") {
|
|
@@ -778,18 +1294,35 @@ function labelTree(get, node, approximate) {
|
|
|
778
1294
|
const style = (weight === "bold" ? "bold" : "") + (italic === true ? "italic" : "");
|
|
779
1295
|
label["@_fontStyle"] = style.length === 0 ? "plain" : style;
|
|
780
1296
|
}
|
|
1297
|
+
return label;
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* The label attributes and text of one element.
|
|
1301
|
+
* @param get - the element's values
|
|
1302
|
+
* @param node - whether it is a node label (which has a position)
|
|
1303
|
+
* @param approximate - records approximations
|
|
1304
|
+
* @returns the label element, or null when the element has no label text
|
|
1305
|
+
*/
|
|
1306
|
+
function labelTree(get, node, approximate) {
|
|
1307
|
+
const text = get("label");
|
|
1308
|
+
if (typeof text !== "string" || text.trim().length === 0) {
|
|
1309
|
+
return null;
|
|
1310
|
+
}
|
|
1311
|
+
const label = labelFontTree(get);
|
|
781
1312
|
const color = get("labelColor");
|
|
782
1313
|
if (typeof color === "string") {
|
|
783
1314
|
label["@_textColor"] = color.toUpperCase();
|
|
784
1315
|
}
|
|
785
1316
|
const position = node ? get("labelPosition") : null;
|
|
786
1317
|
if (typeof position === "string") {
|
|
787
|
-
const
|
|
788
|
-
|
|
1318
|
+
const inside = INTERNAL_MODEL_POSITIONS.get(position);
|
|
1319
|
+
const outside = YED_MODEL_POSITIONS.get(position);
|
|
1320
|
+
if (inside === undefined && outside === undefined) {
|
|
789
1321
|
approximate("labelPosition", position);
|
|
790
1322
|
}
|
|
791
|
-
|
|
792
|
-
label["@
|
|
1323
|
+
// the center and the inside positions in yEd's internal model, the outside ones in its eight-position one
|
|
1324
|
+
label["@_modelName"] = outside === undefined ? "internal" : "eight_pos";
|
|
1325
|
+
label["@_modelPosition"] = outside ?? inside ?? "c";
|
|
793
1326
|
}
|
|
794
1327
|
label["#text"] = text;
|
|
795
1328
|
return label;
|
|
@@ -808,6 +1341,14 @@ function shapeNodeTree(get, at, approximate) {
|
|
|
808
1341
|
const fillOpacity = get("fillOpacity");
|
|
809
1342
|
if (typeof fill === "string") {
|
|
810
1343
|
node["y:Fill"] = { "@_color": yedColor(fill, fillOpacity), "@_transparent": "false" };
|
|
1344
|
+
const second = get("fillGradient");
|
|
1345
|
+
if (typeof second === "string") {
|
|
1346
|
+
node["y:Fill"]["@_color2"] = second.toUpperCase();
|
|
1347
|
+
const angle = get("fillGradientAngle");
|
|
1348
|
+
if (angle !== YED_GRADIENT_ANGLE) {
|
|
1349
|
+
approximate("fillGradientAngle", angle ?? 0);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
811
1352
|
}
|
|
812
1353
|
else if (fillOpacity === 0) {
|
|
813
1354
|
node["y:Fill"] = { "@_hasColor": "false", "@_transparent": "false" };
|
|
@@ -912,50 +1453,25 @@ function polyLineEdgeTree(get, path, approximate) {
|
|
|
912
1453
|
}
|
|
913
1454
|
return { "y:PolyLineEdge": edge };
|
|
914
1455
|
}
|
|
915
|
-
/**
|
|
916
|
-
* Each element's values of the properties the writer writes, as a getter per element.
|
|
917
|
-
* @param picture - each element's value of a property
|
|
918
|
-
* @param target - nodes or edges
|
|
919
|
-
* @returns the getter
|
|
920
|
-
*/
|
|
921
|
-
function getter(picture, target) {
|
|
922
|
-
const columns = new Map();
|
|
923
|
-
for (const p of GRAPHML_STYLE_CAPABILITIES[target]) {
|
|
924
|
-
columns.set(p, picture(target, p));
|
|
925
|
-
}
|
|
926
|
-
return (i) => (property) => columns.get(property)?.[i] ?? null;
|
|
927
|
-
}
|
|
928
1456
|
/**
|
|
929
1457
|
* For a file graphty wrote: where a value read from the yEd graphics is what the writer writes for the block's own
|
|
930
1458
|
* value (a pentagon written as a hexagon, an opacity rounded to yEd's 255 steps), the block's exact value is the
|
|
931
1459
|
* truth, so a re-import gives back the same rules; a value another program changed since stays the truth.
|
|
1460
|
+
* @param snapshot - the graph
|
|
1461
|
+
* @param text - the block's text
|
|
932
1462
|
* @param read - the values the reader read, changed in place
|
|
933
|
-
* @param picture - each element's value of a property under the block's rules
|
|
934
|
-
* @param counts - the node and edge counts
|
|
935
|
-
* @param counts.node - the node count
|
|
936
|
-
* @param counts.edge - the edge count
|
|
937
|
-
* @param notes - a scratch note list for reading back what the writer writes
|
|
938
1463
|
*/
|
|
939
|
-
export function exactFromBlock(
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1464
|
+
export function exactFromBlock(snapshot, text, read) {
|
|
1465
|
+
const notes = new StyleNotes();
|
|
1466
|
+
takeFromBlock(snapshot, text, "graphml", (target) => ({
|
|
1467
|
+
values: read[target],
|
|
1468
|
+
properties: GRAPHML_STYLE_CAPABILITIES[target],
|
|
1469
|
+
writes: GRAPHML_STYLE_CAPABILITIES[target],
|
|
1470
|
+
readBack: (_i, want) => {
|
|
945
1471
|
const back = writtenAndReadBack(target, want, notes);
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
for (const property of GRAPHML_STYLE_CAPABILITIES[target]) {
|
|
950
|
-
const native = values[property]?.[i] ?? null;
|
|
951
|
-
const w = want(property);
|
|
952
|
-
if (native !== w && native === (back.get(property) ?? null)) {
|
|
953
|
-
values[property] ?? (values[property] = new Array(counts[target]).fill(null));
|
|
954
|
-
values[property][i] = w;
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
}
|
|
1472
|
+
return back === null ? null : (property) => back.get(property) ?? null;
|
|
1473
|
+
},
|
|
1474
|
+
}));
|
|
959
1475
|
}
|
|
960
1476
|
/**
|
|
961
1477
|
* An element's values written as the writer writes them and read back as the reader reads them.
|
|
@@ -1054,24 +1570,39 @@ function keptPath(table, columns, e) {
|
|
|
1054
1570
|
return undefined;
|
|
1055
1571
|
}
|
|
1056
1572
|
/**
|
|
1057
|
-
* An edge's `y:Path` with its points placed from its `bends` value between the written node centers
|
|
1058
|
-
*
|
|
1059
|
-
* had.
|
|
1573
|
+
* An edge's `y:Path` with its points placed from its `bends` value between the written node centers (a self-loop's
|
|
1574
|
+
* around its node) and its ports from its `sourcePort` and `targetPort`, so they read back as written; a port with no
|
|
1575
|
+
* value keeps the one of the path it had. Without a bend or port value, or without both centers, the path it had.
|
|
1060
1576
|
* @param kept - the path from the graphics the edge had, or undefined
|
|
1061
|
-
* @param
|
|
1062
|
-
* @param ends - the written
|
|
1577
|
+
* @param get - the edge's values
|
|
1578
|
+
* @param ends - the written boxes of its source and target
|
|
1579
|
+
* @param loop - whether the edge is a self-loop
|
|
1063
1580
|
* @returns the path, or undefined
|
|
1064
1581
|
*/
|
|
1065
|
-
function
|
|
1066
|
-
const
|
|
1067
|
-
|
|
1582
|
+
function pathWithRoute(kept, get, ends, loop) {
|
|
1583
|
+
const bends = get("bends");
|
|
1584
|
+
const [[c0, size0], [c1]] = ends;
|
|
1585
|
+
let points = null;
|
|
1586
|
+
if (typeof bends === "string") {
|
|
1587
|
+
points = loop ? nodeOffsetsToPoints(c0, size0, bends, true) : bendsToPoints(c0, c1, bends, true);
|
|
1588
|
+
}
|
|
1589
|
+
const ports = ["sourcePort", "targetPort"].map((property, k) => {
|
|
1590
|
+
const value = get(property);
|
|
1591
|
+
const [center, size] = ends[k];
|
|
1592
|
+
const at = typeof value === "string" ? nodeOffsetsToPoints(center, size, value, true) : null;
|
|
1593
|
+
return at === null ? null : [at[0][0] - center[0], at[0][1] - center[1]];
|
|
1594
|
+
});
|
|
1595
|
+
if (points === null && ports.every((p) => p === null)) {
|
|
1068
1596
|
return kept;
|
|
1069
1597
|
}
|
|
1070
1598
|
const path = {};
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1599
|
+
["sx", "sy", "tx", "ty"].forEach((key, k) => {
|
|
1600
|
+
const port = ports[k >> 1];
|
|
1601
|
+
path[`@_${key}`] = port === null ? (treeAttr(kept, key) ?? "0.0") : String(port[k & 1]);
|
|
1602
|
+
});
|
|
1603
|
+
const written = points ??
|
|
1604
|
+
treeChildren(kept, "Point").map((q) => [Number(treeAttr(q, "x")), Number(treeAttr(q, "y"))]);
|
|
1605
|
+
path["y:Point"] = written.map(([x, y]) => ({ "@_x": String(x), "@_y": String(y) }));
|
|
1075
1606
|
return path;
|
|
1076
1607
|
}
|
|
1077
1608
|
/**
|
|
@@ -1109,27 +1640,27 @@ export function graphmlStyledExport(snapshot, input) {
|
|
|
1109
1640
|
const picture = (target, property) => input.picture(target, property);
|
|
1110
1641
|
const nodeColumns = treeColumns(snapshot.nodes);
|
|
1111
1642
|
const edgeColumns = treeColumns(snapshot.edges);
|
|
1112
|
-
const getNode =
|
|
1113
|
-
const getEdge =
|
|
1643
|
+
const getNode = elementValues(picture, "node", GRAPHML_STYLE_CAPABILITIES.node);
|
|
1644
|
+
const getEdge = elementValues(picture, "edge", GRAPHML_STYLE_CAPABILITIES.edge);
|
|
1114
1645
|
const nodeTrees = [];
|
|
1115
1646
|
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
1116
1647
|
const get = getNode(i);
|
|
1117
1648
|
const at = keptPosition(snapshot.nodes, nodeColumns, i) ?? columnPosition(snapshot, i, get);
|
|
1118
1649
|
nodeTrees.push(shapeNodeTree(get, at, approximateFor("node")));
|
|
1119
1650
|
}
|
|
1120
|
-
const
|
|
1651
|
+
const boxes = nodeTrees.map((tree) => {
|
|
1121
1652
|
const geometry = treeChild(treeChild(tree, "ShapeNode"), "Geometry");
|
|
1122
1653
|
const at = (k) => Number(treeAttr(geometry, k) ?? Number.NaN);
|
|
1123
|
-
return [
|
|
1654
|
+
return [
|
|
1655
|
+
[at("x") + at("width") / 2, at("y") + at("height") / 2],
|
|
1656
|
+
[at("width"), at("height")],
|
|
1657
|
+
];
|
|
1124
1658
|
});
|
|
1125
1659
|
const edgeTrees = [];
|
|
1126
1660
|
for (let e = 0; e < snapshot.edgeCount; e++) {
|
|
1127
1661
|
const get = getEdge(e);
|
|
1128
|
-
const
|
|
1129
|
-
|
|
1130
|
-
centers[snapshot.edgeTarget(e)],
|
|
1131
|
-
];
|
|
1132
|
-
const path = pathWithBends(keptPath(snapshot.edges, edgeColumns, e), get("bends"), ends);
|
|
1662
|
+
const [source, target] = [snapshot.edgeSource(e), snapshot.edgeTarget(e)];
|
|
1663
|
+
const path = pathWithRoute(keptPath(snapshot.edges, edgeColumns, e), get, [boxes[source], boxes[target]], source === target);
|
|
1133
1664
|
edgeTrees.push(polyLineEdgeTree(get, path, approximateFor("edge")));
|
|
1134
1665
|
}
|
|
1135
1666
|
const out = snapshot.withColumns();
|