@graphty/graph-io 0.3.48 → 0.3.50
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-BRXsll0T.js} +2 -2
- package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-BRXsll0T.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-yl0f_qLO.js} +931 -164
- package/dist/chunks/block-yl0f_qLO.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-DizmppHy.js} +5 -4
- package/dist/chunks/{context-cgmmOxZ2.js.map → context-DizmppHy.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-CmvJXYeH.js} +67 -16
- package/dist/chunks/credentials-CmvJXYeH.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-Dhez_Cew.js} +11 -2
- package/dist/chunks/descriptor-Dhez_Cew.js.map +1 -0
- package/dist/chunks/{emit-CD8xnY8s.js → emit-7Jkpg0yd.js} +1788 -133
- package/dist/chunks/emit-7Jkpg0yd.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-ChjL5fmP.js → exporter-1Ajud15J.js} +9 -8
- package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-1Ajud15J.js.map} +1 -1
- package/dist/chunks/{exporter-BIdaoIgh.js → exporter-B6yvL3wy.js} +7 -7
- package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-B6yvL3wy.js.map} +1 -1
- 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-DtVU80Fa.js → exporter-CA5q8ROP.js} +9 -8
- package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-CA5q8ROP.js.map} +1 -1
- package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-CQQZFJ2v.js} +1284 -156
- package/dist/chunks/exporter-CQQZFJ2v.js.map +1 -0
- 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-Dc21MAdg.js} +387 -31
- package/dist/chunks/generic-Dc21MAdg.js.map +1 -0
- package/dist/chunks/{importer-B87_fmVx.js → importer-C6NVpCXp.js} +327 -84
- package/dist/chunks/importer-C6NVpCXp.js.map +1 -0
- package/dist/chunks/{importer-DPZDN40-.js → importer-CKFe4q54.js} +25 -17
- package/dist/chunks/importer-CKFe4q54.js.map +1 -0
- package/dist/chunks/{importer-Bji2MeWr.js → importer-CKbUbsJA.js} +13 -10
- package/dist/chunks/{importer-Bji2MeWr.js.map → importer-CKbUbsJA.js.map} +1 -1
- package/dist/chunks/{importer-CB_zV5_L.js → importer-ClCsdgTJ.js} +208 -1104
- package/dist/chunks/importer-ClCsdgTJ.js.map +1 -0
- package/dist/chunks/{importer-e3huMZbm.js → importer-CyVZTrf0.js} +14 -10
- package/dist/chunks/importer-CyVZTrf0.js.map +1 -0
- package/dist/chunks/{importer-CVT-JyDE.js → importer-DgG4v1Ms.js} +1537 -355
- package/dist/chunks/importer-DgG4v1Ms.js.map +1 -0
- package/dist/chunks/{importer-Cyy6UseH.js → importer-asFUrIsj.js} +66 -13
- package/dist/chunks/importer-asFUrIsj.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-IVRq2Uoo.js} +282 -74
- package/dist/chunks/lexicon-IVRq2Uoo.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-Cy3_SHRZ.js +79 -0
- package/dist/chunks/round-trip-Cy3_SHRZ.js.map +1 -0
- package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-BXwVbza3.js} +5 -5
- package/dist/chunks/sigv4-BXwVbza3.js.map +1 -0
- package/dist/chunks/{styles-CaABMoO1.js → styles-CAVmBLgp.js} +1237 -138
- package/dist/chunks/styles-CAVmBLgp.js.map +1 -0
- package/dist/chunks/styles-CPczw1Jz.js +1928 -0
- package/dist/chunks/styles-CPczw1Jz.js.map +1 -0
- package/dist/chunks/styles-boK6Ln54.js +2847 -0
- package/dist/chunks/styles-boK6Ln54.js.map +1 -0
- package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-XeFBQ6VS.js} +506 -175
- package/dist/chunks/styles-yed-XeFBQ6VS.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 +8 -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 +848 -194
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +230 -193
- 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 +141 -23
- package/dist/sources-cypher.js.map +1 -1
- package/dist/sources-ndex.js +2 -2
- package/dist/sources-rest.js +32 -6
- package/dist/sources-rest.js.map +1 -1
- package/dist/sources-sparql.d.ts +1 -0
- package/dist/sources-sparql.js +439 -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/exporter.d.ts.map +1 -1
- package/dist/src/formats/dot/exporter.js +34 -2
- package/dist/src/formats/dot/exporter.js.map +1 -1
- package/dist/src/formats/dot/importer.d.ts +6 -1
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +170 -33
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/index.d.ts +3 -1
- package/dist/src/formats/dot/index.d.ts.map +1 -1
- package/dist/src/formats/dot/index.js +2 -1
- package/dist/src/formats/dot/index.js.map +1 -1
- package/dist/src/formats/dot/label-places.d.ts +41 -0
- package/dist/src/formats/dot/label-places.d.ts.map +1 -0
- package/dist/src/formats/dot/label-places.js +185 -0
- package/dist/src/formats/dot/label-places.js.map +1 -0
- package/dist/src/formats/dot/names.d.ts +13 -0
- package/dist/src/formats/dot/names.d.ts.map +1 -1
- package/dist/src/formats/dot/names.js +13 -0
- package/dist/src/formats/dot/names.js.map +1 -1
- 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 +72 -2
- package/dist/src/formats/dot/styles.d.ts.map +1 -1
- package/dist/src/formats/dot/styles.js +1500 -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 +754 -102
- 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 +695 -164
- 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 +431 -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 +1843 -136
- package/dist/src/formats/json/styles.js.map +1 -1
- package/dist/src/formats/pajek/draw.d.ts +104 -0
- package/dist/src/formats/pajek/draw.d.ts.map +1 -0
- package/dist/src/formats/pajek/draw.js +382 -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 +1395 -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 +6 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -5
- 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/credentials.d.ts +50 -1
- package/dist/src/sources/credentials.d.ts.map +1 -1
- package/dist/src/sources/credentials.js +69 -0
- package/dist/src/sources/credentials.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 +125 -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 +9 -0
- package/dist/src/sources/rest/descriptor.js.map +1 -1
- package/dist/src/sources/rest/openalex.d.ts +4 -2
- package/dist/src/sources/rest/openalex.d.ts.map +1 -1
- package/dist/src/sources/rest/openalex.js +4 -2
- package/dist/src/sources/rest/openalex.js.map +1 -1
- package/dist/src/sources/rest/source.d.ts.map +1 -1
- package/dist/src/sources/rest/source.js +38 -0
- package/dist/src/sources/rest/source.js.map +1 -1
- package/dist/src/sources/run.d.ts +2 -0
- package/dist/src/sources/run.d.ts.map +1 -1
- package/dist/src/sources/run.js +30 -3
- package/dist/src/sources/run.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 +327 -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 +73 -0
- package/dist/src/sources/sparql/query.d.ts.map +1 -0
- package/dist/src/sources/sparql/query.js +164 -0
- package/dist/src/sources/sparql/query.js.map +1 -0
- package/dist/src/sources/types.d.ts +60 -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 +89 -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 +1139 -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 +4 -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 +232 -10
- 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 +475 -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 +687 -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 +224 -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/exporter.ts +37 -1
- package/src/formats/dot/importer.ts +192 -36
- package/src/formats/dot/index.ts +3 -1
- package/src/formats/dot/label-places.ts +241 -0
- package/src/formats/dot/names.ts +15 -0
- package/src/formats/dot/record.ts +336 -0
- package/src/formats/dot/styles.ts +1702 -149
- 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 +852 -110
- package/src/formats/graphml/styles-plain.ts +6 -15
- package/src/formats/graphml/styles-yed.ts +765 -176
- package/src/formats/graphml/styles-yfiles3.ts +487 -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 +2123 -171
- package/src/formats/pajek/draw.ts +469 -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 +1506 -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 +12 -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/credentials.ts +90 -1
- package/src/sources/cypher/descriptor.ts +7 -1
- package/src/sources/cypher/index.ts +149 -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 +9 -0
- package/src/sources/rest/openalex.ts +4 -2
- package/src/sources/rest/source.ts +41 -0
- package/src/sources/run.ts +35 -3
- package/src/sources/sigv4.ts +6 -4
- package/src/sources/sparql/descriptor.ts +67 -0
- package/src/sources/sparql/index.ts +371 -0
- package/src/sources/sparql/ntriples.ts +219 -0
- package/src/sources/sparql/params.ts +28 -0
- package/src/sources/sparql/query.ts +216 -0
- package/src/sources/types.ts +68 -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 +107 -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 +1303 -84
- package/src/styles/cyjs/defaults-table.ts +4 -0
- package/src/styles/cyjs/emit.ts +268 -14
- package/src/styles/cyjs/face.ts +372 -0
- package/src/styles/cyjs/mappers.ts +506 -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 +698 -5
- package/src/styles/vocabulary.ts +232 -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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles-boK6Ln54.js","sources":["../../src/formats/dot/names.ts","../../src/styles/io/writer.ts","../../src/formats/dot/label-places.ts","../../src/formats/dot/record.ts","../../src/formats/dot/styles.ts"],"sourcesContent":["/**\n * The names the DOT importer and exporter share: the format name, the column origin, the\n * format-owned columns (design section 5.6: `graphty.` prefix) and the attribute names the format\n * gives a fixed meaning to.\n */\n\nimport { type ColumnOriginInput } from \"@graphty/graph-format\";\n\n/**\n * The format name.\n * @category Plugin helpers\n */\nexport const DOT_FORMAT = \"dot\";\n\n/**\n * The origin recorded on every column the importer declares.\n * @category Plugin helpers\n */\nexport const DOT_ORIGIN: ColumnOriginInput = Object.freeze({ format: DOT_FORMAT });\n\n/**\n * The bool node column marking a cluster's container node.\n * @category Plugin helpers\n */\nexport const CLUSTER_COLUMN = \"graphty.cluster\";\n\n/**\n * The u32 node column (role parent, refersTo node) holding a member's cluster.\n * @category Plugin helpers\n */\nexport const PARENT_COLUMN = \"graphty.parent\";\n\n/**\n * The string edge column (role sourcePort) holding an edge's tail port.\n * @category Plugin helpers\n */\nexport const SOURCE_PORT_COLUMN = \"graphty.sourcePort\";\n\n/**\n * The string edge column (role targetPort) holding an edge's head port.\n * @category Plugin helpers\n */\nexport const TARGET_PORT_COLUMN = \"graphty.targetPort\";\n\n/**\n * The attribute that is the display label (kept as text with role label).\n * @category Plugin helpers\n */\nexport const LABEL_ATTRIBUTE = \"label\";\n\n/**\n * The node attribute holding a position, mapped to the position role column (design section 5.2).\n * @category Plugin helpers\n */\nexport const POS_ATTRIBUTE = \"pos\";\n\n/**\n * The node position column when the import keeps `pos` as text too (the `keepPositionSource` option).\n * @category Plugin helpers\n */\nexport const POSITION_COLUMN = \"graphty.position\";\n\n/**\n * The edge attribute cgraph uses as an edge's identity within its endpoints, mapped to the edge id role.\n * @category Plugin helpers\n */\nexport const KEY_ATTRIBUTE = \"key\";\n\n/**\n * The node attribute a `!` suffix of `pos` sets (Graphviz's own spelling of a pinned position).\n * @category Plugin helpers\n */\nexport const PIN_ATTRIBUTE = \"pin\";\n\n/**\n * The key under meta.extra holding the format's graph flags (`{ strict: true }`).\n * @category Plugin helpers\n */\nexport const DOT_META_KEY = \"dot\";\n\n/**\n * The string node column holding the `rank` of the non-cluster subgraph a node is in (`same`,\n * `min`, `max`, `source` or `sink`): Graphviz's dot puts the subgraph's nodes on one rank, or on\n * the first or last. Set only on nodes of such a subgraph.\n * @category Plugin helpers\n */\nexport const RANK_COLUMN = \"graphty.rank\";\n\n/**\n * The string node column naming the rank subgraph a node is in (`graphty.rank`): the subgraph's\n * name, or `%<n>` for the n-th anonymous one, so the nodes of one subgraph share a value.\n * @category Plugin helpers\n */\nexport const RANK_SET_COLUMN = \"graphty.rankSet\";\n","/**\n * Writing a graph's styles: what `exportGraph(snapshot, format, { styles })` hands a format's exporter, the losses\n * reported before anything is written, and, for an exporter whose block goes into attributes, the snapshot with the\n * `graphty.styles` block and the tagged per-element values added as attributes.\n */\n\nimport type { GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { agree, plural } from \"../../common/plural.js\";\nimport type { GraphExporter, LossNote } from \"../../types.js\";\nimport { STYLE_ISSUE } from \"../codes.js\";\nimport { toolDefaults } from \"../defaults.js\";\nimport { styleFingerprint } from \"../plan/features.js\";\nimport { canonicalFor, dataCell, degreeValues, plainCell, resolveStyles } from \"../plan/resolve.js\";\nimport type {\n ExtractedStyles,\n Mapping,\n StyleColumn,\n StyleProperty,\n StyleRule,\n StyleTarget,\n StyleValue,\n StyleWriteCapabilities,\n} from \"../types.js\";\nimport { STYLE_BLOCK_NAME, styleBlockLosses, styleTag, writeStyleBlock } from \"./block.js\";\n\n/**\n * What an exporter with a `styles` member receives as `options.styles` when styles are being written.\n * @category Styles\n */\nexport interface ExporterStyleInput {\n /**\n * Each element's value of one property, by element index (null where no rule gives one): what graphty draws, to\n * write into the format's own style slots.\n * @param target - nodes or edges\n * @param property - the property\n * @returns the values\n */\n picture(target: StyleTarget, property: StyleProperty): readonly (StyleValue | null)[];\n /** The `graphty.styles` block (JSON text) to place where the format keeps extra data. */\n readonly block: string;\n /** The per-element style values the block's rules read, by attribute name (`graphty.style.<target>.<key>`). */\n readonly tags: {\n /** Node values. */\n readonly node: ReadonlyMap<string, StyleColumn>;\n /** Edge values. */\n readonly edge: ReadonlyMap<string, StyleColumn>;\n };\n /** The styles themselves, for a format with a style language of its own. */\n readonly rules: ExtractedStyles;\n}\n\n/**\n * The options an exporter with a `styles` member reads its styles from: type its options as `Opts &\n * ExporterStyleOptions`.\n * @category Styles\n */\nexport interface ExporterStyleOptions {\n /** Present when styles are being written. */\n readonly styles?: ExporterStyleInput | undefined;\n}\n\n/** What an export with styles writes and loses, worked out before writing. */\ninterface PreparedStyleExport {\n /** The snapshot to hand the exporter: style roles removed, and the block and tagged values added as attributes. */\n readonly snapshot: GraphSnapshot;\n /** The exporter's `options.styles`, or null for an exporter without a `styles` member. */\n readonly input: ExporterStyleInput | null;\n /** W_STYLE_ notes: every property not written natively, and the rules when they are not kept. */\n readonly notes: readonly LossNote[];\n /** E_STYLES_MISMATCH when the styles belong to a different graph; nothing is then written. */\n readonly refusal: LossNote | null;\n}\n\n/** The roles of columns that hold styles; with styles given they are data, never written into a style slot. */\nconst STYLE_ROLES: ReadonlySet<string> = new Set([\"color\", \"size\", \"shape\", \"thickness\", \"hidden\"]);\nconst TARGETS: readonly StyleTarget[] = [\"node\", \"edge\"];\n\n/**\n * Works out an export with styles: the refusal when the styles belong to another graph, the losses, the exporter's\n * `options.styles`, and the snapshot to write.\n * @param snapshot - the graph being written\n * @param exporter - the format's exporter\n * @param given - the styles\n * @param plain - the export's other options, which decide what the format loses of the graph's data\n * @returns what to write and what is lost\n */\nexport function prepareStyleExport(\n snapshot: GraphSnapshot,\n exporter: GraphExporter,\n given: ExtractedStyles,\n plain?: Readonly<Record<string, unknown>>,\n): PreparedStyleExport {\n const fp = styleFingerprint(snapshot);\n const want = given.fingerprint;\n if (fp.nodes !== want.nodes || fp.edges !== want.edges || fp.ids !== want.ids) {\n return {\n snapshot,\n input: null,\n notes: [],\n refusal: Object.freeze({\n code: STYLE_ISSUE.MISMATCH,\n message: `the styles were read from or built for a different graph (${String(want.nodes)} nodes and ${String(want.edges)} edges, this graph has ${String(fp.nodes)} and ${String(fp.edges)}, or other node ids); nothing is written`,\n column: null,\n count: null,\n }),\n };\n }\n const caps = exporter.styles?.capabilities ?? null;\n let plan = writePlan(snapshot, exporter, given);\n if (keepsStyleBlock(exporter)) {\n // what the export loses of the graph's data, styles written as they are: the rules' inputs among it are carried\n let checked: readonly LossNote[];\n try {\n checked = exporter.check(plan.snapshot, plan.input === null ? plain : { ...plain, styles: plan.input });\n } catch {\n checked = [];\n }\n const carried = withLostInputsCarried(given, snapshot, checked);\n if (carried !== given) {\n plan = writePlan(snapshot, exporter, carried);\n }\n }\n return {\n snapshot: plan.snapshot,\n input: plan.input,\n notes: lossNotes(plan.extracted, exporter, caps, plan.picture, snapshot),\n refusal: null,\n };\n}\n\n/**\n * The work an exporter shares between the check and the write of one export call, by the styles input made for that\n * call (null until the first exporter step does it). Only an input writePlan() made is here, so an input a caller\n * builds and changes in place is always worked out again.\n */\nconst CALL_WORK = new WeakMap<\n ExporterStyleInput,\n { readonly key: readonly unknown[]; readonly value: unknown } | null\n>();\n\n/**\n * Work an exporter does from its styles input once per export call: the registry checks before it writes, with the\n * same input, graph and options. Outside an export call (an input the caller made) it is done every time.\n * @param input - the exporter's `options.styles`\n * @param key - what else the work reads (the graph, options), compared by identity\n * @param compute - the work\n * @returns its result\n */\nexport function sharedInExportCall<T>(input: ExporterStyleInput, key: readonly unknown[], compute: () => T): T {\n if (!CALL_WORK.has(input)) {\n return compute();\n }\n const done = CALL_WORK.get(input);\n if (done?.key.length === key.length && done.key.every((k, i) => k === key[i])) {\n return done.value as T;\n }\n const value = compute();\n CALL_WORK.set(input, { key, value });\n return value;\n}\n\n/**\n * What an exporter is handed to write a graph's styles: the snapshot with the block and tagged values added where\n * the format keeps them, and its `options.styles`.\n * @param snapshot - the graph\n * @param exporter - the exporter\n * @param extracted - the styles\n * @returns the plan\n */\nfunction writePlan(\n snapshot: GraphSnapshot,\n exporter: GraphExporter,\n extracted: ExtractedStyles,\n): {\n readonly snapshot: GraphSnapshot;\n readonly input: ExporterStyleInput | null;\n readonly extracted: ExtractedStyles;\n readonly picture: (target: StyleTarget, property: StyleProperty) => readonly (StyleValue | null)[];\n} {\n const caps = exporter.styles?.capabilities ?? null;\n const pictures = new Map<string, readonly (StyleValue | null)[]>();\n const picture = (target: StyleTarget, property: StyleProperty): readonly (StyleValue | null)[] => {\n const key = `${target}\\u0000${property}`;\n let values = pictures.get(key);\n if (values === undefined) {\n values = resolveStyles(extracted, target, property, snapshot);\n pictures.set(key, values);\n }\n return values;\n };\n const tags = { node: new Map<string, StyleColumn>(), edge: new Map<string, StyleColumn>() };\n for (const target of TARGETS) {\n for (const [key, col] of extracted.columns[target]) {\n tags[target].set(styleTag(target, key), col);\n }\n }\n const block = writeStyleBlock(extracted, { snapshot });\n const input = exporter.styles === undefined ? null : { picture, block, tags, rules: extracted };\n if (input !== null) {\n CALL_WORK.set(input, null);\n }\n return {\n snapshot: styledSnapshot(snapshot, caps, tags, block, extracted.styles.rules),\n input,\n extracted,\n picture,\n };\n}\n\n/**\n * Loss notes about a column whose values read back the same: written elsewhere (CSV's node table), under another\n * name a block finds by its values, with another role, storage or number type, or as a wider type.\n */\nconst VALUES_KEPT = /NODE_TABLE|NAME_CHANGED|ROLE_ASSUMED|STORAGE_CLASS|NUMBER_TYPE|INTEGRAL|WIDENED/;\n\n/**\n * The styles with every input the format will not read back as it is given carried as a style column of its own: a\n * data column the export drops or changes (its loss notes name it), and the in and out degrees when the file does not\n * keep the edges' direction. The rules then read the copies, which the file keeps beside the block, and give back the\n * same values.\n * @param extracted - the styles\n * @param snapshot - the graph\n * @param notes - what the export, styles written as they are, loses\n * @returns the styles, the same object when nothing is lost\n */\nfunction withLostInputsCarried(\n extracted: ExtractedStyles,\n snapshot: GraphSnapshot,\n notes: readonly LossNote[],\n): ExtractedStyles {\n const lost = new Set<string>();\n let direction = false;\n for (const note of notes) {\n if (!VALUES_KEPT.test(note.code)) {\n for (const name of note.columns ?? (note.column === null ? [] : [note.column])) {\n lost.add(name);\n }\n }\n direction ||= /DIRECTION/.test(note.code);\n }\n const carrier = new LostInputs(snapshot, lost, direction, extracted.columns);\n const rules = extracted.styles.rules.map((rule) => carrier.carry(rule));\n const changed = rules.some((rule, i) => rule !== extracted.styles.rules[i]);\n return changed ? { ...extracted, styles: { ...extracted.styles, rules }, columns: carrier.columns } : extracted;\n}\n\n/** Carries the inputs of rules that the format will not read back into style columns of their own. */\nclass LostInputs {\n /** The style columns, the copies added. */\n readonly columns: { readonly node: Map<string, StyleColumn>; readonly edge: Map<string, StyleColumn> };\n\n /** Whether the rule being carried read a lost input. */\n private touched = false;\n\n /**\n * A carrier for one export.\n * @param snapshot - the graph\n * @param lost - the data columns the export drops or changes\n * @param direction - whether the file loses the edges' direction (and so the in and out degrees)\n * @param columns - the styles' own style columns\n * @param columns.node - the node columns\n * @param columns.edge - the edge columns\n */\n constructor(\n private readonly snapshot: GraphSnapshot,\n private readonly lost: ReadonlySet<string>,\n private readonly direction: boolean,\n columns: { readonly node: ReadonlyMap<string, StyleColumn>; readonly edge: ReadonlyMap<string, StyleColumn> },\n ) {\n this.columns = { node: new Map(columns.node), edge: new Map(columns.edge) };\n }\n\n /**\n * A rule with every lost input it reads replaced by a copy of its values.\n * @param rule - the rule\n * @returns the rule read from copies, or the rule itself when it reads no lost input\n */\n carry(rule: StyleRule): StyleRule {\n this.touched = false;\n const { ext, ...given } = rule;\n const map = this.carryMap(rule);\n const where = this.walk(rule, given.where);\n if (!this.touched) {\n return rule;\n }\n const { map: _given, ...unmapped } = given;\n const plain = Object.keys(map).length === 0 ? { ...unmapped, where } : { ...unmapped, where, map };\n // a JSON copy drops undefined members, as the written block does; structuredClone would keep them\n const moved = JSON.parse(JSON.stringify(plain)) as StyleRule; // NOSONAR(S7784): undefined members must go\n return ext === undefined ? moved : { ...moved, ext };\n }\n\n /**\n * A rule's mappings with their lost inputs replaced. A passthrough reads a data column as the property's value: its\n * copy holds those values; one that gives no element a value (a list, text that is not a color) is left out, so\n * no other value the file reads back in the column (a list written as text) is given either.\n * @param rule - the rule\n * @returns the mappings\n */\n private carryMap(rule: StyleRule): Record<string, Mapping> {\n const map = Object.create(null) as Record<string, Mapping>;\n const { table } = this.tableOf(rule.target);\n for (const [property, mapping] of Object.entries(rule.map ?? {})) {\n if (mapping === undefined) {\n continue;\n }\n if (mapping.kind !== \"passthrough\") {\n map[property] = this.walk(rule, mapping);\n continue;\n }\n const name = (mapping.by as { data?: unknown }).data;\n const lostColumn = typeof name === \"string\" && this.lost.has(name) && table.has(name);\n const values = lostColumn ? this.cells(rule.target, name, canonicalFor(rule.target, property)) : null;\n if (values !== null && !values.some((v) => v !== null)) {\n this.touched = true;\n } else if (values !== null && this.isLost(rule.target, name)) {\n this.touched = true;\n map[property] = { ...mapping, by: this.copy(rule.target, `${property}.data.${name}`, () => values) };\n } else {\n map[property] = mapping;\n }\n }\n return map;\n }\n\n /**\n * A value with every other reference to a lost input reading a copy of its values as they are.\n * @param rule - the rule it belongs to\n * @param value - the value\n * @returns the value, references replaced\n */\n private walk<T>(rule: StyleRule, value: T): T {\n return JSON.parse(JSON.stringify(value, (_k, v: unknown) => this.replaced(rule, v))) as T;\n }\n\n /**\n * One reference with a lost input replaced by its copy: a data column, or a degree the file does not keep.\n * @param rule - the rule it belongs to\n * @param v - a value of the rule\n * @returns the value, or the reference to the copy\n */\n private replaced(rule: StyleRule, v: unknown): unknown {\n if (typeof v !== \"object\" || v === null || Array.isArray(v) || Object.keys(v).length !== 1) {\n return v;\n }\n const ref = v as { data?: unknown; computed?: unknown };\n if (this.isLost(rule.target, ref.data)) {\n const name = ref.data;\n this.touched = true;\n return this.copy(rule.target, `data.${name}`, () =>\n this.cells(rule.target, name, (raw) => (isStyleScalar(raw) ? raw : null)),\n );\n }\n const which = ref.computed;\n if ((which === \"indegree\" || which === \"outdegree\") && this.direction && rule.target === \"node\") {\n this.touched = true;\n return this.copy(rule.target, `computed.${which}`, () => degreeValues(this.snapshot, which));\n }\n return v;\n }\n\n /**\n * The reference to a copy of an input, made on first use and shared by every rule that reads it.\n * @param target - nodes or edges\n * @param base - what is copied\n * @param values - its values\n * @returns the reference\n */\n private copy(target: StyleTarget, base: string, values: () => StyleColumn): { style: string } {\n const key = `input.${base}`;\n const held = this.columns[target];\n if (!held.has(key)) {\n held.set(key, values());\n }\n return { style: key };\n }\n\n /**\n * Whether a name is a lost input that can be copied: only a column of plain values can, and a list, or a column with\n * no value, stays as it is.\n * @param target - nodes or edges\n * @param name - the name\n * @returns true for a lost input\n */\n private isLost(target: StyleTarget, name: unknown): name is string {\n const { table, n } = this.tableOf(target);\n return typeof name === \"string\" && this.lost.has(name) && table.has(name) && carriable(table, n, name);\n }\n\n /**\n * Every element's value of a data column.\n * @param target - nodes or edges\n * @param name - the column\n * @param read - the value of a cell\n * @returns the values\n */\n private cells(target: StyleTarget, name: string, read: (raw: unknown) => StyleValue | null): StyleColumn {\n const { table, n } = this.tableOf(target);\n return Array.from({ length: n }, (_u, i) => read(dataCell(table, name, i)));\n }\n\n /**\n * A target's table and row count.\n * @param target - nodes or edges\n * @returns the table and its row count\n */\n private tableOf(target: StyleTarget): { table: GraphSnapshot[\"nodes\"]; n: number } {\n const { snapshot } = this;\n return target === \"node\"\n ? { table: snapshot.nodes, n: snapshot.nodeCount }\n : { table: snapshot.edges, n: snapshot.edgeCount };\n }\n}\n\n/**\n * Whether a data column can be copied into a style column: some value, and every value text, a finite number or a\n * boolean.\n * @param table - the table\n * @param n - its row count\n * @param name - the column\n * @returns true when it can\n */\nfunction carriable(table: GraphSnapshot[\"nodes\"], n: number, name: string): boolean {\n let some = false;\n for (let i = 0; i < n; i++) {\n const cell = plainCell(table.value(name, i));\n if (cell !== null && cell !== undefined) {\n if (!isStyleScalar(cell)) {\n return false;\n }\n some = true;\n }\n }\n return some;\n}\n\n/**\n * Whether a cell is a value a style column holds: text, a finite number or a boolean.\n * @param v - the cell\n * @returns true for a scalar\n */\nfunction isStyleScalar(v: unknown): v is StyleValue {\n return typeof v === \"string\" || typeof v === \"boolean\" || (typeof v === \"number\" && Number.isFinite(v));\n}\n\n/**\n * Whether an exporter keeps the `graphty.styles` block, natively or as a graph attribute.\n * @param exporter - the exporter\n * @returns true when the block is written\n */\nfunction keepsStyleBlock(exporter: GraphExporter): boolean {\n const caps = exporter.styles?.capabilities;\n return (\n caps !== undefined &&\n (caps.block === \"native\" || (caps.block === \"attributes\" && exporter.capabilities.graphAttributes))\n );\n}\n\n/**\n * Whether a loss note is about a property only graphty draws (`graphty:<channel>`) in a file that keeps the block:\n * the block carries it, and no other program would draw it, so nothing is lost.\n * @param note - the note\n * @param exporter - the exporter writing the file\n * @returns true when the note names nothing lost\n */\nexport function isKeptGraphtyProperty(note: LossNote, exporter: GraphExporter): boolean {\n return note.style?.property.startsWith(\"graphty:\") === true && keepsStyleBlock(exporter);\n}\n\n/**\n * The losses of an export with styles: W_STYLE_NOT_WRITTEN for every property the format does not write natively\n * that at least one element carries a value of\n * (all of them for an exporter without a `styles` member), and W_STYLE_RULES_NOT_KEPT when the block is not kept.\n * @param extracted - the styles\n * @param exporter - the exporter\n * @param caps - its style capabilities, or null\n * @param picture - each element's value of a property\n * @param snapshot - the graph\n * @returns the notes\n */\nfunction lossNotes(\n extracted: ExtractedStyles,\n exporter: GraphExporter,\n caps: StyleWriteCapabilities | null,\n picture: (target: StyleTarget, property: StyleProperty) => readonly (StyleValue | null)[],\n snapshot: GraphSnapshot,\n): LossNote[] {\n const notes: LossNote[] = [];\n const kept = keepsStyleBlock(exporter);\n for (const target of TARGETS) {\n const written = new Set<string>(caps?.[target] ?? []);\n for (const property of ruleProperties(extracted.styles.rules, target)) {\n // a property only graphty draws is written into the block alone: lost only when the block is\n if (written.has(property) || (kept && property.startsWith(\"graphty:\"))) {\n if (target === \"edge\") {\n notes.push(...pairNotes(snapshot, exporter, property, picture(\"edge\", property as StyleProperty)));\n }\n } else {\n // a rule whose property no element ends up carrying loses nothing\n const note = notWrittenNote(target, property, exporter, picture);\n if (note.count !== 0) {\n notes.push(note);\n }\n }\n }\n }\n notes.push(...graphLossNotes(extracted, exporter, caps));\n if (kept) {\n notes.push(...styleBlockLosses(writeStyleBlock(extracted, { snapshot }), extracted.styles.rules.length));\n } else if (extracted.styles.rules.length > 0) {\n notes.push(\n Object.freeze({\n code: STYLE_ISSUE.RULES_NOT_KEPT,\n message: `the style rules are not kept: the ${exporter.format} format has no place for them; importing the file infers them again from what it holds`,\n column: null,\n count: extracted.styles.rules.length,\n }),\n );\n }\n return notes;\n}\n\n/**\n * W_STYLE_NOT_WRITTEN for every graph property the format does not write, except one whose value is what the program\n * the format is written for draws anyway (a white background for yEd): nothing is lost there.\n * @param extracted - the styles\n * @param exporter - the exporter\n * @param caps - its style capabilities, or null\n * @returns the notes\n */\nfunction graphLossNotes(\n extracted: ExtractedStyles,\n exporter: GraphExporter,\n caps: StyleWriteCapabilities | null,\n): LossNote[] {\n const graphWritten = new Set<string>(caps?.graph ?? []);\n const drawn: Readonly<Record<string, { readonly value: unknown } | undefined>> =\n (caps?.tool === undefined ? null : toolDefaults(caps.tool))?.graph ?? {};\n return Object.entries(extracted.styles.graph)\n .filter(([property, value]) => !graphWritten.has(property) && drawn[property]?.value !== value)\n .map(([property]) => property)\n .map((property) =>\n Object.freeze({\n code: STYLE_ISSUE.NOT_WRITTEN,\n message: `the graph's ${property} is not written: the ${exporter.format} format has no place for it`,\n column: null,\n count: 1,\n style: Object.freeze({ target: \"graph\" as const, property: property as \"background\" }),\n }),\n );\n}\n\n/**\n * The properties the rules of a target write, in first-written order.\n * @param rules - the rules\n * @param target - nodes or edges\n * @returns the properties\n */\nfunction ruleProperties(rules: readonly StyleRule[], target: StyleTarget): Set<string> {\n return new Set(\n rules\n .filter((rule) => rule.target === target)\n .flatMap((rule) => [...Object.keys(rule.set ?? {}), ...Object.keys(rule.map ?? {})]),\n );\n}\n\n/**\n * W_STYLE_NOT_WRITTEN for a property the format has no place for.\n * @param target - nodes or edges\n * @param property - the property\n * @param exporter - the exporter\n * @param picture - each element's value of a property\n * @returns the note\n */\nfunction notWrittenNote(\n target: StyleTarget,\n property: string,\n exporter: GraphExporter,\n picture: (target: StyleTarget, property: StyleProperty) => readonly (StyleValue | null)[],\n): LossNote {\n const count = picture(target, property as StyleProperty).filter((v) => v !== null).length;\n return Object.freeze({\n code: STYLE_ISSUE.NOT_WRITTEN,\n message: `${target} ${property} is not written: the ${exporter.format} format has no place for it (${String(count)} ${target}${plural(count)} ${agree(count, \"has\", \"have\")} a value)`,\n column: null,\n count,\n style: Object.freeze({ target, property: property as StyleProperty }),\n });\n}\n\n/**\n * W_STYLE_APPROXIMATED for the second halves of undirected edges in a directed graph whose value of a property\n * differs from the first half's: every format writes such an edge once, so both halves read back with one value.\n * @param snapshot - the graph\n * @param exporter - the exporter\n * @param property - the edge property\n * @param values - each edge's value\n * @returns the note, or none\n */\nfunction pairNotes(\n snapshot: GraphSnapshot,\n exporter: GraphExporter,\n property: string,\n values: readonly (StyleValue | null)[],\n): LossNote[] {\n const pair = snapshot.edges.byRole(\"pair\");\n let count = 0;\n for (let i = 0; pair !== null && i < values.length; i++) {\n const other = pair.isSet(i) ? (pair.value(i) as number) : i;\n if (other < i && values[i] !== values[other]) {\n count++;\n }\n }\n if (count === 0) {\n return [];\n }\n return [\n Object.freeze({\n code: STYLE_ISSUE.APPROXIMATED,\n message: `edge ${property}: ${String(count)} undirected edge${plural(count)} in a directed graph ${agree(count, \"has\", \"have\")} another value on each half; the ${exporter.format} format writes the edge once, with the first half's value`,\n column: null,\n count,\n style: Object.freeze({ target: \"edge\" as const, property: property as StyleProperty }),\n }),\n ];\n}\n\n/**\n * The snapshot an exporter writes when styles are given: columns with a style role keep their data but lose the\n * role (the style writer is the only thing that writes the format's style slots), and for `block: \"attributes\"`\n * the block becomes a graph attribute and the tagged values element attributes.\n * @param snapshot - the graph\n * @param caps - the exporter's style capabilities, or null\n * @param tags - the tagged per-element values\n * @param tags.node - node values by attribute name\n * @param tags.edge - edge values by attribute name\n * @param block - the block's text\n * @param rules - the rules written, which keep a style value column of an earlier write they read as data\n * @returns the snapshot to write (the same object when nothing changes)\n */\nfunction styledSnapshot(\n snapshot: GraphSnapshot,\n caps: StyleWriteCapabilities | null,\n tags: { readonly node: ReadonlyMap<string, StyleColumn>; readonly edge: ReadonlyMap<string, StyleColumn> },\n block: string,\n rules: readonly StyleRule[],\n): GraphSnapshot {\n const attributes = caps?.block === \"attributes\";\n // the per-element style values of an earlier write whose block was set aside are data now; these styles write\n // their own under the same names, so the old ones go, unless these styles read them as data\n const stale = { node: staleTags(snapshot.nodes, rules, \"node\"), edge: staleTags(snapshot.edges, rules, \"edge\") };\n // a format that writes the label from the styles has its label slot taken: the label column is data there too\n const roles = { node: roledNames(snapshot.nodes, caps, \"node\"), edge: roledNames(snapshot.edges, caps, \"edge\") };\n // the block of an earlier import is replaced by the one these styles write, wherever the format puts that\n const staleBlock = snapshot.graph.has(STYLE_BLOCK_NAME);\n const changes = [stale.node, stale.edge, roles.node, roles.edge].some((names) => names.length > 0);\n if (!attributes && !staleBlock && !changes) {\n return snapshot;\n }\n const out = snapshot.withColumns();\n if (staleBlock) {\n out.graph.remove(STYLE_BLOCK_NAME);\n }\n for (const target of TARGETS) {\n const table = target === \"node\" ? out.nodes : out.edges;\n for (const name of stale[target]) {\n table.remove(name);\n }\n for (const name of roles[target]) {\n const col = table.get(name);\n if (col !== null) {\n // an explicit undefined role in the patch replaces the column's role with none\n table.set(name, col, { role: undefined });\n }\n }\n }\n if (attributes) {\n setTagAttributes(out, tags);\n out.graph.set(STYLE_BLOCK_NAME, [block], { dtype: \"string\" });\n }\n return out;\n}\n\n/**\n * The per-element style values of an earlier write that these rules do not read as data.\n * @param table - the node or edge table\n * @param rules - the rules written\n * @param target - nodes or edges\n * @returns the column names\n */\nfunction staleTags(table: GraphSnapshot[\"nodes\"], rules: readonly StyleRule[], target: StyleTarget): string[] {\n const read = dataRead(rules, target);\n return table.names().filter((name) => isStyleTagName(name) && !read.has(name));\n}\n\n/**\n * The columns whose style role the styles take: every style role, and the label where the format writes the label\n * from the styles.\n * @param table - the node or edge table\n * @param caps - the exporter's style capabilities, or null\n * @param target - nodes or edges\n * @returns the column names\n */\nfunction roledNames(table: GraphSnapshot[\"nodes\"], caps: StyleWriteCapabilities | null, target: StyleTarget): string[] {\n const writesLabel = (caps?.[target] ?? []).includes(\"label\");\n return table.names().filter((name) => {\n const role = table.get(name)?.meta.role ?? \"\";\n return STYLE_ROLES.has(role) || (role === \"label\" && writesLabel);\n });\n}\n\n/**\n * Sets the tagged per-element values as element attributes, replacing those of an earlier import in the order of\n * these styles' columns, so writing a file read back gives the same bytes whichever elements held a value first.\n * @param out - the graph, changed in place\n * @param tags - the tagged values\n * @param tags.node - node values by attribute name\n * @param tags.edge - edge values by attribute name\n */\nfunction setTagAttributes(\n out: GraphSnapshot,\n tags: { readonly node: ReadonlyMap<string, StyleColumn>; readonly edge: ReadonlyMap<string, StyleColumn> },\n): void {\n for (const target of TARGETS) {\n const table = target === \"node\" ? out.nodes : out.edges;\n const prefix = styleTag(target, \"\");\n for (const name of table.names().filter((c) => c.startsWith(prefix))) {\n table.remove(name);\n }\n for (const [name, col] of tags[target]) {\n const dtype = tagDtype(col);\n table.set(name, dtype === \"string\" ? col.map((v) => (v === null ? null : String(v))) : col, { dtype });\n }\n }\n}\n\n/**\n * Whether a column name is one graphty writes per-element style values under: `graphty.style.<target>.<key>`, or\n * `graphty_style_<...>` where the format allows no dots in a name (GML, Cytoscape.js).\n * @param name - the column name\n * @returns true for a style value name\n */\nfunction isStyleTagName(name: string): boolean {\n return name.startsWith(\"graphty.style.\") || name.startsWith(\"graphty_style_\");\n}\n\n/**\n * The data columns the rules of one target read.\n * @param rules - the rules\n * @param target - nodes or edges\n * @returns the column names\n */\nexport function dataRead(rules: readonly StyleRule[], target: StyleTarget): Set<string> {\n const out = new Set<string>();\n for (const { ext: _ext, ...rule } of rules.filter((r) => r.target === target)) {\n JSON.stringify(rule, (_k, v: unknown) => {\n const data =\n typeof v === \"object\" && v !== null && !Array.isArray(v) ? (v as { data?: unknown }).data : null;\n if (typeof data === \"string\" && Object.keys(v as object).length === 1) {\n out.add(data);\n }\n return v;\n });\n }\n return out;\n}\n\n/**\n * The dtype a tagged column is written with: numbers, booleans or text (a mixed column as text).\n * @param col - the values\n * @returns the dtype\n */\nfunction tagDtype(col: StyleColumn): \"f64\" | \"bool\" | \"string\" {\n let kind: string | null = null;\n for (const v of col) {\n if (v === null) {\n continue;\n }\n if (kind === null) {\n kind = typeof v;\n } else if (kind !== typeof v) {\n return \"string\";\n }\n }\n if (kind === \"number\") {\n return \"f64\";\n }\n return kind === \"boolean\" ? \"bool\" : \"string\";\n}\n","/**\n * Where Graphviz puts an edge's labels: a stored `lp` (the label's center), and the head and tail labels at\n * `head_lp` / `tail_lp` -- kept only with the edge's stored `pos` (`neato -n2` routes an edge without one again, and\n * places its labels again) -- or where Graphviz's `place_portlabel` (lib/common/splines.c) puts them, when the edge's\n * `labelangle` or `labeldistance` is not its default: `10 * labeldistance` points from the end of the line, turned\n * `labelangle` degrees (default -25) from the line. With both at their defaults Graphviz places end labels as external\n * labels, which graphty leaves to its own place beside the end. Read as offsets from where graphty puts each label:\n * the edge label from the middle of its route, an end label from where the line meets its node.\n */\n\nimport type { GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { type BendPoint, flattenCubic } from \"../../styles/canon/bends.js\";\nimport { num6 } from \"../../styles/canon/number.js\";\nimport type { StyleValue } from \"../../styles/types.js\";\n\n/** Graphviz's `PORT_LABEL_DISTANCE`, in points. */\nconst PORT_LABEL_DISTANCE = 10;\n\n/** Graphviz's `PORT_LABEL_ANGLE`, in degrees. */\nconst PORT_LABEL_ANGLE = -25;\n\n/** Graphviz's default node size, in inches. */\nconst DEFAULT_SIZE = { w: 0.75, h: 0.5 } as const;\n\n/** One attribute of an element as text, or null when it is unset. */\ntype Attr = (name: string) => string | null;\n\n/** Receives one property's value. */\ntype Put = (property: string, value: StyleValue | null) => void;\n\n/** What the label places of one graph's edges are read against. */\nexport interface LabelPlaceContext {\n /** A node's center from its position, in points, y up. */\n readonly center: (n: number) => BendPoint | null;\n /** A node's attribute. */\n readonly node: (n: number, name: string) => string | null;\n /**\n * Whether the layout engine places an edge label it was not given as an external label (every engine but `dot`,\n * which ranks a label as a node of its own): lib/common/postproc.c `addXLabels` takes each unplaced edge label as\n * an xlabel of the edge's middle, and lib/label/xlabels.c puts it, where nothing else is drawn, up and to the left\n * of that point, its box's lower right corner on it.\n */\n readonly external: boolean;\n}\n\n/**\n * Reads an edge's stored label places and its head and tail label places as offsets.\n * @param snapshot - the graph\n * @param cx - the graph's label place context\n * @param e - the edge\n * @param get - the edge's attributes\n * @param put - receives the values\n */\nexport function readLabelPlaces(snapshot: GraphSnapshot, cx: LabelPlaceContext, e: number, get: Attr, put: Put): void {\n const s = snapshot.edgeSource(e);\n const t = snapshot.edgeTarget(e);\n const [source, target] = [cx.center(s), cx.center(t)];\n const route = source === null || target === null ? null : edgeRoute(source, target, get(\"pos\"));\n const lp = (route?.start ?? null) === null ? null : point(get(\"lp\"));\n if (lp === null && cx.external && s !== t && (get(\"label\") ?? get(\"xlabel\")) !== null) {\n // ponytail: the first place xlabels.c tries; one that would cover another label or node moves elsewhere\n put(\"labelPosition\", \"center\");\n put(\"labelShiftX\", -0.5);\n put(\"labelShiftY\", -0.5);\n }\n if (route === null || source === null || target === null || s === t) {\n return;\n }\n if (lp !== null && get(\"label\") !== null) {\n const mid = routeMiddle(route.points);\n put(\"labelOffsetX\", num6(lp[0] - mid[0]));\n put(\"labelOffsetY\", num6(mid[1] - lp[1]));\n }\n readEndLabel(cx, route, { node: t, at: target, other: source }, \"head\", get, put);\n readEndLabel(cx, route, { node: s, at: source, other: target }, \"tail\", get, put);\n}\n\n/** One end of an edge: its node, that node's center and the other end's center. */\ninterface EdgeEnd {\n readonly node: number;\n readonly at: BendPoint;\n readonly other: BendPoint;\n}\n\n/**\n * Reads one end's label place as an offset from where its line meets its node.\n * @param cx - the graph's label place context\n * @param route - the edge's route\n * @param end - the end's node and the two centers\n * @param which - which end\n * @param get - the edge's attributes\n * @param put - receives the values\n */\nfunction readEndLabel(\n cx: LabelPlaceContext,\n route: EdgeRoute,\n end: EdgeEnd,\n which: \"head\" | \"tail\",\n get: Attr,\n put: Put,\n): void {\n if (get(`${which}label`) === null) {\n return;\n }\n const head = which === \"head\";\n const tip = (head ? route.end : route.start) ?? boundary(cx, end.node, end.at, end.other);\n // the nearest route point back from the end that is not the end itself (a spline with no arrow ends at it);\n // the route's last point is the node's center, past the end\n const back = head ? route.points.slice(0, -1).reverse() : route.points.slice(1);\n const toward = back.find((p) => Math.hypot(p[0] - tip[0], p[1] - tip[1]) > 1e-6) ?? end.other;\n const stored = route.start === null ? null : point(get(`${which}_lp`));\n const at = stored ?? portLabel(get, tip, toward);\n if (at !== null) {\n const prefix = head ? \"target\" : \"source\";\n put(`${prefix}LabelOffset`, 0);\n put(`${prefix}LabelOffsetX`, num6(at[0] - tip[0]));\n put(`${prefix}LabelOffsetY`, num6(tip[1] - at[1]));\n }\n}\n\n/**\n * Where Graphviz's `place_portlabel` puts an end label's center: only when the edge's `labelangle` or\n * `labeldistance` is not its default.\n * @param get - the edge's attributes\n * @param tip - the end of the line\n * @param toward - a point back along the line from the end\n * @returns the center, or null when Graphviz places the label as an external label\n */\nfunction portLabel(get: Attr, tip: BendPoint, toward: BendPoint): BendPoint | null {\n const turn = finite(get(\"labelangle\"), PORT_LABEL_ANGLE, -180);\n const distance = finite(get(\"labeldistance\"), 1, 0);\n if (turn === PORT_LABEL_ANGLE && distance === 1) {\n return null;\n }\n const angle = Math.atan2(toward[1] - tip[1], toward[0] - tip[0]) + (turn * Math.PI) / 180;\n const dist = PORT_LABEL_DISTANCE * distance;\n return [tip[0] + dist * Math.cos(angle), tip[1] + dist * Math.sin(angle)];\n}\n\n/**\n * A number attribute as Graphviz's `late_double` reads it: the default when unset or not a number, at least `low`.\n * @param raw - the value\n * @param fallback - the default\n * @param low - the least value\n * @returns the number\n */\nfunction finite(raw: string | null, fallback: number, low: number): number {\n const v = raw === null || raw.trim() === \"\" ? Number.NaN : Number(raw);\n return Number.isFinite(v) ? Math.max(low, v) : fallback;\n}\n\n/**\n * An \"x,y\" point (a trailing `!` allowed).\n * @param raw - the text\n * @returns the point, or null\n */\nfunction point(raw: string | null): BendPoint | null {\n const parts = (raw ?? \"\").replace(/!$/, \"\").split(\",\").map(Number);\n return parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1]) ? [parts[0], parts[1]] : null;\n}\n\n/** An edge's route: its points from center to center, and the ends of its line when stored. */\ninterface EdgeRoute {\n readonly points: BendPoint[];\n readonly start: BendPoint | null;\n readonly end: BendPoint | null;\n}\n\n/**\n * The route an edge is drawn along: its stored spline's points (flattened) between the two centers, and the ends of\n * its line where `pos` gives arrow points (`s,` / `e,`) or its spline's own ends.\n * @param source - the source's center\n * @param target - the target's center\n * @param pos - the edge's `pos`\n * @returns the route\n */\nfunction edgeRoute(source: BendPoint, target: BendPoint, pos: string | null): EdgeRoute {\n const tokens = (pos ?? \"\").split(\";\")[0].trim().split(/\\s+/).filter(Boolean);\n const marked = (flag: string): BendPoint | null => {\n const token = tokens.find((x) => x.startsWith(`${flag},`));\n return token === undefined ? null : point(token.slice(2));\n };\n const controls = tokens.filter((x) => !/^[es],/.test(x)).map((x) => point(x));\n const flat = controls.every((p) => p !== null) && controls.length >= 4 ? flattenCubic(controls) : null;\n if (flat === null) {\n return { points: [source, target], start: null, end: null };\n }\n return {\n points: [source, ...flat, target],\n start: marked(\"s\") ?? flat[0],\n end: marked(\"e\") ?? flat.at(-1) ?? null,\n };\n}\n\n/**\n * The point halfway along a route.\n * @param points - the route\n * @returns the point\n */\nfunction routeMiddle(points: readonly BendPoint[]): BendPoint {\n // ponytail: halfway by length; graphty puts a bent edge's label at its middle segment, close to it\n const lengths = points.slice(1).map((p, i) => Math.hypot(p[0] - points[i][0], p[1] - points[i][1]));\n let left = lengths.reduce((a, b) => a + b, 0) / 2;\n for (let i = 0; i < lengths.length; i++) {\n if (left <= lengths[i] && lengths[i] > 0) {\n const f = left / lengths[i];\n return [\n points[i][0] + f * (points[i + 1][0] - points[i][0]),\n points[i][1] + f * (points[i + 1][1] - points[i][1]),\n ];\n }\n left -= lengths[i];\n }\n return points[0];\n}\n\n/**\n * Where the straight line from a node's center toward a point leaves the node, the node taken as the ellipse of its\n * `width` and `height`.\n * @param cx - the label place context\n * @param n - the node\n * @param center - its center\n * @param toward - the point\n * @returns the point on its outline\n */\nfunction boundary(cx: LabelPlaceContext, n: number, center: BendPoint, toward: BendPoint): BendPoint {\n // ponytail: every shape taken as its ellipse; exact for the circles and ellipses the end labels sit on\n const inch = (name: \"width\" | \"height\", fallback: number): number => {\n const v = Number(cx.node(n, name) ?? Number.NaN);\n return (Number.isFinite(v) && v >= 0 ? v : fallback) * 72;\n };\n const [rx, ry] = [inch(\"width\", DEFAULT_SIZE.w) / 2, inch(\"height\", DEFAULT_SIZE.h) / 2];\n const [dx, dy] = [toward[0] - center[0], toward[1] - center[1]];\n const len = Math.hypot(dx, dy);\n if (len === 0 || rx === 0 || ry === 0) {\n return center;\n }\n const r = 1 / Math.hypot(dx / len / rx, dy / len / ry);\n return [center[0] + (dx / len) * r, center[1] + (dy / len) * r];\n}\n","/**\n * @file Graphviz record shapes (`record`, `Mrecord`): the field tree a record label describes and where Graphviz lays\n * each field, its dividers and its text lines out inside the node (lib/common/shapes.c `parse_reclbl`,\n * `size_reclbl`, `resize_reclbl`, `pos_reclbl`, `gen_fields`). Text widths are estimated from DejaVu Sans's advance\n * widths, which the specimen sheets pin; another font is measured as if it were DejaVu Sans.\n */\n\n/** One field of a record: its text lines (a leaf) or its sub-fields, laid left to right (`lr`) or top to bottom. */\ninterface Field {\n lines: RecordLine[] | null;\n port: string | null;\n readonly children: readonly Field[];\n readonly lr: boolean;\n w: number;\n h: number;\n x: number;\n y: number;\n}\n\n/** One text line of a field and how it is justified (`\\l` left, `\\r` right, else centered). */\ninterface RecordLine {\n readonly text: string;\n readonly justify: \"l\" | \"r\" | \"c\";\n}\n\n/** Where a record's dividers and text lines go, in points from the node's center, y up. */\ninterface RecordLayout {\n /** The node's width and height in points. */\n readonly width: number;\n readonly height: number;\n /** Each divider, from one point to the other. */\n readonly dividers: readonly (readonly [number, number, number, number])[];\n /** Each text line, centered on its point. */\n readonly texts: readonly { readonly x: number; readonly y: number; readonly text: string }[];\n /** Each named field's box center and half size, by port name. */\n readonly ports: ReadonlyMap<\n string,\n { readonly x: number; readonly y: number; readonly hw: number; readonly hh: number }\n >;\n}\n\n/** Graphviz's padding of a field's text: 4 GAP across (8 a side), 2 GAP down (4 above and below). */\nconst PAD = { x: 16, y: 8 } as const;\n\n/** Graphviz's line height as a multiple of the font size. */\nconst LINE_SPACING = 1.2;\n\n/** DejaVu Sans advance widths of the printable ASCII characters, in 1/2048 em, from space (32) to tilde (126). */\n// prettier-ignore\nconst DEJAVU_SANS = [\n 651, 821, 942, 1716, 1303, 1946, 1597, 563, 799, 799, 1024, 1716, 651, 739, 651, 690,\n 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 1303, 690, 690, 1716, 1716, 1716, 1087,\n 2048, 1401, 1405, 1430, 1577, 1294, 1178, 1587, 1540, 604, 604, 1343, 1141, 1767, 1532, 1612,\n 1235, 1612, 1423, 1300, 1251, 1499, 1401, 2025, 1403, 1251, 1403, 799, 690, 799, 1716, 1024,\n 1024, 1255, 1300, 1126, 1300, 1260, 721, 1300, 1298, 569, 569, 1186, 569, 1995, 1298, 1253,\n 1300, 1300, 842, 1067, 803, 1298, 1212, 1675, 1212, 1212, 1075, 1303, 690, 1303, 1716,\n];\n\n/**\n * A text's width in points at a font size, from DejaVu Sans's advances (any other character: 0.6 em).\n * @param text - the text\n * @param size - the font size\n * @returns the width\n */\nexport function textWidth(text: string, size: number): number {\n let units = 0;\n for (const ch of text) {\n const code = ch.codePointAt(0) ?? 0;\n units += code >= 32 && code <= 126 ? DEJAVU_SANS[code - 32] : 1229;\n }\n return (units / 2048) * size;\n}\n\n/**\n * Splits a field's text into lines at `\\n`, `\\l` and `\\r`, each line justified by the escape that ends it; a last\n * line with no escape is centered. Other escapes are kept for the caller.\n * @param text - the field's text, record escapes already removed\n * @returns the lines\n */\nfunction splitLines(text: string): RecordLine[] {\n const lines: RecordLine[] = [];\n let line = \"\";\n let i = 0;\n while (i < text.length) {\n const c = text[i];\n const next = text[i + 1];\n if (c === \"\\\\\" && (next === \"n\" || next === \"l\" || next === \"r\")) {\n lines.push({ text: line, justify: next === \"n\" ? \"c\" : next });\n line = \"\";\n i += 2;\n } else if (c === \"\\\\\" && next !== undefined) {\n line += c + next;\n i += 2;\n } else {\n line += c;\n i++;\n }\n }\n if (line !== \"\" || lines.length === 0) {\n lines.push({ text: line, justify: \"c\" });\n }\n return lines;\n}\n\n/**\n * Parses a record label into its field tree, as `parse_reclbl` does: `|` parts fields, `{ }` opens a sub-record laid\n * the other way, `<name>` names a field's port, and `\\{ \\} \\| \\< \\>` and `\\ ` stand for themselves.\n * @param label - the label\n * @param lr - whether the top level lays its fields left to right\n * @returns the root field\n */\nfunction parseRecord(label: string, lr: boolean): Field {\n return parseFields(label, { i: 0 }, lr, true);\n}\n\n/** Where reading a record label is: the index of the next character. */\ninterface Cursor {\n i: number;\n}\n\n/** The field being read: its text so far, its port and the sub-record it holds. */\ninterface PendingField {\n text: string;\n port: string | null;\n sub: Field | null;\n}\n\n/**\n * A parent field holding its children.\n * @param children - the children\n * @param across - whether they lay left to right\n * @returns the field\n */\nfunction parentField(children: Field[], across: boolean): Field {\n return { lines: null, port: null, children, lr: across, w: 0, h: 0, x: 0, y: 0 };\n}\n\n/**\n * Parses the fields of one (sub-)record from the cursor up to its closing `}` (or the label's end).\n * @param label - the label\n * @param cursor - where reading is, moved past what is read\n * @param across - whether these fields lay left to right\n * @param top - whether this is the top level, where a stray `}` is skipped\n * @returns the field holding them\n */\nfunction parseFields(label: string, cursor: Cursor, across: boolean, top: boolean): Field {\n const children: Field[] = [];\n const pending: PendingField = { text: \"\", port: null, sub: null };\n while (cursor.i < label.length) {\n const c = label[cursor.i];\n if (c === \"{\") {\n cursor.i++;\n pending.sub = parseFields(label, cursor, !across, false);\n } else if (c === \"}\") {\n cursor.i++;\n if (!top) {\n flushField(children, pending, across);\n return parentField(children, across);\n }\n } else if (c === \"|\") {\n cursor.i++;\n flushField(children, pending, across);\n } else {\n readFieldText(label, cursor, pending);\n }\n }\n flushField(children, pending, across);\n return parentField(children, across);\n}\n\n/**\n * Reads one escape, port name or character of a field's text at the cursor.\n * @param label - the label\n * @param cursor - where reading is, moved past what is read\n * @param pending - the field being read\n */\nfunction readFieldText(label: string, cursor: Cursor, pending: PendingField): void {\n const c = label[cursor.i];\n const next = label.at(cursor.i + 1);\n if (c === \"\\\\\" && next !== undefined) {\n pending.text += \"{}|<> \".includes(next) ? next : c + next;\n cursor.i += 2;\n } else if (c === \"<\") {\n const close = label.indexOf(\">\", cursor.i + 1);\n const end = close < 0 ? label.length : close;\n pending.port = label.slice(cursor.i + 1, end).trim();\n cursor.i = close < 0 ? label.length : close + 1;\n } else {\n pending.text += c;\n cursor.i++;\n }\n}\n\n/**\n * Ends the field being read: adds it (its sub-record, or a leaf of its text) to the children and starts the next.\n * @param children - the children so far\n * @param pending - the field being read, cleared\n * @param across - whether the children lay left to right\n */\nfunction flushField(children: Field[], pending: PendingField, across: boolean): void {\n const { sub, port } = pending;\n children.push(\n sub ?? { lines: splitLines(pending.text.trim()), port, children: [], lr: !across, w: 0, h: 0, x: 0, y: 0 },\n );\n if (sub !== null && port !== null) {\n sub.port = port;\n }\n pending.text = \"\";\n pending.port = null;\n pending.sub = null;\n}\n\n/**\n * Each field's natural size (`size_reclbl`): a leaf's text padded, a parent's children side by side along its way.\n * @param f - the field\n * @param size - the font size\n */\nfunction sizeField(f: Field, size: number): void {\n if (f.lines !== null) {\n const w = Math.max(...f.lines.map((l) => textWidth(l.text, size)));\n const h = f.lines.length * size * LINE_SPACING;\n [f.w, f.h] = w > 0 || h > 0 ? [w + PAD.x, h + PAD.y] : [0, 0];\n return;\n }\n f.w = 0;\n f.h = 0;\n for (const c of f.children) {\n sizeField(c, size);\n f.w = f.lr ? f.w + c.w : Math.max(f.w, c.w);\n f.h = f.lr ? Math.max(f.h, c.h) : f.h + c.h;\n }\n}\n\n/**\n * Grows or shrinks each field to its share of a new size (`resize_reclbl`): the difference is shared evenly along\n * the field's way, in whole points.\n * @param f - the field\n * @param w - its new width\n * @param h - its new height\n */\nfunction resizeField(f: Field, w: number, h: number): void {\n const inc = (f.lr ? w - f.w : h - f.h) / Math.max(1, f.children.length);\n f.w = w;\n f.h = h;\n f.children.forEach((c, k) => {\n const amt = Math.trunc((k + 1) * inc) - Math.trunc(k * inc);\n resizeField(c, f.lr ? c.w + amt : w, f.lr ? h : c.h + amt);\n });\n}\n\n/**\n * Places each field from its upper left corner (`pos_reclbl`), y up.\n * @param f - the field\n * @param x - its left side\n * @param y - its top\n */\nfunction placeField(f: Field, x: number, y: number): void {\n f.x = x;\n f.y = y;\n let at = f.lr ? x : y;\n for (const c of f.children) {\n placeField(c, f.lr ? at : x, f.lr ? y : at);\n at += f.lr ? c.w : -c.h;\n }\n}\n\n/**\n * Lays a record out in a node as Graphviz does: the fields at their natural sizes, the node at least that big unless\n * it is `fixedsize`, every field then grown to share the node, its dividers between neighbors and its lines centered,\n * or set in from its side by 8 points when justified left or right.\n * @param label - the record label, before its escapes are applied\n * @param lr - whether the top level lays its fields left to right (true unless `rankdir` is LR or RL)\n * @param width - the node's width in points\n * @param height - its height in points\n * @param fixed - whether the node keeps its size (`fixedsize`)\n * @param fontSize - the font size in points\n * @param text - applies the label escapes to one line\n * @returns the layout\n */\nexport function layoutRecord(\n label: string,\n lr: boolean,\n width: number,\n height: number,\n fixed: boolean,\n fontSize: number,\n text: (line: string) => string,\n): RecordLayout {\n const root = parseRecord(label, lr);\n const leaves = (f: Field): void => {\n if (f.lines !== null) {\n f.lines = f.lines.map((l) => ({ ...l, text: text(l.text) }));\n }\n f.children.forEach(leaves);\n };\n leaves(root);\n sizeField(root, fontSize);\n const w = fixed ? width : Math.max(width, root.w);\n const h = fixed ? height : Math.max(height, root.h);\n resizeField(root, w, h);\n placeField(root, -w / 2, h / 2);\n const dividers: [number, number, number, number][] = [];\n const texts: { x: number; y: number; text: string }[] = [];\n const ports = new Map<string, { x: number; y: number; hw: number; hh: number }>();\n const lineHeight = fontSize * LINE_SPACING;\n const visit = (f: Field): void => {\n if (f.port !== null && f.port !== \"\") {\n ports.set(f.port, { x: f.x + f.w / 2, y: f.y - f.h / 2, hw: f.w / 2, hh: f.h / 2 });\n }\n f.children.forEach((c, k) => {\n if (k > 0) {\n dividers.push(f.lr ? [c.x, c.y, c.x, c.y - c.h] : [c.x, c.y, c.x + c.w, c.y]);\n }\n visit(c);\n });\n if (f.lines === null) {\n return;\n }\n const n = f.lines.length;\n f.lines.forEach((l, k) => {\n if (l.text === \"\") {\n return;\n }\n const half = textWidth(l.text, fontSize) / 2;\n let x = f.x + f.w / 2;\n if (l.justify === \"l\") {\n x = f.x + PAD.x / 2 + half;\n } else if (l.justify === \"r\") {\n x = f.x + f.w - PAD.x / 2 - half;\n }\n texts.push({ x, y: f.y - f.h / 2 + ((n - 1) / 2 - k) * lineHeight, text: l.text });\n });\n };\n visit(root);\n return { width: w, height: h, dividers, texts, ports };\n}\n","/**\n * DOT styles: every node's, cluster's and edge's attributes read the way Graphviz draws them, with Graphviz's\n * defaults beneath, and a graph's styles written back as Graphviz attributes.\n *\n * Reading follows Graphviz's own rules, measured against `dot` 2.43:\n *\n * - Labels: a node with no `label` shows its name (`\\N`), as one tool-default rule over a style column holding each\n * node's name. Escapes are applied in Graphviz's two passes; an HTML label shows its text, a record label its\n * fields, and a `point` draws no label.\n * - Fills: `point` is always filled; `filled` and `radial` fill any shape, `striped` only boxes, `wedged` only\n * ellipses; an empty `fillcolor` falls back to `color`, then light gray.\n * - Colors through Graphviz's color rules: a `colorscheme` applies to its own object only, an unknown color is black,\n * `none` and `invis` are transparent, and a color list is read as Graphviz draws it for that use.\n * - Outlines: `plain`, `plaintext` and `none` draw none. `setlinewidth(n)` is a pen width, `bold` a width of 2.\n * - Sizes: exact with `fixedsize`, an empty label or a `point`; otherwise minimums Graphviz grows to fit the label,\n * carried as `labelFit: \"inside\"` with the label's padding (`margin`, else 8 by 4 points).\n * - Arrows per `dir`, `arrowhead` and `arrowtail`, with the graph's kind deciding the default: a target arrow on\n * directed edges, as one tool-default rule.\n * - A cluster's container node holds the cluster's attributes: its fill (`bgcolor`, or the fill when `filled`) and\n * outline (`pencolor`, else `color`) are the cluster's, it is drawn as a rectangle, and it has no label by default.\n * Cluster membership is offered to the planner, so clusters whose nodes share a fill become one rule.\n *\n * Writing: Graphviz attributes from what graphty draws (`fillcolor` with `style=filled`, `width` and `height` with\n * `fixedsize=true`, `penwidth`, `style`, arrows with `dir`, font attributes, graph `bgcolor`) replace every style\n * attribute the reader reads. The `graphty.styles` block is the quoted graph attribute `\"graphty.styles\"`, and the\n * per-element values its rules read are quoted `\"graphty.style.<target>.<key>\"` attributes.\n */\n\nimport type { GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { isWritableDotText } from \"../../common/escape.js\";\nimport { inferTextDtype } from \"../../common/text.js\";\nimport { type BendPoint, canonBends, canonNodeOffsets, flattenCubic } from \"../../styles/canon/bends.js\";\nimport { canonColor, colorOpacity } from \"../../styles/canon/color.js\";\nimport { canonEnum } from \"../../styles/canon/enums.js\";\nimport { canonNumber, DOT_POINTS_PER_INCH, num6 } from \"../../styles/canon/number.js\";\nimport { type CanonSite, MAX_STYLE_VALUE_LENGTH, noteAt } from \"../../styles/canon/site.js\";\nimport {\n type DotEscapeNames,\n dotLabelAlign,\n dotLabelText,\n htmlLabelSpans,\n htmlLabelText,\n recordLabelText,\n} from \"../../styles/canon/text.js\";\nimport { STYLE_ISSUE } from \"../../styles/codes.js\";\nimport { toolDefaults } from \"../../styles/defaults.js\";\nimport { StyleApproximations } from \"../../styles/io/approximations.js\";\nimport { STYLE_BLOCK_NAME, styleBlockLosses, writeStyleBlock } from \"../../styles/io/block.js\";\nimport { elementValues, takeFromBlock } from \"../../styles/io/round-trip.js\";\nimport { type ExporterStyleInput, sharedInExportCall } from \"../../styles/io/writer.js\";\nimport { StyleNotes } from \"../../styles/notes.js\";\nimport { plainCell } from \"../../styles/plan/resolve.js\";\nimport type {\n ImporterStyles,\n StyleColumn,\n StyleFeature,\n StyleReadContext,\n StyleRule,\n StyleTarget,\n StyleValue,\n StyleWriteCapabilities,\n} from \"../../styles/types.js\";\nimport type { LossNote } from \"../../types.js\";\nimport { type ValueColumns, valueColumns } from \"../graphml/styles-yed.js\";\nimport {\n GRAPHVIZ_DECORATED_BOXES,\n GRAPHVIZ_GLYPH_SHAPES,\n GRAPHVIZ_POLYGON_SHAPES,\n graphvizFont,\n graphvizFontName,\n graphvizGlyph,\n graphvizPolygonCorners,\n isGraphvizBox,\n} from \"./drawing.js\";\nimport { type LabelPlaceContext, readLabelPlaces } from \"./label-places.js\";\nimport { CLUSTER_COLUMN, LABEL_ATTRIBUTE, POS_ATTRIBUTE } from \"./names.js\";\nimport { layoutRecord } from \"./record.js\";\n\n/**\n * The graph attribute holding the `graphty.styles` block of a DOT file graphty wrote.\n * @category Built-in formats\n */\nexport { STYLE_BLOCK_NAME as DOT_STYLE_BLOCK_ATTRIBUTE } from \"../../styles/io/block.js\";\n\n/**\n * What the DOT writer holds natively: Graphviz's node, cluster and edge attributes, and the graph's `bgcolor`. The\n * `graphty.styles` block and the per-element values its rules read are quoted attributes.\n * @category Built-in formats\n */\nexport const DOT_STYLE_CAPABILITIES: StyleWriteCapabilities = Object.freeze({\n tool: \"graphviz\",\n node: Object.freeze([\n \"fill\",\n \"fillOpacity\",\n \"borderColor\",\n \"borderWidth\",\n \"borderStyle\",\n \"shape\",\n \"width\",\n \"height\",\n \"label\",\n \"labelColor\",\n \"labelSize\",\n \"labelFont\",\n \"labelWeight\",\n \"labelItalic\",\n \"labelPosition\",\n \"shapePoints\",\n \"shapePointsStretch\",\n \"shapeParts\",\n \"shapeLines\",\n \"shapeLineWidth\",\n \"tooltip\",\n \"visible\",\n ] as const),\n edge: Object.freeze([\n \"color\",\n \"opacity\",\n \"width\",\n \"lineStyle\",\n \"sourceArrow\",\n \"targetArrow\",\n \"sourceArrowColor\",\n \"targetArrowColor\",\n \"arrowSize\",\n \"label\",\n \"sourceLabel\",\n \"targetLabel\",\n \"labelColor\",\n \"labelSize\",\n \"labelFont\",\n \"labelWeight\",\n \"labelItalic\",\n \"tooltip\",\n \"visible\",\n ] as const),\n graph: Object.freeze([\"background\"] as const),\n block: \"native\",\n});\n\n/** The style column holding the name each node shows when it has no label (Graphviz's `\\N`). */\nconst NAME_KEY = \"name\";\n\n/** The style column marking directed edges, which Graphviz draws with an arrow at the target. */\nconst DIRECTED_KEY = \"directed\";\n\n/** The style column marking a cluster's container node. */\nconst CLUSTER_KEY = \"cluster\";\n\n/** Every node and cluster attribute the reader reads; the writer replaces them all. */\nconst NODE_ATTRIBUTES: readonly string[] = [\n \"colorscheme\",\n \"color\",\n \"fillcolor\",\n \"bgcolor\",\n \"pencolor\",\n \"style\",\n \"shape\",\n \"width\",\n \"height\",\n \"fixedsize\",\n \"regular\",\n \"sides\",\n \"distortion\",\n \"skew\",\n \"orientation\",\n \"penwidth\",\n \"gradientangle\",\n \"fontname\",\n \"fontsize\",\n \"fontcolor\",\n \"tooltip\",\n];\n\n/** Every edge attribute the reader reads; the writer replaces them all. */\nconst EDGE_ATTRIBUTES: readonly string[] = [\n \"colorscheme\",\n \"color\",\n \"style\",\n \"penwidth\",\n \"fontname\",\n \"fontsize\",\n \"fontcolor\",\n \"tooltip\",\n \"edgetooltip\",\n \"arrowhead\",\n \"arrowtail\",\n \"dir\",\n \"arrowsize\",\n \"fillcolor\",\n \"headlabel\",\n \"taillabel\",\n \"labelfontsize\",\n \"labelfontcolor\",\n \"labelfontname\",\n \"xlabel\",\n];\n\n/** Attributes the reader notes as not carried. */\nconst NOTED_ATTRIBUTES: readonly string[] = [\"peripheries\", \"xlabel\"];\n\nconst CIRCLE_LIKE: ReadonlySet<string> = new Set([\"circle\", \"doublecircle\", \"mcircle\", \"square\", \"msquare\"]);\nconst BOX_LIKE: ReadonlySet<string> = new Set([\"box\", \"rect\", \"rectangle\", \"square\"]);\nconst ELLIPSE_LIKE: ReadonlySet<string> = new Set([\"\", \"ellipse\", \"oval\", \"circle\"]);\nconst NO_OUTLINE: ReadonlySet<string> = new Set([\"plain\", \"plaintext\", \"none\"]);\nconst RECORD: ReadonlySet<string> = new Set([\"record\", \"mrecord\"]);\nconst TRUE_TEXTS: ReadonlySet<string> = new Set([\"true\", \"yes\", \"shape\"]);\n\n/** A point's size when the file gives none: 0.05 inch. */\nconst POINT_SIZE = 0.05;\n\n/** The size in inches Graphviz gives a circle, a square or a `regular` node that states none. */\nconst REGULAR_SIZE = 0.5;\n\n/** One attribute of an element as text, or null when it is unset. */\ntype Attr = (name: string) => string | null;\n\n/** One element's canonical value of a property; null leaves it unset. */\ntype Put = (property: string, value: StyleValue | null) => void;\n\n/** Where a value of an element was read, by property. */\ntype At = (property: string) => CanonSite;\n\n/** What a node's label escapes and its defaults depend on. */\ninterface NodeContext {\n /** The node's name (its id as text). */\n readonly name: string;\n /** The graph's name, for `\\G`. */\n readonly graph: string;\n /** Whether the node is a cluster's container. */\n readonly cluster: boolean;\n /** The HTML strings of the file, for Graphviz's shared string pool. */\n readonly html: ReadonlySet<string>;\n /** Whether the graph's `rankdir` is LR or RL, which turns a record's fields top to bottom. */\n readonly flip: boolean;\n /** The graph's `quantum` in points (a node's padded label box is rounded up to a multiple of it), 0 for none. */\n readonly quantum: number;\n}\n\n/** What an edge's label escapes depend on. */\ninterface EdgeContext {\n /** The names `\\E`, `\\T`, `\\H` and `\\G` stand for. */\n readonly names: DotEscapeNames;\n /** Whether the edge is directed. */\n readonly directed: boolean;\n /** The HTML strings of the file. */\n readonly html: ReadonlySet<string>;\n}\n\n/**\n * Whether a text is an HTML string (balanced angle brackets around the whole text), which graph-io keeps with its\n * brackets and DOT writes bare as `<...>`.\n * @param text - the text\n * @returns true for an HTML string\n */\nexport function isHtmlString(text: string): boolean {\n if (text.length < 2 || !text.startsWith(\"<\") || !text.endsWith(\">\")) {\n return false;\n }\n let depth = 0;\n for (let i = 0; i < text.length; i++) {\n const c = text.codePointAt(i);\n if (c === 0x3c) {\n depth++;\n } else if (c === 0x3e) {\n depth--;\n if (depth === 0 && i !== text.length - 1) {\n return false;\n }\n }\n }\n return depth === 0;\n}\n\n/**\n * The value of an attribute cell as text, or null when it is unset.\n * @param table - the node, edge or graph table\n * @param name - the attribute\n * @param i - the row\n * @returns the text\n */\nfunction cellText(table: GraphSnapshot[\"nodes\"], name: string, i: number): string | null {\n if (!table.has(name)) {\n return null;\n }\n const v = plainCell(table.value(name, i));\n if (typeof v === \"string\") {\n return v;\n }\n return typeof v === \"number\" || typeof v === \"boolean\" ? String(v) : null;\n}\n\n/**\n * A text, or null when it is empty.\n * @param v - the text\n * @returns the text\n */\nfunction nonEmpty(v: string | null): string | null {\n return v === null || v === \"\" ? null : v;\n}\n\n/**\n * The tokens of a `style` value: split on commas, lowercased, blanks before a token skipped (blanks after it make it\n * a token Graphviz does not know, so they are kept).\n * @param raw - the value\n * @param at - where it was read\n * @returns the tokens\n */\nfunction styleTokens(raw: string | null, at: CanonSite): string[] {\n if (raw === null) {\n return [];\n }\n if (raw.length > MAX_STYLE_VALUE_LENGTH) {\n noteAt(at, STYLE_ISSUE.VALUE_TOO_LONG, `${String(raw.length)} characters`);\n return [];\n }\n return raw\n .toLowerCase()\n .split(\",\")\n .map((t) => t.replace(/^[ \\t\\r\\n]+/, \"\"))\n .filter((t) => t !== \"\");\n}\n\n/**\n * The pen width a style's `setlinewidth(n)` gives, or null.\n * @param tokens - the style's tokens\n * @returns the width's text\n */\nfunction setLineWidth(tokens: readonly string[]): string | null {\n for (const t of tokens) {\n if (t.startsWith(\"setlinewidth(\") && t.endsWith(\")\")) {\n return t.slice(\"setlinewidth(\".length, -1).trim();\n }\n }\n return null;\n}\n\n/**\n * Whether an attribute is one of Graphviz's true spellings (`true`, `yes`, a non-zero number; `fixedsize` also\n * takes `shape`).\n * @param raw - the value\n * @returns true when set\n */\nfunction isTrue(raw: string | null): boolean {\n if (raw === null) {\n return false;\n }\n const t = raw.trim().toLowerCase();\n return TRUE_TEXTS.has(t) || (/^-?\\d+$/.test(t) && Number(t) !== 0);\n}\n\n/**\n * The text a label draws: an HTML label's text (also for a quoted label equal to an HTML label's content elsewhere\n * in the file, since Graphviz 2.43 marks HTML on a pooled string), a record's fields, the escapes applied.\n * @param raw - the label as the file gives it\n * @param names - what the escapes stand for\n * @param html - the file's HTML strings\n * @param record - whether the node is a record\n * @param at - where it was read\n * @returns the text\n */\nfunction labelText(\n raw: string,\n names: DotEscapeNames,\n html: ReadonlySet<string>,\n record: boolean,\n at: CanonSite,\n): string {\n if (isHtmlString(raw)) {\n return htmlLabelText(raw, at);\n }\n if (html.has(`<${raw}>`)) {\n return htmlLabelText(`<${raw}>`, at);\n }\n return dotLabelText(record ? recordLabelText(raw, at) : raw, names, at);\n}\n\n/**\n * Reads how a plain label's lines line up (`\\l`, `\\r`); an HTML-like or a record label lines up its own way.\n * @param raw - the label as the file gives it\n * @param names - what the label's escapes stand for\n * @param html - the file's HTML strings\n * @param record - whether the node is a record\n * @param put - receives the value\n */\nfunction readLabelAlign(\n raw: string,\n names: DotEscapeNames,\n html: ReadonlySet<string>,\n record: boolean,\n put: Put,\n): void {\n if (isHtmlString(raw) || html.has(`<${raw}>`)) {\n // each <BR ALIGN> lines up the line before it: one alignment on every break lines up the label\n const aligns = new Set(\n [...raw.matchAll(/<br\\b([^>]*)>/gi)].map(\n (m) => /\\balign\\s*=\\s*[\"']?(left|right|center)/i.exec(m[1])?.[1].toLowerCase() ?? \"center\",\n ),\n );\n // words after the last break are a line of their own, centered\n const body = isHtmlString(raw) ? raw.slice(1, -1) : raw;\n const last = /<br\\b[^>]*>(?![\\s\\S]*<br\\b)/i.exec(body);\n const tail = last === null ? \"\" : body.slice(last.index + last[0].length);\n if (stripTags(tail).trim() !== \"\") {\n aligns.add(\"center\");\n }\n const [only] = aligns;\n if (aligns.size === 1 && only !== \"center\") {\n put(\"labelTextAlign\", only);\n }\n return;\n }\n if (record) {\n return;\n }\n const align = dotLabelAlign(raw, names);\n if (align !== null) {\n put(\"labelTextAlign\", align);\n }\n}\n\n/**\n * Text with its tags (`<` to the next `>`) dropped; a `<` with no `>` after it, and the rest, kept.\n * @param text - the text\n * @returns the text without tags\n */\nfunction stripTags(text: string): string {\n let out = \"\";\n let i = 0;\n while (i < text.length) {\n const open = text.indexOf(\"<\", i);\n const close = open < 0 ? -1 : text.indexOf(\">\", open + 1);\n if (close < 0) {\n return out + text.slice(i);\n }\n out += text.slice(i, open);\n i = close + 1;\n }\n return out;\n}\n\n/**\n * Reads the font runs of an HTML-like label (`<B>`, `<I>`, `<FONT COLOR FACE POINT-SIZE>`) as Graphviz draws them:\n * one run in a font of its own sets the label's own font (color, size, family, weight, slant), several are\n * `labelRuns`. Underline, overline, strike-through, `<SUB>` and `<SUP>` have no neutral slot and draw plain.\n * @param raw - the label as the file gives it\n * @param html - the file's HTML strings\n * @param scheme - the element's color scheme\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readHtmlRuns(raw: string, html: ReadonlySet<string>, scheme: string | null, put: Put, at: At): void {\n if (!isHtmlString(raw) && !html.has(`<${raw}>`)) {\n return;\n }\n const markup = isHtmlString(raw) ? raw : `<${raw}>`;\n const runs: Record<string, StyleValue>[] = [];\n for (const span of htmlLabelSpans(markup)) {\n const run = { text: span.text, ...htmlRunFont(span.tags, scheme, at(\"labelRuns\")) };\n const last = runs.at(-1);\n if (last !== undefined && JSON.stringify({ ...last, text: \"\" }) === JSON.stringify({ ...run, text: \"\" })) {\n last.text = `${String(last.text)}${run.text}`;\n } else {\n runs.push(run);\n }\n }\n trimBlankRuns(runs);\n if (runs.every((r) => Object.keys(r).length === 1)) {\n return;\n }\n if (runs.length === 1) {\n const { text: _text, ...font } = runs[0];\n for (const [property, value] of Object.entries(font)) {\n put(RUN_PROPERTY[property], value);\n }\n return;\n }\n runs[0].text = String(runs[0].text).trimStart();\n const end = runs.at(-1);\n if (end !== undefined) {\n end.text = String(end.text).trimEnd();\n }\n put(\"labelRuns\", JSON.stringify(runs));\n}\n\n/**\n * Drops the blank runs at a label's ends, as htmlLabelText trims its blanks.\n * @param runs - the runs, trimmed in place\n */\nfunction trimBlankRuns(runs: Record<string, StyleValue>[]): void {\n while (runs.length > 0 && String(runs[0].text).trim() === \"\") {\n runs.shift();\n }\n while (runs.length > 0 && String(runs.at(-1)?.text).trim() === \"\") {\n runs.pop();\n }\n}\n\n/** The label property a run's own font field sets when the whole label is one run. */\nconst RUN_PROPERTY: Readonly<Record<string, string>> = {\n weight: \"labelWeight\",\n italic: \"labelItalic\",\n font: \"labelFont\",\n size: \"labelSize\",\n color: \"labelColor\",\n};\n\n/**\n * The font of a run inside HTML font tags, as `labelRuns` fields: bold, italic, and the innermost `FONT`'s face,\n * point size and color.\n * @param tags - the open tags, outermost first\n * @param scheme - the element's color scheme\n * @param site - where a bad color is noted\n * @returns the fields that differ from the label's own font\n */\nfunction htmlRunFont(tags: readonly string[], scheme: string | null, site: CanonSite): Record<string, StyleValue> {\n const out: Record<string, StyleValue> = {};\n for (const tag of tags) {\n const name = /^<(\\w+)/.exec(tag)?.[1].toLowerCase();\n if (name === \"b\") {\n out.weight = \"bold\";\n } else if (name === \"i\") {\n out.italic = true;\n } else if (name === \"font\") {\n for (const [attr, value] of tagAttributes(tag)) {\n readFontAttribute(attr.toLowerCase(), value, scheme, site, out);\n }\n }\n }\n return out;\n}\n\n/**\n * Reads one attribute of a `FONT` tag into a run's font fields: its face, point size or color.\n * @param attr - the attribute's name, lowercase\n * @param value - its value\n * @param scheme - the element's color scheme\n * @param site - where a bad color is noted\n * @param out - the run's font fields, set\n */\nfunction readFontAttribute(\n attr: string,\n value: string,\n scheme: string | null,\n site: CanonSite,\n out: Record<string, StyleValue>,\n): void {\n if (attr === \"face\" && value.trim() !== \"\" && value.length <= MAX_STYLE_VALUE_LENGTH) {\n const drawn = graphvizFont(value);\n out.font = drawn.family;\n if (drawn.bold) {\n out.weight = \"bold\";\n }\n if (drawn.italic) {\n out.italic = true;\n }\n } else if (attr === \"point-size\" && Number(value) > 0) {\n out.size = Number(value);\n } else if (attr === \"color\") {\n const c = canonColor(value, \"graphviz\", site, { scheme, use: \"text\" });\n if (c !== null) {\n out.color = c.color;\n }\n }\n}\n\n/** Whether a character can be part of an HTML attribute's name (a word character or `-`). */\nconst ATTRIBUTE_NAME_CHAR = /^[\\w-]$/;\n\n/**\n * The quoted attributes of a tag, `name = \"value\"` or `name = 'value'`, in order; an unquoted or unclosed value is\n * skipped. Scans the tag once (an attribute regex would backtrack on a long name with no `=`).\n * @param tag - the tag\n * @returns each attribute's name and value\n */\nfunction tagAttributes(tag: string): [string, string][] {\n const attributes: [string, string][] = [];\n let i = 0;\n while (i < tag.length) {\n if (!ATTRIBUTE_NAME_CHAR.test(tag[i])) {\n i++;\n continue;\n }\n let end = i;\n while (end < tag.length && ATTRIBUTE_NAME_CHAR.test(tag[end])) {\n end++;\n }\n const value = quotedValueAt(tag, end);\n if (value !== null) {\n attributes.push([tag.slice(i, end), value.text]);\n }\n i = value === null ? end : value.next;\n }\n return attributes;\n}\n\n/**\n * The quoted value of an attribute whose name ends at `at`: blanks, `=`, blanks, then text between matching quotes.\n * @param tag - the tag\n * @param at - where the name ends\n * @returns the value and where reading goes on after its closing quote, or null when there is none\n */\nfunction quotedValueAt(tag: string, at: number): { text: string; next: number } | null {\n let i = at;\n while (i < tag.length && /\\s/.test(tag[i])) {\n i++;\n }\n if (tag[i] !== \"=\") {\n return null;\n }\n i++;\n while (i < tag.length && /\\s/.test(tag[i])) {\n i++;\n }\n const quote = tag[i];\n const close = quote === '\"' || quote === \"'\" ? tag.indexOf(quote, i + 1) : -1;\n return close < 0 ? null : { text: tag.slice(i + 1, close), next: close + 1 };\n}\n\n/**\n * Reads a color into a property and its alpha into the property's opacity.\n * @param raw - the color\n * @param scheme - the object's color scheme\n * @param use - how Graphviz draws it\n * @param property - the color property\n * @param opacity - its opacity property, or null when the alpha is dropped (an outline's is its borderOpacity)\n * @param put - receives the values\n * @param at - the sites\n * @returns the alpha, or null when the color is absent\n */\nfunction readColor(\n raw: string | null,\n scheme: string | null,\n use: \"line\" | \"text\" | \"fill\" | \"edge\",\n property: string,\n opacity: string | null,\n put: Put,\n at: At,\n): number | null {\n if (raw === null) {\n return null;\n }\n const c = canonColor(raw, \"graphviz\", at(property), { scheme, use });\n if (c === null) {\n return null;\n }\n put(property, c.color);\n if (property === \"borderColor\") {\n // a transparent outline is no outline (the caller sets its width to 0); a part-transparent one is drawn so\n put(\"borderOpacity\", c.alpha > 0 && c.alpha < 1 ? c.alpha : null);\n } else if (opacity !== null) {\n put(opacity, c.alpha);\n } else {\n // any other alpha is dropped, noted\n colorOpacity(c, null, at(property), false);\n }\n return c.alpha;\n}\n\n/**\n * A length in points as the shortest inches (at least 6 significant digits) that read back as the same length.\n * @param points - the length\n * @returns the inches\n */\nfunction inchesOf(points: number): number {\n const want = num6(points);\n for (let digits = 6; digits < 17; digits++) {\n const inches = Number((points / DOT_POINTS_PER_INCH).toPrecision(digits));\n if (num6(inches * DOT_POINTS_PER_INCH) === want) {\n return inches + 0;\n }\n }\n return points / DOT_POINTS_PER_INCH;\n}\n\n/**\n * A size attribute in inches, or null with a note when it is not a non-negative number.\n * @param raw - the value\n * @param at - where it was read\n * @returns the inches\n */\nfunction inches(raw: string | null, at: CanonSite): number | null {\n if (raw === null) {\n return null;\n }\n const v = raw.trim() === \"\" ? Number.NaN : Number(raw);\n if (!Number.isFinite(v) || v < 0) {\n noteAt(at, STYLE_ISSUE.BAD_VALUE, raw.slice(0, MAX_STYLE_VALUE_LENGTH));\n return null;\n }\n return v;\n}\n\n/**\n * Reads the attributes every element shares: font, tooltip, visibility.\n * @param get - the element's attributes\n * @param tokens - its style tokens\n * @param scheme - its color scheme\n * @param names - what the tooltip's escapes stand for\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readCommon(\n get: Attr,\n tokens: readonly string[],\n scheme: string | null,\n names: DotEscapeNames,\n put: Put,\n at: At,\n): void {\n // Graphviz takes `invisible` for `invis` too (emit.c `parse_style`)\n if (tokens.includes(\"invis\") || tokens.includes(\"invisible\")) {\n put(\"visible\", false);\n }\n // a part-transparent font color draws its text so (`#377eb880`); an opaque one needs no opacity\n const putFont: Put = (property, value) => {\n put(property, property === \"labelOpacity\" && value === 1 ? null : value);\n };\n readColor(nonEmpty(get(\"fontcolor\")), scheme, \"text\", \"labelColor\", \"labelOpacity\", putFont, at);\n const size = get(\"fontsize\");\n put(\"labelSize\", size === null ? null : canonNumber(size, at(\"labelSize\")));\n const font = get(\"fontname\");\n if (font !== null && font.length <= MAX_STYLE_VALUE_LENGTH) {\n const drawn = graphvizFont(font);\n put(\"labelFont\", drawn.family);\n put(\"labelWeight\", drawn.bold ? \"bold\" : null);\n put(\"labelItalic\", drawn.italic ? true : null);\n }\n const tip = get(\"tooltip\") ?? get(\"edgetooltip\");\n if (tip !== null) {\n put(\"tooltip\", dotLabelText(tip, names, at(\"tooltip\")));\n }\n}\n\n/** What the parts of readNode() read: the node's attributes and what is worked out from them once. */\ninterface NodeRead {\n readonly get: Attr;\n readonly cx: NodeContext;\n readonly put: Put;\n readonly at: At;\n readonly tokens: readonly string[];\n /** The shape as written, or null. */\n readonly shapeRaw: string | null;\n /** The shape, lowercase (\"\" when none is written). */\n readonly shape: string;\n /** Whether it is a point (never a cluster). */\n readonly point: boolean;\n readonly scheme: string | null;\n readonly color: string | null;\n}\n\n/**\n * Reads a node's label and, for a node that is not a cluster, its size and how it grows to hold the label.\n * @param n - the node\n * @param names - what the label's escapes stand for\n */\nfunction readNodeLabelAndSize(n: NodeRead, names: DotEscapeNames): void {\n const { get, cx, put, at, shape } = n;\n // label: a node shows its name unless it has a label (the tool-default rule); a cluster and a point show none\n const label = n.point ? null : get(LABEL_ATTRIBUTE);\n const shown = label === null ? cx.name : labelText(label, names, cx.html, RECORD.has(shape), at(\"label\"));\n readNodeLabel(n, label, shown, names);\n // plain is its label alone at size 0: with an empty label Graphviz draws nothing, filled or not; an HTML label\n // with no words (a table holding an IMG) still draws its cells\n const htmlLabel = label !== null && (isHtmlString(label) || cx.html.has(`<${label}>`));\n if (shape === \"plain\" && shown === \"\" && !htmlLabel) {\n put(\"visible\", false);\n }\n if (cx.cluster) {\n readClusterBox(get, put);\n } else {\n readNodeSize(n, label, shown, htmlLabel, names);\n }\n}\n\n/**\n * Reads a node's label, its alignment and runs, and where it sits.\n * @param n - the node\n * @param label - its label, or null when it has none\n * @param shown - the text it shows\n * @param names - what the label's escapes stand for\n */\nfunction readNodeLabel(n: NodeRead, label: string | null, shown: string, names: DotEscapeNames): void {\n const { get, cx, put, at, shape } = n;\n // a cluster has no label of its own unless one is given, so an empty one is none\n if (label !== null && !(cx.cluster && label === \"\")) {\n put(\"label\", shown);\n readLabelAlign(label, names, cx.html, RECORD.has(shape), put);\n readHtmlRuns(label, cx.html, n.scheme, put, at);\n if (cx.cluster) {\n put(\"labelPosition\", clusterLabelPosition(get));\n readClusterLabelPlace(get, put);\n }\n }\n if (!cx.cluster && !n.point) {\n const position = nodeLabelPosition(get);\n put(\"labelPosition\", position === \"center\" ? null : position);\n }\n}\n\n/**\n * Reads the size of a node that is not a cluster and how it grows to hold its label (a record's fields, or its\n * label's fit).\n * @param n - the node\n * @param label - its label, or null when it has none\n * @param shown - the text it shows\n * @param htmlLabel - whether the label is HTML-like\n * @param names - what the label's escapes stand for\n */\nfunction readNodeSize(\n n: NodeRead,\n label: string | null,\n shown: string,\n htmlLabel: boolean,\n names: DotEscapeNames,\n): void {\n const { get, put, at, shape } = n;\n readSize(get, shape, n.point, put, at);\n if (RECORD.has(shape) && label !== null && !htmlLabel) {\n readRecord(n, label, names);\n } else if (!n.point) {\n readLabelFit(get, shape, label, shown, put);\n readQuantum(n, label);\n }\n}\n\n/** Graphviz's default node width and height, in points (0.75 and 0.5 inch). */\nconst DEFAULT_NODE_SIZE = { w: 54, h: 36 } as const;\n\n/**\n * Reads a record node as Graphviz lays it out: its size (at least its fields' unless `fixedsize`), the dividers\n * between its fields as lines over the node, and each field's text lines where Graphviz centers or justifies them,\n * in place of one label.\n * @param n - the node\n * @param label - its record label\n * @param names - what the label's escapes stand for\n */\nfunction readRecord(n: NodeRead, label: string, names: DotEscapeNames): void {\n const { get, put, at, cx } = n;\n const pt = (attr: string, fallback: number): number => {\n const v = inches(get(attr), at(attr === \"width\" ? \"width\" : \"height\"));\n return v === null ? fallback : v * DOT_POINTS_PER_INCH;\n };\n const size = Number(get(\"fontsize\") ?? 14);\n const lay = layoutRecord(\n label,\n !cx.flip,\n pt(\"width\", DEFAULT_NODE_SIZE.w),\n pt(\"height\", DEFAULT_NODE_SIZE.h),\n isTrue(get(\"fixedsize\")),\n Number.isFinite(size) && size > 0 ? size : 14,\n (line) => dotLabelText(line, names),\n );\n const hw = lay.width / 2;\n const hh = lay.height / 2;\n const fx = (x: number): string => String(num6(hw > 0 ? x / hw : 0));\n const fy = (y: number): string => String(num6(hh > 0 ? y / hh : 0));\n put(\"width\", num6(lay.width));\n put(\"height\", num6(lay.height));\n put(\"label\", \"\");\n put(\n \"shapeLines\",\n lay.dividers.length === 0\n ? null\n : lay.dividers.map(([x0, y0, x1, y1]) => `${fx(x0)},${fy(y0)} ${fx(x1)},${fy(y1)}`).join(\"; \"),\n );\n put(\n \"shapeTexts\",\n lay.texts.length === 0\n ? null\n : JSON.stringify(lay.texts.map((t) => [Number(fx(t.x)), Number(fy(t.y)), t.text])),\n );\n}\n\n/**\n * Reads a laid-out cluster's size from its `bb` (\"llx,lly,urx,ury\" in points), the box Graphviz draws round its\n * members and its label; a cluster with no `bb` is drawn round its members.\n * @param get - the cluster's attributes\n * @param put - receives the values\n */\nfunction readClusterBox(get: Attr, put: Put): void {\n const parts = (get(\"bb\") ?? \"\").split(\",\").map(Number);\n if (parts.length === 4 && parts.every(Number.isFinite) && parts[2] >= parts[0] && parts[3] >= parts[1]) {\n put(\"width\", num6(parts[2] - parts[0]));\n put(\"height\", num6(parts[3] - parts[1]));\n }\n}\n\n/**\n * Reads one node, or one cluster's container, the way Graphviz draws it.\n * @param get - its attributes\n * @param cx - its name and kind\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readNode(get: Attr, cx: NodeContext, put: Put, at: At): void {\n const tokens = styleTokens(get(\"style\"), at(\"visible\"));\n const shapeRaw = nonEmpty(get(\"shape\"));\n const shape = (shapeRaw ?? \"\").toLowerCase();\n const n: NodeRead = {\n get,\n cx,\n put,\n at,\n tokens,\n shapeRaw,\n shape,\n point: !cx.cluster && shape === \"point\",\n scheme: get(\"colorscheme\"),\n color: nonEmpty(get(\"color\")),\n };\n // in a node's label \\E stands for nothing (measured with dot 2.43); \\T and \\H stand for their letters\n const names: DotEscapeNames = cx.cluster ? { graph: cx.name } : { node: cx.name, graph: cx.graph, edge: \"\" };\n readCommon(get, tokens, n.scheme, names, put, at);\n if (cx.cluster) {\n readClusterFill(n);\n } else {\n readNodeFill(n);\n }\n readNodeBands(n);\n readNodeOutline(n);\n readNodeShape(n);\n readNodeLabelAndSize(n, names);\n if (nonEmpty(get(\"xlabel\")) !== null) {\n noteAt(at(\"label\"), STYLE_ISSUE.NOT_CARRIED, \"xlabel\");\n }\n}\n\n/**\n * Where a node's label sits: its `labelloc` puts it against the top or bottom of the node's box, inside it; it is\n * centered by default.\n * @param get - the node's attributes\n * @returns the position\n */\nfunction nodeLabelPosition(get: Attr): \"inside-top\" | \"inside-bottom\" | \"center\" {\n const loc = (get(\"labelloc\") ?? \"\").trim().toLowerCase();\n if (loc.startsWith(\"t\")) {\n return \"inside-top\";\n }\n return loc.startsWith(\"b\") ? \"inside-bottom\" : \"center\";\n}\n\n/** How far in from the cluster's side Graphviz draws a label justified left or right: half its label's padding. */\nconst CLUSTER_LABEL_INSET = 8;\n\n/**\n * Where Graphviz draws a cluster's label beyond its position: at a stored `lp` (its center) inside the cluster's\n * `bb`, else `CLUSTER_LABEL_INSET` points in from the side `labeljust` puts it against.\n * @param get - the cluster's attributes\n * @param put - receives the values\n */\nfunction readClusterLabelPlace(get: Attr, put: Put): void {\n const lp = (get(\"lp\") ?? \"\").split(\",\").map(Number);\n const bb = (get(\"bb\") ?? \"\").split(\",\").map(Number);\n if (lp.length === 2 && bb.length === 4 && [...lp, ...bb].every(Number.isFinite)) {\n put(\"labelPosition\", \"center\");\n put(\"labelOffsetX\", num6(lp[0] - (bb[0] + bb[2]) / 2));\n put(\"labelOffsetY\", num6((bb[1] + bb[3]) / 2 - lp[1]));\n return;\n }\n const just = (get(\"labeljust\") ?? \"\").trim().toLowerCase();\n if (just.startsWith(\"l\")) {\n put(\"labelOffsetX\", CLUSTER_LABEL_INSET);\n } else if (just.startsWith(\"r\")) {\n put(\"labelOffsetX\", -CLUSTER_LABEL_INSET);\n }\n}\n\n/**\n * Where a cluster's label sits: inside the cluster's box (Graphviz grows the box to hold it), at the top unless\n * `labelloc` is `b`, centered unless `labeljust` is `l` or `r`.\n * @param get - the cluster's attributes\n * @returns the position\n */\nfunction clusterLabelPosition(\n get: Attr,\n): `inside-${\"top\" | \"top-left\" | \"top-right\" | \"bottom\" | \"bottom-left\" | \"bottom-right\"}` {\n const loc = (get(\"labelloc\") ?? \"\").trim().toLowerCase().startsWith(\"b\") ? \"inside-bottom\" : \"inside-top\";\n const just = (get(\"labeljust\") ?? \"\").trim().toLowerCase();\n if (just.startsWith(\"l\")) {\n return `${loc}-left`;\n }\n return just.startsWith(\"r\") ? `${loc}-right` : loc;\n}\n\n/**\n * Reads a cluster's fill: its fill color when filled, else its background.\n * @param n - the cluster\n */\nfunction readClusterFill(n: NodeRead): void {\n const { get, tokens } = n;\n const filled = tokens.includes(\"filled\") || tokens.includes(\"radial\") || tokens.includes(\"striped\");\n const bg = nonEmpty(get(\"bgcolor\"));\n const raw = filled ? (nonEmpty(get(\"fillcolor\")) ?? n.color ?? bg ?? \"lightgrey\") : bg;\n readColor(raw, n.scheme, \"fill\", \"fill\", \"fillOpacity\", n.put, n.at);\n if (!tokens.includes(\"striped\")) {\n readFillGradient(n, raw);\n }\n}\n\n/**\n * Reads a gradient fill (`fillcolor=\"a:b\"`, `gradientangle`): Graphviz runs it from the list's first color to\n * its second, `gradientangle` degrees counter-clockwise from left to right (0 by default), which is the neutral\n * angle's clockwise turn negated, from 0 up to 360. `style=radial` runs it out from the middle instead. A second color\n * left out is black; colors after the second are not drawn. A first color's `;fraction` makes Graphviz switch colors\n * at that fraction, which its SVG writes as stops at the fraction less 0.001 and at the fraction.\n * @param n - the node or cluster\n * @param raw - its fill color value\n */\nfunction readFillGradient(n: NodeRead, raw: string | null): void {\n const colon = raw === null ? -1 : raw.indexOf(\":\");\n if (raw === null || colon < 0) {\n return;\n }\n const radial = n.tokens.includes(\"radial\");\n if (radial) {\n // ponytail: a radial gradientangle moves Graphviz's focus off the middle; graphty's radial ramp has no focus\n n.put(\"fillGradientKind\", \"radial\");\n }\n const frac = Number(raw.slice(0, colon).split(\";\")[1]);\n if (frac > 0 && frac < 1) {\n n.put(\"fillGradientStops\", `${String(num6(frac - 0.001))} ${String(num6(frac))}`);\n }\n const second = raw\n .slice(colon + 1)\n .split(\":\")[0]\n .split(\";\")[0];\n const c = canonColor(second === \"\" ? \"black\" : second, \"graphviz\", n.at(\"fillGradient\"), {\n scheme: n.scheme,\n use: \"fill\",\n });\n if (c === null) {\n return;\n }\n n.put(\"fillGradient\", c.color);\n if (radial) {\n return;\n }\n const angle = Number(nonEmpty(n.get(\"gradientangle\")) ?? \"0\");\n // 0 up to 360: the neutral angle turns clockwise on screen, Graphviz's counter-clockwise\n const turned = Number.isFinite(angle) ? ((-angle % 360) + 360) % 360 : 0;\n n.put(\"fillGradientAngle\", num6(turned) + 0);\n}\n\n/**\n * Reads a node's fill: a point is always filled; a striped fill fills a box and a wedged one an ellipse only.\n * @param n - the node\n */\nfunction readNodeFill(n: NodeRead): void {\n const { point } = n;\n const fillcolor = nonEmpty(n.get(\"fillcolor\"));\n if (isFilled(n)) {\n const raw = fillcolor ?? n.color ?? (point ? \"black\" : \"lightgrey\");\n readColor(raw, n.scheme, \"fill\", \"fill\", \"fillOpacity\", n.put, n.at);\n // stripes on a box and wedges on an ellipse take the color list in place of a gradient\n const banded =\n (n.tokens.includes(\"striped\") && BOX_LIKE.has(n.shape)) ||\n (n.tokens.includes(\"wedged\") && ELLIPSE_LIKE.has(n.shape));\n if ((n.tokens.includes(\"filled\") || n.tokens.includes(\"radial\")) && !banded) {\n readFillGradient(n, raw);\n }\n } else if (fillcolor !== null) {\n noteAt(n.at(\"fill\"), STYLE_ISSUE.UNFILLED, fillcolor.slice(0, MAX_STYLE_VALUE_LENGTH));\n }\n}\n\n/**\n * Reads a node's striped or wedged fill (`style=striped` on a box, `style=wedged` on an ellipse) from its color\n * list, `color;fraction` separated by `:`: a color with no fraction shares what the others leave, the last color takes\n * what sized colors leave when none is unsized, and the shares stop at the whole\n * (https://graphviz.org/docs/attr-types/colorList/). Graphviz draws stripes left to right and\n * wedges counter-clockwise from 3 o'clock, which is the same pie as the wedges in reverse order clockwise from there.\n * @param n - the node\n */\nfunction readNodeBands(n: NodeRead): void {\n // a cluster is a box, so it takes stripes too (and never wedges)\n const striped = n.tokens.includes(\"striped\") && (n.cx.cluster || BOX_LIKE.has(n.shape));\n const wedged = !n.cx.cluster && n.tokens.includes(\"wedged\") && ELLIPSE_LIKE.has(n.shape);\n const list = nonEmpty(n.get(\"fillcolor\")) ?? n.color;\n if ((!striped && !wedged) || !list?.includes(\":\")) {\n return;\n }\n const bands = colorBands(list, n.scheme, \"fill\", n.at(striped ? \"stripeColors\" : \"pieColors\"));\n if (bands.length === 0) {\n return;\n }\n const order = striped ? bands : [...bands].reverse();\n const prefix = striped ? \"stripe\" : \"pie\";\n n.put(`${prefix}Colors`, order.map((b) => b.color).join(\" \"));\n n.put(`${prefix}Sizes`, order.map((b) => String(b.size)).join(\" \"));\n if (striped) {\n n.put(\"stripeDirection\", \"right\");\n } else {\n n.put(\"pieFitBox\", true);\n n.put(\"pieRotation\", 90);\n }\n}\n\n/**\n * The bands of a Graphviz color list (`color;fraction` separated by `:`), in order: a color with no fraction shares\n * what the others leave, the last color takes what sized colors leave when none is unsized, and the shares stop at\n * the whole (https://graphviz.org/docs/attr-types/colorList/, emit.c `parseSegs`).\n * @param list - the color list\n * @param scheme - the color scheme\n * @param use - how Graphviz draws the colors\n * @param site - where it was read\n * @returns each band's color and share of the whole\n */\nfunction colorBands(\n list: string,\n scheme: string | null,\n use: \"fill\" | \"edge\",\n site: CanonSite,\n): { color: string; size: number }[] {\n const parts = list.split(\":\").map((part) => {\n const [color, fraction] = part.split(\";\");\n const c = canonColor(color.trim(), \"graphviz\", site, { scheme, use });\n const f = fraction === undefined ? Number.NaN : Number(fraction);\n return { color: c?.color ?? null, fraction: Number.isFinite(f) && f >= 0 ? f : null };\n });\n const kept = parts.flatMap((p) => (p.color === null ? [] : [{ color: p.color, fraction: p.fraction }]));\n const given = kept.reduce((sum, p) => sum + (p.fraction ?? 0), 0);\n const unsized = kept.filter((p) => p.fraction === null).length;\n const share = unsized > 0 ? Math.max(0, 1 - given) / unsized : 0;\n let used = 0;\n const bands = kept.flatMap((p) => {\n const size = Math.min(p.fraction ?? share, 1 - used);\n used += Math.max(size, 0);\n return size > 0 ? [{ color: p.color, size: num6(size) }] : [];\n });\n // every color sized and short of the whole: Graphviz gives what is left to the last one (emit.c parseSegs)\n const last = bands.at(-1);\n if (last !== undefined && unsized === 0 && used < 1) {\n last.size = num6(last.size + 1 - used);\n }\n return bands;\n}\n\n/**\n * Whether Graphviz fills a node: a point always; `filled` and `radial` any shape, `striped` a box and `wedged` an\n * ellipse only.\n * @param n - the node\n * @returns true when its box or shape is filled\n */\nfunction isFilled(n: NodeRead): boolean {\n const { shape, point } = n;\n return (\n point ||\n n.tokens.some(\n (t) =>\n t === \"filled\" ||\n t === \"radial\" ||\n (t === \"striped\" && BOX_LIKE.has(shape)) ||\n (t === \"wedged\" && ELLIPSE_LIKE.has(shape)),\n )\n );\n}\n\n/**\n * Reads a node's or cluster's outline: its color, width and dashes.\n * @param n - the node\n */\nfunction readNodeOutline(n: NodeRead): void {\n const { get, cx, put, at, tokens } = n;\n if (!cx.cluster && NO_OUTLINE.has(n.shape)) {\n put(\"borderWidth\", 0);\n } else {\n const outline = cx.cluster ? (nonEmpty(get(\"pencolor\")) ?? n.color) : n.color;\n const alpha = readColor(outline, n.scheme, \"line\", \"borderColor\", null, put, at);\n const width = nonEmpty(get(\"penwidth\")) ?? setLineWidth(tokens);\n // peripheries=0 draws no outline, on a node and on a cluster alike\n if (alpha === 0 || Number(nonEmpty(get(\"peripheries\")) ?? \"1\") === 0) {\n put(\"borderWidth\", 0);\n } else if (width !== null) {\n put(\"borderWidth\", penWidth(width, get(\"penwidth\") !== null, at(\"borderWidth\")));\n } else if (tokens.includes(\"bold\")) {\n put(\"borderWidth\", 2);\n }\n }\n if (tokens.includes(\"dashed\")) {\n put(\"borderStyle\", \"dashed\");\n } else if (tokens.includes(\"dotted\")) {\n put(\"borderStyle\", \"dotted\");\n }\n if (!cx.cluster) {\n readNodeRings(n);\n }\n}\n\n/** The outlines Graphviz draws round a node of these shapes when `peripheries` is not set. */\nexport const SHAPE_PERIPHERIES: ReadonlyMap<string, number> = new Map([\n [\"doublecircle\", 2],\n [\"doubleoctagon\", 2],\n [\"tripleoctagon\", 3],\n]);\n\n/** How far apart Graphviz draws a node's outlines, center to center (`GAP`, lib/common/shapes.c). */\nexport const PERIPHERY_GAP = 4;\n\n/**\n * Reads a node's second outline (`peripheries=2`, `doublecircle`): Graphviz draws it `PERIPHERY_GAP` points outside\n * the first, in the same color, width and dashes. graphty draws one outer ring, so a third and later outline is\n * noted as not carried.\n * @param n - the node\n */\nfunction readNodeRings(n: NodeRead): void {\n const raw = nonEmpty(n.get(\"peripheries\"));\n const count = raw === null ? (SHAPE_PERIPHERIES.get(n.shape) ?? 1) : Math.trunc(Number(raw));\n if (Number.isNaN(count) || count <= 1 || NO_OUTLINE.has(n.shape)) {\n return;\n }\n const c =\n n.color === null\n ? null\n : canonColor(n.color, \"graphviz\", n.at(\"outerBorderColor\"), {\n scheme: n.scheme,\n use: \"line\",\n });\n if (c !== null && c.alpha === 0) {\n return;\n }\n const widthRaw = nonEmpty(n.get(\"penwidth\")) ?? setLineWidth(n.tokens);\n const parsed = widthRaw === null ? Number.NaN : Number(widthRaw);\n const unset = n.tokens.includes(\"bold\") ? 2 : 1;\n const pen = Number.isFinite(parsed) ? Math.max(0, parsed) : unset;\n n.put(\"outerBorderColor\", c?.color ?? \"#000000\");\n n.put(\"outerBorderOpacity\", c !== null && c.alpha < 1 ? c.alpha : null);\n n.put(\"outerBorderWidth\", num6(pen));\n // the gap between the outline's outer edge and the ring's inner edge\n n.put(\"outerBorderOffset\", num6(Math.max(0, PERIPHERY_GAP - pen)));\n if (n.tokens.includes(\"dashed\") || n.tokens.includes(\"dotted\")) {\n n.put(\"outerBorderStyle\", n.tokens.includes(\"dashed\") ? \"dashed\" : \"dotted\");\n }\n if (count > 2) {\n noteAt(n.at(\"outerBorderWidth\"), STYLE_ISSUE.NOT_CARRIED, `peripheries=${String(count)}`);\n }\n}\n\n/**\n * Reads a node's or cluster's shape: a cluster is a rectangle, rounded by the `rounded` style as a box is. Graphviz draws\n * a striped box with square corners whatever `rounded` says.\n * @param n - the node\n */\nfunction readNodeShape(n: NodeRead): void {\n const rounded = n.tokens.includes(\"rounded\") && !n.tokens.includes(\"striped\");\n const turned = turnedPolygon(n);\n if (n.cx.cluster) {\n n.put(\"shape\", rounded ? \"round-rectangle\" : \"rectangle\");\n } else if (n.shape === \"polygon\") {\n readPolygon(n, rounded);\n } else if (turned !== null) {\n n.put(\"shape\", \"polygon\");\n n.put(\"shapePoints\", cornersText(graphvizDrawnCorners(turned)));\n n.put(\"shapePointsStretch\", false);\n } else if (NAMED_OUTLINES.has(n.shape)) {\n n.put(\"shape\", \"polygon\");\n n.put(\"shapePoints\", NAMED_OUTLINES.get(n.shape) ?? null);\n // a polygon shape's corners are where Graphviz draws them, one reaching past its box too\n n.put(\"shapePointsStretch\", false);\n } else if (GRAPHVIZ_GLYPH_SHAPES.has(n.shape)) {\n const size = (name: string): number | null => {\n const v = inches(n.get(name), n.at(name));\n return v === null ? null : v * DOT_POINTS_PER_INCH;\n };\n putGlyph(\n n.shape,\n size(\"width\"),\n size(\"height\"),\n n.put,\n () => {\n const raw = nonEmpty(n.get(\"penwidth\")) ?? setLineWidth(n.tokens);\n const pen = raw === null ? Number.NaN : Number(raw);\n if (Number.isFinite(pen)) {\n return Math.max(0, pen);\n }\n return n.tokens.includes(\"bold\") ? 2 : 1;\n },\n () =>\n n.color === null\n ? null\n : (canonColor(n.color, \"graphviz\", n.at(\"outerBorderColor\"), { scheme: n.scheme, use: \"line\" })\n ?.color ?? null),\n );\n } else if (n.shapeRaw !== null) {\n const shape =\n rounded && BOX_LIKE.has(n.shape)\n ? \"round-rectangle\"\n : canonEnum(\"shape\", n.shapeRaw, \"graphviz\", n.at(\"shape\"));\n // a filled shape=none is its box filled, with no outline (its border is 0): a rectangle, not a node with no body\n n.put(\"shape\", shape === \"none\" && isFilled(n) ? \"rectangle\" : shape);\n }\n}\n\n/** The polygon shapes `orientation` turns, by their own sides and orientation (`shapes.c`). */\nconst TURNABLE_POLYGONS: ReadonlyMap<string, { readonly sides: number; readonly orientation: number }> = new Map([\n ...[...BOX_LIKE].map((name) => [name, { sides: 4, orientation: 0 }] as const),\n [\"diamond\", { sides: 4, orientation: 45 }],\n [\"hexagon\", { sides: 6, orientation: 0 }],\n [\"octagon\", { sides: 8, orientation: 0 }],\n]);\n\n/**\n * The polygon a named polygon shape is when its `orientation` turns it off its own axes (a box turned 30 degrees),\n * or null when it is drawn as its shape: Graphviz adds the attribute to the shape's own orientation.\n * @param n - the node\n * @returns the polygon, or null\n */\nfunction turnedPolygon(n: NodeRead): Parameters<typeof graphvizPolygonCorners>[0] | null {\n const turn = Number(nonEmpty(n.get(\"orientation\")) ?? \"0\");\n const own = TURNABLE_POLYGONS.get(n.shape) ?? GRAPHVIZ_POLYGON_SHAPES.get(n.shape);\n if (own === undefined || !Number.isFinite(turn) || turn % 360 === 0) {\n return null;\n }\n const polygon = {\n distortion: 0,\n skew: 0,\n ...own,\n orientation: own.orientation + Math.max(-360, turn),\n };\n // a quarter turn of a box is a box again\n return isGraphvizBox(polygon) ? null : polygon;\n}\n\n/**\n * Reads a `shape=polygon` node: a box when it is one (four sides, no distortion or skew, square to the axes), an\n * ellipse below three sides, else its corners as Graphviz places them.\n * @param n - the node\n * @param rounded - whether its style rounds a box's corners\n */\nfunction readPolygon(n: NodeRead, rounded: boolean): void {\n const number = (name: string, fallback: number, least: number): number => {\n const raw = nonEmpty(n.get(name));\n const v = raw === null ? Number.NaN : Number(raw);\n return Number.isFinite(v) ? Math.max(least, v) : fallback;\n };\n const polygon = {\n sides: Math.trunc(number(\"sides\", 4, 0)),\n distortion: number(\"distortion\", 0, -100),\n skew: number(\"skew\", 0, -100),\n orientation: number(\"orientation\", 0, -360),\n };\n if (isGraphvizBox(polygon)) {\n n.put(\"shape\", rounded ? \"round-rectangle\" : \"rectangle\");\n } else if (polygon.sides < 3) {\n n.put(\"shape\", \"ellipse\");\n } else {\n n.put(\"shape\", \"polygon\");\n n.put(\"shapePoints\", cornersText(graphvizDrawnCorners(polygon)));\n n.put(\"shapePointsStretch\", false);\n }\n}\n\n/**\n * A Graphviz polygon's corners where Graphviz draws them, as fractions of its box's half width and half height: it\n * grows a polygon that falls short of the box along an axis until it reaches the box's sides, and keeps one that\n * reaches past them (a distortion, a skew, an egg) as it is (shapes.c `poly_init`: `scalex = bb.x / xmax`).\n * @param polygon - the polygon's attributes\n * @returns the corners\n */\nfunction graphvizDrawnCorners(polygon: Parameters<typeof graphvizPolygonCorners>[0]): [number, number][] {\n const corners = graphvizPolygonCorners(polygon);\n const grow = (axis: 0 | 1): number => Math.max(1, 1 / Math.max(...corners.map((c) => Math.abs(c[axis]))));\n const [gx, gy] = [grow(0), grow(1)];\n return corners.map(([x, y]) => [x * gx, y * gy]);\n}\n\n/**\n * Corners as a `shapePoints` value.\n * @param corners - the corners\n * @returns `x,y x,y ...`\n */\nfunction cornersText(corners: readonly (readonly [number, number])[]): string {\n return corners.map(([x, y]) => `${num6(x)},${num6(y)}`).join(\" \");\n}\n\n/** The outline of each Graphviz polygon shape graphty draws as a polygon of its corners, by shape name. */\nconst NAMED_OUTLINES: ReadonlyMap<string, string> = new Map(\n [...GRAPHVIZ_POLYGON_SHAPES].map(([name, polygon]) => [name, cornersText(graphvizDrawnCorners(polygon))] as const),\n);\n\n/**\n * A Graphviz shape drawn as pieces of its own (`graphvizGlyph`) at a node's size, as the neutral values that draw it:\n * a polygon of its outline drawn where it says, its further pieces (`shapeParts`) and lines (`shapeLines`), each as\n * fractions of the node's half width and half height. An `underline` is filled with no line round it, its line alone\n * drawn in the pen's width.\n * @param shape - the shape name, lowercase\n * @param width - the node's width in points, or null for Graphviz's default\n * @param height - its height, or null\n * @param put - receives the values\n * @param pen - the node's pen width, for an outline drawn as a line alone and a ring\n * @param color - the node's pen color, for a ring\n */\nexport function putGlyph(\n shape: string,\n width: number | null,\n height: number | null,\n put: (property: string, value: StyleValue | null) => void,\n pen: () => number,\n color: () => string | null,\n): void {\n const text = glyphTexts(shape, width, height);\n if (text === null) {\n return;\n }\n put(\"shape\", \"polygon\");\n put(\"shapePoints\", text.outline);\n put(\"shapePointsStretch\", false);\n put(\"shapeParts\", text.parts);\n put(\"shapeLines\", text.lines);\n if (text.unstroked) {\n put(\"shapeLineWidth\", pen());\n put(\"borderWidth\", 0);\n }\n if (text.ring !== null) {\n // drawn in the pen, its gap the distance less a pen's width (the outline's half and its own)\n put(\"outerBorderColor\", color() ?? \"#000000\");\n put(\"outerBorderWidth\", num6(pen()));\n put(\"outerBorderOffset\", num6(Math.max(0, text.ring - pen())));\n }\n}\n\n/**\n * A Graphviz glyph's pieces as `shapePoints`, `shapeParts` and `shapeLines` text at a node's size, or null for a shape\n * that is not one.\n * @param shape - the shape name, lowercase\n * @param width - the node's width in points, or null for Graphviz's default\n * @param height - its height, or null\n * @returns the texts (parts and lines null when there are none)\n */\nfunction glyphTexts(\n shape: string,\n width: number | null,\n height: number | null,\n): { outline: string; parts: string | null; lines: string | null; unstroked: boolean; ring: number | null } | null {\n const glyph = graphvizGlyph(shape, width, height);\n if (glyph === null) {\n return null;\n }\n // fractions of the half width and half height the glyph was laid out at\n const half = (v: number | null, fallback: number): number => (v !== null && v > 0 ? v : fallback) / 2;\n const [W, H] = [half(width, 54), half(height, 36)];\n const list = (points: readonly (readonly [number, number])[]): string =>\n cornersText(points.map(([x, y]) => [x / W, y / H] as const));\n const lists = (all: readonly (readonly (readonly [number, number])[])[]): string | null =>\n all.length === 0 ? null : all.map(list).join(\"; \");\n return {\n outline: list(glyph.outline),\n parts: lists(glyph.parts),\n lines: lists(glyph.lines),\n unstroked: glyph.unstroked === true,\n ring: glyph.ring ?? null,\n };\n}\n\n/**\n * The corners of a Graphviz shape graphty draws as a polygon (`house`, `cylinder`, `note` ...), as a `shapePoints`\n * value, or undefined for a shape graphty draws by name.\n * @param shape - the shape name, lowercase\n * @returns the corners, or undefined\n */\nexport function graphvizOutline(shape: string): string | undefined {\n return NAMED_OUTLINES.get(shape);\n}\n\n/**\n * Whether Graphviz draws a shape with no outline (`plain`, `plaintext`, `none`).\n * @param shape - the shape name, lowercase\n * @returns true for a shape with no outline\n */\nexport function graphvizHasNoOutline(shape: string): boolean {\n return NO_OUTLINE.has(shape);\n}\n\n/** The shape name of each outline in `NAMED_OUTLINES`, so a written node keeps its Graphviz shape. */\nconst OUTLINE_NAMES: ReadonlyMap<string, string> = new Map([...NAMED_OUTLINES].map(([name, text]) => [text, name]));\n\n/**\n * The Graphviz glyph shape a polygon is at a node's size, its outline, parts and lines alike, so a written node keeps\n * its shape (a ribosome site and a protease site share their outline and differ in their stem).\n * @param get - the node's values\n * @param width - the node's width in points, or null\n * @param height - its height, or null\n * @returns the shape name and whether it is filled with no line round it, or undefined\n */\nfunction glyphOf(\n get: Get,\n width: number | null,\n height: number | null,\n): { name: string; unstroked: boolean } | undefined {\n const text = (property: string): string | null => {\n const v = get(property);\n return typeof v === \"string\" ? v.trim() : null;\n };\n const outline = text(\"shapePoints\");\n if (outline === null) {\n return undefined;\n }\n // a glyph with another number of corners cannot match: skip writing its texts, which is most of the work\n const corners = outline === \"\" ? 0 : outline.split(/\\s+/).length;\n for (const name of GRAPHVIZ_GLYPH_SHAPES) {\n if (graphvizGlyph(name, width, height)?.outline.length !== corners) {\n continue;\n }\n const g = glyphTexts(name, width, height);\n if (g !== null && g.outline === outline && g.parts === text(\"shapeParts\") && g.lines === text(\"shapeLines\")) {\n return { name, unstroked: g.unstroked };\n }\n }\n return undefined;\n}\n\n/**\n * A pen width as Graphviz draws it: a negative `penwidth` is raised to 0, its minimum, and noted.\n * @param raw - the `penwidth` or `setlinewidth` value\n * @param attribute - whether it is the `penwidth` attribute\n * @param site - where it was read\n * @returns the width, or null when it does not parse\n */\nfunction penWidth(raw: string, attribute: boolean, site: CanonSite): number | null {\n const value = Number(raw.trim());\n if (attribute && Number.isFinite(value) && value < 0) {\n noteAt(site, STYLE_ISSUE.BAD_VALUE, raw.slice(0, MAX_STYLE_VALUE_LENGTH));\n return 0;\n }\n return canonNumber(raw, site);\n}\n\n/**\n * Reads a node's width and height: exact where Graphviz draws them exactly (`fixedsize`, an empty label that is not\n * a record's, a point), otherwise minimums it grows to fit the label (`readLabelFit`).\n * @param get - the node's attributes\n * @param shape - its shape, lowercase\n * @param point - whether it is a point\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readSize(get: Attr, shape: string, point: boolean, put: Put, at: At): void {\n let w = inches(get(\"width\"), at(\"width\"));\n let h = inches(get(\"height\"), at(\"height\"));\n const same = point || CIRCLE_LIKE.has(shape) || isTrue(get(\"regular\"));\n if (shape === \"plain\") {\n // plain is plaintext with its width and height forced to 0: exactly the size of its label\n w = h = 0;\n } else if (w === null && h === null) {\n if (point) {\n put(\"width\", num6(POINT_SIZE * DOT_POINTS_PER_INCH));\n put(\"height\", num6(POINT_SIZE * DOT_POINTS_PER_INCH));\n return;\n }\n if (!same) {\n return;\n }\n // a regular shape takes the smaller of the default width and height (0.5 inch) for both\n w = h = REGULAR_SIZE;\n }\n let ww = w;\n let hh = h;\n if (point) {\n ww = hh = Math.min(w ?? Infinity, h ?? Infinity);\n } else if (same) {\n ww = hh = Math.max(w ?? 0, h ?? 0);\n }\n put(\"width\", ww === null ? null : canonNumber(ww, at(\"width\"), DOT_POINTS_PER_INCH));\n put(\"height\", hh === null ? null : canonNumber(hh, at(\"height\"), DOT_POINTS_PER_INCH));\n}\n\n/**\n * Reads the graph's `quantum` for a node that grows to hold its label: Graphviz rounds the padded label box up to a\n * multiple of it before fitting the outline round it (`poly_init`), so the node is at least one quantum across, an\n * ellipse's box times the square root of 2.\n * @param n - the node\n * @param label - its `label` attribute, or null\n */\nfunction readQuantum(n: NodeRead, label: string | null): void {\n const { get, put, shape } = n;\n let scale: number | null = BOX_LIKE.has(shape) ? 1 : null;\n if (ELLIPSE_LIKE.has(shape)) {\n scale = Math.SQRT2;\n }\n const w = Number(get(\"width\") ?? Number.NaN);\n const h = Number(get(\"height\") ?? Number.NaN);\n // ponytail: one quantum is the least size; a label box over one quantum is not rounded up to the next, and only\n // boxes and ellipses with their size given are read (other polygons fit their box by factors of their own)\n if (n.cx.quantum === 0 || scale === null || label === \"\" || isTrue(get(\"fixedsize\")) || !(w >= 0 && h >= 0)) {\n return;\n }\n const least = n.cx.quantum * scale;\n put(\"width\", num6(Math.max(w * DOT_POINTS_PER_INCH, least)));\n put(\"height\", num6(Math.max(h * DOT_POINTS_PER_INCH, least)));\n}\n\n/** Graphviz's padding around a node's label when it has no `margin`: 8 points left and right, 4 above and below. */\nconst LABEL_PAD = { x: 8, y: 4 } as const;\n\n/** Graphviz's line height, as a multiple of the font size (`LINESPACING`, lib/common/const.h). */\nconst LINE_SPACING = 1.2;\n\n/**\n * Reads how a node that is not drawn at a fixed size grows to hold its label (`poly_init`, lib/common/shapes.c):\n * its padded label box fits inside its outline, the `margin` (else 8 points by 4) on each side, and a circle, a\n * square or a `regular` node stays as wide as it is tall. The neutral label box is one font size per line, so the\n * rest of Graphviz's line height (1.2 font sizes) goes into the vertical padding.\n * @param get - the node's attributes\n * @param shape - its shape, lowercase\n * @param label - its `label` attribute, or null\n * @param shown - the label it shows\n * @param put - receives the values\n */\nfunction readLabelFit(get: Attr, shape: string, label: string | null, shown: string, put: Put): void {\n if (isTrue(get(\"fixedsize\")) || (label === \"\" && !RECORD.has(shape))) {\n return;\n }\n const lines = Math.max(1, shown.replace(/\\n$/, \"\").split(\"\\n\").length);\n const size = Number(get(\"fontsize\") ?? 14);\n const fontSize = Number.isFinite(size) && size > 0 ? size : 14;\n const margin = (get(\"margin\") ?? \"\")\n .split(\",\")\n .filter((text) => text.trim() !== \"\")\n .map(Number)\n .filter(isLength);\n // plain is plaintext with a margin of 0\n const pad = shape === \"plain\" ? { x: 0, y: 0 } : LABEL_PAD;\n const padX = margin.length > 0 ? margin[0] * DOT_POINTS_PER_INCH : pad.x;\n const padY = margin.length > 0 ? (margin[1] ?? margin[0]) * DOT_POINTS_PER_INCH : pad.y;\n // a decorated box holds its label as a box does, exactly\n put(\"labelFit\", GRAPHVIZ_DECORATED_BOXES.has(shape) ? \"bounds\" : \"inside\");\n put(\"labelPaddingX\", num6(padX));\n put(\"labelPaddingY\", num6(padY + ((LINE_SPACING - 1) * fontSize * lines) / 2));\n if (CIRCLE_LIKE.has(shape) || isTrue(get(\"regular\"))) {\n put(\"labelFitSquare\", true);\n }\n}\n\n/**\n * Whether a `margin` part is a usable length: a number at least 0.\n * @param value - the part\n * @returns whether it is\n */\nfunction isLength(value: number): boolean {\n return Number.isFinite(value) && value >= 0;\n}\n\n/**\n * Reads one edge the way Graphviz draws it.\n * @param get - its attributes\n * @param cx - its names and direction\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readEdge(get: Attr, cx: EdgeContext, put: Put, at: At): void {\n const tokens = styleTokens(get(\"style\"), at(\"visible\"));\n const scheme = get(\"colorscheme\");\n readCommon(get, tokens, scheme, cx.names, put, at);\n readColor(nonEmpty(get(\"color\")), scheme, \"edge\", \"color\", \"opacity\", put, at);\n readEdgeSegments(nonEmpty(get(\"color\")), scheme, put, at);\n readEdgeLine(get, tokens, put, at);\n readEdgeArrows(get, cx, put, at);\n for (const [attribute, property] of [\n [LABEL_ATTRIBUTE, \"label\"],\n [\"headlabel\", \"targetLabel\"],\n [\"taillabel\", \"sourceLabel\"],\n ] as const) {\n // an edge's xlabel is drawn beside its middle, as its label is: it is the label when there is no other\n const raw = attribute === LABEL_ATTRIBUTE ? (get(attribute) ?? nonEmpty(get(\"xlabel\"))) : get(attribute);\n if (raw !== null) {\n put(property, labelText(raw, cx.names, cx.html, false, at(property)));\n if (property === \"label\") {\n readLabelAlign(raw, cx.names, cx.html, false, put);\n readHtmlRuns(raw, cx.html, scheme, put, at);\n }\n }\n }\n if (get(LABEL_ATTRIBUTE) !== null && nonEmpty(get(\"xlabel\")) !== null) {\n noteAt(at(\"label\"), STYLE_ISSUE.NOT_CARRIED, \"xlabel\");\n }\n readEndLabelFace(get, scheme, put, at);\n}\n\n/**\n * Reads the face of an edge's head and tail labels where it is not the label's: `labelfontsize`, `labelfontcolor` and\n * `labelfontname` (https://graphviz.org/docs/attrs/labelfontsize/), each the edge's `fontsize`, `fontcolor` and\n * `fontname` when unset, which the end labels then take from the label.\n * @param get - the edge's attributes\n * @param scheme - its color scheme\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readEndLabelFace(get: Attr, scheme: string | null, put: Put, at: At): void {\n const ends = ([\"target\", \"source\"] as const).filter(\n (end) => get(end === \"target\" ? \"headlabel\" : \"taillabel\") !== null,\n );\n const size = get(\"labelfontsize\");\n const font = get(\"labelfontname\");\n for (const end of ends) {\n readColor(nonEmpty(get(\"labelfontcolor\")), scheme, \"text\", `${end}LabelColor`, null, put, at);\n if (size !== null) {\n put(`${end}LabelSize`, canonNumber(size, at(`${end}LabelSize`)));\n }\n // ponytail: the family only; a bold or italic end-label face is drawn in the label's weight and slant\n if (font !== null && font.length <= MAX_STYLE_VALUE_LENGTH) {\n put(`${end}LabelFont`, graphvizFont(font).family);\n }\n }\n}\n\n/**\n * Reads an edge's colored segments: a color list with a `;fraction` in it (`red;0.3:blue`) draws the line in one piece\n * per color along its length, which is a linear gradient with a hard switch at each band's end. A list with no\n * fraction draws parallel lines, which graphty does not draw (the line is in the first color).\n * @param list - the edge's `color`\n * @param scheme - its color scheme\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readEdgeSegments(list: string | null, scheme: string | null, put: Put, at: At): void {\n if (list === null || !list.includes(\":\") || !list.includes(\";\")) {\n return;\n }\n const bands = colorBands(list, scheme, \"edge\", at(\"gradientColors\"));\n if (bands.length < 2) {\n return;\n }\n const colors: string[] = [];\n const stops: number[] = [];\n let start = 0;\n for (const band of bands) {\n colors.push(band.color, band.color);\n stops.push(num6(start), num6(Math.min(1, start + band.size)));\n start += band.size;\n }\n put(\"gradientKind\", \"linear\");\n put(\"gradientColors\", colors.join(\" \"));\n put(\"gradientStops\", stops.join(\" \"));\n}\n\n/**\n * What an edge's label places are read against: the nodes' centers and sizes.\n * @param snapshot - the graph\n * @returns the context\n */\nfunction labelPlaceContext(snapshot: GraphSnapshot): LabelPlaceContext {\n const column = snapshot.nodes.byRole(\"position\");\n return {\n center: (i) => {\n const v = column?.isSet(i) === true ? (column.value(i) as ArrayLike<number>) : null;\n return v === null ? null : [v[0], v[1]];\n },\n node: (i, name) => nonEmpty(cellText(snapshot.nodes, name, i)),\n external: (cellText(snapshot.graph, \"layout\", 0)?.trim().toLowerCase() ?? \"dot\") !== \"dot\",\n };\n}\n\n/**\n * The route Graphviz laid an edge along, from its `pos`: `[e,x,y] [s,x,y]` arrow tips, then the B-spline's `3n + 1`\n * control points (y up), flattened into bends between the two nodes' centers. Null for an edge Graphviz drew\n * straight, a `pos` that is not a spline, or nodes without positions.\n * @param snapshot - the graph\n * @param e - the edge\n * @param pos - its `pos` text\n * @returns the `bends` value, or null\n */\nfunction splineBends(snapshot: GraphSnapshot, e: number, pos: string | null): string | null {\n if (pos === null) {\n return null;\n }\n const column = snapshot.nodes.byRole(\"position\");\n const center = (i: number): BendPoint | null => {\n const v = column?.isSet(i) === true ? (column.value(i) as ArrayLike<number>) : null;\n return v === null ? null : [v[0], v[1]];\n };\n const [source, target] = [center(snapshot.edgeSource(e)), center(snapshot.edgeTarget(e))];\n if (source === null || target === null) {\n return null;\n }\n return graphvizPosBends(source, target, pos);\n}\n\n/**\n * The bends of an edge Graphviz laid, from its `pos` text (`[e,x,y] [s,x,y]` arrow tips, then each spline's\n * `3n + 1` control points, y up, splines separated by `;`), between the two nodes' centers in the same coordinates.\n * @param source - the source node's center\n * @param target - the target node's center\n * @param pos - the edge's `pos` text\n * @returns the `bends` value, or null for a straight route or a `pos` that is not a spline\n * @category Styles\n */\nexport function graphvizPosBends(source: BendPoint, target: BendPoint, pos: string): string | null {\n // the arrow tips of the first spline's start and the last spline's end\n const tip = (spline: string | undefined, flag: \"s\" | \"e\"): BendPoint | null => {\n const token = (spline ?? \"\")\n .trim()\n .split(/\\s+/)\n .find((t) => t.startsWith(`${flag},`));\n const [x, y] = (token ?? \"\").slice(2).split(\",\").map(Number);\n return token !== undefined && Number.isFinite(x) && Number.isFinite(y) ? [x, y] : null;\n };\n const parts = pos.split(\";\");\n const tips = { start: tip(parts[0], \"s\"), end: tip(parts.at(-1), \"e\") };\n // ponytail: the splines of a concentrated edge (\";\"-separated) are joined end to end\n const splines = parts.map((spline) =>\n spline\n .trim()\n .split(/\\s+/)\n .filter((t) => !/^[es],/.test(t))\n .map((t): BendPoint => {\n const [x, y] = t.split(\",\").map(Number);\n return [x, y];\n }),\n );\n return graphvizRouteBends(source, target, splines, tips);\n}\n\n/** How far off the line between its nodes' centers, in points, a Graphviz route may pass and still be straight. */\nconst GRAPHVIZ_STRAIGHT_POINTS = 1;\n\n/** How far apart Graphviz's neato lays the loops on one node, across (x) and along (y) its side, in points. */\nconst GRAPHVIZ_LOOP_STEP = { x: 18, y: 9 } as const;\n\n/**\n * The self-loops Graphviz lays itself, with no `pos` of their own and no ports: neato's `selfRight` (splines.c), on\n * the node's right side, the k-th of a node's n loops two cubic curves from its center out to `rw + 18k` points right\n * of it and back, `9k / n` points above and then below its center line (measured on Graphviz 14.1.2's and 2.43's\n * drawings of nodes from 0.33 to 1 inch).\n * @param snapshot - the graph\n * @returns the bends of an edge that is such a loop, or null\n */\nfunction graphvizLoops(snapshot: GraphSnapshot): { bendsOf: (e: number, get: Attr) => string | null } {\n const portless = (get: Attr): boolean =>\n nonEmpty(get(\"tailport\")) === null &&\n nonEmpty(get(\"headport\")) === null &&\n nonEmpty(get(POS_ATTRIBUTE)) === null;\n const onNode = new Map<number, number[]>();\n // ponytail: ortho routes a loop round the node's corners and none draws no edge; both keep the element's loop.\n const splines = (nonEmpty(cellText(snapshot.graph, \"splines\", 0)) ?? \"\").toLowerCase();\n // a file graphty wrote keeps its loops' look in its own block\n const laid =\n splines !== \"ortho\" && splines !== \"none\" && nonEmpty(cellText(snapshot.graph, STYLE_BLOCK_NAME, 0)) === null;\n for (let e = 0; e < snapshot.edgeCount && laid; e++) {\n const n = snapshot.edgeSource(e);\n if (n === snapshot.edgeTarget(e) && portless((name) => cellText(snapshot.edges, name, e))) {\n onNode.set(n, [...(onNode.get(n) ?? []), e]);\n }\n }\n const inches = (n: number, name: string, fallback: number): number => {\n const v = Number(nonEmpty(cellText(snapshot.nodes, name, n)) ?? Number.NaN);\n return (Number.isFinite(v) && v > 0 ? v : fallback) * DOT_POINTS_PER_INCH;\n };\n return {\n bendsOf: (e, get) => {\n const n = snapshot.edgeSource(e);\n const list = onNode.get(n);\n if (n !== snapshot.edgeTarget(e) || list === undefined || !portless(get)) {\n return null;\n }\n // ponytail: a node Graphviz grows to fit its label is taken at its stated width and height\n const [w, h] = [inches(n, \"width\", 0.75), inches(n, \"height\", 0.5)];\n const k = list.indexOf(e) + 1;\n const dx = w / 2 + GRAPHVIZ_LOOP_STEP.x * k;\n const dy = (GRAPHVIZ_LOOP_STEP.y * k) / list.length;\n const curve = flattenCubic([\n [0, 0],\n [dx / 3, dy],\n [dx, dy],\n [dx, 0],\n [dx, -dy],\n [dx / 3, -dy],\n [0, 0],\n ]);\n return curve === null ? null : canonNodeOffsets([0, 0], [w, h], curve.slice(1, -1), false);\n },\n };\n}\n\n/**\n * The bends of a route Graphviz laid: B-splines of `3n + 1` control points each (y up), flattened into bends between\n * the two nodes' centers. Null for a route on the line between the centers, which is the straight edge it looks like,\n * or for control points that are not a spline. Also reads the `Line` of a GML file Graphviz's gv2gml wrote.\n * @param source - the source node's center\n * @param target - the target node's center\n * @param splines - the control points of each spline, joined end to end\n * @param tips - the arrow tips `pos` stores (`s,x,y` and `e,x,y`): the line runs on to each, along its arrow\n * @param tips.start - the tail arrow's tip, or null\n * @param tips.end - the head arrow's tip, or null\n * @returns the `bends` value, or null\n */\nexport function graphvizRouteBends(\n source: BendPoint,\n target: BendPoint,\n splines: readonly (readonly BendPoint[])[],\n tips?: { readonly start: BendPoint | null; readonly end: BendPoint | null },\n): string | null {\n const points: BendPoint[] = [];\n for (const controls of splines) {\n const flat = flattenCubic(controls);\n if (flat === null || flat.some(([x, y]) => !Number.isFinite(x) || !Number.isFinite(y))) {\n return null;\n }\n points.push(...flat);\n }\n // a tip where the spline already ends adds no point\n const apart = (a: BendPoint, b: BendPoint | undefined): boolean =>\n b === undefined || Math.hypot(a[0] - b[0], a[1] - b[1]) > 1e-6;\n const start = tips?.start ?? null;\n const end = tips?.end ?? null;\n if (start !== null && apart(start, points[0])) {\n points.unshift(start);\n }\n if (end !== null && apart(end, points.at(-1))) {\n points.push(end);\n }\n const [dx, dy] = [target[0] - source[0], target[1] - source[1]];\n const length = Math.hypot(dx, dy);\n const off =\n length > 0\n ? Math.max(...points.map(([x, y]) => Math.abs((x - source[0]) * dy - (y - source[1]) * dx))) / length\n : 0;\n // a route on the line between the centers is the straight edge it looks like: Graphviz draws its straight lines\n // (`splines=false`) up to half a point off that line\n return off > Math.max(1e-3 * length, GRAPHVIZ_STRAIGHT_POINTS) ? canonBends(source, target, points, false) : null;\n}\n\n/**\n * Reads an edge's line: its width and dashes.\n * @param get - its attributes\n * @param tokens - its style tokens\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readEdgeLine(get: Attr, tokens: readonly string[], put: Put, at: At): void {\n const width = nonEmpty(get(\"penwidth\")) ?? setLineWidth(tokens);\n if (width !== null) {\n put(\"width\", penWidth(width, get(\"penwidth\") !== null, at(\"width\")));\n } else if (tokens.includes(\"bold\")) {\n put(\"width\", 2);\n }\n if (tokens.includes(\"dashed\")) {\n put(\"lineStyle\", \"dashed\");\n } else if (tokens.includes(\"dotted\")) {\n put(\"lineStyle\", \"dotted\");\n } else if (tokens.includes(\"solid\") || tokens.includes(\"bold\")) {\n put(\"lineStyle\", \"solid\");\n } else if (tokens.includes(\"tapered\")) {\n put(\"lineStyle\", \"other:tapered\");\n }\n}\n\n/**\n * Reads an edge's arrows and their size.\n * @param get - its attributes\n * @param cx - its names and direction\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readEdgeArrows(get: Attr, cx: EdgeContext, put: Put, at: At): void {\n const dirRaw = nonEmpty(get(\"dir\"));\n const head = nonEmpty(get(\"arrowhead\"));\n const tail = nonEmpty(get(\"arrowtail\"));\n // with none of these the tool-default rule draws the arrow of the graph's kind\n if (dirRaw !== null || head !== null || tail !== null) {\n const dir = (dirRaw ?? (cx.directed ? \"forward\" : \"none\")).trim().toLowerCase();\n readEdgeArrow(\"target\", head, dir === \"forward\" || dir === \"both\", put, at);\n readEdgeArrow(\"source\", tail, dir === \"back\" || dir === \"both\", put, at);\n }\n const size = get(\"arrowsize\");\n if (size !== null) {\n put(\"arrowSize\", canonNumber(size, at(\"arrowSize\")));\n }\n // an edge's `fillcolor` fills its arrowheads (their outline stays the edge's color)\n const fill = nonEmpty(get(\"fillcolor\"));\n for (const property of [\"targetArrowColor\", \"sourceArrowColor\"]) {\n readColor(fill, get(\"colorscheme\"), \"fill\", property, null, put, at);\n }\n}\n\n/**\n * Reads one end's arrow: its shape, or none when the edge's direction draws no arrow there, and the side it keeps.\n * @param end - which end\n * @param raw - its `arrowhead` or `arrowtail`, or null\n * @param on - whether the edge's direction draws an arrow there\n * @param put - receives the values\n * @param at - the sites\n */\nfunction readEdgeArrow(end: \"target\" | \"source\", raw: string | null, on: boolean, put: Put, at: At): void {\n const arrow = on ? graphvizArrowValue(raw ?? \"normal\", at(`${end}Arrow`)) : null;\n put(`${end}Arrow`, arrow === null ? \"none\" : arrow.value);\n if (arrow?.side !== null && arrow?.side !== undefined) {\n put(`${end}ArrowSide`, arrow.side);\n }\n}\n\n/** The sides an `l` or `r` arrow modifier keeps, by their first letters. */\nconst ARROW_SIDES = [\"left\", \"right\"] as const;\n\n/** The open forms of Graphviz arrows that a neutral shape draws; the others are drawn filled. */\nconst GRAPHVIZ_OPEN_ARROWS: ReadonlySet<string> = new Set([\"normal\", \"diamond\", \"dot\", \"box\", \"inv\"]);\n\n/** The open Graphviz arrows the neutral vocabulary has no name for, by the value graphty draws them as. */\nconst GRAPHVIZ_OTHER_ARROWS: ReadonlyMap<string, string> = new Map([\n [\"obox\", \"other:open-square\"],\n [\"oinv\", \"other:open-inverted\"],\n]);\n\n/**\n * The neutral arrow value Graphviz draws for an arrow name (`onormal`, `lbox`, `invempty`), with an open shape the\n * neutral vocabulary has no name for (`obox`, `oinv`) as the value graphty draws it as, and the side an `l` or `r`\n * keeps. Read so by the DOT reader and by the GML reader for gv2gml's `targetArrow` / `sourceArrow`.\n * @param raw - the arrow name\n * @param site - where it was read\n * @returns the value and its side (null for the whole shape)\n */\nexport function graphvizArrowValue(\n raw: string,\n site: CanonSite,\n): { readonly value: string | null; readonly side: \"left\" | \"right\" | null } {\n const first = graphvizArrow(raw);\n const other = first === null ? undefined : GRAPHVIZ_OTHER_ARROWS.get(first.name);\n return {\n value: other ?? canonEnum(\"arrow\", first?.name ?? raw, \"graphviz\", site),\n side: first?.side ?? null,\n };\n}\n\n/**\n * The arrow Graphviz draws at an edge's very end, from an arrow name of up to four shapes (`dotodot`,\n * `lteeoldiamond`): the first shape that is not `none`, with its `o` (open) kept where a neutral shape draws it, and\n * the side an `l` or `r` keeps alone (\"clip the shape, leaving only the part to the left of the edge\", looking along\n * the edge toward the arrow's tip).\n * @param raw - the arrow name\n * @returns the shape's own name and its side (null for the whole shape), or null for a name outside the grammar (a\n * synonym such as `empty`)\n */\nfunction graphvizArrow(raw: string): { readonly name: string; readonly side: \"left\" | \"right\" | null } | null {\n let rest = raw.trim().toLowerCase();\n // the one synonym the grammar would misread (as `inv`): arrows.c's `invempty` is an open `inv`\n if (rest === \"invempty\") {\n rest = \"oinv\";\n }\n while (rest.length > 0) {\n const m = /^([olr]{0,3})(normal|crow|tee|box|diamond|dot|none|inv|vee|icurve|curve)/.exec(rest);\n if (m === null) {\n return null;\n }\n rest = rest.slice(m[0].length);\n const [, mods, shape] = m;\n if (shape !== \"none\") {\n const side = ARROW_SIDES.find((s) => mods.includes(s[0])) ?? null;\n const open = mods.includes(\"o\") && GRAPHVIZ_OPEN_ARROWS.has(shape) ? \"o\" : \"\";\n return { name: open + shape, side };\n }\n }\n return null;\n}\n\n/**\n * The HTML strings of a file: its HTML node names and labels, for Graphviz's shared string pool.\n * @param snapshot - the graph\n * @returns the strings, with their brackets\n */\nfunction htmlStrings(snapshot: GraphSnapshot): Set<string> {\n const out = new Set<string>();\n for (let i = 0; i < snapshot.nodeCount; i++) {\n const id = snapshot.ids.idOf(i);\n if (typeof id === \"string\" && isHtmlString(id)) {\n out.add(id);\n }\n }\n for (const [table, n] of [\n [snapshot.nodes, snapshot.nodeCount],\n [snapshot.edges, snapshot.edgeCount],\n ] as const) {\n for (const name of [LABEL_ATTRIBUTE, \"headlabel\", \"taillabel\"].filter((c) => table.has(c))) {\n addHtmlCells(table, name, n, out);\n }\n }\n return out;\n}\n\n/**\n * Adds the HTML strings of one label column.\n * @param table - the node or edge table\n * @param name - the column\n * @param n - its rows\n * @param out - receives the strings\n */\nfunction addHtmlCells(table: GraphSnapshot[\"nodes\"], name: string, n: number, out: Set<string>): void {\n for (let i = 0; i < n; i++) {\n const v = cellText(table, name, i);\n if (v !== null && isHtmlString(v)) {\n out.add(v);\n }\n }\n}\n\n/**\n * Which edges are directed: every edge of a directed graph, or as its direction column says.\n * @param snapshot - the graph\n * @returns per edge\n */\nfunction directedEdges(snapshot: GraphSnapshot): boolean[] {\n const out = new Array<boolean>(snapshot.edgeCount).fill(snapshot.directed);\n const col = snapshot.directed ? snapshot.edges.byRole(\"directed\") : null;\n if (col !== null) {\n for (let e = 0; e < snapshot.edgeCount; e++) {\n const v = plainCell(col.value(e));\n if (typeof v === \"boolean\") {\n out[e] = v;\n }\n }\n }\n return out;\n}\n\n/**\n * Whether a node is a cluster's container.\n * @param snapshot - the graph\n * @param i - the node\n * @returns true for a container\n */\nfunction isCluster(snapshot: GraphSnapshot, i: number): boolean {\n return snapshot.nodes.has(CLUSTER_COLUMN) && snapshot.nodes.value(CLUSTER_COLUMN, i) === true;\n}\n\n/**\n * Per element, what its labels' escapes and defaults depend on.\n * @param snapshot - the graph\n * @param written - the direction every edge is written with when the graph mixes both, or null to read it per edge\n * @returns the contexts\n */\nfunction contexts(\n snapshot: GraphSnapshot,\n written: boolean | null = null,\n): {\n readonly node: (i: number) => NodeContext;\n readonly edge: (e: number) => EdgeContext;\n} {\n const html = htmlStrings(snapshot);\n const graph = snapshot.meta.name ?? \"\";\n const rankdir = (cellText(snapshot.graph, \"rankdir\", 0) ?? \"\").trim().toUpperCase();\n const flip = rankdir === \"LR\" || rankdir === \"RL\";\n const q = Number(cellText(snapshot.graph, \"quantum\", 0) ?? Number.NaN);\n const quantum = Number.isFinite(q) && q > 0 ? q * DOT_POINTS_PER_INCH : 0;\n const own = directedEdges(snapshot);\n // a graph mixing both directions is written with one, every edge then drawn as that one\n const directed = written === null || own.every((d) => d === snapshot.directed) ? own : own.map(() => written);\n const name = (i: number): string => String(snapshot.ids.idOf(i));\n return {\n node: (i) => ({ name: name(i), graph, cluster: isCluster(snapshot, i), html, flip, quantum }),\n edge: (e) => {\n const tail = name(snapshot.edgeSource(e));\n const head = name(snapshot.edgeTarget(e));\n return {\n names: { graph, tail, head, edge: `${tail}${directed[e] ? \"->\" : \"--\"}${head}` },\n directed: directed[e],\n html,\n };\n },\n };\n}\n\n/**\n * The label a node shows when it has none of its own: its name, escapes applied (an HTML name shows its text); null\n * for a cluster's container and a point.\n * @param cx - the node\n * @param shape - its shape, lowercase\n * @param notes - where an HTML name is noted\n * @returns the label, or null\n */\nfunction defaultLabel(cx: NodeContext, shape: string, notes: StyleNotes): string | null {\n if (cx.cluster || shape === \"point\") {\n return null;\n }\n const at: CanonSite = { notes, target: \"node\", property: \"label\" };\n return isHtmlString(cx.name)\n ? htmlLabelText(cx.name, at)\n : dotLabelText(String.raw`\\N`, { node: cx.name, graph: cx.graph }, at);\n}\n\n/**\n * The columns of a table that hold styles: Graphviz's style attributes and graphty's per-element style values.\n * @param table - the node or edge table\n * @param attributes - the style attributes of the table\n * @returns the column names\n */\nfunction styleColumns(table: GraphSnapshot[\"nodes\"], attributes: readonly string[]): string[] {\n const own = new Set([...attributes, ...NOTED_ATTRIBUTES]);\n return [...table.names()].filter((c) => own.has(c) || c.startsWith(\"graphty.style.\"));\n}\n\n/**\n * The graph's own styles: its `bgcolor` as its background.\n * @param snapshot - the graph\n * @param notes - where a bad color is noted\n * @returns the graph's values\n */\nfunction graphBackground(snapshot: GraphSnapshot, notes: StyleNotes): Record<string, StyleValue> {\n const graph: Record<string, StyleValue> = {};\n const bg = nonEmpty(cellText(snapshot.graph, \"bgcolor\", 0));\n if (!snapshot.graph.has(\"bgcolor\") || bg === null) {\n return graph;\n }\n readColor(\n bg,\n cellText(snapshot.graph, \"colorscheme\", 0),\n \"fill\",\n \"background\",\n null,\n (p, v) => {\n if (v !== null) {\n graph[p] = v;\n }\n },\n (property) => ({ notes, target: \"graph\", property }),\n );\n return graph;\n}\n\n/**\n * The styles of a DOT file, read the way Graphviz draws it, with Graphviz's defaults beneath: an unfilled black\n * ellipse 54 x 36 labeled with its name, black edges with a target arrow in a directed graph. A file graphty wrote\n * gives back its `graphty.styles` block.\n * @param snapshot - the graph the import built\n * @param context - the work budget\n * @returns the styles\n */\nexport function dotStyles(snapshot: GraphSnapshot, context: StyleReadContext): ImporterStyles {\n const notes = new StyleNotes();\n const cx = contexts(snapshot);\n const node = valueColumns(snapshot.nodeCount);\n const nameColumn = new Array<StyleValue | null>(snapshot.nodeCount).fill(null);\n const clusterColumn = new Array<StyleValue | null>(snapshot.nodeCount).fill(null);\n let named = 0;\n let clusters = 0;\n for (let i = 0; i < snapshot.nodeCount; i++) {\n context.budget.spend(\"node\", NODE_ATTRIBUTES.length);\n const get: Attr = (name) => cellText(snapshot.nodes, name, i);\n const ncx = cx.node(i);\n const at: At = (property) => ({ notes, target: \"node\", property, element: i, budget: context.budget });\n readNode(\n get,\n ncx,\n (p, v) => {\n node.put(i, p, v);\n },\n at,\n );\n const shown = defaultLabel(ncx, (get(\"shape\") ?? \"\").toLowerCase(), notes);\n if (shown !== null) {\n nameColumn[i] = shown;\n named++;\n }\n if (ncx.cluster) {\n clusterColumn[i] = true;\n clusters++;\n }\n }\n const edge = valueColumns(snapshot.edgeCount);\n const loops = graphvizLoops(snapshot);\n // `splines=none` and `splines=\"\"` draw no edges at all (https://graphviz.org/docs/attrs/splines/)\n const splines = cellText(snapshot.graph, \"splines\", 0)?.trim().toLowerCase();\n const noEdges = splines === \"\" || splines === \"none\";\n const places = labelPlaceContext(snapshot);\n for (let e = 0; e < snapshot.edgeCount; e++) {\n context.budget.spend(\"edge\", EDGE_ATTRIBUTES.length);\n const get: Attr = (name) => cellText(snapshot.edges, name, e);\n const at: At = (property) => ({ notes, target: \"edge\", property, element: e, budget: context.budget });\n readEdge(\n get,\n cx.edge(e),\n (p, v) => {\n edge.put(e, p, v);\n },\n at,\n );\n if (noEdges) {\n edge.put(e, \"visible\", false);\n }\n const bends = splineBends(snapshot, e, get(POS_ATTRIBUTE)) ?? loops.bendsOf(e, get);\n if (bends !== null) {\n edge.put(e, \"bends\", bends);\n }\n readLabelPlaces(snapshot, places, e, get, (p, v) => {\n edge.put(e, p, v);\n });\n }\n const graph = graphBackground(snapshot, notes);\n const blockText = cellText(snapshot.graph, STYLE_BLOCK_NAME, 0);\n if (blockText !== null) {\n exactFromBlock(snapshot, blockText, { node: node.values, edge: edge.values }, cx);\n }\n // Graphviz's defaults that are rules: each node shows its name, and a directed edge has an arrow at its target\n const nodeRules: StyleRule[] = [];\n const nodeColumns = new Map<string, StyleColumn>();\n if (named > 0) {\n nodeColumns.set(NAME_KEY, nameColumn);\n nodeRules.push({\n id: \"node.tool.name-label\",\n target: \"node\",\n role: \"passthrough\",\n origin: \"tool\",\n where: { has: { style: NAME_KEY } },\n map: { label: { kind: \"passthrough\", by: { style: NAME_KEY } } },\n facts: { elements: named, reason: \"NODE_NAME\" },\n });\n }\n const features: StyleFeature[] = clusters > 0 ? [{ ref: { style: CLUSTER_KEY }, values: clusterColumn }] : [];\n const edgeRules: StyleRule[] = [];\n const edgeColumns = new Map<string, StyleColumn>();\n const directed = directedEdges(snapshot);\n if (directed.some(Boolean)) {\n edgeColumns.set(\n DIRECTED_KEY,\n directed.map((d) => (d ? true : null)),\n );\n edgeRules.push({\n id: \"edge.tool.arrow\",\n target: \"edge\",\n role: \"group\",\n origin: \"tool\",\n where: { has: { style: DIRECTED_KEY } },\n set: { targetArrow: \"triangle\" },\n });\n }\n return {\n canonical: true,\n dialect: \"graphviz\",\n tool: \"graphviz\",\n units: \"px\",\n node: { values: node.values, rules: nodeRules, columns: nodeColumns, features },\n edge: { values: edge.values, rules: edgeRules, columns: edgeColumns },\n graph,\n notes: notes.list(),\n readFrom: {\n node: styleColumns(snapshot.nodes, NODE_ATTRIBUTES),\n edge: styleColumns(snapshot.edges, EDGE_ATTRIBUTES),\n },\n };\n}\n\n// ============================================================ writing\n\n/** One element's value of a property. */\ntype Get = (property: string) => StyleValue | null;\n\n/** Records a value written as the nearest one Graphviz has. */\ntype Approximate = (property: string, value: StyleValue) => void;\n\n/** A written attribute value: text, or a number written as one. */\ntype Written = string | number;\n\n/** Neutral shapes by the Graphviz shape that draws them exactly. */\nconst SHAPES: ReadonlyMap<string, string> = new Map([\n [\"ellipse\", \"ellipse\"],\n [\"rectangle\", \"box\"],\n [\"round-rectangle\", \"box\"],\n [\"triangle\", \"triangle\"],\n [\"diamond\", \"diamond\"],\n [\"pentagon\", \"pentagon\"],\n [\"hexagon\", \"hexagon\"],\n [\"octagon\", \"octagon\"],\n [\"parallelogram\", \"parallelogram\"],\n [\"trapezoid\", \"trapezium\"],\n [\"star\", \"star\"],\n [\"none\", \"none\"],\n]);\n\n/** Neutral arrows by the Graphviz arrow that draws them. */\nconst ARROWS: ReadonlyMap<string, string> = new Map([\n [\"none\", \"none\"],\n [\"triangle\", \"normal\"],\n [\"triangle-open\", \"onormal\"],\n [\"vee\", \"vee\"],\n [\"tee\", \"tee\"],\n [\"diamond\", \"diamond\"],\n [\"diamond-open\", \"odiamond\"],\n [\"circle\", \"dot\"],\n [\"circle-open\", \"odot\"],\n [\"square\", \"box\"],\n [\"crow\", \"crow\"],\n [\"inverted\", \"inv\"],\n [\"other:open-square\", \"obox\"],\n [\"other:open-inverted\", \"oinv\"],\n]);\n\n/** Line and border styles Graphviz draws exactly; the others are written as the nearest. */\nconst STROKES: ReadonlyMap<string, string> = new Map([\n [\"dashed\", \"dashed\"],\n [\"dotted\", \"dotted\"],\n]);\n\n/**\n * The attribute values Graphviz draws when an attribute is absent, from the tool-defaults table: the writer leaves\n * them out, so a file states what differs from Graphviz's drawing (and a size stays one Graphviz may grow).\n * @param target - nodes or edges\n * @returns the default text of each attribute\n */\nfunction graphvizDefaults(target: StyleTarget): ReadonlyMap<string, Written> {\n const t = toolDefaults(\"graphviz\")?.[target] as Readonly<Record<string, { readonly value: unknown } | undefined>>;\n const out = new Map<string, Written>();\n const add = (attribute: string, property: string, scale = 1): void => {\n const v = t[property]?.value;\n if (typeof v === \"number\") {\n out.set(attribute, num6(v / scale));\n } else if (typeof v === \"string\") {\n out.set(attribute, v);\n }\n };\n add(\"fontcolor\", \"labelColor\");\n add(\"fontsize\", \"labelSize\");\n const font = t.labelFont?.value;\n if (typeof font === \"string\") {\n out.set(\"fontname\", graphvizFontName(font, false, false));\n }\n if (target === \"node\") {\n add(\"color\", \"borderColor\");\n add(\"pencolor\", \"borderColor\");\n add(\"penwidth\", \"borderWidth\");\n add(\"shape\", \"shape\");\n add(\"width\", \"width\", DOT_POINTS_PER_INCH);\n add(\"height\", \"height\", DOT_POINTS_PER_INCH);\n } else {\n add(\"color\", \"color\");\n add(\"penwidth\", \"width\");\n add(\"arrowsize\", \"arrowSize\");\n }\n return out;\n}\n\nconst DEFAULT_ATTRIBUTES: Readonly<Record<StyleTarget, ReadonlyMap<string, Written>>> = {\n node: graphvizDefaults(\"node\"),\n edge: graphvizDefaults(\"edge\"),\n};\n\n/**\n * Leaves out every attribute whose value is the one Graphviz draws without it.\n * @param out - the attributes, changed in place\n * @param target - nodes or edges\n * @returns the attributes\n */\nfunction withoutDefaults(out: Map<string, Written>, target: StyleTarget): Map<string, Written> {\n for (const [attribute, value] of DEFAULT_ATTRIBUTES[target]) {\n if (out.get(attribute) === value) {\n out.delete(attribute);\n }\n }\n if (!out.has(\"width\") && !out.has(\"height\")) {\n out.delete(\"fixedsize\");\n }\n return out;\n}\n\n/**\n * A color as Graphviz writes it: `#rrggbb`, or `#rrggbbaa` with an opacity below 1.\n * @param color - the canonical color\n * @param opacity - the opacity, or null\n * @returns the text\n */\nfunction gvColor(color: string, opacity: StyleValue | null): string {\n if (typeof opacity !== \"number\" || opacity >= 1) {\n return color;\n }\n const a = Math.max(0, Math.min(255, Math.round(opacity * 255)));\n return color + a.toString(16).padStart(2, \"0\");\n}\n\n/**\n * A label's text as a DOT label: backslashes, line breaks and `&` escaped, so Graphviz's escape and entity passes\n * give the text back.\n * @param text - the text\n * @returns the label\n */\nfunction escapeLabel(text: string): string {\n return text\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"\\\\\", String.raw`\\\\`)\n .replaceAll(\"\\n\", String.raw`\\n`);\n}\n\n/**\n * A shape, line or arrow value in Graphviz's spelling.\n * @param table - the exact spellings\n * @param value - the neutral value\n * @param nearest - the spelling written when there is no exact one\n * @param property - the property, for the approximation note\n * @param approximate - records approximations\n * @returns the spelling\n */\nfunction spelled(\n table: ReadonlyMap<string, string>,\n value: string,\n nearest: string,\n property: string,\n approximate: Approximate,\n): string {\n const exact = table.get(value);\n if (exact !== undefined) {\n return exact;\n }\n if (value.startsWith(\"other:\")) {\n return value.slice(\"other:\".length);\n }\n approximate(property, value);\n return nearest;\n}\n\n/**\n * The font, tooltip and visibility attributes every element shares.\n * @param get - the element's values\n * @param approximate - records approximations\n * @param out - the attributes, added to\n * @param tokens - the style tokens, added to\n */\nfunction writeCommon(get: Get, approximate: Approximate, out: Map<string, Written>, tokens: string[]): void {\n const color = get(\"labelColor\");\n if (typeof color === \"string\") {\n out.set(\"fontcolor\", color);\n }\n const size = get(\"labelSize\");\n if (typeof size === \"number\") {\n out.set(\"fontsize\", size);\n }\n const font = get(\"labelFont\");\n const bold = get(\"labelWeight\") === \"bold\";\n const italic = get(\"labelItalic\") === true;\n if (typeof font === \"string\") {\n const name = graphvizFontName(font, bold, italic);\n out.set(\"fontname\", name);\n const drawn = graphvizFont(name);\n if (drawn.bold !== bold) {\n approximate(\"labelWeight\", get(\"labelWeight\") ?? \"normal\");\n }\n if (drawn.italic !== italic) {\n approximate(\"labelItalic\", italic);\n }\n } else if (bold || italic) {\n approximate(bold ? \"labelWeight\" : \"labelItalic\", bold ? \"bold\" : true);\n }\n const tip = get(\"tooltip\");\n if (typeof tip === \"string\") {\n out.set(\"tooltip\", escapeLabel(tip));\n }\n if (get(\"visible\") === false) {\n tokens.push(\"invis\");\n }\n}\n\n/**\n * A node's or cluster's Graphviz attributes from its values.\n * @param get - the node's values\n * @param cx - the node's name and kind\n * @param raw - its attributes as data\n * @param approximate - records approximations\n * @param notes - where an HTML name is noted\n * @returns the attributes\n */\nfunction nodeAttributes(\n get: Get,\n cx: NodeContext,\n raw: Attr,\n approximate: Approximate,\n notes: StyleNotes,\n): Map<string, Written> {\n const out = new Map<string, Written>();\n const tokens: string[] = [];\n writeCommon(get, approximate, out, tokens);\n writeNodeOutline(get, cx, approximate, out, tokens);\n const gvShape = writeNodeShape(get, cx, approximate, out, tokens);\n if (!cx.cluster) {\n writeNodeSize(get, out);\n }\n // the label is written where it differs from what Graphviz shows without one (the name), \"\" for none\n const label = get(\"label\");\n const shown = defaultLabel(cx, gvShape, notes);\n if (typeof label === \"string\" && label !== shown) {\n out.set(LABEL_ATTRIBUTE, escapeLabel(label));\n } else if (label === null && shown !== null) {\n out.set(LABEL_ATTRIBUTE, \"\");\n }\n noteLabelPosition(get(\"labelPosition\"), cx, raw, approximate);\n if (tokens.length > 0) {\n out.set(\"style\", tokens.join(\",\"));\n }\n return withoutDefaults(out, \"node\");\n}\n\n/**\n * Notes a label position Graphviz does not draw: a node's label sits where its own `labelloc` (kept as data) puts\n * it, and a cluster's where its `labelloc` and `labeljust` do.\n * @param position - the label's position\n * @param cx - the node's name and kind\n * @param raw - the node's attributes as data\n * @param approximate - records approximations\n */\nfunction noteLabelPosition(position: StyleValue | null, cx: NodeContext, raw: Attr, approximate: Approximate): void {\n if (\n typeof position === \"string\" &&\n position !== (cx.cluster ? clusterLabelPosition(raw) : nodeLabelPosition(raw))\n ) {\n approximate(\"labelPosition\", position);\n }\n}\n\n/**\n * A node's or cluster's fill and outline attributes.\n * @param get - the node's values\n * @param cx - the node's name and kind\n * @param approximate - records approximations\n * @param out - the attributes, added to\n * @param tokens - the style tokens, added to\n */\nfunction writeNodeOutline(\n get: Get,\n cx: NodeContext,\n approximate: Approximate,\n out: Map<string, Written>,\n tokens: string[],\n): void {\n const fill = get(\"fill\");\n const fillOpacity = get(\"fillOpacity\");\n if (typeof fill === \"string\" && fillOpacity !== 0) {\n tokens.push(\"filled\");\n out.set(\"fillcolor\", gvColor(fill, fillOpacity));\n }\n const border = get(\"borderColor\");\n if (typeof border === \"string\") {\n out.set(cx.cluster ? \"pencolor\" : \"color\", border);\n }\n const borderWidth = get(\"borderWidth\");\n if (typeof borderWidth === \"number\") {\n out.set(\"penwidth\", borderWidth);\n }\n const borderStyle = get(\"borderStyle\");\n if (typeof borderStyle === \"string\" && borderStyle !== \"solid\") {\n const nearest = borderStyle.includes(\"dash\") ? \"dashed\" : \"solid\";\n tokens.push(spelled(STROKES, borderStyle, nearest, \"borderStyle\", approximate));\n }\n}\n\n/**\n * A node's shape attribute; a cluster is always a rectangle, rounded or not, and any other shape is approximated.\n * @param get - the node's values\n * @param cx - the node's name and kind\n * @param approximate - records approximations\n * @param out - the attributes, added to\n * @param tokens - the style tokens, added to\n * @returns the Graphviz shape written, \"\" for none\n */\nfunction writeNodeShape(\n get: Get,\n cx: NodeContext,\n approximate: Approximate,\n out: Map<string, Written>,\n tokens: string[],\n): string {\n const shape = get(\"shape\");\n if (typeof shape !== \"string\") {\n return \"\";\n }\n if (shape === \"round-rectangle\") {\n tokens.push(\"rounded\");\n }\n if (cx.cluster) {\n if (shape !== \"rectangle\" && shape !== \"round-rectangle\") {\n approximate(\"shape\", shape);\n }\n return \"\";\n }\n const size = (name: string): number | null => {\n const v = get(name);\n return typeof v === \"number\" ? v : null;\n };\n const glyph = shape === \"polygon\" ? glyphOf(get, size(\"width\"), size(\"height\")) : undefined;\n if (glyph !== undefined) {\n return writeGlyph(get, glyph, out);\n }\n approximateShapeLines(get, approximate);\n const polygon = shape === \"polygon\" ? writePolygon(get(\"shapePoints\"), approximate, out) : null;\n if (polygon !== null) {\n // Graphviz draws its polygon's corners where it lays them, which read back unstretched\n if (get(\"shapePointsStretch\") !== false) {\n approximate(\"shapePointsStretch\", true);\n }\n return polygon;\n }\n const gvShape = spelled(SHAPES, shape, shape === \"vee\" ? \"invtriangle\" : \"box\", \"shape\", approximate);\n out.set(\"shape\", gvShape);\n return gvShape;\n}\n\n/**\n * A glyph's shape attribute, and its line's width as its pen's when it draws no outline.\n * @param get - the node's values\n * @param glyph - the glyph\n * @param out - the attributes, added to\n * @returns the Graphviz shape written\n */\nfunction writeGlyph(get: Get, glyph: NonNullable<ReturnType<typeof glyphOf>>, out: Map<string, Written>): string {\n out.set(\"shape\", glyph.name);\n // an underline's line is drawn in its pen, which draws no outline round it\n const line = get(\"shapeLineWidth\");\n if (glyph.unstroked && typeof line === \"number\") {\n out.set(\"penwidth\", line);\n }\n return glyph.name;\n}\n\n/**\n * Notes a node's pieces and lines of no Graphviz shape as approximated: Graphviz has no attribute for them.\n * @param get - the node's values\n * @param approximate - records approximations\n */\nfunction approximateShapeLines(get: Get, approximate: Approximate): void {\n for (const property of [\"shapeParts\", \"shapeLines\", \"shapeLineWidth\"]) {\n const v = get(property);\n if (v !== null && v !== undefined) {\n approximate(property, v);\n }\n }\n}\n\n/**\n * A polygon's shape attribute: the Graphviz shape whose outline it is, else `shape=polygon` with its number of sides.\n * @param points - its `shapePoints`\n * @param approximate - records approximations\n * @param out - the attributes, added to\n * @returns the Graphviz shape written, or null for corners too few to be a polygon\n */\nfunction writePolygon(points: unknown, approximate: Approximate, out: Map<string, Written>): string | null {\n if (typeof points !== \"string\") {\n return null;\n }\n const named = OUTLINE_NAMES.get(points.trim());\n if (named !== undefined) {\n out.set(\"shape\", named);\n return named;\n }\n // the corners themselves are not Graphviz attributes: the polygon keeps its number of sides\n const sides = points.trim().split(/\\s+/).length;\n if (sides < 3) {\n return null;\n }\n out.set(\"shape\", \"polygon\");\n out.set(\"sides\", sides);\n approximate(\"shapePoints\", points);\n return \"polygon\";\n}\n\n/**\n * A node's width and height, fixed so Graphviz does not grow them to fit the label, unless the node grows to fit it.\n * @param get - the node's values\n * @param out - the attributes, added to\n */\nfunction writeNodeSize(get: Get, out: Map<string, Written>): void {\n const width = get(\"width\");\n const height = get(\"height\");\n if ((typeof width === \"number\" || typeof height === \"number\") && typeof get(\"labelFit\") !== \"string\") {\n out.set(\"fixedsize\", \"true\");\n }\n if (typeof width === \"number\") {\n out.set(\"width\", inchesOf(width));\n }\n if (typeof height === \"number\") {\n out.set(\"height\", inchesOf(height));\n }\n}\n\n/**\n * An edge's Graphviz attributes from its values.\n * @param get - the edge's values\n * @param directed - whether the edge is directed (its default arrows)\n * @param approximate - records approximations\n * @returns the attributes\n */\nfunction edgeAttributes(get: Get, directed: boolean, approximate: Approximate): Map<string, Written> {\n const out = new Map<string, Written>();\n const tokens: string[] = [];\n writeCommon(get, approximate, out, tokens);\n const color = get(\"color\");\n if (typeof color === \"string\") {\n out.set(\"color\", gvColor(color, get(\"opacity\")));\n }\n const width = get(\"width\");\n if (typeof width === \"number\") {\n out.set(\"penwidth\", width);\n }\n const line = get(\"lineStyle\");\n if (typeof line === \"string\" && line !== \"solid\") {\n tokens.push(spelled(STROKES, line, line.includes(\"dash\") ? \"dashed\" : \"solid\", \"lineStyle\", approximate));\n }\n writeEdgeArrows(get, directed, approximate, out);\n // Graphviz fills both arrowheads with the one `fillcolor`\n const head = get(\"targetArrowColor\");\n const tail = get(\"sourceArrowColor\");\n const fill = head ?? tail;\n if (typeof fill === \"string\") {\n out.set(\"fillcolor\", fill);\n if (head !== null && tail !== null && head !== tail) {\n approximate(\"sourceArrowColor\", tail);\n }\n }\n const arrowSize = get(\"arrowSize\");\n if (typeof arrowSize === \"number\") {\n out.set(\"arrowsize\", arrowSize);\n }\n for (const [property, attribute] of [\n [\"label\", LABEL_ATTRIBUTE],\n [\"targetLabel\", \"headlabel\"],\n [\"sourceLabel\", \"taillabel\"],\n ] as const) {\n const v = get(property);\n if (typeof v === \"string\") {\n out.set(attribute, escapeLabel(v));\n }\n }\n if (tokens.length > 0) {\n out.set(\"style\", tokens.join(\",\"));\n }\n return withoutDefaults(out, \"edge\");\n}\n\n/**\n * An edge's arrow attributes, written where they differ from the graph's own: a target arrow on a directed edge.\n * @param get - the edge's values\n * @param directed - whether the edge is directed\n * @param approximate - records approximations\n * @param out - the attributes, added to\n */\nfunction writeEdgeArrows(get: Get, directed: boolean, approximate: Approximate, out: Map<string, Written>): void {\n const source = get(\"sourceArrow\");\n const target = get(\"targetArrow\");\n const tail = typeof source === \"string\" && source !== \"none\";\n const head = typeof target === \"string\" && target !== \"none\";\n const plain = directed ? head && !tail && target === \"triangle\" && get(\"targetArrowSide\") === null : !head && !tail;\n if (plain || (source === null && target === null)) {\n return;\n }\n let dir = \"none\";\n if (head && tail) {\n dir = \"both\";\n } else if (head) {\n dir = \"forward\";\n } else if (tail) {\n dir = \"back\";\n }\n out.set(\"dir\", dir);\n // a one-sided arrow is its shape with an `l` or `r` before it; the neutral half arrow, one barb, is nearest to the\n // left half of Graphviz's triangle, which reads back as that\n const arrow = (value: string, side: StyleValue | null, property: string): string => {\n if (value === \"half\") {\n approximate(property, value);\n approximate(`${property}Side`, value);\n return \"lnormal\";\n }\n const name = spelled(ARROWS, value, \"normal\", property, approximate);\n return side === \"left\" || side === \"right\" ? `${side[0]}${name}` : name;\n };\n if (head) {\n out.set(\"arrowhead\", arrow(target, get(\"targetArrowSide\"), \"targetArrow\"));\n }\n if (tail) {\n out.set(\"arrowtail\", arrow(source, get(\"sourceArrowSide\"), \"sourceArrow\"));\n }\n}\n\n/**\n * For a file graphty wrote: where a value read from the attributes is what the writer writes for the block's own\n * value (a hexagon written as a hexagon, a pentagon-like vee as an inverted triangle, an opacity rounded to 255 steps,\n * a size rounded in inches), the block's exact value is the truth, so a re-import gives back the same rules; a value\n * another program changed since stays the truth.\n * @param snapshot - the graph\n * @param text - the block's text\n * @param read - the values read, changed in place\n * @param read.node - the node values\n * @param read.edge - the edge values\n * @param cx - the elements' contexts\n */\nfunction exactFromBlock(\n snapshot: GraphSnapshot,\n text: string,\n read: { readonly node: ValueColumns; readonly edge: ValueColumns },\n cx: ReturnType<typeof contexts>,\n): void {\n const notes = new StyleNotes();\n takeFromBlock(snapshot, text, \"dot\", (target) => ({\n values: read[target],\n properties: DOT_STYLE_CAPABILITIES[target],\n writes: DOT_STYLE_CAPABILITIES[target],\n readBack: (i, want) => {\n const raw: Attr = (name) => cellText(target === \"node\" ? snapshot.nodes : snapshot.edges, name, i);\n const back = writtenAndReadBack(target, i, want, { cx, raw }, notes);\n return (property) => back.get(property) ?? null;\n },\n }));\n}\n\n/**\n * An element's values written as the writer writes them and read back as the reader reads them.\n * @param target - nodes or edges\n * @param i - the element\n * @param want - its values\n * @param data - the elements' contexts, and the element's attributes as data (what the writer leaves as it is)\n * @param data.cx - the elements' contexts\n * @param data.raw - the element's attributes as data\n * @param notes - a scratch for the notes the round trip makes\n * @returns the values read back, by property\n */\nfunction writtenAndReadBack(\n target: StyleTarget,\n i: number,\n want: Get,\n data: { readonly cx: ReturnType<typeof contexts>; readonly raw: Attr },\n notes: StyleNotes,\n): Map<string, StyleValue> {\n const { cx, raw } = data;\n const ignore: Approximate = () => undefined;\n const back = new Map<string, StyleValue>();\n const put: Put = (property, value) => {\n if (value !== null) {\n back.set(property, value);\n }\n };\n const at: At = (property) => ({ notes, target, property });\n if (target === \"node\") {\n const ncx = cx.node(i);\n const attrs = nodeAttributes(want, ncx, raw, ignore, notes);\n // a cluster's label position stays in its data (`labelloc`, `labeljust`), which the writer leaves alone\n const kept = (name: string): string | null => (name === \"labelloc\" || name === \"labeljust\" ? raw(name) : null);\n readNode((name) => (attrs.has(name) ? textOf(attrs.get(name)) : kept(name)), ncx, put, at);\n } else {\n const ecx = cx.edge(i);\n const attrs = edgeAttributes(want, ecx.directed, ignore);\n readEdge((name) => textOf(attrs.get(name)), ecx, put, at);\n }\n return back;\n}\n\n/**\n * A written value as the text the importer would read back.\n * @param v - the value\n * @returns its text, or null\n */\nfunction textOf(v: Written | undefined): string | null {\n return v === undefined ? null : String(v);\n}\n\n/**\n * Whether a style column written as a DOT attribute reads back as the same values: DOT values are untyped and the\n * importer infers a column's type from its text, so a text column whose every value looks like a number does not.\n * @param col - the values\n * @returns true when it reads back unchanged\n */\nfunction readsBack(col: StyleColumn): boolean {\n const vals = col.filter((v): v is StyleValue => v !== null);\n if (vals.every((v) => typeof v === \"number\")) {\n return vals.every((v) => Number.isFinite(v));\n }\n if (vals.every((v) => typeof v === \"boolean\")) {\n return true;\n }\n if (vals.every((v) => typeof v === \"string\")) {\n return vals.some((v) => inferTextDtype(v) === \"string\") && vals.every((v) => isWritableDotText(v));\n }\n return false;\n}\n\n/**\n * A `graphty.styles` block's JSON with every quote and backslash inside its strings written as a `\\u` escape, so the\n * text holds no backslash before a quote, which a DOT quoted string cannot carry; it parses to the same value.\n * @param json - the block\n * @returns the block\n */\nfunction dotSafeJson(json: string): string {\n return json.replaceAll(/\\\\([\"\\\\])/g, (_m, c: string) => (c === '\"' ? String.raw`\\u0022` : String.raw`\\u005c`));\n}\n\n/** A DOT export with styles worked out. */\ninterface DotStyledExport {\n /** The graph to write: Graphviz attributes written from the styles, the block and the per-element values added. */\n readonly snapshot: GraphSnapshot;\n /** W_STYLE_APPROXIMATED for every value written as the nearest one Graphviz has. */\n readonly notes: readonly LossNote[];\n}\n\n/**\n * Works out a DOT export with styles: every node's, cluster's and edge's Graphviz attributes from what graphty draws,\n * in place of every style attribute it had; the graph's `bgcolor`; the `graphty.styles` block as the graph attribute\n * `\"graphty.styles\"` and the per-element values its rules read as `\"graphty.style.<target>.<key>\"` attributes. A\n * style column whose values would not read back as written (text that looks like numbers) goes inside the block\n * instead, with all the others.\n * @param snapshot - the graph handed to the exporter\n * @param input - the styles, or undefined when none are written\n * @param onMixedDirection - the exporter's option: the direction a graph mixing both is written with\n * @returns the styled export, or null without styles\n */\nexport function dotStyledExport(\n snapshot: GraphSnapshot,\n input: ExporterStyleInput | undefined,\n onMixedDirection?: unknown,\n): DotStyledExport | null {\n if (input === undefined) {\n return null;\n }\n // the registry's check before writing and the write of one export call share the work\n return sharedInExportCall(input, [snapshot, onMixedDirection], () =>\n styledExport(snapshot, input, onMixedDirection),\n );\n}\n\n/**\n * Works out a DOT export with styles: dotStyledExport() without the sharing.\n * @param snapshot - the graph handed to the exporter\n * @param input - the styles\n * @param onMixedDirection - the exporter's option\n * @returns the styled export\n */\nfunction styledExport(snapshot: GraphSnapshot, input: ExporterStyleInput, onMixedDirection: unknown): DotStyledExport {\n const approximated = new StyleApproximations();\n const replaced: LossNote[] = [];\n const out = snapshot.withColumns();\n const written = onMixedDirection === \"directed\" || onMixedDirection === \"undirected\";\n const cx = contexts(snapshot, written ? onMixedDirection === \"directed\" : null);\n const notes = new StyleNotes();\n for (const target of [\"node\", \"edge\"] as const) {\n const table = target === \"node\" ? out.nodes : out.edges;\n const read = dataRead(input.rules.styles.rules, target);\n const approximate: Approximate = (property, value) => {\n approximated.add(target, property, value);\n };\n const columns = attributeColumns(snapshot, input, target, { cx, approximate, notes, read });\n replaced.push(...removeStyleAttributes(table, target, columns, read));\n setAttributeColumns(table, columns);\n }\n const { background } = input.rules.styles.graph;\n if (out.graph.has(\"bgcolor\")) {\n out.graph.remove(\"bgcolor\");\n }\n // Graphviz paints a graph without bgcolor white, so the writer leaves that default out like the others\n if (typeof background === \"string\" && background !== toolDefaults(\"graphviz\")?.graph.background?.value) {\n out.graph.set(\"bgcolor\", [background], { dtype: \"string\" });\n }\n const inline = [...input.tags.node.values(), ...input.tags.edge.values()].some((col) => !readsBack(col));\n if (!inline) {\n setTagColumns(out, input);\n }\n const block = inline ? writeStyleBlock(input.rules, { inlineColumns: true, snapshot }) : input.block;\n out.graph.set(STYLE_BLOCK_NAME, [dotSafeJson(block)], { dtype: \"string\" });\n const losses = approximated.notes(\"Graphviz\");\n if (inline) {\n losses.push(...styleBlockLosses(block, input.rules.styles.rules.length, \"size\"));\n }\n return { snapshot: out, notes: [...replaced, ...losses] };\n}\n\n/** What attributeColumns() reads besides the graph and the styles. */\ninterface AttributeWrite {\n /** The elements' contexts. */\n readonly cx: ReturnType<typeof contexts>;\n /** Records approximations. */\n readonly approximate: Approximate;\n /** Where an HTML name is noted. */\n readonly notes: StyleNotes;\n /** The data columns the target's rules read. */\n readonly read: ReadonlySet<string>;\n}\n\n/**\n * Every element's Graphviz attributes of a target, as columns.\n * @param snapshot - the graph handed to the exporter\n * @param input - the styles\n * @param target - nodes or edges\n * @param w - the contexts, the recorders and the columns the rules read\n * @returns the attribute columns, by name\n */\nfunction attributeColumns(\n snapshot: GraphSnapshot,\n input: ExporterStyleInput,\n target: StyleTarget,\n w: AttributeWrite,\n): Map<string, (Written | null)[]> {\n const n = target === \"node\" ? snapshot.nodeCount : snapshot.edgeCount;\n const get = elementValues((t, p) => input.picture(t, p as never), target, DOT_STYLE_CAPABILITIES[target]);\n const columns = new Map<string, (Written | null)[]>();\n for (let i = 0; i < n; i++) {\n const attrs =\n target === \"node\"\n ? nodeAttributes(\n get(i),\n w.cx.node(i),\n (name) => cellText(snapshot.nodes, name, i),\n w.approximate,\n w.notes,\n )\n : edgeAttributes(get(i), w.cx.edge(i).directed, w.approximate);\n // a self-loop's route is not written: Graphviz lays the loop itself, which is what reads back\n if (target === \"edge\" && snapshot.edgeSource(i) === snapshot.edgeTarget(i)) {\n w.approximate(\"bends\", \"self-loop\");\n }\n // no label is written label=\"\" (Graphviz would show the name), which a rule reading the label column\n // reads back as the empty label\n if (w.read.has(LABEL_ATTRIBUTE) && attrs.get(LABEL_ATTRIBUTE) === \"\" && get(i)(\"label\") === null) {\n w.approximate(\"label\", \"\");\n }\n setColumnValues(columns, attrs, i, n);\n }\n if (target === \"node\") {\n stopInheritance(snapshot, w.cx, columns, input.rules.styles.graph.background);\n }\n return columns;\n}\n\n/**\n * Puts one element's attributes into the columns, adding a column for an attribute not seen before.\n * @param columns - the columns, by name\n * @param attrs - the element's attributes\n * @param i - the element\n * @param n - how many elements there are\n */\nfunction setColumnValues(\n columns: Map<string, (Written | null)[]>,\n attrs: ReadonlyMap<string, Written>,\n i: number,\n n: number,\n): void {\n for (const [name, value] of attrs) {\n let col = columns.get(name);\n if (col === undefined) {\n col = new Array<Written | null>(n).fill(null);\n columns.set(name, col);\n }\n col[i] = value;\n }\n}\n\n/** What a cluster draws when neither it nor a graph around it sets the attribute: Graphviz's defaults. */\nconst CLUSTER_UNSET: ReadonlyMap<string, Written> = new Map<string, Written>([\n [\"style\", \"\"],\n [\"penwidth\", 1],\n [\"color\", \"\"],\n [\"pencolor\", \"\"],\n [\"fillcolor\", \"\"],\n [\"bgcolor\", \"\"],\n [\"fontname\", \"Times-Roman\"],\n [\"fontsize\", 14],\n [\"fontcolor\", \"black\"],\n [LABEL_ATTRIBUTE, \"\"],\n]);\n\n/**\n * Gives every cluster its own value of each attribute a graph around it sets, Graphviz's default where the cluster\n * has none, since Graphviz gives a cluster the attributes of the graphs around it (the root's are kept as data).\n * @param snapshot - the graph handed to the exporter\n * @param cx - the elements' contexts\n * @param columns - the node attributes written, by name, changed in place\n * @param background - the background the writer gives the root graph (its `bgcolor`), which a cluster would inherit\n */\nfunction stopInheritance(\n snapshot: GraphSnapshot,\n cx: ReturnType<typeof contexts>,\n columns: Map<string, (Written | null)[]>,\n background: unknown,\n): void {\n const clusters = Array.from({ length: snapshot.nodeCount }, (_, i) => i).filter((i) => cx.node(i).cluster);\n for (const [name, unset] of CLUSTER_UNSET) {\n const col = columns.get(name);\n const enclosing =\n cellText(snapshot.graph, name, 0) !== null ||\n (name === \"bgcolor\" && typeof background === \"string\") ||\n clusters.some((i) => (col?.[i] ?? null) !== null);\n if (!enclosing) {\n continue;\n }\n const filled = col ?? new Array<Written | null>(snapshot.nodeCount).fill(null);\n for (const i of clusters) {\n filled[i] ??= unset;\n }\n columns.set(name, filled);\n }\n}\n\n/**\n * Removes every column Graphviz reads as how to draw: the picture writes them, so a data column of the same name (a\n * `label` attribute graphty does not draw) would draw something graphty does not. One a rule reads, whose values the\n * picture does not write, is lost to the rule, and said so.\n * @param table - the node or edge table, changed in place\n * @param target - nodes or edges\n * @param columns - the attributes the picture writes\n * @param read - the data columns the rules read\n * @returns the notes of the columns lost to a rule\n */\nfunction removeStyleAttributes(\n table: GraphSnapshot[\"nodes\"],\n target: StyleTarget,\n columns: ReadonlyMap<string, (Written | null)[]>,\n read: ReadonlySet<string>,\n): LossNote[] {\n const attributes = target === \"node\" ? NODE_ATTRIBUTES : EDGE_ATTRIBUTES;\n const replaced: LossNote[] = [];\n for (const name of table.names()) {\n if (!attributes.includes(name) && name !== LABEL_ATTRIBUTE && !name.startsWith(\"graphty.style.\")) {\n continue;\n }\n const differs = read.has(name) ? replacedRows(table, name, columns.get(name)) : 0;\n if (differs > 0) {\n replaced.push(\n Object.freeze({\n code: DOT_ATTRIBUTE_CLASH_CODE,\n message: `${target} column \"${name}\" is not written: the ${name} attribute holds what graphty draws (${String(differs)} ${target}${differs === 1 ? \"\" : \"s\"} differ)`,\n column: name,\n count: differs,\n }),\n );\n }\n table.remove(name);\n }\n return replaced;\n}\n\n/**\n * Sets the attribute columns the picture writes: the label with its role, numbers as f64, the rest as text.\n * @param table - the node or edge table, changed in place\n * @param columns - the attributes\n */\nfunction setAttributeColumns(table: GraphSnapshot[\"nodes\"], columns: ReadonlyMap<string, (Written | null)[]>): void {\n for (const [name, col] of columns) {\n if (name === LABEL_ATTRIBUTE) {\n table.set(name, col, { dtype: \"string\", role: \"label\" }, { replaceRole: true });\n } else if (col.every((v) => v === null || typeof v === \"number\")) {\n table.set(name, col, { dtype: \"f64\" });\n } else {\n table.set(\n name,\n col.map((v) => (v === null ? null : String(v))),\n { dtype: \"string\" },\n );\n }\n }\n}\n\n/**\n * Sets the per-element values the rules read as `\"graphty.style.<target>.<key>\"` attributes.\n * @param out - the graph, changed in place\n * @param input - the styles\n */\nfunction setTagColumns(out: GraphSnapshot, input: ExporterStyleInput): void {\n for (const target of [\"node\", \"edge\"] as const) {\n const table = target === \"node\" ? out.nodes : out.edges;\n for (const [name, col] of input.tags[target]) {\n const kinds = new Set(col.filter((v) => v !== null).map((v) => typeof v));\n let dtype: \"string\" | \"bool\" | \"f64\" = \"string\";\n if (kinds.has(\"number\")) {\n dtype = \"f64\";\n } else if (kinds.has(\"boolean\")) {\n dtype = \"bool\";\n }\n table.set(name, col, { dtype });\n }\n }\n}\n\n/**\n * The data columns the rules of a target read.\n * @param rules - the rules\n * @param target - nodes or edges\n * @returns the column names\n */\nfunction dataRead(rules: readonly StyleRule[], target: StyleTarget): Set<string> {\n const out = new Set<string>();\n for (const { ext: _ext, ...rule } of rules.filter((r) => r.target === target)) {\n JSON.stringify(rule, (_k, v: unknown) => {\n if (typeof v === \"object\" && v !== null && !Array.isArray(v) && Object.keys(v).length === 1) {\n const { data } = v as { data?: unknown };\n if (typeof data === \"string\") {\n out.add(data);\n }\n }\n return v;\n });\n }\n return out;\n}\n\n/**\n * A data column named like an attribute the export writes is not written: the exporter's `DOT_LOSS.ATTRIBUTE_CLASH`.\n */\nexport const DOT_ATTRIBUTE_CLASH_CODE = \"W_DOT_ATTRIBUTE_CLASH\";\n\n/**\n * How many rows of a data column the attribute written in its place does not hold as it is.\n * @param table - the table\n * @param name - the column\n * @param written - the attribute's values, or undefined when none is written\n * @returns the rows that differ\n */\nfunction replacedRows(\n table: GraphSnapshot[\"nodes\"],\n name: string,\n written: readonly (Written | null)[] | undefined,\n): number {\n const column = table.get(name);\n let n = 0;\n for (let i = 0; column !== null && i < column.length; i++) {\n const cell = column.isSet(i) ? plainCell(column.value(i)) : null;\n const w = written?.[i] ?? null;\n const text = typeof cell === \"string\" ? cell : JSON.stringify(cell);\n if (cell !== null && (w === null || String(w) !== text)) {\n n++;\n }\n }\n return n;\n}\n"],"names":["dataRead","LINE_SPACING","inches","point"],"mappings":"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"}
|