@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
|
@@ -1,15 +1,272 @@
|
|
|
1
1
|
import { GraphFormatError, INVALID_INDEX } from "@graphty/graph-format";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { p as plural, a as agree, P as PRECISION_CODE, l as DUPLICATE_ATTRIBUTE_CODE, S as SINK_OPTION_CODE, O as OPTION_IGNORED_CODE, R as ROLE_TAKEN_CODE, I as ID_MERGED_CODE, k as DUPLICATE_NODE_CODE, Q as SYNTAX_CODE, W as AMBIGUOUS_GRAPH_NAME_CODE, Y as GRAPH_NOT_FOUND_CODE, i as MULTIPLE_GRAPHS_CODE, s as UNKNOWN_ENCODING_CODE, t as ENCODING_FALLBACK_CODE, u as INVALID_ENCODING_CODE, v as INVALID_UTF8_CODE, y as ELEMENT_ISSUE, z as INPUT_ISSUE, K as ImportReportBuilder } from "./report-
|
|
6
|
-
import { i as inferTextDtype, W as WIDENING_UNSUPPORTED_CODE, a as isNumericText, T as TextCellWriter } from "./text-
|
|
2
|
+
import { p as pairFolding, i as idText, b as formatNumber, d as formatDecimal, f as formatF32, c as formatInteger, D as DirectionResolver } from "./format-BXiAb-1h.js";
|
|
3
|
+
import { h as isPajekLabel, j as quotePajekLabel } from "./escape-CuCIzNMB.js";
|
|
4
|
+
import { e as explicitWeights, L as LOSS, c as capabilities, r as resolveExportOptions, z as sanitizeIds, a as checkCapabilities, H as canonicalId, R as RENAMED_CODE, b as resolveImportOptions, d as reportUnusedOptions, h as graphChosen, f as reportSinkOptions, I as IdCoercer, u as uniqueColumnName, i as declareResolved, Q as coerceIdText, k as isWeightField, p as parseWeightText } from "./export-Cha4dRFz.js";
|
|
5
|
+
import { p as plural, a as agree, P as PRECISION_CODE, l as DUPLICATE_ATTRIBUTE_CODE, S as SINK_OPTION_CODE, O as OPTION_IGNORED_CODE, R as ROLE_TAKEN_CODE, I as ID_MERGED_CODE, k as DUPLICATE_NODE_CODE, Q as SYNTAX_CODE, W as AMBIGUOUS_GRAPH_NAME_CODE, Y as GRAPH_NOT_FOUND_CODE, i as MULTIPLE_GRAPHS_CODE, s as UNKNOWN_ENCODING_CODE, t as ENCODING_FALLBACK_CODE, u as INVALID_ENCODING_CODE, v as INVALID_UTF8_CODE, y as ELEMENT_ISSUE, z as INPUT_ISSUE, K as ImportReportBuilder } from "./report-CwMfYa9J.js";
|
|
6
|
+
import { i as inferTextDtype, W as WIDENING_UNSUPPORTED_CODE, a as isNumericText, T as TextCellWriter } from "./text-ystE2bYi.js";
|
|
7
7
|
import { j as joinText, e as encodeChunks } from "./writer-DxjgHwSe.js";
|
|
8
|
-
import { i as importChosenGraph } from "./choose-
|
|
9
|
-
import { L as LineReader, b as throwIfAborted } from "./input-
|
|
10
|
-
import {
|
|
11
|
-
import { S as StyleApproximations } from "./approximations-
|
|
12
|
-
import {
|
|
8
|
+
import { p as postscriptFont, f as graphvizFontName, i as importChosenGraph } from "./choose-CczZJaX_.js";
|
|
9
|
+
import { L as LineReader, b as throwIfAborted } from "./input-CAxt_aV-.js";
|
|
10
|
+
import { A as writeStyleBlock, B as styleBlockLosses, h as StyleNotes, p as plainCell, f as canonText, a as canonEnum, d as canonColor, e as colorOpacity, c as canonNumber, n as noteAt, b as STYLE_ISSUE, y as toolDefaults, L as DVIPS_COLORS } from "./block-yl0f_qLO.js";
|
|
11
|
+
import { S as StyleApproximations } from "./approximations-BRXsll0T.js";
|
|
12
|
+
import { e as elementValues, t as takeFromBlock } from "./round-trip-Cy3_SHRZ.js";
|
|
13
|
+
import { v as valueColumns } from "./styles-yed-XeFBQ6VS.js";
|
|
14
|
+
const PAJEK_WINDOW = 500;
|
|
15
|
+
function resolvePajekDraw(option) {
|
|
16
|
+
if (option === void 0) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const bad = (found) => {
|
|
20
|
+
throw new GraphFormatError("E_UNSUPPORTED", "option pajekDraw: not an object of Pajek draw settings", {
|
|
21
|
+
option: "pajekDraw",
|
|
22
|
+
found
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
if (typeof option !== "object" || option === null || Array.isArray(option)) {
|
|
26
|
+
return bad(option);
|
|
27
|
+
}
|
|
28
|
+
const o = option;
|
|
29
|
+
const num = (v, fallback, positive) => {
|
|
30
|
+
if (v === void 0) {
|
|
31
|
+
return fallback;
|
|
32
|
+
}
|
|
33
|
+
if (typeof v !== "number" || !Number.isFinite(v)) {
|
|
34
|
+
return bad(v);
|
|
35
|
+
}
|
|
36
|
+
const inRange = positive ? v > 0 : v >= 0;
|
|
37
|
+
return inRange ? v : bad(v);
|
|
38
|
+
};
|
|
39
|
+
const ini = /* @__PURE__ */ new Map();
|
|
40
|
+
for (const [name, value] of Object.entries(o.ini ?? {})) {
|
|
41
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
|
|
42
|
+
return bad(value);
|
|
43
|
+
}
|
|
44
|
+
ini.set(name, String(value));
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
width: num(o.width, PAJEK_WINDOW, true),
|
|
48
|
+
height: num(o.height, PAJEK_WINDOW, true),
|
|
49
|
+
partition: num(o.partition, 0, false),
|
|
50
|
+
vector: num(o.vector, 0, false),
|
|
51
|
+
vector2: num(o.vector2, 0, false),
|
|
52
|
+
ini
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function flag(draw, name) {
|
|
56
|
+
const v = draw.ini.get(name);
|
|
57
|
+
return v !== void 0 && v !== "0" && v !== "false";
|
|
58
|
+
}
|
|
59
|
+
function drawsLineLabels(draw) {
|
|
60
|
+
return draw !== null && flag(draw, "Form8.withLabels1");
|
|
61
|
+
}
|
|
62
|
+
function drawsStraightLines(draw) {
|
|
63
|
+
return draw !== null && flag(draw, "Form10.StraightLinesOnly1");
|
|
64
|
+
}
|
|
65
|
+
function iniNumber(draw, name) {
|
|
66
|
+
const v = draw.ini.get(name);
|
|
67
|
+
const n = v === void 0 || v.trim() === "" ? Number.NaN : Number(v);
|
|
68
|
+
return Number.isFinite(n) ? n : null;
|
|
69
|
+
}
|
|
70
|
+
const PARTITION_COLORS = [
|
|
71
|
+
"#00ffff",
|
|
72
|
+
"#ffff00",
|
|
73
|
+
"#7fff00",
|
|
74
|
+
"#ff0000",
|
|
75
|
+
"#0000ff",
|
|
76
|
+
"#ffd8f2",
|
|
77
|
+
"#ffffff",
|
|
78
|
+
"#ff6321",
|
|
79
|
+
"#8c23ff",
|
|
80
|
+
"#606dc4",
|
|
81
|
+
"#1ef9a3",
|
|
82
|
+
"#009900",
|
|
83
|
+
"#7f7f7f",
|
|
84
|
+
"#000000",
|
|
85
|
+
"#ad0000",
|
|
86
|
+
"#ccffb2",
|
|
87
|
+
"#ffff99",
|
|
88
|
+
"#ff00ff",
|
|
89
|
+
"#007091",
|
|
90
|
+
"#ffb528",
|
|
91
|
+
"#ff0a9b",
|
|
92
|
+
"#00e000",
|
|
93
|
+
"#ff779e",
|
|
94
|
+
"#d8f2ff",
|
|
95
|
+
"#d8ff4f",
|
|
96
|
+
"#ff84ff",
|
|
97
|
+
"#e5ffcc",
|
|
98
|
+
"#ccccff",
|
|
99
|
+
"#59ddff",
|
|
100
|
+
"#ffd9bc",
|
|
101
|
+
"#db9370",
|
|
102
|
+
"#ccffff",
|
|
103
|
+
"#d8d8d8",
|
|
104
|
+
"#666666",
|
|
105
|
+
"#a5a5a5",
|
|
106
|
+
"#3f3f3f",
|
|
107
|
+
"#e5e5e5",
|
|
108
|
+
"#262626",
|
|
109
|
+
"#bfbfbf",
|
|
110
|
+
"#595959"
|
|
111
|
+
];
|
|
112
|
+
const VERTEX_SIZE = 20;
|
|
113
|
+
const VERTEX_FILL = "#ffd9bc";
|
|
114
|
+
const SIZE_OF_VERTICES = 8;
|
|
115
|
+
function objectValues(snapshot, kind, n) {
|
|
116
|
+
if (n < 1) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const pajek = snapshot.meta.extra.pajek;
|
|
120
|
+
const name = pajek?.objects?.filter((o) => o.kind === kind)[n - 1]?.column;
|
|
121
|
+
if (name === void 0 || !snapshot.nodes.has(name)) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
return (i) => {
|
|
125
|
+
const v = snapshot.nodes.value(name, i);
|
|
126
|
+
return typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function column(values, property, n) {
|
|
130
|
+
values[property] ??= new Array(n).fill(null);
|
|
131
|
+
return values[property];
|
|
132
|
+
}
|
|
133
|
+
function drawVertices(draw, snapshot, node) {
|
|
134
|
+
const n = snapshot.nodeCount;
|
|
135
|
+
const width = column(node, "width", n);
|
|
136
|
+
const height = column(node, "height", n);
|
|
137
|
+
scaleVertexSizes(draw, width, height);
|
|
138
|
+
sizeByVectors(draw, snapshot, width, height);
|
|
139
|
+
colorByPartition(draw, snapshot, node);
|
|
140
|
+
const opacity = iniNumber(draw, "TransparencyofVertices");
|
|
141
|
+
if (opacity !== null && opacity < 1) {
|
|
142
|
+
const o = Math.max(0, opacity);
|
|
143
|
+
const fill = column(node, "fillOpacity", n);
|
|
144
|
+
fill.forEach((v, i) => {
|
|
145
|
+
fill[i] = (typeof v === "number" ? v : 1) * o;
|
|
146
|
+
});
|
|
147
|
+
column(node, "borderOpacity", n).fill(o * o);
|
|
148
|
+
}
|
|
149
|
+
if (flag(draw, "Form10.effect3d")) {
|
|
150
|
+
effect3d(snapshot, node);
|
|
151
|
+
}
|
|
152
|
+
markVertices(draw, node, n);
|
|
153
|
+
for (const property of ["width", "height"]) {
|
|
154
|
+
if (node[property].every((v) => v === null)) {
|
|
155
|
+
Reflect.deleteProperty(node, property);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function scaleVertexSizes(draw, width, height) {
|
|
160
|
+
const size = iniNumber(draw, "Form8.SizeofVertices");
|
|
161
|
+
if (size === null || size === SIZE_OF_VERTICES) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const f = size / SIZE_OF_VERTICES;
|
|
165
|
+
const scaled = (v) => typeof v === "number" ? v * f : VERTEX_SIZE * f * f;
|
|
166
|
+
for (let i = 0; i < width.length; i++) {
|
|
167
|
+
width[i] = scaled(width[i]);
|
|
168
|
+
height[i] = scaled(height[i]);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function colorByPartition(draw, snapshot, node) {
|
|
172
|
+
const partition = objectValues(snapshot, "partition", draw.partition);
|
|
173
|
+
if (partition === null) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const fill = column(node, "fill", snapshot.nodeCount);
|
|
177
|
+
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
178
|
+
const k = partition(i);
|
|
179
|
+
if (k !== null) {
|
|
180
|
+
fill[i] = PARTITION_COLORS[Math.abs(k) % PARTITION_COLORS.length];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function markVertices(draw, node, n) {
|
|
185
|
+
const mark = iniNumber(draw, "Form8.MarkVerticesUsing");
|
|
186
|
+
if (mark === 2) {
|
|
187
|
+
column(node, "label", n).forEach((_, i, a) => {
|
|
188
|
+
a[i] = String(i + 1);
|
|
189
|
+
});
|
|
190
|
+
} else if (mark === 3 || mark === 4) {
|
|
191
|
+
column(node, "label", n).fill("");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function effect3d(snapshot, node) {
|
|
195
|
+
const n = snapshot.nodeCount;
|
|
196
|
+
const fill = column(node, "fill", n);
|
|
197
|
+
const end = column(node, "fillGradient", n);
|
|
198
|
+
const angle = column(node, "fillGradientAngle", n);
|
|
199
|
+
const half = (v) => {
|
|
200
|
+
const h = v / 2;
|
|
201
|
+
const f = Math.floor(h);
|
|
202
|
+
return h - f === 0.5 && f % 2 === 0 ? f : Math.round(h);
|
|
203
|
+
};
|
|
204
|
+
for (let i = 0; i < n; i++) {
|
|
205
|
+
const color = typeof fill[i] === "string" ? String(fill[i]) : VERTEX_FILL;
|
|
206
|
+
end[i] = `#${[1, 3, 5].map(
|
|
207
|
+
(k) => half(Number.parseInt(color.slice(k, k + 2), 16)).toString(16).padStart(2, "0")
|
|
208
|
+
).join("")}`;
|
|
209
|
+
const phi = snapshot.nodes.has("phi") ? Number(snapshot.nodes.value("phi", i)) : 0;
|
|
210
|
+
angle[i] = Number.isFinite(phi) ? ((90 - phi) % 360 + 360) % 360 : 90;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function sizeByVectors(draw, snapshot, width, height) {
|
|
214
|
+
const first = objectValues(snapshot, "vector", draw.vector);
|
|
215
|
+
if (first === null) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const second = objectValues(snapshot, "vector", draw.vector2);
|
|
219
|
+
const scale = (sizes, i, v) => {
|
|
220
|
+
if (v !== null && v >= 0) {
|
|
221
|
+
sizes[i] = (typeof sizes[i] === "number" ? sizes[i] : VERTEX_SIZE) * v;
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
225
|
+
const v = first(i);
|
|
226
|
+
if (second === null) {
|
|
227
|
+
const root = v === null || v < 0 ? null : Math.sqrt(v);
|
|
228
|
+
scale(width, i, root);
|
|
229
|
+
scale(height, i, root);
|
|
230
|
+
} else {
|
|
231
|
+
scale(width, i, v);
|
|
232
|
+
scale(height, i, second(i));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function drawLines(draw, snapshot, node, edge) {
|
|
237
|
+
const m = snapshot.edgeCount;
|
|
238
|
+
const opacity = iniNumber(draw, "TransparencyofLines");
|
|
239
|
+
if (opacity !== null && opacity < 1) {
|
|
240
|
+
const o = column(edge, "opacity", m);
|
|
241
|
+
o.forEach((v, e) => {
|
|
242
|
+
o[e] = (typeof v === "number" ? v : 1) * Math.max(0, opacity);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
if (flag(draw, "Form10.StraightLinesOnly1")) {
|
|
246
|
+
const curved = column(edge, "curved", m);
|
|
247
|
+
for (let e = 0; e < m; e++) {
|
|
248
|
+
const bends = edge.bends?.[e];
|
|
249
|
+
if (bends === null || bends === void 0) {
|
|
250
|
+
curved[e] = false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (flag(draw, "Form10.ColorGradientLines")) {
|
|
255
|
+
const fill = node.fill;
|
|
256
|
+
const fillOf = (i) => typeof fill?.[i] === "string" ? fill[i] : VERTEX_FILL;
|
|
257
|
+
const colors = column(edge, "gradientColors", m);
|
|
258
|
+
const kind = column(edge, "gradientKind", m);
|
|
259
|
+
const sourceArrow = column(edge, "sourceArrowColor", m);
|
|
260
|
+
const targetArrow = column(edge, "targetArrowColor", m);
|
|
261
|
+
for (let e = 0; e < m; e++) {
|
|
262
|
+
const [s, t] = [fillOf(snapshot.edgeSource(e)), fillOf(snapshot.edgeTarget(e))];
|
|
263
|
+
colors[e] = `${s} ${t}`;
|
|
264
|
+
kind[e] = "linear";
|
|
265
|
+
sourceArrow[e] = s;
|
|
266
|
+
targetArrow[e] = t;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
13
270
|
const LABEL_COLUMN = "label";
|
|
14
271
|
const POSITION_COLUMN = "position";
|
|
15
272
|
const SHAPE_COLUMN = "shape";
|
|
@@ -256,7 +513,7 @@ function parseIntervals(token) {
|
|
|
256
513
|
return [];
|
|
257
514
|
}
|
|
258
515
|
const spells = [];
|
|
259
|
-
for (const part of body.split(
|
|
516
|
+
for (const part of body.split(/[,/]/)) {
|
|
260
517
|
spells.push(parseSpell(token, part));
|
|
261
518
|
}
|
|
262
519
|
return spells;
|
|
@@ -328,6 +585,20 @@ function isParameterKey(text) {
|
|
|
328
585
|
}
|
|
329
586
|
return !/^[+-]?(\.\d|\d)/.test(text) && !/^[+-]?(?:nan|inf|infinity)$/i.test(text);
|
|
330
587
|
}
|
|
588
|
+
const VOIDING_KEYS = /* @__PURE__ */ new Set([
|
|
589
|
+
"bc",
|
|
590
|
+
"bw",
|
|
591
|
+
"s_size",
|
|
592
|
+
"phi",
|
|
593
|
+
"r",
|
|
594
|
+
"q",
|
|
595
|
+
"lc",
|
|
596
|
+
"la",
|
|
597
|
+
"lr",
|
|
598
|
+
"lphi",
|
|
599
|
+
"fos",
|
|
600
|
+
"font"
|
|
601
|
+
]);
|
|
331
602
|
const PAJEK_STYLE_CAPABILITIES = Object.freeze({
|
|
332
603
|
tool: "pajek",
|
|
333
604
|
node: Object.freeze([
|
|
@@ -338,22 +609,95 @@ const PAJEK_STYLE_CAPABILITIES = Object.freeze({
|
|
|
338
609
|
"borderColor",
|
|
339
610
|
"borderWidth",
|
|
340
611
|
"shape",
|
|
612
|
+
"shapePoints",
|
|
341
613
|
"width",
|
|
342
614
|
"height",
|
|
343
615
|
"labelColor",
|
|
344
|
-
"labelSize"
|
|
616
|
+
"labelSize",
|
|
617
|
+
"labelFont",
|
|
618
|
+
"labelPosition",
|
|
619
|
+
"labelOffsetX",
|
|
620
|
+
"labelOffsetY",
|
|
621
|
+
"labelShiftX"
|
|
622
|
+
]),
|
|
623
|
+
edge: Object.freeze([
|
|
624
|
+
"color",
|
|
625
|
+
"opacity",
|
|
626
|
+
"width",
|
|
627
|
+
"lineStyle",
|
|
628
|
+
"sourceArrow",
|
|
629
|
+
"targetArrow",
|
|
630
|
+
"arrowSize",
|
|
631
|
+
"arrowPosition",
|
|
632
|
+
"label",
|
|
633
|
+
"labelColor",
|
|
634
|
+
"labelSize",
|
|
635
|
+
"labelFont"
|
|
345
636
|
]),
|
|
346
|
-
edge: Object.freeze(["color", "opacity", "width", "lineStyle", "sourceArrow", "targetArrow"]),
|
|
347
637
|
block: "native"
|
|
348
638
|
});
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
|
|
639
|
+
const PAJEK_VERTEX_SIZE = 20;
|
|
640
|
+
const PAJEK_FIGURES = /* @__PURE__ */ new Map([
|
|
641
|
+
["other:man", [2.502, 6.487]],
|
|
642
|
+
["other:woman", [3.003, 6.478]]
|
|
643
|
+
]);
|
|
644
|
+
const PAJEK_FIGURE_UNSET_FACTOR = 0.3;
|
|
645
|
+
const PAJEK_POINTS_PER_UNIT = 500;
|
|
646
|
+
const NODE_KEYS = [
|
|
647
|
+
"ic",
|
|
648
|
+
"bc",
|
|
649
|
+
"bw",
|
|
650
|
+
"s_size",
|
|
651
|
+
"x_fact",
|
|
652
|
+
"y_fact",
|
|
653
|
+
"phi",
|
|
654
|
+
"q",
|
|
655
|
+
"lc",
|
|
656
|
+
"fos",
|
|
657
|
+
"font",
|
|
658
|
+
"lr",
|
|
659
|
+
"lphi",
|
|
660
|
+
"la"
|
|
661
|
+
];
|
|
662
|
+
const EDGE_KEYS = ["c", "w", "p", "s", "ap", "l", "lc", "fos", "font"];
|
|
663
|
+
const CARRIED = {
|
|
664
|
+
node: [SHAPE_COLUMN, ...NODE_KEYS],
|
|
665
|
+
edge: ["c", "w", "p", "s", "ap"]
|
|
666
|
+
};
|
|
667
|
+
const CARRIED_LINE = CARRIED.edge.filter((key) => key !== "p" && key !== "ap");
|
|
668
|
+
const EDGE_WIDTH_PER_W = 2;
|
|
669
|
+
const ARC_DEFAULTS = { color: "#999999", width: 1 };
|
|
670
|
+
function carriedParams(keys, whole) {
|
|
671
|
+
let last = /* @__PURE__ */ new Map();
|
|
672
|
+
return (get) => {
|
|
673
|
+
const own = /* @__PURE__ */ new Map();
|
|
674
|
+
for (const key of keys) {
|
|
675
|
+
const v = get(key);
|
|
676
|
+
if (v !== null) {
|
|
677
|
+
own.set(key, v);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
if (whole) {
|
|
681
|
+
if (own.size > 0) {
|
|
682
|
+
last = own;
|
|
683
|
+
return get;
|
|
684
|
+
}
|
|
685
|
+
} else {
|
|
686
|
+
for (const [key, v] of own) {
|
|
687
|
+
last.set(key, v);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
const carried = last;
|
|
691
|
+
return (key) => get(key) ?? (keys.includes(key) ? carried.get(key) ?? null : null);
|
|
692
|
+
};
|
|
693
|
+
}
|
|
352
694
|
const DIRECTED_KEY = "directed";
|
|
353
695
|
const READ = {
|
|
354
696
|
node: [
|
|
355
697
|
"label",
|
|
356
698
|
"shape",
|
|
699
|
+
"shapePoints",
|
|
700
|
+
"shapePointsStretch",
|
|
357
701
|
"fill",
|
|
358
702
|
"fillOpacity",
|
|
359
703
|
"borderColor",
|
|
@@ -361,9 +705,26 @@ const READ = {
|
|
|
361
705
|
"width",
|
|
362
706
|
"height",
|
|
363
707
|
"labelColor",
|
|
364
|
-
"labelSize"
|
|
708
|
+
"labelSize",
|
|
709
|
+
"labelFont",
|
|
710
|
+
"labelPosition",
|
|
711
|
+
"labelOffsetX",
|
|
712
|
+
"labelOffsetY",
|
|
713
|
+
"labelShiftX",
|
|
714
|
+
"labelRotation"
|
|
365
715
|
],
|
|
366
|
-
edge: [
|
|
716
|
+
edge: [
|
|
717
|
+
"color",
|
|
718
|
+
"opacity",
|
|
719
|
+
"width",
|
|
720
|
+
"lineStyle",
|
|
721
|
+
"arrowSize",
|
|
722
|
+
"arrowPosition",
|
|
723
|
+
"label",
|
|
724
|
+
"labelColor",
|
|
725
|
+
"labelSize",
|
|
726
|
+
"labelFont"
|
|
727
|
+
]
|
|
367
728
|
};
|
|
368
729
|
function readColor(raw, property, opacity, put, at) {
|
|
369
730
|
if (raw === null) {
|
|
@@ -371,6 +732,10 @@ function readColor(raw, property, opacity, put, at) {
|
|
|
371
732
|
}
|
|
372
733
|
const c = canonColor(raw, "dvips", at(property));
|
|
373
734
|
if (c === null) {
|
|
735
|
+
const unknown = UNKNOWN_COLORS.get(property);
|
|
736
|
+
if (unknown !== void 0 && typeof raw === "string" && /^[A-Za-z]\w*$/.test(raw.trim())) {
|
|
737
|
+
put(property, unknown);
|
|
738
|
+
}
|
|
374
739
|
return;
|
|
375
740
|
}
|
|
376
741
|
put(property, c.color);
|
|
@@ -379,43 +744,454 @@ function readColor(raw, property, opacity, put, at) {
|
|
|
379
744
|
put(opacity, alpha);
|
|
380
745
|
}
|
|
381
746
|
}
|
|
747
|
+
const UNKNOWN_COLORS = /* @__PURE__ */ new Map([
|
|
748
|
+
["fill", "#ffffff"],
|
|
749
|
+
["color", "#000000"]
|
|
750
|
+
]);
|
|
382
751
|
function readNumber(raw, property, put, at) {
|
|
383
752
|
if (raw !== null) {
|
|
384
753
|
put(property, canonNumber(raw, at(property)));
|
|
385
754
|
}
|
|
386
755
|
}
|
|
387
|
-
function readVertex(get, put, at) {
|
|
756
|
+
function readVertex(get, put, at, place = null) {
|
|
388
757
|
const label = get(LABEL_COLUMN);
|
|
389
758
|
if (label !== null && label !== "") {
|
|
390
759
|
put("label", canonText(label, at("label")));
|
|
391
760
|
}
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
761
|
+
const raw = get(SHAPE_COLUMN);
|
|
762
|
+
const shape = raw === null ? null : canonEnum("shape", raw, "dvips", at("shape"));
|
|
763
|
+
if (raw !== null) {
|
|
764
|
+
put("shape", shape);
|
|
395
765
|
}
|
|
396
766
|
readColor(get("ic"), "fill", "fillOpacity", put, at);
|
|
397
767
|
readColor(get("bc"), "borderColor", null, put, at);
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
put("borderWidth", width === null ? null : width / VERTEX_SIZE);
|
|
402
|
-
}
|
|
403
|
-
readNumber(get("x_fact"), "width", put, at);
|
|
404
|
-
readNumber(get("y_fact"), "height", put, at);
|
|
768
|
+
readNumber(get("bw"), "borderWidth", put, at);
|
|
769
|
+
readSize(get, put, at, PAJEK_FIGURES.get(String(shape)));
|
|
770
|
+
readOutline(get, put, shape);
|
|
405
771
|
readColor(get("lc"), "labelColor", null, put, at);
|
|
406
772
|
readNumber(get("fos"), "labelSize", put, at);
|
|
773
|
+
readFont(get("font"), put, at);
|
|
774
|
+
readLabelPosition(get, put, at);
|
|
775
|
+
readLabelAngle(get("la"), put, at, place);
|
|
776
|
+
if (shape === "none") {
|
|
777
|
+
for (const [property, value] of EMPTY_LABEL) {
|
|
778
|
+
put(property, value);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
const PAJEK_OUTLINES = /* @__PURE__ */ new Map([
|
|
783
|
+
[
|
|
784
|
+
"rectangle",
|
|
785
|
+
[
|
|
786
|
+
[-1, 1],
|
|
787
|
+
[1, 1],
|
|
788
|
+
[1, -1],
|
|
789
|
+
[-1, -1]
|
|
790
|
+
]
|
|
791
|
+
],
|
|
792
|
+
[
|
|
793
|
+
"triangle",
|
|
794
|
+
[
|
|
795
|
+
[1, -1],
|
|
796
|
+
[0, 1],
|
|
797
|
+
[-1, -1]
|
|
798
|
+
]
|
|
799
|
+
],
|
|
800
|
+
[
|
|
801
|
+
"other:house",
|
|
802
|
+
[
|
|
803
|
+
[-0.7, -1],
|
|
804
|
+
[0.7, -1],
|
|
805
|
+
[0.7, 0.3],
|
|
806
|
+
[1, 0.3],
|
|
807
|
+
[1, 0.4],
|
|
808
|
+
[0, 1],
|
|
809
|
+
[-1, 0.4],
|
|
810
|
+
[-1, 0.3],
|
|
811
|
+
[-0.7, 0.3]
|
|
812
|
+
]
|
|
813
|
+
]
|
|
814
|
+
]);
|
|
815
|
+
const PAJEK_DIAMOND_Q = 1e-3;
|
|
816
|
+
function readOutline(get, put, shape) {
|
|
817
|
+
const phi = numberOrNull(get("phi")) ?? 0;
|
|
818
|
+
const q = numberOrNull(get("q")) ?? PAJEK_DIAMOND_Q;
|
|
819
|
+
const diamond = [
|
|
820
|
+
[-1, 0],
|
|
821
|
+
[-q, 1],
|
|
822
|
+
[q, 1],
|
|
823
|
+
[1, 0],
|
|
824
|
+
[q, -1],
|
|
825
|
+
[-q, -1]
|
|
826
|
+
];
|
|
827
|
+
const corners = shape === "diamond" ? diamond : PAJEK_OUTLINES.get(String(shape));
|
|
828
|
+
if (corners === void 0 || shape !== "diamond" && phi % 360 === 0) {
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
const [w, h] = [numberOrNull(get("x_fact")) || 1, numberOrNull(get("y_fact")) || 1];
|
|
832
|
+
const [c, s] = [Math.cos(phi * Math.PI / 180), Math.sin(phi * Math.PI / 180)];
|
|
833
|
+
const round = (v) => String(Number(v.toFixed(4)) + 0);
|
|
834
|
+
const points = corners.map(([x, y]) => {
|
|
835
|
+
const [px, py] = [x * w, y * h];
|
|
836
|
+
return `${round((px * c - py * s) / w)},${round((px * s + py * c) / h)}`;
|
|
837
|
+
});
|
|
838
|
+
put("shape", "polygon");
|
|
839
|
+
put("shapePoints", points.join(" "));
|
|
840
|
+
put("shapePointsStretch", false);
|
|
841
|
+
}
|
|
842
|
+
const EMPTY_LABEL = [
|
|
843
|
+
["labelSize", 1],
|
|
844
|
+
["labelColor", "#ffffff"],
|
|
845
|
+
["labelPosition", "center"],
|
|
846
|
+
["labelOffsetX", 0],
|
|
847
|
+
["labelOffsetY", 0],
|
|
848
|
+
["labelShiftX", 0]
|
|
849
|
+
];
|
|
850
|
+
function readFont(raw, put, at) {
|
|
851
|
+
if (raw === null || raw === "") {
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
const ps = typeof raw === "string" ? postscriptFont(raw.trim()) : null;
|
|
855
|
+
if (ps === null) {
|
|
856
|
+
readText(raw, "labelFont", put, at);
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
put("labelFont", ps.family);
|
|
860
|
+
}
|
|
861
|
+
function readLabelAngle(raw, put, at, place) {
|
|
862
|
+
let a = raw === null ? null : canonNumber(raw, at("labelRotation"));
|
|
863
|
+
if (a !== null && a >= 360) {
|
|
864
|
+
a = place === null ? null : Math.atan2(0.5 - place[1], place[0] - 0.5) * 180 / Math.PI + a - 360;
|
|
865
|
+
}
|
|
866
|
+
if (a !== null) {
|
|
867
|
+
put("labelRotation", Number((((360 - a) % 360 + 360) % 360).toPrecision(12)));
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
function readSize(get, put, at, figure) {
|
|
871
|
+
for (const [key, property, k] of [
|
|
872
|
+
["x_fact", "width", 0],
|
|
873
|
+
["y_fact", "height", 1]
|
|
874
|
+
]) {
|
|
875
|
+
const f = get(key);
|
|
876
|
+
if (f === null && figure === void 0) {
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
const unset = figure === void 0 ? 1 : PAJEK_FIGURE_UNSET_FACTOR;
|
|
880
|
+
const factor = f === null ? unset : canonNumber(f, at(property));
|
|
881
|
+
const over = figure?.[k] ?? 1;
|
|
882
|
+
put(property, factor === null ? null : Number((PAJEK_VERTEX_SIZE * factor * over).toPrecision(15)));
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
function readText(raw, property, put, at) {
|
|
886
|
+
if (raw !== null && raw !== "") {
|
|
887
|
+
put(property, canonText(raw, at(property)));
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
const SIDE_ANGLES = /* @__PURE__ */ new Map([
|
|
891
|
+
["right", 0],
|
|
892
|
+
["top-right", 90],
|
|
893
|
+
["left", 180],
|
|
894
|
+
["bottom-right", 285]
|
|
895
|
+
]);
|
|
896
|
+
const NEAREST_SIDES = /* @__PURE__ */ new Map([
|
|
897
|
+
["top", "top-right"],
|
|
898
|
+
["top-left", "top-right"],
|
|
899
|
+
["bottom", "bottom-right"],
|
|
900
|
+
["bottom-left", "bottom-right"]
|
|
901
|
+
]);
|
|
902
|
+
function readLabelPosition(get, put, at) {
|
|
903
|
+
const [lr, lphi, fos] = [get("lr"), get("lphi"), get("fos")];
|
|
904
|
+
if (lr === null && lphi === null && fos === null) {
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
const radius = lr === null ? PAJEK_LABEL_RADIUS : canonNumber(lr, at("labelPosition"));
|
|
908
|
+
const angle = lphi === null ? PAJEK_LABEL_ANGLE : canonNumber(lphi, at("labelPosition"));
|
|
909
|
+
const size = fos === null ? PAJEK_LABEL_SIZE : canonNumber(fos, at("labelSize"));
|
|
910
|
+
if (radius === null || angle === null || size === null) {
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
const [x, y] = labelOffset(radius, angle, size);
|
|
914
|
+
put("labelPosition", "center");
|
|
915
|
+
put("labelOffsetX", x);
|
|
916
|
+
put("labelOffsetY", y);
|
|
917
|
+
put("labelShiftX", radius === 0 ? 0 : 0.5);
|
|
918
|
+
}
|
|
919
|
+
function labelOffset(radius, angle, size) {
|
|
920
|
+
if (radius === 0) {
|
|
921
|
+
return [0, 0];
|
|
922
|
+
}
|
|
923
|
+
const t = angle * Math.PI / 180;
|
|
924
|
+
const round = (v) => Number(v.toFixed(9)) + 0;
|
|
925
|
+
return [round(radius * Math.cos(t)), round(-radius * Math.sin(t) - PAJEK_BASELINE_TO_MIDDLE * size)];
|
|
407
926
|
}
|
|
408
|
-
|
|
927
|
+
const PAJEK_LABEL_RADIUS = 20;
|
|
928
|
+
const PAJEK_LABEL_ANGLE = 285;
|
|
929
|
+
const PAJEK_LABEL_SIZE = 15;
|
|
930
|
+
const PAJEK_BASELINE_TO_MIDDLE = 0.3465;
|
|
931
|
+
function readLine(get, put, at, directed, labels = true, run = null, loop = null) {
|
|
409
932
|
readColor(get("c"), "color", "opacity", put, at);
|
|
410
|
-
readNumber(
|
|
933
|
+
readNumber(
|
|
934
|
+
get("w"),
|
|
935
|
+
"width",
|
|
936
|
+
(property, value) => {
|
|
937
|
+
put(property, typeof value === "number" && !directed ? value * EDGE_WIDTH_PER_W : value);
|
|
938
|
+
},
|
|
939
|
+
at
|
|
940
|
+
);
|
|
411
941
|
const p = get("p");
|
|
412
|
-
if (p
|
|
413
|
-
put("lineStyle",
|
|
942
|
+
if (p === "Dots") {
|
|
943
|
+
put("lineStyle", pajekDash(get, directed));
|
|
944
|
+
} else if (p === "Solid") {
|
|
945
|
+
put("lineStyle", "solid");
|
|
946
|
+
} else if (p !== null) {
|
|
947
|
+
noteAt(at("lineStyle"), STYLE_ISSUE.UNKNOWN_VALUE, typeof p === "string" ? p : JSON.stringify(p));
|
|
948
|
+
put("lineStyle", "solid");
|
|
949
|
+
}
|
|
950
|
+
readNumber(get("s"), "arrowSize", put, at);
|
|
951
|
+
readArrowPosition(get("ap"), put, at, run);
|
|
952
|
+
const line = loop === null ? get : loopParam(get);
|
|
953
|
+
const controls = loop === null ? null : readLoop(line, put, loop);
|
|
954
|
+
if (labels) {
|
|
955
|
+
readText(get("l"), "label", put, at);
|
|
956
|
+
if (controls === null) {
|
|
957
|
+
readLineLabelPlace(get, put, at, run);
|
|
958
|
+
} else {
|
|
959
|
+
readLineLabelPlace(line, put, at, [PAJEK_POINTS_PER_UNIT, 0], loopTop(controls));
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
if (loop === null) {
|
|
963
|
+
readBezier(get, put, run);
|
|
964
|
+
}
|
|
965
|
+
readColor(get("lc"), "labelColor", null, put, at);
|
|
966
|
+
readNumber(get("fos"), "labelSize", put, at);
|
|
967
|
+
readFont(get("font"), put, at);
|
|
968
|
+
}
|
|
969
|
+
const LOOP_DEFAULTS = { a1: -70, k1: 0.3, a2: -70, k2: 0.3 };
|
|
970
|
+
function loopParam(get) {
|
|
971
|
+
return (key) => get(key) ?? (key in LOOP_DEFAULTS ? LOOP_DEFAULTS[key] : null);
|
|
972
|
+
}
|
|
973
|
+
function readLoop(get, put, loop) {
|
|
974
|
+
const run = [PAJEK_POINTS_PER_UNIT, 0];
|
|
975
|
+
const controls = bezierControls(get, run);
|
|
976
|
+
if (controls === null) {
|
|
977
|
+
return null;
|
|
978
|
+
}
|
|
979
|
+
const [[a1, l1], [a2, l2]] = controls;
|
|
980
|
+
const L = PAJEK_POINTS_PER_UNIT;
|
|
981
|
+
const [c1, c2] = [
|
|
982
|
+
[a1 * L, -l1 * L],
|
|
983
|
+
[(a2 - 1) * L, -l2 * L]
|
|
984
|
+
];
|
|
985
|
+
loop([c1, c2]);
|
|
986
|
+
put("curved", true);
|
|
987
|
+
put("bendCurve", "bezier");
|
|
988
|
+
put("targetArrow", "none");
|
|
989
|
+
return [c1, c2];
|
|
990
|
+
}
|
|
991
|
+
function loopTop(controls) {
|
|
992
|
+
const [c1, c2] = controls;
|
|
993
|
+
return Math.atan2(c2[1] - c1[1], c2[0] - c1[0]) * 180 / Math.PI;
|
|
994
|
+
}
|
|
995
|
+
function layLoops(snapshot, loops, node, edge) {
|
|
996
|
+
const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
|
|
997
|
+
for (const [e, controls] of loops) {
|
|
998
|
+
const v = snapshot.edgeSource(e);
|
|
999
|
+
const half = (property) => {
|
|
1000
|
+
const size = node[property]?.[v];
|
|
1001
|
+
return (typeof size === "number" && size > 0 ? size : PAJEK_VERTEX_SIZE) / 2;
|
|
1002
|
+
};
|
|
1003
|
+
const [hw, hh] = [half("width"), half("height")];
|
|
1004
|
+
const column2 = (property) => edge[property] ??= new Array(snapshot.edgeCount).fill(null);
|
|
1005
|
+
column2("bends")[e] = controls.map(([x, y]) => `${fraction(x / hw)},${fraction(-y / hh)}`).join(" ");
|
|
1006
|
+
column2("curved")[e] = true;
|
|
1007
|
+
column2("bendCurve")[e] = "bezier";
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
function readLineLabelPlace(get, put, at, run, direction) {
|
|
1011
|
+
const length = run === null ? 0 : Math.hypot(run[0], run[1]);
|
|
1012
|
+
if (run === null || length === 0) {
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
const n = (key, fallback, property) => {
|
|
1016
|
+
const v = get(key);
|
|
1017
|
+
return v === null ? fallback : canonNumber(v, at(property));
|
|
1018
|
+
};
|
|
1019
|
+
const [lp, lr, lphi, la] = [
|
|
1020
|
+
n("lp", 0.5, "labelOffsetX"),
|
|
1021
|
+
n("lr", 0, "labelOffsetX"),
|
|
1022
|
+
n("lphi", 0, "labelOffsetX"),
|
|
1023
|
+
n("la", 0, "labelRotation")
|
|
1024
|
+
];
|
|
1025
|
+
const size = n("fos", PAJEK_LABEL_SIZE, "labelSize");
|
|
1026
|
+
if (lp === null || lr === null || lphi === null || la === null || size === null) {
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
const along = 0.5 - (lp <= 1 ? lp : lp / length);
|
|
1030
|
+
const t = lphi * Math.PI / 180;
|
|
1031
|
+
const round = (v) => Number(v.toFixed(9)) + 0;
|
|
1032
|
+
const turn = ((direction ?? lineDirection(get, run, along + 0.5)) - la) % 360 + 360;
|
|
1033
|
+
const up = turn * Math.PI / 180;
|
|
1034
|
+
const rise = PAJEK_BASELINE_TO_MIDDLE * size;
|
|
1035
|
+
put("labelPosition", "center");
|
|
1036
|
+
put("labelOffsetX", round(along * run[0] + lr * Math.cos(t) + rise * Math.sin(up)));
|
|
1037
|
+
put("labelOffsetY", round(along * run[1] - lr * Math.sin(t) - rise * Math.cos(up)));
|
|
1038
|
+
put("labelRotation", round(turn % 360));
|
|
1039
|
+
}
|
|
1040
|
+
function readBezier(get, put, run) {
|
|
1041
|
+
const controls = bezierControls(get, run);
|
|
1042
|
+
if (controls === null) {
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
|
|
1046
|
+
put("curved", true);
|
|
1047
|
+
put("bendCurve", "bezier");
|
|
1048
|
+
put("bends", controls.map(([along, across]) => `${fraction(along)},${fraction(across)}`).join(" "));
|
|
1049
|
+
}
|
|
1050
|
+
const PAJEK_TIP_BACK = 1.5;
|
|
1051
|
+
function readArcEnd(get, put, run, target) {
|
|
1052
|
+
const ap = numberOrNull(get("ap")) ?? 0;
|
|
1053
|
+
const length = Math.hypot(run[0], run[1]);
|
|
1054
|
+
if (ap !== 0 || length === 0 || bezierControls(get, run) === null) {
|
|
1055
|
+
return false;
|
|
1056
|
+
}
|
|
1057
|
+
const [ux, uy] = [run[0] / length, run[1] / length];
|
|
1058
|
+
const r = 1 / Math.hypot(ux / (target[0] / 2), uy / (target[1] / 2));
|
|
1059
|
+
const back = PAJEK_TIP_BACK + 5 * (numberOrNull(get("s")) ?? 1);
|
|
1060
|
+
const turn = -(numberOrNull(get("a2")) ?? 0) * Math.PI / 180;
|
|
1061
|
+
const [c, s] = [Math.cos(turn), Math.sin(turn)];
|
|
1062
|
+
const end = [run[0] - r * ux - back * (ux * c - uy * s), run[1] - r * uy - back * (ux * s + uy * c)];
|
|
1063
|
+
const controls = bezierControls(get, end);
|
|
1064
|
+
if (controls === null) {
|
|
1065
|
+
return false;
|
|
1066
|
+
}
|
|
1067
|
+
const L2 = length * length;
|
|
1068
|
+
const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
|
|
1069
|
+
const bends = controls.map(([along, left]) => {
|
|
1070
|
+
const [x, y] = [along * end[0] + left * end[1], along * end[1] - left * end[0]];
|
|
1071
|
+
return `${fraction((x * run[0] + y * run[1]) / L2)},${fraction((x * run[1] - y * run[0]) / L2)}`;
|
|
1072
|
+
});
|
|
1073
|
+
put("bends", bends.join(" "));
|
|
1074
|
+
const tip = [-r * ux - PAJEK_TIP_BACK * (ux * c - uy * s), -r * uy - PAJEK_TIP_BACK * (ux * s + uy * c)];
|
|
1075
|
+
put("targetPort", `${fraction(tip[0] / (target[0] / 2))},${fraction(-tip[1] / (target[1] / 2))}`);
|
|
1076
|
+
return true;
|
|
1077
|
+
}
|
|
1078
|
+
const PAJEK_TIP_GAP = 1;
|
|
1079
|
+
function readTipGap(get, put) {
|
|
1080
|
+
const s = numberOrNull(get("s")) ?? 1;
|
|
1081
|
+
if (s > 0) {
|
|
1082
|
+
put("targetArrowGap", Number((PAJEK_TIP_GAP / (6 * s)).toPrecision(6)));
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
function bezierControls(get, run) {
|
|
1086
|
+
const [a1, k1, a2, k2] = ["a1", "k1", "a2", "k2"].map((key) => numberOrNull(get(key)));
|
|
1087
|
+
if (a1 === null && k1 === null && a2 === null && k2 === null || run === null || run[0] === 0 && run[1] === 0) {
|
|
1088
|
+
return null;
|
|
1089
|
+
}
|
|
1090
|
+
const [s, t] = [k1 ?? 1, k2 ?? 1];
|
|
1091
|
+
if (s < 0 || t < 0) {
|
|
1092
|
+
return null;
|
|
1093
|
+
}
|
|
1094
|
+
const rad = Math.PI / 180;
|
|
1095
|
+
const [u, v] = [(a1 ?? 0) * rad, (a2 ?? 0) * rad];
|
|
1096
|
+
return [
|
|
1097
|
+
[s / 2 * Math.cos(u), -s / 2 * Math.sin(u)],
|
|
1098
|
+
[1 - t / 2 * Math.cos(v), -t / 2 * Math.sin(v)]
|
|
1099
|
+
];
|
|
1100
|
+
}
|
|
1101
|
+
function lineDirection(get, run, along) {
|
|
1102
|
+
const controls = bezierControls(get, run);
|
|
1103
|
+
let [dx, dy] = run;
|
|
1104
|
+
if (controls !== null) {
|
|
1105
|
+
const t = Math.min(1, Math.max(0, along));
|
|
1106
|
+
const p = [[0, 0], ...controls, [1, 0]];
|
|
1107
|
+
const d = (k) => 3 * (1 - t) ** 2 * (p[1][k] - p[0][k]) + 6 * (1 - t) * t * (p[2][k] - p[1][k]) + 3 * t ** 2 * (p[3][k] - p[2][k]);
|
|
1108
|
+
const [a, l] = [d(0), d(1)];
|
|
1109
|
+
[dx, dy] = [a * run[0] + l * run[1], a * run[1] - l * run[0]];
|
|
1110
|
+
}
|
|
1111
|
+
return Math.atan2(dy, dx) * 180 / Math.PI;
|
|
1112
|
+
}
|
|
1113
|
+
function readLineValue(value, get, put, directed = true) {
|
|
1114
|
+
if (value === 0) {
|
|
1115
|
+
put("visible", false);
|
|
1116
|
+
} else if (value !== null && value < 0 && get("p") === null) {
|
|
1117
|
+
put("lineStyle", pajekDash(get, directed));
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
const PAJEK_DASH = 5;
|
|
1121
|
+
function pajekDash(get, directed) {
|
|
1122
|
+
const w = numberOrNull(get("w"));
|
|
1123
|
+
const width = (w ?? 1) * (directed ? 1 : EDGE_WIDTH_PER_W);
|
|
1124
|
+
return PAJEK_DASH <= 1.5 * Math.max(1, width) ? "dotted" : "dashed";
|
|
1125
|
+
}
|
|
1126
|
+
function readHooks(get, put, source, target) {
|
|
1127
|
+
for (const [key, property, shape] of [
|
|
1128
|
+
["h1", "sourcePort", source],
|
|
1129
|
+
["h2", "targetPort", target]
|
|
1130
|
+
]) {
|
|
1131
|
+
const hook = numberOrNull(get(key));
|
|
1132
|
+
const port = hook === null ? null : hookPort(shape, hook);
|
|
1133
|
+
if (port !== null) {
|
|
1134
|
+
const round = (v) => String(Number(v.toFixed(4)) + 0);
|
|
1135
|
+
put(property, `${round(port[0])},${round(port[1])}`);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
function hookPort(shape, hook) {
|
|
1140
|
+
if (!Number.isInteger(hook) || hook < 1) {
|
|
1141
|
+
return null;
|
|
1142
|
+
}
|
|
1143
|
+
const keyword = typeof shape === "string" ? shape.toLowerCase() : "ellipse";
|
|
1144
|
+
if (keyword === "ellipse" || keyword === "cross") {
|
|
1145
|
+
const a = hook * Math.PI / 180;
|
|
1146
|
+
return [Math.cos(a), Math.sin(a)];
|
|
1147
|
+
}
|
|
1148
|
+
if (keyword !== "box" || hook > 400) {
|
|
1149
|
+
return null;
|
|
1150
|
+
}
|
|
1151
|
+
const d = hook * 0.02;
|
|
1152
|
+
if (hook <= 50) {
|
|
1153
|
+
return [1, d];
|
|
1154
|
+
}
|
|
1155
|
+
if (hook <= 150) {
|
|
1156
|
+
return [2 - d, 1];
|
|
1157
|
+
}
|
|
1158
|
+
if (hook <= 250) {
|
|
1159
|
+
return [-1, 4 - d];
|
|
1160
|
+
}
|
|
1161
|
+
return hook <= 350 ? [d - 6, -1] : [1, d - 8];
|
|
1162
|
+
}
|
|
1163
|
+
function numberOrNull(raw) {
|
|
1164
|
+
if (typeof raw === "string" && raw.trim() !== "") {
|
|
1165
|
+
raw = Number(raw);
|
|
1166
|
+
}
|
|
1167
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : null;
|
|
1168
|
+
}
|
|
1169
|
+
function readArrowPosition(raw, put, at, run = null) {
|
|
1170
|
+
if (raw === null) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
const ap = canonNumber(raw, at("arrowPosition"));
|
|
1174
|
+
const length = run === null ? 0 : Math.hypot(run[0], run[1]);
|
|
1175
|
+
if (ap !== null && ap > 1) {
|
|
1176
|
+
if (length > 0) {
|
|
1177
|
+
put("arrowPosition", Number(Math.min(1, ap / length).toPrecision(6)));
|
|
1178
|
+
} else {
|
|
1179
|
+
noteAt(at("arrowPosition"), STYLE_ISSUE.NOT_CARRIED, `ap ${String(ap)}`);
|
|
1180
|
+
}
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
if (ap !== 0) {
|
|
1184
|
+
put("arrowPosition", ap);
|
|
414
1185
|
}
|
|
415
1186
|
}
|
|
416
1187
|
function cells(table, i) {
|
|
417
|
-
return (key) =>
|
|
1188
|
+
return (key) => {
|
|
1189
|
+
const v = table.has(key) ? plainCell(table.value(key, i)) : null;
|
|
1190
|
+
return COLOR_PARAMS.has(key) && typeof v === "string" && NUMERIC_COLOR.test(v) ? null : v;
|
|
1191
|
+
};
|
|
418
1192
|
}
|
|
1193
|
+
const COLOR_PARAMS = /* @__PURE__ */ new Set(["ic", "bc", "lc", "c"]);
|
|
1194
|
+
const NUMERIC_COLOR = /^[\d.]+(?: [\d.]+)*$/;
|
|
419
1195
|
function directedEdges(snapshot) {
|
|
420
1196
|
const out = new Array(snapshot.edgeCount).fill(snapshot.directed);
|
|
421
1197
|
const col = snapshot.directed ? snapshot.edges.byRole("directed") : null;
|
|
@@ -426,37 +1202,115 @@ function directedEdges(snapshot) {
|
|
|
426
1202
|
}
|
|
427
1203
|
return out;
|
|
428
1204
|
}
|
|
1205
|
+
const SHARED_ARC_BOW = { a1: 15, k1: 0.25, a2: 15, k2: 0.25 };
|
|
1206
|
+
function sharedArcBows(snapshot, directed) {
|
|
1207
|
+
const byPair = /* @__PURE__ */ new Map();
|
|
1208
|
+
for (let e = 0; e < snapshot.edgeCount; e++) {
|
|
1209
|
+
const [u, v] = [snapshot.edgeSource(e), snapshot.edgeTarget(e)];
|
|
1210
|
+
if (directed[e] && u !== v) {
|
|
1211
|
+
const key = u < v ? `${String(u)} ${String(v)}` : `${String(v)} ${String(u)}`;
|
|
1212
|
+
byPair.set(key, [...byPair.get(key) ?? [], e]);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
const out = /* @__PURE__ */ new Map();
|
|
1216
|
+
for (const arcs of byPair.values()) {
|
|
1217
|
+
if (arcs.length < 2) {
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
for (const e of arcs) {
|
|
1221
|
+
const same = arcs.filter((x) => snapshot.edgeSource(x) === snapshot.edgeSource(e));
|
|
1222
|
+
out.set(e, (same.length - 1 - same.indexOf(e)) % 2 === 0 ? 1 : -1);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
return out;
|
|
1226
|
+
}
|
|
1227
|
+
function bowedParams(get, side) {
|
|
1228
|
+
if (Object.keys(SHARED_ARC_BOW).some((key) => get(key) !== null)) {
|
|
1229
|
+
return get;
|
|
1230
|
+
}
|
|
1231
|
+
return (key) => {
|
|
1232
|
+
const bow = SHARED_ARC_BOW[key];
|
|
1233
|
+
if (bow === void 0) {
|
|
1234
|
+
return get(key);
|
|
1235
|
+
}
|
|
1236
|
+
return key.startsWith("a") ? side * bow : bow;
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
429
1239
|
function styleColumns(table, keys) {
|
|
430
1240
|
return keys.filter((k) => table.has(k));
|
|
431
1241
|
}
|
|
432
1242
|
function pajekStyles(snapshot, context) {
|
|
433
1243
|
const notes = new StyleNotes();
|
|
1244
|
+
const { block, draw, voided } = keptOf(context.kept);
|
|
1245
|
+
const labels = drawsLineLabels(draw);
|
|
1246
|
+
const place = places(snapshot);
|
|
1247
|
+
const window = draw ?? { width: PAJEK_POINTS_PER_UNIT, height: PAJEK_POINTS_PER_UNIT };
|
|
1248
|
+
const loops = /* @__PURE__ */ new Map();
|
|
1249
|
+
const runOf = (e) => {
|
|
1250
|
+
const [s, t] = [place(snapshot.edgeSource(e)), place(snapshot.edgeTarget(e))];
|
|
1251
|
+
return s === null || t === null ? null : [(t[0] - s[0]) * window.width, (t[1] - s[1]) * window.height];
|
|
1252
|
+
};
|
|
434
1253
|
const read = (target) => {
|
|
435
1254
|
const table = target === "node" ? snapshot.nodes : snapshot.edges;
|
|
436
1255
|
const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
|
|
437
1256
|
const out = valueColumns(n);
|
|
1257
|
+
const carry = carriedParams(target === "node" ? CARRIED.node : CARRIED_LINE, target === "node");
|
|
438
1258
|
for (let i = 0; i < n; i++) {
|
|
439
1259
|
context.budget.spend(target, 1);
|
|
440
1260
|
const at = (property) => ({ notes, target, property, element: i, budget: context.budget });
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
1261
|
+
const put = (property, value) => {
|
|
1262
|
+
out.put(i, property, value);
|
|
1263
|
+
};
|
|
1264
|
+
const own = cells(table, i);
|
|
1265
|
+
const get = target === "node" && voided.has(i) ? voidedParams(own, keywords[i - 1] ?? null) : carry(own);
|
|
1266
|
+
if (target === "node") {
|
|
1267
|
+
readVertex(get, put, at, place(i));
|
|
1268
|
+
keywords[i] = get(SHAPE_COLUMN);
|
|
1269
|
+
} else {
|
|
1270
|
+
readEdge(i, get, put, at);
|
|
1271
|
+
}
|
|
448
1272
|
}
|
|
449
1273
|
return out.values;
|
|
450
1274
|
};
|
|
1275
|
+
const readEdge = (i, get, put, at) => {
|
|
1276
|
+
const run = runOf(i);
|
|
1277
|
+
const loop = run !== null && block === null && snapshot.edgeSource(i) === snapshot.edgeTarget(i) ? (controls) => {
|
|
1278
|
+
loops.set(i, controls);
|
|
1279
|
+
} : null;
|
|
1280
|
+
const bow = bows.get(i);
|
|
1281
|
+
const line = bow === void 0 ? get : bowedParams(get, bow);
|
|
1282
|
+
readLine(line, put, at, directed[i], labels, run, loop);
|
|
1283
|
+
const ported = directed[i] && run !== null && readArcEnd(line, put, run, targetSize(snapshot.edgeTarget(i)));
|
|
1284
|
+
if (directed[i] && loop === null && !ported && block === null) {
|
|
1285
|
+
readTipGap(get, put);
|
|
1286
|
+
}
|
|
1287
|
+
readLineValue(lineValue(i), get, put, directed[i]);
|
|
1288
|
+
readHooks(get, put, keywords[snapshot.edgeSource(i)], keywords[snapshot.edgeTarget(i)]);
|
|
1289
|
+
};
|
|
1290
|
+
const directed = directedEdges(snapshot);
|
|
1291
|
+
const bows = drawsStraightLines(draw) || block !== null ? /* @__PURE__ */ new Map() : sharedArcBows(snapshot, directed);
|
|
1292
|
+
const keywords = [];
|
|
1293
|
+
const weights = explicitWeights(snapshot);
|
|
1294
|
+
const lineValue = (e) => weights.isExplicit(e) ? weights.value(e) : numberOrNull(cells(snapshot.edges, e)(VALUE_COLUMN));
|
|
451
1295
|
const node = read("node");
|
|
1296
|
+
const targetSize = (v) => {
|
|
1297
|
+
const size = (property) => {
|
|
1298
|
+
const s = node[property]?.[v];
|
|
1299
|
+
return typeof s === "number" && s > 0 ? s : PAJEK_VERTEX_SIZE;
|
|
1300
|
+
};
|
|
1301
|
+
return [size("width"), size("height")];
|
|
1302
|
+
};
|
|
452
1303
|
const edge = read("edge");
|
|
453
|
-
|
|
1304
|
+
if (draw !== null) {
|
|
1305
|
+
drawVertices(draw, snapshot, node);
|
|
1306
|
+
drawLines(draw, snapshot, node, edge);
|
|
1307
|
+
}
|
|
1308
|
+
layLoops(snapshot, loops, node, edge);
|
|
454
1309
|
if (block !== null) {
|
|
455
|
-
exactFromBlock(snapshot, block, { node, edge });
|
|
1310
|
+
exactFromBlock(snapshot, block, { node, edge }, labels);
|
|
456
1311
|
}
|
|
457
1312
|
const rules = [];
|
|
458
1313
|
const columns = /* @__PURE__ */ new Map();
|
|
459
|
-
const directed = directedEdges(snapshot);
|
|
460
1314
|
if (directed.some(Boolean)) {
|
|
461
1315
|
columns.set(
|
|
462
1316
|
DIRECTED_KEY,
|
|
@@ -468,14 +1322,14 @@ function pajekStyles(snapshot, context) {
|
|
|
468
1322
|
role: "group",
|
|
469
1323
|
origin: "tool",
|
|
470
1324
|
where: { has: { style: DIRECTED_KEY } },
|
|
471
|
-
set: { targetArrow: "triangle" }
|
|
1325
|
+
set: { targetArrow: "triangle", color: ARC_DEFAULTS.color, width: ARC_DEFAULTS.width }
|
|
472
1326
|
});
|
|
473
1327
|
}
|
|
474
1328
|
return {
|
|
475
1329
|
canonical: true,
|
|
476
1330
|
dialect: "dvips",
|
|
477
1331
|
tool: "pajek",
|
|
478
|
-
units: "
|
|
1332
|
+
units: "px",
|
|
479
1333
|
node: { values: node },
|
|
480
1334
|
edge: { values: edge, rules, columns },
|
|
481
1335
|
notes: notes.list(),
|
|
@@ -486,6 +1340,39 @@ function pajekStyles(snapshot, context) {
|
|
|
486
1340
|
}
|
|
487
1341
|
};
|
|
488
1342
|
}
|
|
1343
|
+
function places(snapshot) {
|
|
1344
|
+
const col = snapshot.nodes.byRole("position");
|
|
1345
|
+
return (i) => {
|
|
1346
|
+
const v = col === null || col === void 0 ? null : col.value(i);
|
|
1347
|
+
if (v === null || typeof v !== "object" || !("length" in v)) {
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
const [x, y] = v;
|
|
1351
|
+
return typeof x === "number" && typeof y === "number" ? [x, y] : null;
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
function keptOf(kept) {
|
|
1355
|
+
if (typeof kept === "string") {
|
|
1356
|
+
return { block: kept, draw: null, voided: /* @__PURE__ */ new Set() };
|
|
1357
|
+
}
|
|
1358
|
+
if (typeof kept === "object" && kept !== null) {
|
|
1359
|
+
const { block, pajekDraw, voided } = kept;
|
|
1360
|
+
return {
|
|
1361
|
+
block: typeof block === "string" ? block : null,
|
|
1362
|
+
draw: pajekDraw ?? null,
|
|
1363
|
+
voided: new Set(voided ?? [])
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
return { block: null, draw: null, voided: /* @__PURE__ */ new Set() };
|
|
1367
|
+
}
|
|
1368
|
+
function voidedParams(own, before) {
|
|
1369
|
+
return (key) => {
|
|
1370
|
+
if (key === LABEL_COLUMN) {
|
|
1371
|
+
return own(key);
|
|
1372
|
+
}
|
|
1373
|
+
return key === SHAPE_COLUMN ? before : null;
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
489
1376
|
const SHAPES = /* @__PURE__ */ new Map([
|
|
490
1377
|
["ellipse", "ellipse"],
|
|
491
1378
|
["rectangle", "box"],
|
|
@@ -526,9 +1413,37 @@ function shapeKeyword(get, approximate) {
|
|
|
526
1413
|
if (keyword !== void 0) {
|
|
527
1414
|
return keyword;
|
|
528
1415
|
}
|
|
1416
|
+
if (shape === "polygon" && diamondQ(get) !== null) {
|
|
1417
|
+
return "diamond";
|
|
1418
|
+
}
|
|
529
1419
|
approximate("shape", shape);
|
|
1420
|
+
const points = get("shapePoints");
|
|
1421
|
+
if (shape === "polygon" && points !== null) {
|
|
1422
|
+
approximate("shapePoints", points);
|
|
1423
|
+
}
|
|
530
1424
|
return NEAREST_SHAPES.get(shape) ?? "ellipse";
|
|
531
1425
|
}
|
|
1426
|
+
function diamondQ(get) {
|
|
1427
|
+
const points = get("shapePoints");
|
|
1428
|
+
const corners = typeof points === "string" ? points.trim().split(/\s+/).map((p) => p.split(",").map(Number)) : [];
|
|
1429
|
+
if (corners.length !== 6) {
|
|
1430
|
+
return null;
|
|
1431
|
+
}
|
|
1432
|
+
const q = corners[2][0];
|
|
1433
|
+
const want = [
|
|
1434
|
+
[-1, 0],
|
|
1435
|
+
[-q, 1],
|
|
1436
|
+
[q, 1],
|
|
1437
|
+
[1, 0],
|
|
1438
|
+
[q, -1],
|
|
1439
|
+
[-q, -1]
|
|
1440
|
+
];
|
|
1441
|
+
return want.every(([x, y], k) => corners[k][0] === x && corners[k][1] === y) ? q : null;
|
|
1442
|
+
}
|
|
1443
|
+
function pajekDefault(target, property) {
|
|
1444
|
+
const values = toolDefaults("pajek")?.[target];
|
|
1445
|
+
return values?.[property]?.value;
|
|
1446
|
+
}
|
|
532
1447
|
function vertexParams(get, approximate) {
|
|
533
1448
|
const out = /* @__PURE__ */ new Map();
|
|
534
1449
|
opaque(get, ["fillOpacity", "opacity"], approximate);
|
|
@@ -536,54 +1451,114 @@ function vertexParams(get, approximate) {
|
|
|
536
1451
|
if (keyword !== "ellipse") {
|
|
537
1452
|
out.set(SHAPE_COLUMN, keyword);
|
|
538
1453
|
}
|
|
1454
|
+
const q = diamondQ(get);
|
|
1455
|
+
if (q !== null && q !== PAJEK_DIAMOND_Q) {
|
|
1456
|
+
out.set("q", q);
|
|
1457
|
+
}
|
|
1458
|
+
vertexColorParams(get, out);
|
|
1459
|
+
vertexSizeParams(get, out);
|
|
1460
|
+
const bw = get("borderWidth");
|
|
1461
|
+
if (typeof bw === "number" && bw !== pajekDefault("node", "borderWidth")) {
|
|
1462
|
+
out.set("bw", bw);
|
|
1463
|
+
}
|
|
1464
|
+
fontParam(get, out, pajekDefault("node", "labelFont"));
|
|
1465
|
+
labelPositionParams(get, out, approximate);
|
|
1466
|
+
return out;
|
|
1467
|
+
}
|
|
1468
|
+
function vertexColorParams(get, out) {
|
|
539
1469
|
const colors = [
|
|
540
1470
|
["fill", "ic"],
|
|
541
1471
|
["borderColor", "bc"],
|
|
542
1472
|
["labelColor", "lc"]
|
|
543
1473
|
];
|
|
544
|
-
const numbers = [
|
|
545
|
-
["width", "x_fact"],
|
|
546
|
-
["height", "y_fact"],
|
|
547
|
-
["labelSize", "fos"]
|
|
548
|
-
];
|
|
549
1474
|
for (const [property, key] of colors) {
|
|
550
1475
|
const v = get(property);
|
|
551
|
-
if (typeof v === "string" &&
|
|
1476
|
+
if (typeof v === "string" && v !== pajekDefault("node", property)) {
|
|
552
1477
|
out.set(key, pajekColorText(v));
|
|
553
1478
|
}
|
|
554
1479
|
}
|
|
555
|
-
|
|
1480
|
+
}
|
|
1481
|
+
function vertexSizeParams(get, out) {
|
|
1482
|
+
const numbers = [
|
|
1483
|
+
["width", "x_fact", PAJEK_VERTEX_SIZE],
|
|
1484
|
+
["height", "y_fact", PAJEK_VERTEX_SIZE],
|
|
1485
|
+
["labelSize", "fos", 1]
|
|
1486
|
+
];
|
|
1487
|
+
const figure = PAJEK_FIGURES.get(String(get("shape")));
|
|
1488
|
+
for (const [property, key, per] of numbers) {
|
|
556
1489
|
const v = get(property);
|
|
557
|
-
|
|
558
|
-
|
|
1490
|
+
let over = 1;
|
|
1491
|
+
if (figure !== void 0 && key !== "fos") {
|
|
1492
|
+
over = figure[key === "x_fact" ? 0 : 1];
|
|
1493
|
+
}
|
|
1494
|
+
if (typeof v === "number" && (over !== 1 || v !== pajekDefault("node", property))) {
|
|
1495
|
+
out.set(key, Number((v / (per * over)).toPrecision(15)));
|
|
559
1496
|
}
|
|
560
1497
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
1498
|
+
}
|
|
1499
|
+
function fontParam(get, out, skip) {
|
|
1500
|
+
const font = get("labelFont");
|
|
1501
|
+
const name = typeof font === "string" && font !== "" ? graphvizFontName(font, false, false) : null;
|
|
1502
|
+
if (name !== null && name !== skip) {
|
|
1503
|
+
out.set("font", name);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
function labelPositionParams(get, out, approximate) {
|
|
1507
|
+
const position = get("labelPosition");
|
|
1508
|
+
if (typeof position !== "string") {
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
if (position === "center") {
|
|
1512
|
+
const polar = polarOf(get);
|
|
1513
|
+
if (polar === null) {
|
|
1514
|
+
out.set("lr", 0);
|
|
1515
|
+
} else if (polar[0] !== PAJEK_LABEL_RADIUS || polar[1] !== PAJEK_LABEL_ANGLE) {
|
|
1516
|
+
out.set("lr", polar[0]);
|
|
1517
|
+
out.set("lphi", polar[1]);
|
|
568
1518
|
}
|
|
1519
|
+
return;
|
|
569
1520
|
}
|
|
570
|
-
|
|
1521
|
+
const nearest = NEAREST_SIDES.get(position);
|
|
1522
|
+
if (nearest !== void 0) {
|
|
1523
|
+
approximate("labelPosition", position);
|
|
1524
|
+
}
|
|
1525
|
+
const angle = SIDE_ANGLES.get(nearest ?? position);
|
|
1526
|
+
if (angle !== void 0 && angle !== PAJEK_LABEL_ANGLE) {
|
|
1527
|
+
out.set("lphi", angle);
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
function polarOf(get) {
|
|
1531
|
+
const [x, y, shift] = [get("labelOffsetX"), get("labelOffsetY"), get("labelShiftX")];
|
|
1532
|
+
if (typeof x !== "number" || typeof y !== "number" || shift !== 0.5) {
|
|
1533
|
+
return null;
|
|
1534
|
+
}
|
|
1535
|
+
const size = get("labelSize");
|
|
1536
|
+
const up = y + PAJEK_BASELINE_TO_MIDDLE * (typeof size === "number" ? size : PAJEK_LABEL_SIZE);
|
|
1537
|
+
const round = (v) => Number(v.toFixed(6)) + 0;
|
|
1538
|
+
const lr = round(Math.hypot(x, up));
|
|
1539
|
+
return lr === 0 ? null : [lr, round((Math.atan2(-up, x) * 180 / Math.PI % 360 + 360) % 360)];
|
|
1540
|
+
}
|
|
1541
|
+
function lineDefaults(directed) {
|
|
1542
|
+
return directed ? ARC_DEFAULTS : { color: pajekDefault("edge", "color"), width: pajekDefault("edge", "width") };
|
|
571
1543
|
}
|
|
572
1544
|
function lineParams(get, directed, approximate) {
|
|
573
1545
|
const out = /* @__PURE__ */ new Map();
|
|
574
1546
|
opaque(get, ["opacity"], approximate);
|
|
1547
|
+
const defaults = lineDefaults(directed);
|
|
575
1548
|
const color = get("color");
|
|
576
|
-
if (typeof color === "string" && color !==
|
|
1549
|
+
if (typeof color === "string" && color !== defaults.color) {
|
|
577
1550
|
out.set("c", pajekColorText(color));
|
|
578
1551
|
}
|
|
579
1552
|
const width = get("width");
|
|
580
|
-
if (typeof width === "number") {
|
|
581
|
-
out.set("w", width);
|
|
1553
|
+
if (typeof width === "number" && width !== defaults.width) {
|
|
1554
|
+
out.set("w", directed ? width : Number((width / EDGE_WIDTH_PER_W).toPrecision(15)));
|
|
582
1555
|
}
|
|
583
1556
|
const lineStyle = get("lineStyle");
|
|
584
|
-
if (typeof lineStyle === "string" && lineStyle !== "solid" && pajekDots(lineStyle, approximate)) {
|
|
1557
|
+
if (typeof lineStyle === "string" && lineStyle !== "solid" && pajekDots(lineStyle, out, directed, approximate)) {
|
|
585
1558
|
out.set("p", "Dots");
|
|
586
1559
|
}
|
|
1560
|
+
arrowParams(get, out);
|
|
1561
|
+
lineLabelParams(get, out, approximate);
|
|
587
1562
|
const target = get("targetArrow");
|
|
588
1563
|
if (target !== null && target !== (directed ? "triangle" : "none")) {
|
|
589
1564
|
approximate("targetArrow", target);
|
|
@@ -594,47 +1569,60 @@ function lineParams(get, directed, approximate) {
|
|
|
594
1569
|
}
|
|
595
1570
|
return out;
|
|
596
1571
|
}
|
|
597
|
-
function
|
|
598
|
-
|
|
599
|
-
|
|
1572
|
+
function arrowParams(get, out) {
|
|
1573
|
+
const arrowSize = get("arrowSize");
|
|
1574
|
+
if (typeof arrowSize === "number" && arrowSize !== 1) {
|
|
1575
|
+
out.set("s", arrowSize);
|
|
1576
|
+
}
|
|
1577
|
+
const position = get("arrowPosition");
|
|
1578
|
+
if (typeof position === "number" && position > 0) {
|
|
1579
|
+
out.set("ap", position);
|
|
600
1580
|
}
|
|
601
|
-
approximate("lineStyle", lineStyle);
|
|
602
|
-
return lineStyle === "dashed" || lineStyle === "dash-dot" || lineStyle === "long-dash";
|
|
603
1581
|
}
|
|
604
|
-
function
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
1582
|
+
function lineLabelParams(get, out, approximate) {
|
|
1583
|
+
const label = get("label");
|
|
1584
|
+
if (typeof label === "string" && label !== "") {
|
|
1585
|
+
const text = pajekLabelText(label);
|
|
1586
|
+
if (text !== label) {
|
|
1587
|
+
approximate("label", label);
|
|
1588
|
+
}
|
|
1589
|
+
out.set("l", text);
|
|
1590
|
+
}
|
|
1591
|
+
const labelColor = get("labelColor");
|
|
1592
|
+
if (typeof labelColor === "string") {
|
|
1593
|
+
out.set("lc", pajekColorText(labelColor));
|
|
1594
|
+
}
|
|
1595
|
+
const labelSize = get("labelSize");
|
|
1596
|
+
if (typeof labelSize === "number") {
|
|
1597
|
+
out.set("fos", labelSize);
|
|
608
1598
|
}
|
|
609
|
-
|
|
1599
|
+
fontParam(get, out);
|
|
610
1600
|
}
|
|
611
|
-
function
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
if (ex === null) {
|
|
615
|
-
return;
|
|
1601
|
+
function pajekDots(lineStyle, params, directed, approximate) {
|
|
1602
|
+
if (lineStyle === pajekDash((key) => params.get(key) ?? null, directed)) {
|
|
1603
|
+
return true;
|
|
616
1604
|
}
|
|
1605
|
+
approximate("lineStyle", lineStyle);
|
|
1606
|
+
return ["dashed", "dotted", "dash-dot", "long-dash"].includes(lineStyle);
|
|
1607
|
+
}
|
|
1608
|
+
function exactFromBlock(snapshot, text, read, labels) {
|
|
617
1609
|
const notes = new StyleNotes();
|
|
618
1610
|
const directed = directedEdges(snapshot);
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
values[property] ??= new Array(n).fill(null);
|
|
631
|
-
values[property][i] = w;
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
}
|
|
1611
|
+
takeFromBlock(snapshot, text, "pajek", (target) => ({
|
|
1612
|
+
values: read[target],
|
|
1613
|
+
properties: READ[target],
|
|
1614
|
+
writes: PAJEK_STYLE_CAPABILITIES[target],
|
|
1615
|
+
readBack: (i, want) => {
|
|
1616
|
+
const back = writtenAndReadBack(target, want, directed[i], notes, labels);
|
|
1617
|
+
return (property) => back.get(property) ?? null;
|
|
1618
|
+
},
|
|
1619
|
+
// a label the block places by a side clears the offsets its `lphi` reads back as
|
|
1620
|
+
take: (property, wanted) => wanted !== null || LABEL_PLACE.has(property) || OUTLINE.has(property)
|
|
1621
|
+
}));
|
|
636
1622
|
}
|
|
637
|
-
|
|
1623
|
+
const OUTLINE = /* @__PURE__ */ new Set(["shapePoints", "shapePointsStretch"]);
|
|
1624
|
+
const LABEL_PLACE = /* @__PURE__ */ new Set(["labelOffsetX", "labelOffsetY", "labelShiftX"]);
|
|
1625
|
+
function writtenAndReadBack(target, want, directed, notes, labels) {
|
|
638
1626
|
const ignore = () => void 0;
|
|
639
1627
|
const params = target === "node" ? vertexParams(want, ignore) : lineParams(want, directed, ignore);
|
|
640
1628
|
const back = /* @__PURE__ */ new Map();
|
|
@@ -642,15 +1630,26 @@ function writtenAndReadBack(target, want, directed, notes) {
|
|
|
642
1630
|
if (typeof label === "string") {
|
|
643
1631
|
params.set(LABEL_COLUMN, pajekLabelText(label));
|
|
644
1632
|
}
|
|
645
|
-
(target === "node"
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
);
|
|
1633
|
+
if (target === "node" && [...params.keys()].every((key) => key === LABEL_COLUMN)) {
|
|
1634
|
+
params.set(SHAPE_COLUMN, "ellipse");
|
|
1635
|
+
}
|
|
1636
|
+
for (const key of target === "edge" ? CARRIED.edge : []) {
|
|
1637
|
+
if (!params.has(key)) {
|
|
1638
|
+
params.set(key, lineRestated(key, directed));
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
const get = (key) => params.get(key) ?? null;
|
|
1642
|
+
const put = (property, value) => {
|
|
1643
|
+
if (value !== null) {
|
|
1644
|
+
back.set(property, value);
|
|
1645
|
+
}
|
|
1646
|
+
};
|
|
1647
|
+
const at = (property) => ({ notes, target, property });
|
|
1648
|
+
if (target === "node") {
|
|
1649
|
+
readVertex(get, put, at);
|
|
1650
|
+
} else {
|
|
1651
|
+
readLine(get, put, at, directed, labels);
|
|
1652
|
+
}
|
|
654
1653
|
return back;
|
|
655
1654
|
}
|
|
656
1655
|
function pajekStyledExport(snapshot, input) {
|
|
@@ -665,14 +1664,15 @@ function pajekStyledExport(snapshot, input) {
|
|
|
665
1664
|
const approximate = (property, value) => {
|
|
666
1665
|
approximated.add(target, property, value);
|
|
667
1666
|
};
|
|
668
|
-
const get =
|
|
1667
|
+
const get = elementValues((t, p) => input.picture(t, p), target, PAJEK_STYLE_CAPABILITIES[target]);
|
|
669
1668
|
const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
|
|
670
1669
|
const params = (i) => target === "node" ? vertexParams(get(i), approximate) : lineParams(get(i), directed[i], approximate);
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
);
|
|
1670
|
+
const columns = paramColumns(n, params);
|
|
1671
|
+
if (target === "edge") {
|
|
1672
|
+
keepLineLabels(snapshot, columns);
|
|
1673
|
+
}
|
|
1674
|
+
restateCarried(target, columns, directed);
|
|
1675
|
+
replaceParamColumns(table, target === "node" ? [SHAPE_COLUMN, ...NODE_KEYS] : EDGE_KEYS, columns);
|
|
676
1676
|
}
|
|
677
1677
|
out.nodes.set(
|
|
678
1678
|
LABEL_COLUMN,
|
|
@@ -687,6 +1687,23 @@ function pajekStyledExport(snapshot, input) {
|
|
|
687
1687
|
notes.push(...styleBlockLosses(block, input.rules.styles.rules.length, "size"));
|
|
688
1688
|
return { snapshot: out, comment: PAJEK_STYLE_COMMENT + block, notes };
|
|
689
1689
|
}
|
|
1690
|
+
function keepLineLabels(snapshot, columns) {
|
|
1691
|
+
if (!snapshot.edges.has("l")) {
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
const own = (e) => plainCell(snapshot.edges.value("l", e));
|
|
1695
|
+
let col = columns.get("l");
|
|
1696
|
+
for (let e = 0; e < snapshot.edgeCount; e++) {
|
|
1697
|
+
const v = own(e);
|
|
1698
|
+
if (typeof v === "string" && v !== "" && (col?.[e] ?? null) === null) {
|
|
1699
|
+
col ??= new Array(snapshot.edgeCount).fill(null);
|
|
1700
|
+
col[e] = pajekLabelText(v);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
if (col !== void 0) {
|
|
1704
|
+
columns.set("l", col);
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
690
1707
|
function drawnLabels(input, n, approximated) {
|
|
691
1708
|
const drawn = input.picture("node", "label");
|
|
692
1709
|
const out = new Array(n).fill("");
|
|
@@ -715,6 +1732,47 @@ function replaceParamColumns(table, keys, columns) {
|
|
|
715
1732
|
table.set(key, col, { dtype: numeric ? "f64" : "string" });
|
|
716
1733
|
}
|
|
717
1734
|
}
|
|
1735
|
+
function restateCarried(target, columns, directed) {
|
|
1736
|
+
if (target === "node") {
|
|
1737
|
+
const all = [...columns.values()];
|
|
1738
|
+
if (all.length === 0) {
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1741
|
+
const n = all[0].length;
|
|
1742
|
+
const shape = columns.get(SHAPE_COLUMN) ?? new Array(n).fill(null);
|
|
1743
|
+
for (let i = 0; i < n; i++) {
|
|
1744
|
+
if (all.every((col) => col[i] === null)) {
|
|
1745
|
+
shape[i] = "ellipse";
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
columns.set(SHAPE_COLUMN, shape);
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1751
|
+
for (const key of CARRIED.edge) {
|
|
1752
|
+
const col = columns.get(key);
|
|
1753
|
+
if (col === void 0) {
|
|
1754
|
+
continue;
|
|
1755
|
+
}
|
|
1756
|
+
for (let i = 0; i < col.length; i++) {
|
|
1757
|
+
col[i] ??= lineRestated(key, directed[i]);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
function lineRestated(key, directed) {
|
|
1762
|
+
const defaults = lineDefaults(directed);
|
|
1763
|
+
switch (key) {
|
|
1764
|
+
case "c":
|
|
1765
|
+
return pajekColorText(String(defaults.color));
|
|
1766
|
+
case "w":
|
|
1767
|
+
return directed ? Number(defaults.width) : Number(defaults.width) / EDGE_WIDTH_PER_W;
|
|
1768
|
+
case "p":
|
|
1769
|
+
return "Solid";
|
|
1770
|
+
case "s":
|
|
1771
|
+
return 1;
|
|
1772
|
+
default:
|
|
1773
|
+
return 0;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
718
1776
|
function paramColumns(n, params) {
|
|
719
1777
|
const columns = /* @__PURE__ */ new Map();
|
|
720
1778
|
for (let i = 0; i < n; i++) {
|
|
@@ -815,58 +1873,58 @@ const CAPABILITIES = capabilities({
|
|
|
815
1873
|
});
|
|
816
1874
|
function plan(table, domain, notes) {
|
|
817
1875
|
const planned = [];
|
|
818
|
-
for (const
|
|
819
|
-
const slot = columnSlot(
|
|
1876
|
+
for (const column2 of table) {
|
|
1877
|
+
const slot = columnSlot(column2, domain, notes);
|
|
820
1878
|
if (slot !== null) {
|
|
821
|
-
planned.push({ column, slot });
|
|
1879
|
+
planned.push({ column: column2, slot });
|
|
822
1880
|
}
|
|
823
1881
|
}
|
|
824
1882
|
return planned;
|
|
825
1883
|
}
|
|
826
|
-
function columnNote(notes, code, message,
|
|
827
|
-
notes?.push(note(code, message,
|
|
1884
|
+
function columnNote(notes, code, message, column2) {
|
|
1885
|
+
notes?.push(note(code, message, column2.meta.name, column2.length - column2.nullCount));
|
|
828
1886
|
}
|
|
829
|
-
function columnSlot(
|
|
830
|
-
const { role, name } =
|
|
1887
|
+
function columnSlot(column2, domain, notes) {
|
|
1888
|
+
const { role, name } = column2.meta;
|
|
831
1889
|
if (role === "label" && domain === "node") {
|
|
832
|
-
return labelSlot(
|
|
1890
|
+
return labelSlot(column2, notes);
|
|
833
1891
|
}
|
|
834
1892
|
if (role === "position") {
|
|
835
|
-
return positionSlot(
|
|
1893
|
+
return positionSlot(column2, domain, notes);
|
|
836
1894
|
}
|
|
837
1895
|
if (role === "spells") {
|
|
838
|
-
return spellsSlot(
|
|
1896
|
+
return spellsSlot(column2, domain, notes);
|
|
839
1897
|
}
|
|
840
1898
|
if (role !== null && DROPPED_TEMPORAL_ROLES.has(role)) {
|
|
841
1899
|
columnNote(
|
|
842
1900
|
notes,
|
|
843
1901
|
PAJEK_LOSS.TEMPORAL_DROPPED,
|
|
844
1902
|
`${domain} column "${name}" (${role}) cannot be written; Pajek intervals come from the spells role`,
|
|
845
|
-
|
|
1903
|
+
column2
|
|
846
1904
|
);
|
|
847
1905
|
return null;
|
|
848
1906
|
}
|
|
849
|
-
if (writtenElsewhere(
|
|
1907
|
+
if (writtenElsewhere(column2, domain)) {
|
|
850
1908
|
return null;
|
|
851
1909
|
}
|
|
852
|
-
return namedSlot(
|
|
1910
|
+
return namedSlot(column2, domain, notes);
|
|
853
1911
|
}
|
|
854
|
-
function labelSlot(
|
|
855
|
-
const { name, dtype } =
|
|
1912
|
+
function labelSlot(column2, notes) {
|
|
1913
|
+
const { name, dtype } = column2.meta;
|
|
856
1914
|
if (dtype !== "string" && dtype !== "dict") {
|
|
857
1915
|
columnNote(
|
|
858
1916
|
notes,
|
|
859
1917
|
PAJEK_LOSS.LABEL_AS_TEXT,
|
|
860
1918
|
`node column "${name}" (label) is ${dtype}; labels are text and re-import as string`,
|
|
861
|
-
|
|
1919
|
+
column2
|
|
862
1920
|
);
|
|
863
1921
|
}
|
|
864
1922
|
return "label";
|
|
865
1923
|
}
|
|
866
|
-
function positionSlot(
|
|
867
|
-
const { name, components } =
|
|
1924
|
+
function positionSlot(column2, domain, notes) {
|
|
1925
|
+
const { name, components } = column2.meta;
|
|
868
1926
|
if (domain === "edge") {
|
|
869
|
-
columnNote(notes, LOSS.POSITIONS, `edge column "${name}" (position) cannot be written`,
|
|
1927
|
+
columnNote(notes, LOSS.POSITIONS, `edge column "${name}" (position) cannot be written`, column2);
|
|
870
1928
|
return null;
|
|
871
1929
|
}
|
|
872
1930
|
if (components === 2 || components === 3) {
|
|
@@ -876,12 +1934,12 @@ function positionSlot(column, domain, notes) {
|
|
|
876
1934
|
notes,
|
|
877
1935
|
PAJEK_LOSS.POSITION_STRIDE,
|
|
878
1936
|
`node column "${name}" (position) has ${components} components; Pajek coordinates are x y [z]`,
|
|
879
|
-
|
|
1937
|
+
column2
|
|
880
1938
|
);
|
|
881
1939
|
return null;
|
|
882
1940
|
}
|
|
883
|
-
function spellsSlot(
|
|
884
|
-
const { name, dtype, itemDtype } =
|
|
1941
|
+
function spellsSlot(column2, domain, notes) {
|
|
1942
|
+
const { name, dtype, itemDtype } = column2.meta;
|
|
885
1943
|
if (dtype === "list" && (itemDtype === "f64" || itemDtype === "i32" || itemDtype === "f32")) {
|
|
886
1944
|
return "spells";
|
|
887
1945
|
}
|
|
@@ -889,22 +1947,22 @@ function spellsSlot(column, domain, notes) {
|
|
|
889
1947
|
notes,
|
|
890
1948
|
LOSS.SPELLS,
|
|
891
1949
|
`${domain} column "${name}" (spells) is not a list of number pairs; it cannot be written`,
|
|
892
|
-
|
|
1950
|
+
column2
|
|
893
1951
|
);
|
|
894
1952
|
return null;
|
|
895
1953
|
}
|
|
896
|
-
function writtenElsewhere(
|
|
897
|
-
const { role, dtype } =
|
|
1954
|
+
function writtenElsewhere(column2, domain) {
|
|
1955
|
+
const { role, dtype } = column2.meta;
|
|
898
1956
|
if (role !== null && (STRUCTURAL_ROLES.has(role) || CHECKED_ROLES.has(role))) {
|
|
899
1957
|
return true;
|
|
900
1958
|
}
|
|
901
1959
|
return domain === "edge" && role === "id" || dtype === "list" || dtype === "json";
|
|
902
1960
|
}
|
|
903
|
-
function namedSlot(
|
|
904
|
-
const { name, dtype } =
|
|
1961
|
+
function namedSlot(column2, domain, notes) {
|
|
1962
|
+
const { name, dtype } = column2.meta;
|
|
905
1963
|
const text = dtype === "dict" || dtype === "string";
|
|
906
1964
|
if (text && domain === "node" && name === SHAPE_COLUMN) {
|
|
907
|
-
return shapeSlot(
|
|
1965
|
+
return shapeSlot(column2, notes);
|
|
908
1966
|
}
|
|
909
1967
|
if (text && domain === "edge" && name === RELATION_COLUMN) {
|
|
910
1968
|
return "relation";
|
|
@@ -914,22 +1972,22 @@ function namedSlot(column, domain, notes) {
|
|
|
914
1972
|
notes,
|
|
915
1973
|
PAJEK_LOSS.KEY_DROPPED,
|
|
916
1974
|
`${domain} column "${name}" cannot be a Pajek parameter key; it is not written`,
|
|
917
|
-
|
|
1975
|
+
column2
|
|
918
1976
|
);
|
|
919
1977
|
return null;
|
|
920
1978
|
}
|
|
921
1979
|
return "param";
|
|
922
1980
|
}
|
|
923
|
-
function shapeSlot(
|
|
924
|
-
if (allShapeKeywords(
|
|
1981
|
+
function shapeSlot(column2, notes) {
|
|
1982
|
+
if (allShapeKeywords(column2)) {
|
|
925
1983
|
return "shape";
|
|
926
1984
|
}
|
|
927
|
-
if (
|
|
1985
|
+
if (column2.meta.dtype === "dict") {
|
|
928
1986
|
columnNote(
|
|
929
1987
|
notes,
|
|
930
1988
|
PAJEK_LOSS.SHAPE_AS_PARAMETER,
|
|
931
|
-
`node column "${
|
|
932
|
-
|
|
1989
|
+
`node column "${column2.meta.name}" holds values outside the Pajek shape keywords; it is written as a parameter and reads back as string`,
|
|
1990
|
+
column2
|
|
933
1991
|
);
|
|
934
1992
|
}
|
|
935
1993
|
return "param";
|
|
@@ -937,9 +1995,9 @@ function shapeSlot(column, notes) {
|
|
|
937
1995
|
function labelNotes(snapshot, nodePlan, notes) {
|
|
938
1996
|
let labels = null;
|
|
939
1997
|
let carried = 0;
|
|
940
|
-
for (const { column, slot } of nodePlan) {
|
|
1998
|
+
for (const { column: column2, slot } of nodePlan) {
|
|
941
1999
|
if (slot === "label") {
|
|
942
|
-
labels =
|
|
2000
|
+
labels = column2;
|
|
943
2001
|
} else if (slot !== "skip" && slot !== "relation") {
|
|
944
2002
|
carried++;
|
|
945
2003
|
}
|
|
@@ -986,16 +2044,16 @@ function unlabeled(nodeCount, labels) {
|
|
|
986
2044
|
}
|
|
987
2045
|
return count;
|
|
988
2046
|
}
|
|
989
|
-
function allShapeKeywords(
|
|
990
|
-
for (let r = 0; r <
|
|
991
|
-
if (
|
|
2047
|
+
function allShapeKeywords(column2) {
|
|
2048
|
+
for (let r = 0; r < column2.length; r++) {
|
|
2049
|
+
if (column2.isSet(r) && !SHAPES$1.has(column2.value(r))) {
|
|
992
2050
|
return false;
|
|
993
2051
|
}
|
|
994
2052
|
}
|
|
995
2053
|
return true;
|
|
996
2054
|
}
|
|
997
|
-
function note(code, message,
|
|
998
|
-
return Object.freeze({ code, message, column, count });
|
|
2055
|
+
function note(code, message, column2 = null, count = null) {
|
|
2056
|
+
return Object.freeze({ code, message, column: column2, count });
|
|
999
2057
|
}
|
|
1000
2058
|
function numberText(value, dtype) {
|
|
1001
2059
|
switch (dtype) {
|
|
@@ -1013,53 +2071,53 @@ function numberText(value, dtype) {
|
|
|
1013
2071
|
}
|
|
1014
2072
|
}
|
|
1015
2073
|
}
|
|
1016
|
-
function cellText(
|
|
1017
|
-
switch (
|
|
2074
|
+
function cellText(column2, row) {
|
|
2075
|
+
switch (column2.dtype) {
|
|
1018
2076
|
case "f32":
|
|
1019
2077
|
case "f64":
|
|
1020
2078
|
case "i32":
|
|
1021
2079
|
case "u32":
|
|
1022
2080
|
case "u8": {
|
|
1023
|
-
const value =
|
|
2081
|
+
const value = column2.value(row);
|
|
1024
2082
|
if (typeof value === "number") {
|
|
1025
|
-
return numberText(value,
|
|
2083
|
+
return numberText(value, column2.dtype);
|
|
1026
2084
|
}
|
|
1027
2085
|
const parts = [];
|
|
1028
2086
|
const vector = value;
|
|
1029
2087
|
for (let k = 0; k < vector.length; k++) {
|
|
1030
|
-
parts.push(numberText(vector[k],
|
|
2088
|
+
parts.push(numberText(vector[k], column2.dtype));
|
|
1031
2089
|
}
|
|
1032
2090
|
return parts.join(" ");
|
|
1033
2091
|
}
|
|
1034
2092
|
case "bool":
|
|
1035
|
-
return
|
|
2093
|
+
return column2.value(row) === true ? "true" : "false";
|
|
1036
2094
|
case "dict":
|
|
1037
2095
|
case "string":
|
|
1038
|
-
return
|
|
2096
|
+
return column2.value(row);
|
|
1039
2097
|
case "list":
|
|
1040
2098
|
case "json":
|
|
1041
|
-
return JSON.stringify(
|
|
2099
|
+
return JSON.stringify(column2.value(row));
|
|
1042
2100
|
default: {
|
|
1043
|
-
const name =
|
|
2101
|
+
const name = column2.dtype;
|
|
1044
2102
|
throw new Error(`unknown dtype ${name}`);
|
|
1045
2103
|
}
|
|
1046
2104
|
}
|
|
1047
2105
|
}
|
|
1048
2106
|
function checkCells(planned, domain, notes) {
|
|
1049
|
-
for (const { column, slot } of planned) {
|
|
2107
|
+
for (const { column: column2, slot } of planned) {
|
|
1050
2108
|
if (slot === "position" || slot === "spells") {
|
|
1051
2109
|
continue;
|
|
1052
2110
|
}
|
|
1053
|
-
const { name } =
|
|
2111
|
+
const { name } = column2.meta;
|
|
1054
2112
|
let badText = 0;
|
|
1055
2113
|
let nonFinite = 0;
|
|
1056
2114
|
let typed = 0;
|
|
1057
|
-
for (let r = 0; r <
|
|
1058
|
-
if (!
|
|
2115
|
+
for (let r = 0; r < column2.length; r++) {
|
|
2116
|
+
if (!column2.isSet(r)) {
|
|
1059
2117
|
continue;
|
|
1060
2118
|
}
|
|
1061
|
-
if (
|
|
1062
|
-
const value =
|
|
2119
|
+
if (column2.dtype === "f64" || column2.dtype === "f32") {
|
|
2120
|
+
const value = column2.value(r);
|
|
1063
2121
|
if (typeof value === "number") {
|
|
1064
2122
|
if (!Number.isFinite(value)) {
|
|
1065
2123
|
nonFinite++;
|
|
@@ -1067,8 +2125,8 @@ function checkCells(planned, domain, notes) {
|
|
|
1067
2125
|
} else if (value !== void 0 && !Array.from(value).every((v) => Number.isFinite(v))) {
|
|
1068
2126
|
nonFinite++;
|
|
1069
2127
|
}
|
|
1070
|
-
} else if (
|
|
1071
|
-
const text =
|
|
2128
|
+
} else if (column2.dtype === "string" || column2.dtype === "dict") {
|
|
2129
|
+
const text = column2.value(r);
|
|
1072
2130
|
if (!isPajekLabel(text)) {
|
|
1073
2131
|
badText++;
|
|
1074
2132
|
} else if (slot === "param" && inferTextDtype(text) !== "string") {
|
|
@@ -1131,11 +2189,11 @@ function labelOf(labels, ids, i, needed) {
|
|
|
1131
2189
|
}
|
|
1132
2190
|
return null;
|
|
1133
2191
|
}
|
|
1134
|
-
function spellsText(
|
|
1135
|
-
if (
|
|
2192
|
+
function spellsText(column2, row) {
|
|
2193
|
+
if (column2.dtype !== "list" || !column2.isSet(row)) {
|
|
1136
2194
|
return null;
|
|
1137
2195
|
}
|
|
1138
|
-
const items =
|
|
2196
|
+
const items = column2.sliceOf(row);
|
|
1139
2197
|
if (items.length === 0) {
|
|
1140
2198
|
return null;
|
|
1141
2199
|
}
|
|
@@ -1146,29 +2204,29 @@ function spellsText(column, row) {
|
|
|
1146
2204
|
}
|
|
1147
2205
|
return formatIntervals(pairs);
|
|
1148
2206
|
}
|
|
1149
|
-
function coordinatesText(
|
|
1150
|
-
if (!
|
|
2207
|
+
function coordinatesText(column2, i, writeZ) {
|
|
2208
|
+
if (!column2.isSet(i)) {
|
|
1151
2209
|
return null;
|
|
1152
2210
|
}
|
|
1153
|
-
const dtype =
|
|
1154
|
-
const vector =
|
|
2211
|
+
const dtype = column2.dtype;
|
|
2212
|
+
const vector = column2.value(i);
|
|
1155
2213
|
const x = formatNumber(vector[0], dtype);
|
|
1156
2214
|
const y = formatNumber(vector[1], dtype);
|
|
1157
|
-
if (
|
|
2215
|
+
if (column2.meta.components === 3 && writeZ) {
|
|
1158
2216
|
return `${x} ${y} ${formatNumber(vector[2], dtype)}`;
|
|
1159
2217
|
}
|
|
1160
2218
|
return `${x} ${y}`;
|
|
1161
2219
|
}
|
|
1162
|
-
function needsZ(
|
|
1163
|
-
if (
|
|
2220
|
+
function needsZ(column2) {
|
|
2221
|
+
if (column2.meta.components !== 3) {
|
|
1164
2222
|
return false;
|
|
1165
2223
|
}
|
|
1166
|
-
if (
|
|
2224
|
+
if (column2.meta.extra.sourceDims !== 2) {
|
|
1167
2225
|
return true;
|
|
1168
2226
|
}
|
|
1169
|
-
for (let i = 0; i <
|
|
1170
|
-
if (
|
|
1171
|
-
const vector =
|
|
2227
|
+
for (let i = 0; i < column2.length; i++) {
|
|
2228
|
+
if (column2.isSet(i)) {
|
|
2229
|
+
const vector = column2.value(i);
|
|
1172
2230
|
if (vector[2] !== 0) {
|
|
1173
2231
|
return true;
|
|
1174
2232
|
}
|
|
@@ -1251,27 +2309,49 @@ function checkIdTexts(nodeCount, ids, mangle, notes) {
|
|
|
1251
2309
|
}
|
|
1252
2310
|
}
|
|
1253
2311
|
function* writeVertices(snapshot, ids, nodePlan, mangle) {
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
let
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
2312
|
+
const slots = vertexSlots(nodePlan);
|
|
2313
|
+
const writeZ = slots.position !== null && needsZ(slots.position);
|
|
2314
|
+
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
2315
|
+
const parts = vertexParts(slots, i, writeZ);
|
|
2316
|
+
if (mangle && ids.isChanged(i)) {
|
|
2317
|
+
parts.push(`${ORIGINAL_ID_KEY} ${quotePajekLabel(idText(ids.originalAt(i)))}`);
|
|
2318
|
+
}
|
|
2319
|
+
if (slots.spells !== null) {
|
|
2320
|
+
const spells = spellsText(slots.spells, i);
|
|
2321
|
+
if (spells !== null) {
|
|
2322
|
+
parts.push(spells);
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
const label = labelOf(slots.labels, ids, i, parts.length > 0);
|
|
2326
|
+
let line = String(i + 1);
|
|
2327
|
+
if (label !== null) {
|
|
2328
|
+
line += ` ${quotePajekLabel(encodeCharacterReferences(label))}`;
|
|
2329
|
+
}
|
|
2330
|
+
if (parts.length > 0) {
|
|
2331
|
+
line += ` ${parts.join(" ")}`;
|
|
2332
|
+
}
|
|
2333
|
+
yield `${line}
|
|
2334
|
+
`;
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
function vertexSlots(nodePlan) {
|
|
2338
|
+
const slots = { labels: null, position: null, shape: null, spells: null, params: [] };
|
|
2339
|
+
for (const { column: column2, slot } of nodePlan) {
|
|
1260
2340
|
switch (slot) {
|
|
1261
2341
|
case "label":
|
|
1262
|
-
labels =
|
|
2342
|
+
slots.labels = column2;
|
|
1263
2343
|
break;
|
|
1264
2344
|
case "position":
|
|
1265
|
-
position =
|
|
2345
|
+
slots.position = column2;
|
|
1266
2346
|
break;
|
|
1267
2347
|
case "shape":
|
|
1268
|
-
shape =
|
|
2348
|
+
slots.shape = column2;
|
|
1269
2349
|
break;
|
|
1270
2350
|
case "spells":
|
|
1271
|
-
|
|
2351
|
+
slots.spells = column2;
|
|
1272
2352
|
break;
|
|
1273
2353
|
case "param":
|
|
1274
|
-
|
|
2354
|
+
slots.params.push(column2);
|
|
1275
2355
|
break;
|
|
1276
2356
|
case "relation":
|
|
1277
2357
|
case "skip":
|
|
@@ -1282,48 +2362,32 @@ function* writeVertices(snapshot, ids, nodePlan, mangle) {
|
|
|
1282
2362
|
}
|
|
1283
2363
|
}
|
|
1284
2364
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
parts.push(`${column.meta.name} ${quotePajekLabel(cellText(column, i))}`);
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
if (mangle && ids.isChanged(i)) {
|
|
1308
|
-
parts.push(`${ORIGINAL_ID_KEY} ${quotePajekLabel(idText(ids.originalAt(i)))}`);
|
|
1309
|
-
}
|
|
1310
|
-
if (nodeSpells !== null) {
|
|
1311
|
-
const spells = spellsText(nodeSpells, i);
|
|
1312
|
-
if (spells !== null) {
|
|
1313
|
-
parts.push(spells);
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
const label = labelOf(labels, ids, i, parts.length > 0);
|
|
1317
|
-
let line = String(i + 1);
|
|
1318
|
-
if (label !== null) {
|
|
1319
|
-
line += ` ${quotePajekLabel(encodeCharacterReferences(label))}`;
|
|
2365
|
+
return slots;
|
|
2366
|
+
}
|
|
2367
|
+
function vertexParts(slots, i, writeZ) {
|
|
2368
|
+
const { position, shape } = slots;
|
|
2369
|
+
const parts = [];
|
|
2370
|
+
const coordinates = position === null ? null : coordinatesText(position, i, writeZ);
|
|
2371
|
+
if (coordinates !== null) {
|
|
2372
|
+
parts.push(coordinates);
|
|
2373
|
+
}
|
|
2374
|
+
const placed = parts.length > 0;
|
|
2375
|
+
const shaped = shape?.isSet(i) === true;
|
|
2376
|
+
if (shaped) {
|
|
2377
|
+
const keyword = cellText(shape, i);
|
|
2378
|
+
parts.push(SHAPES$1.has(keyword) ? keyword : `${SHAPE_COLUMN} ${quotePajekLabel(keyword)}`);
|
|
2379
|
+
}
|
|
2380
|
+
const named = parts.length;
|
|
2381
|
+
for (const column2 of slots.params) {
|
|
2382
|
+
if (!column2.isSet(i)) {
|
|
2383
|
+
continue;
|
|
1320
2384
|
}
|
|
1321
|
-
if (parts.length
|
|
1322
|
-
|
|
2385
|
+
if (placed && !shaped && parts.length === named && VOIDING_KEYS.has(column2.meta.name)) {
|
|
2386
|
+
parts.push("ellipse");
|
|
1323
2387
|
}
|
|
1324
|
-
|
|
1325
|
-
`;
|
|
2388
|
+
parts.push(`${column2.meta.name} ${quotePajekLabel(cellText(column2, i))}`);
|
|
1326
2389
|
}
|
|
2390
|
+
return parts;
|
|
1327
2391
|
}
|
|
1328
2392
|
function* writeLines(snapshot, edgePlan) {
|
|
1329
2393
|
const folding = pairFolding(snapshot, { foldMutual: true });
|
|
@@ -1332,16 +2396,16 @@ function* writeLines(snapshot, edgePlan) {
|
|
|
1332
2396
|
let relation = null;
|
|
1333
2397
|
let edgeSpells = null;
|
|
1334
2398
|
const edgeParams = [];
|
|
1335
|
-
for (const { column, slot } of edgePlan) {
|
|
2399
|
+
for (const { column: column2, slot } of edgePlan) {
|
|
1336
2400
|
switch (slot) {
|
|
1337
2401
|
case "relation":
|
|
1338
|
-
relation =
|
|
2402
|
+
relation = column2;
|
|
1339
2403
|
break;
|
|
1340
2404
|
case "spells":
|
|
1341
|
-
edgeSpells =
|
|
2405
|
+
edgeSpells = column2;
|
|
1342
2406
|
break;
|
|
1343
2407
|
case "param":
|
|
1344
|
-
edgeParams.push(
|
|
2408
|
+
edgeParams.push(column2);
|
|
1345
2409
|
break;
|
|
1346
2410
|
case "label":
|
|
1347
2411
|
case "position":
|
|
@@ -1388,9 +2452,9 @@ function* writeLines(snapshot, edgePlan) {
|
|
|
1388
2452
|
if (weight !== null) {
|
|
1389
2453
|
line += ` ${weight}`;
|
|
1390
2454
|
}
|
|
1391
|
-
for (const
|
|
1392
|
-
if (
|
|
1393
|
-
line += ` ${
|
|
2455
|
+
for (const column2 of edgeParams) {
|
|
2456
|
+
if (column2.isSet(e)) {
|
|
2457
|
+
line += ` ${column2.meta.name} ${quotePajekLabel(cellText(column2, e))}`;
|
|
1394
2458
|
}
|
|
1395
2459
|
}
|
|
1396
2460
|
if (edgeSpells !== null) {
|
|
@@ -1478,16 +2542,16 @@ function withOriginalIds(options) {
|
|
|
1478
2542
|
}
|
|
1479
2543
|
function ownedColumns(snapshot, planned) {
|
|
1480
2544
|
const owned = /* @__PURE__ */ new Set();
|
|
1481
|
-
const key = (
|
|
1482
|
-
for (const { column, slot } of planned) {
|
|
1483
|
-
const shapeParam = slot === "param" &&
|
|
2545
|
+
const key = (column2) => `${column2.meta.domain}:${column2.meta.name}`;
|
|
2546
|
+
for (const { column: column2, slot } of planned) {
|
|
2547
|
+
const shapeParam = slot === "param" && column2.meta.domain === "node" && column2.meta.name === SHAPE_COLUMN;
|
|
1484
2548
|
if (slot === "shape" || slot === "relation" || shapeParam) {
|
|
1485
|
-
owned.add(key(
|
|
2549
|
+
owned.add(key(column2));
|
|
1486
2550
|
}
|
|
1487
2551
|
}
|
|
1488
|
-
for (const
|
|
1489
|
-
if (
|
|
1490
|
-
owned.add(key(
|
|
2552
|
+
for (const column2 of [...snapshot.nodes, ...snapshot.edges]) {
|
|
2553
|
+
if (column2.meta.role === "spells") {
|
|
2554
|
+
owned.add(key(column2));
|
|
1491
2555
|
}
|
|
1492
2556
|
}
|
|
1493
2557
|
return owned;
|
|
@@ -1530,13 +2594,13 @@ function checkPlain(snapshot, options) {
|
|
|
1530
2594
|
const owned = ownedColumns(snapshot, [...nodePlan, ...edgePlan]);
|
|
1531
2595
|
notes.push(...capabilityNotes(snapshot, resolved, owned));
|
|
1532
2596
|
labelNotes(snapshot, nodePlan, notes);
|
|
1533
|
-
for (const
|
|
2597
|
+
for (const column2 of [...snapshot.edges].filter((c) => c.meta.role === "label")) {
|
|
1534
2598
|
notes.push(
|
|
1535
2599
|
note(
|
|
1536
2600
|
LOSS.ROLE,
|
|
1537
|
-
`edge column "${
|
|
1538
|
-
|
|
1539
|
-
|
|
2601
|
+
`edge column "${column2.meta.name}" (label) is written as a plain parameter; Pajek labels vertices only and the role is lost`,
|
|
2602
|
+
column2.meta.name,
|
|
2603
|
+
column2.length - column2.nullCount
|
|
1540
2604
|
)
|
|
1541
2605
|
);
|
|
1542
2606
|
}
|
|
@@ -1731,7 +2795,7 @@ function spellsDecl() {
|
|
|
1731
2795
|
origin: { format: "pajek", id: "interval" }
|
|
1732
2796
|
};
|
|
1733
2797
|
}
|
|
1734
|
-
function positionDecl(sourceDims) {
|
|
2798
|
+
function positionDecl(sourceDims, window) {
|
|
1735
2799
|
return {
|
|
1736
2800
|
name: POSITION_COLUMN,
|
|
1737
2801
|
dtype: "f64",
|
|
@@ -1740,10 +2804,21 @@ function positionDecl(sourceDims) {
|
|
|
1740
2804
|
role: "position",
|
|
1741
2805
|
origin: { format: "pajek", id: "coordinates" },
|
|
1742
2806
|
// Pajek draws y downward (USAir97.net has Deadhorse, Alaska at y 0.10 and Miami at 0.53),
|
|
1743
|
-
// centers depth on 0.5, and NetworkX writes "0.0 0.0" for a node with no position
|
|
1744
|
-
|
|
2807
|
+
// centers depth on 0.5, and NetworkX writes "0.0 0.0" for a node with no position; one unit
|
|
2808
|
+
// is the Draw window's width in points across and its height down (500 each by default,
|
|
2809
|
+
// PAJEK_POINTS_PER_UNIT): Pajek stretches 0..1 to the window one axis at a time
|
|
2810
|
+
extra: {
|
|
2811
|
+
sourceDims,
|
|
2812
|
+
units: "file",
|
|
2813
|
+
pxPerUnit: window.width,
|
|
2814
|
+
...window.height === window.width ? {} : { pxPerUnitY: window.height },
|
|
2815
|
+
yAxis: "down",
|
|
2816
|
+
zOrigin: 0.5,
|
|
2817
|
+
zeroUnplaced: true
|
|
2818
|
+
}
|
|
1745
2819
|
};
|
|
1746
2820
|
}
|
|
2821
|
+
const DEFAULT_WINDOW = { width: PAJEK_POINTS_PER_UNIT, height: PAJEK_POINTS_PER_UNIT };
|
|
1747
2822
|
class LineError extends Error {
|
|
1748
2823
|
/**
|
|
1749
2824
|
* Create a line error.
|
|
@@ -1770,8 +2845,11 @@ class PajekParser {
|
|
|
1770
2845
|
* @param report - the report
|
|
1771
2846
|
* @param options - the resolved common options
|
|
1772
2847
|
* @param firstVertex - the firstVertex format option
|
|
2848
|
+
* @param window - the Draw window the coordinates are stretched to
|
|
1773
2849
|
*/
|
|
1774
|
-
constructor(sink, report, options, firstVertex) {
|
|
2850
|
+
constructor(sink, report, options, firstVertex, window = DEFAULT_WINDOW) {
|
|
2851
|
+
this.keptBlock = null;
|
|
2852
|
+
this.voided = [];
|
|
1775
2853
|
this.section = "none";
|
|
1776
2854
|
this.kind = "directed";
|
|
1777
2855
|
this.relation = null;
|
|
@@ -1808,6 +2886,7 @@ class PajekParser {
|
|
|
1808
2886
|
this.ended = false;
|
|
1809
2887
|
this.edgeParams = /* @__PURE__ */ new Map();
|
|
1810
2888
|
this.styleBlockKept = false;
|
|
2889
|
+
this.window = window;
|
|
1811
2890
|
this.sink = sink;
|
|
1812
2891
|
this.report = report;
|
|
1813
2892
|
this.options = options;
|
|
@@ -1827,7 +2906,8 @@ class PajekParser {
|
|
|
1827
2906
|
const trimmed = text.trimStart();
|
|
1828
2907
|
if (trimmed.startsWith(PAJEK_STYLE_COMMENT)) {
|
|
1829
2908
|
this.styleBlockKept = true;
|
|
1830
|
-
this.
|
|
2909
|
+
this.keptBlock = trimmed.slice(PAJEK_STYLE_COMMENT.length);
|
|
2910
|
+
this.report.keepForStyles(this.keptBlock);
|
|
1831
2911
|
}
|
|
1832
2912
|
}
|
|
1833
2913
|
/**
|
|
@@ -2290,6 +3370,55 @@ class PajekParser {
|
|
|
2290
3370
|
*/
|
|
2291
3371
|
vertexLine(text, line) {
|
|
2292
3372
|
const tokens = this.tokens(text, "node", line);
|
|
3373
|
+
const { k, pos } = this.vertexNumber(tokens, line);
|
|
3374
|
+
let i = 1;
|
|
3375
|
+
let label = null;
|
|
3376
|
+
if (tokens.length > 1 && !startsWithCoordinates(text, tokens)) {
|
|
3377
|
+
label = this.labelOf(tokens[1], k, line);
|
|
3378
|
+
i = 2;
|
|
3379
|
+
}
|
|
3380
|
+
const { xyz, dims, next } = this.vertexCoordinates(tokens, i, k);
|
|
3381
|
+
i = next;
|
|
3382
|
+
this.checkCoordinates(text, tokens, i, dims === 2 && label !== null, k, line);
|
|
3383
|
+
let shape = null;
|
|
3384
|
+
if (i < tokens.length && isShapeKeyword(tokens[i])) {
|
|
3385
|
+
shape = tokens[i].toLowerCase();
|
|
3386
|
+
i++;
|
|
3387
|
+
}
|
|
3388
|
+
const extras = this.extras(tokens, i, "node", line);
|
|
3389
|
+
shape = extras.shape ?? shape;
|
|
3390
|
+
const restored = this.restoredId(extras);
|
|
3391
|
+
this.createNodes();
|
|
3392
|
+
const repeated = this.markVertexSeen(pos, k, line);
|
|
3393
|
+
const index = this.vertexIndex(pos, k, label, restored, repeated, line);
|
|
3394
|
+
if (shape === null && dims > 0 && extras.keys.length > 0 && VOIDING_KEYS.has(extras.keys[0])) {
|
|
3395
|
+
this.voided.push(index);
|
|
3396
|
+
}
|
|
3397
|
+
if (label !== null) {
|
|
3398
|
+
this.labelHandle = this.nodeHandle(this.labelHandle, LABEL_DECL, line);
|
|
3399
|
+
this.sink.setNodeValue(this.labelHandle, index, label);
|
|
3400
|
+
}
|
|
3401
|
+
if (dims > 0) {
|
|
3402
|
+
this.writePosition(index, dims, xyz, k, line);
|
|
3403
|
+
}
|
|
3404
|
+
if (shape !== null) {
|
|
3405
|
+
this.writeShape(index, shape, line);
|
|
3406
|
+
}
|
|
3407
|
+
for (let p = 0; p < extras.keys.length; p++) {
|
|
3408
|
+
this.writeParameter("node", extras.keys[p], index, extras.values[p]);
|
|
3409
|
+
}
|
|
3410
|
+
if (extras.spells !== null) {
|
|
3411
|
+
this.nodeSpellsHandle = this.nodeHandle(this.nodeSpellsHandle, spellsDecl(), line);
|
|
3412
|
+
this.sink.setNodeValue(this.nodeSpellsHandle, index, extras.spells);
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
/**
|
|
3416
|
+
* A vertex line's number, checked: it starts the line and is in the declared range.
|
|
3417
|
+
* @param tokens - the line's tokens
|
|
3418
|
+
* @param line - the line number
|
|
3419
|
+
* @returns the vertex number and its position
|
|
3420
|
+
*/
|
|
3421
|
+
vertexNumber(tokens, line) {
|
|
2293
3422
|
if (!isVertexNumber(tokens[0])) {
|
|
2294
3423
|
this.report.counts.skippedNodes++;
|
|
2295
3424
|
throw new LineError(
|
|
@@ -2312,27 +3441,25 @@ class PajekParser {
|
|
|
2312
3441
|
`vertex ${k} is outside ${this.base}..${this.base + this.vertexCount - 1}`
|
|
2313
3442
|
);
|
|
2314
3443
|
}
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
3444
|
+
return { k, pos };
|
|
3445
|
+
}
|
|
3446
|
+
/**
|
|
3447
|
+
* A vertex line's coordinates: two or three numbers, or none; a single one is an error.
|
|
3448
|
+
* @param tokens - the line's tokens
|
|
3449
|
+
* @param i - where the coordinates would start
|
|
3450
|
+
* @param k - the vertex number
|
|
3451
|
+
* @returns x, y and z (0 when absent), how many were read, and the index after them
|
|
3452
|
+
*/
|
|
3453
|
+
vertexCoordinates(tokens, i, k) {
|
|
2325
3454
|
if (i + 1 < tokens.length && isNumericText(tokens[i]) && isNumericText(tokens[i + 1])) {
|
|
2326
|
-
x = Number(tokens[i]);
|
|
2327
|
-
y = Number(tokens[i + 1]);
|
|
2328
|
-
i
|
|
2329
|
-
|
|
2330
|
-
if (i < tokens.length && isNumericText(tokens[i])) {
|
|
2331
|
-
z = Number(tokens[i]);
|
|
2332
|
-
i++;
|
|
2333
|
-
dims = 3;
|
|
3455
|
+
const x = Number(tokens[i]);
|
|
3456
|
+
const y = Number(tokens[i + 1]);
|
|
3457
|
+
if (i + 2 < tokens.length && isNumericText(tokens[i + 2])) {
|
|
3458
|
+
return { xyz: [x, y, Number(tokens[i + 2])], dims: 3, next: i + 3 };
|
|
2334
3459
|
}
|
|
2335
|
-
|
|
3460
|
+
return { xyz: [x, y, 0], dims: 2, next: i + 2 };
|
|
3461
|
+
}
|
|
3462
|
+
if (i < tokens.length && isNumericText(tokens[i])) {
|
|
2336
3463
|
this.report.counts.skippedNodes++;
|
|
2337
3464
|
throw new LineError(
|
|
2338
3465
|
"parse-error",
|
|
@@ -2340,81 +3467,88 @@ class PajekParser {
|
|
|
2340
3467
|
`vertex ${k}: a single coordinate "${tokens[i]}"; coordinates are x y [z]`
|
|
2341
3468
|
);
|
|
2342
3469
|
}
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
if (repeated) {
|
|
3470
|
+
return { xyz: [0, 0, 0], dims: 0, next: i };
|
|
3471
|
+
}
|
|
3472
|
+
/**
|
|
3473
|
+
* Marks a vertex's position as having a line, warning when it already had one.
|
|
3474
|
+
* @param pos - the vertex's position
|
|
3475
|
+
* @param k - the vertex number
|
|
3476
|
+
* @param line - the line number
|
|
3477
|
+
* @returns whether the vertex already had a line
|
|
3478
|
+
*/
|
|
3479
|
+
markVertexSeen(pos, k, line) {
|
|
3480
|
+
if (this.seen[pos] !== 0) {
|
|
2355
3481
|
this.report.warning(
|
|
2356
3482
|
"merged",
|
|
2357
3483
|
PAJEK_ISSUE.DUPLICATE_NODE,
|
|
2358
3484
|
`vertex ${k} has more than one line; the later values overwrite`,
|
|
2359
3485
|
{ line, element: String(k) }
|
|
2360
3486
|
);
|
|
2361
|
-
|
|
2362
|
-
this.seen[pos] = 1;
|
|
2363
|
-
this.seenCount++;
|
|
3487
|
+
return true;
|
|
2364
3488
|
}
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
3489
|
+
this.seen[pos] = 1;
|
|
3490
|
+
this.seenCount++;
|
|
3491
|
+
return false;
|
|
3492
|
+
}
|
|
3493
|
+
/**
|
|
3494
|
+
* The node index a vertex line writes to, creating the node when its id is deferred to its line.
|
|
3495
|
+
* @param pos - the vertex's position
|
|
3496
|
+
* @param k - the vertex number
|
|
3497
|
+
* @param label - the line's label, or null
|
|
3498
|
+
* @param restored - the original id the line carries, or null
|
|
3499
|
+
* @param repeated - whether the vertex already had a line
|
|
3500
|
+
* @param line - the line number
|
|
3501
|
+
* @returns the node index
|
|
3502
|
+
*/
|
|
3503
|
+
vertexIndex(pos, k, label, restored, repeated, line) {
|
|
3504
|
+
const { idOfPos } = this;
|
|
3505
|
+
if (idOfPos !== null && !repeated && this.options.nodeIdFrom === "label") {
|
|
3506
|
+
return this.deferredNode(idOfPos, pos, k, label, line, "label");
|
|
3507
|
+
}
|
|
3508
|
+
if (idOfPos !== null && idOfPos[pos] === void 0) {
|
|
2369
3509
|
for (let p = this.filledBelow; p < pos; p++) {
|
|
2370
|
-
if (
|
|
2371
|
-
this.numberedNode(
|
|
3510
|
+
if (idOfPos[p] === void 0) {
|
|
3511
|
+
this.numberedNode(idOfPos, p);
|
|
2372
3512
|
}
|
|
2373
3513
|
}
|
|
2374
3514
|
if (pos > this.filledBelow) {
|
|
2375
3515
|
this.filledBelow = pos;
|
|
2376
3516
|
}
|
|
2377
|
-
|
|
2378
|
-
} else {
|
|
2379
|
-
index = this.indexOfPos[pos];
|
|
2380
|
-
if (restored !== null && !repeated) {
|
|
2381
|
-
this.report.warning(
|
|
2382
|
-
"coercion",
|
|
2383
|
-
PAJEK_ISSUE.ORIGINAL_ID_UNRESTORED,
|
|
2384
|
-
`vertex ${k} carries ${ORIGINAL_ID_KEY} ${JSON.stringify(restored)} but a later vertex's line came first and created it under its number; the original id is not restored`,
|
|
2385
|
-
{ line, element: String(k) }
|
|
2386
|
-
);
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
const { sink } = this;
|
|
2390
|
-
if (label !== null) {
|
|
2391
|
-
if (this.labelHandle === INVALID_INDEX) {
|
|
2392
|
-
this.labelHandle = declareResolved(sink, "node", LABEL_DECL, this.report, { line }).handle;
|
|
2393
|
-
}
|
|
2394
|
-
sink.setNodeValue(this.labelHandle, index, label);
|
|
2395
|
-
}
|
|
2396
|
-
if (dims > 0) {
|
|
2397
|
-
this.writePosition(index, dims, [x, y, z], k, line);
|
|
3517
|
+
return this.deferredNode(idOfPos, pos, k, restored, line, "originalId");
|
|
2398
3518
|
}
|
|
2399
|
-
if (
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
sink.setNodeValue(this.shapeHandle, index, shape);
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
for (let p = 0; p < extras.keys.length; p++) {
|
|
2410
|
-
this.writeParameter("node", extras.keys[p], index, extras.values[p]);
|
|
3519
|
+
if (restored !== null && !repeated) {
|
|
3520
|
+
this.report.warning(
|
|
3521
|
+
"coercion",
|
|
3522
|
+
PAJEK_ISSUE.ORIGINAL_ID_UNRESTORED,
|
|
3523
|
+
`vertex ${k} carries ${ORIGINAL_ID_KEY} ${JSON.stringify(restored)} but a later vertex's line came first and created it under its number; the original id is not restored`,
|
|
3524
|
+
{ line, element: String(k) }
|
|
3525
|
+
);
|
|
2411
3526
|
}
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
3527
|
+
return this.indexOfPos[pos];
|
|
3528
|
+
}
|
|
3529
|
+
/**
|
|
3530
|
+
* A node column's handle, declared on first use.
|
|
3531
|
+
* @param handle - the handle so far, or INVALID_INDEX
|
|
3532
|
+
* @param decl - the column's declaration
|
|
3533
|
+
* @param line - the line number
|
|
3534
|
+
* @returns the handle
|
|
3535
|
+
*/
|
|
3536
|
+
nodeHandle(handle, decl, line) {
|
|
3537
|
+
return handle === INVALID_INDEX ? declareResolved(this.sink, "node", decl, this.report, { line }).handle : handle;
|
|
3538
|
+
}
|
|
3539
|
+
/**
|
|
3540
|
+
* Writes a vertex's shape keyword: to the shape column, or to an earlier `shape "<text>"` parameter's column.
|
|
3541
|
+
* @param index - the node index
|
|
3542
|
+
* @param shape - the keyword
|
|
3543
|
+
* @param line - the line number
|
|
3544
|
+
*/
|
|
3545
|
+
writeShape(index, shape, line) {
|
|
3546
|
+
if (this.shapeHandle === INVALID_INDEX && this.nodeParams.has(SHAPE_COLUMN)) {
|
|
3547
|
+
this.writeParameter("node", SHAPE_COLUMN, index, shape);
|
|
3548
|
+
return;
|
|
2417
3549
|
}
|
|
3550
|
+
this.shapeHandle = this.nodeHandle(this.shapeHandle, SHAPE_DECL, line);
|
|
3551
|
+
this.sink.setNodeValue(this.shapeHandle, index, shape);
|
|
2418
3552
|
}
|
|
2419
3553
|
/**
|
|
2420
3554
|
* A vertex label as written, its character references decoded.
|
|
@@ -2475,7 +3609,9 @@ class PajekParser {
|
|
|
2475
3609
|
writePosition(index, dims, point, k, line) {
|
|
2476
3610
|
if (this.positionHandle === INVALID_INDEX) {
|
|
2477
3611
|
this.coordDims = dims;
|
|
2478
|
-
this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims), this.report, {
|
|
3612
|
+
this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims, this.window), this.report, {
|
|
3613
|
+
line
|
|
3614
|
+
}).handle;
|
|
2479
3615
|
} else if (dims !== this.coordDims) {
|
|
2480
3616
|
this.report.warnOnce(
|
|
2481
3617
|
"validation-error",
|
|
@@ -2862,7 +3998,7 @@ class PajekParser {
|
|
|
2862
3998
|
for (let i = start; i < tokens.length; ) {
|
|
2863
3999
|
const token = tokens[i];
|
|
2864
4000
|
if (token.startsWith("[")) {
|
|
2865
|
-
extras.spells = this.intervals(token, domain);
|
|
4001
|
+
extras.spells = this.intervals(token, domain, line);
|
|
2866
4002
|
i++;
|
|
2867
4003
|
continue;
|
|
2868
4004
|
}
|
|
@@ -2885,8 +4021,9 @@ class PajekParser {
|
|
|
2885
4021
|
}
|
|
2886
4022
|
seen.add(token);
|
|
2887
4023
|
extras.keys.push(token);
|
|
2888
|
-
|
|
2889
|
-
i
|
|
4024
|
+
const triple = COLOR_KEYS.has(token) ? colorTriple(tokens, i + 1) : null;
|
|
4025
|
+
extras.values.push(triple ?? tokens[i + 1]);
|
|
4026
|
+
i += triple === null ? 2 : 4;
|
|
2890
4027
|
}
|
|
2891
4028
|
return extras;
|
|
2892
4029
|
}
|
|
@@ -2915,12 +4052,15 @@ class PajekParser {
|
|
|
2915
4052
|
);
|
|
2916
4053
|
}
|
|
2917
4054
|
/**
|
|
2918
|
-
* The spells of a row's interval token
|
|
4055
|
+
* The spells of a row's interval token. A token not closed by "]" skips the row; a closed one
|
|
4056
|
+
* whose times cannot be read (`[287-?]`, lin-rel4.net) is reported and dropped, and the rest of
|
|
4057
|
+
* the row (its label, coordinates and parameters) is kept.
|
|
2919
4058
|
* @param token - the token, starting with "["
|
|
2920
|
-
* @param domain - what is skipped when the token is
|
|
2921
|
-
* @
|
|
4059
|
+
* @param domain - what is skipped when the token is not closed
|
|
4060
|
+
* @param line - the line number
|
|
4061
|
+
* @returns the spells, or null for an empty `[]`, which is no spell at all, and for a dropped one
|
|
2922
4062
|
*/
|
|
2923
|
-
intervals(token, domain) {
|
|
4063
|
+
intervals(token, domain, line) {
|
|
2924
4064
|
if (!isIntervalToken(token)) {
|
|
2925
4065
|
this.skip(domain);
|
|
2926
4066
|
throw new LineError(
|
|
@@ -2933,12 +4073,13 @@ class PajekParser {
|
|
|
2933
4073
|
const spells = parseIntervals(token);
|
|
2934
4074
|
return spells.length === 0 ? null : spells;
|
|
2935
4075
|
} catch (err) {
|
|
2936
|
-
this.
|
|
2937
|
-
throw new LineError(
|
|
4076
|
+
this.report.error(
|
|
2938
4077
|
"validation-error",
|
|
2939
4078
|
PAJEK_ISSUE.INTERVAL,
|
|
2940
|
-
err instanceof Error ? err.message : String(err)
|
|
4079
|
+
`${err instanceof Error ? err.message : String(err)}; the interval is dropped and the rest of the line kept`,
|
|
4080
|
+
{ line }
|
|
2941
4081
|
);
|
|
4082
|
+
return null;
|
|
2942
4083
|
}
|
|
2943
4084
|
}
|
|
2944
4085
|
/**
|
|
@@ -2976,6 +4117,12 @@ class PajekParser {
|
|
|
2976
4117
|
writer.write(row, text);
|
|
2977
4118
|
}
|
|
2978
4119
|
}
|
|
4120
|
+
const COLOR_KEYS = /* @__PURE__ */ new Set(["ic", "bc", "lc", "c"]);
|
|
4121
|
+
function colorTriple(tokens, at) {
|
|
4122
|
+
const parts = tokens.slice(at, at + 3);
|
|
4123
|
+
const fraction = (t) => /^[01]?(?:\.\d+)?$/.test(t) && t !== "" && Number(t) <= 1;
|
|
4124
|
+
return parts.length === 3 && parts.every(fraction) ? parts.join(" ") : null;
|
|
4125
|
+
}
|
|
2979
4126
|
function startsWithCoordinates(text, tokens) {
|
|
2980
4127
|
if (quotedAfterNumber(text, tokens)) {
|
|
2981
4128
|
return false;
|
|
@@ -3015,10 +4162,29 @@ function headSection(text) {
|
|
|
3015
4162
|
}
|
|
3016
4163
|
const pajekImporter = Object.freeze({
|
|
3017
4164
|
format: "pajek",
|
|
3018
|
-
options: Object.freeze(["firstVertex"]),
|
|
4165
|
+
options: Object.freeze(["firstVertex", "pajekDraw"]),
|
|
3019
4166
|
extensions: Object.freeze([".net", ".paj"]),
|
|
3020
4167
|
mimeTypes: Object.freeze(["text/x-pajek", "text/plain"]),
|
|
3021
4168
|
styles: pajekStyles,
|
|
4169
|
+
/**
|
|
4170
|
+
* Where Pajek 6.02 draws a network whose vertices have no coordinates: round a circle in vertex order, the first
|
|
4171
|
+
* on the left, the rest going clockwise on screen (y down), at radius 0.4 about the middle of the Draw window
|
|
4172
|
+
* (pajek-iliad: 311 vertices 200 points from the middle of its 500-point window). A file with coordinates is read
|
|
4173
|
+
* from its position column.
|
|
4174
|
+
* @param snapshot - the imported graph
|
|
4175
|
+
* @returns the circle for a file with no coordinates, else null
|
|
4176
|
+
*/
|
|
4177
|
+
positions(snapshot) {
|
|
4178
|
+
if (snapshot.nodes.byRole("position") !== null) {
|
|
4179
|
+
return null;
|
|
4180
|
+
}
|
|
4181
|
+
return {
|
|
4182
|
+
units: "file",
|
|
4183
|
+
pxPerUnit: PAJEK_POINTS_PER_UNIT,
|
|
4184
|
+
yAxis: "down",
|
|
4185
|
+
unplacedCircle: { center: [0.5, 0.5], radius: 0.4, startDegrees: 180, direction: 1 }
|
|
4186
|
+
};
|
|
4187
|
+
},
|
|
3022
4188
|
/**
|
|
3023
4189
|
* Confidence that the input is a Pajek network: it starts with `*Vertices` (or `*Network`),
|
|
3024
4190
|
* after any `%` comment lines.
|
|
@@ -3046,10 +4212,11 @@ const pajekImporter = Object.freeze({
|
|
|
3046
4212
|
}
|
|
3047
4213
|
const resolved = resolveImportOptions(options, DEFAULTS);
|
|
3048
4214
|
const firstVertex = firstVertexOption(options?.firstVertex);
|
|
4215
|
+
const draw = resolvePajekDraw(options?.pajekDraw);
|
|
3049
4216
|
const report = new ImportReportBuilder("pajek", resolved.errorLimit);
|
|
3050
4217
|
reportSinkOptions(sink, options, report);
|
|
3051
4218
|
reportUnusedOptions(options, report, USED_OPTIONS);
|
|
3052
|
-
const parser = new PajekParser(sink, report, resolved, firstVertex);
|
|
4219
|
+
const parser = new PajekParser(sink, report, resolved, firstVertex, draw ?? DEFAULT_WINDOW);
|
|
3053
4220
|
const reader = new LineReader(input, report, resolved);
|
|
3054
4221
|
let rest = null;
|
|
3055
4222
|
let restLine = 0;
|
|
@@ -3069,6 +4236,9 @@ const pajekImporter = Object.freeze({
|
|
|
3069
4236
|
}
|
|
3070
4237
|
}
|
|
3071
4238
|
parser.finish();
|
|
4239
|
+
if (draw !== null || parser.voided.length > 0) {
|
|
4240
|
+
report.keepForStyles({ block: parser.keptBlock, pajekDraw: draw ?? void 0, voided: parser.voided });
|
|
4241
|
+
}
|
|
3072
4242
|
if (rest !== null) {
|
|
3073
4243
|
const objects = rest.objects > 0 ? `; ${rest.objects} *Partition / *Vector object(s) after them are not read` : "";
|
|
3074
4244
|
report.warning(
|
|
@@ -3093,13 +4263,25 @@ const pajekImporter = Object.freeze({
|
|
|
3093
4263
|
async importAll(input, sinkFor, options) {
|
|
3094
4264
|
const resolved = resolveImportOptions(options, DEFAULTS);
|
|
3095
4265
|
const firstVertex = firstVertexOption(options?.firstVertex);
|
|
4266
|
+
const draw = resolvePajekDraw(options?.pajekDraw);
|
|
3096
4267
|
const reports = [new ImportReportBuilder("pajek", resolved.errorLimit)];
|
|
3097
4268
|
reportUnusedOptions(options, reports[0], USED_OPTIONS);
|
|
3098
4269
|
const open = () => {
|
|
3099
4270
|
const report = reports[reports.length - 1];
|
|
3100
4271
|
const sink = sinkFor(reports.length - 1);
|
|
3101
4272
|
reportSinkOptions(sink, options, report);
|
|
3102
|
-
return new PajekParser(sink, report, resolved, firstVertex);
|
|
4273
|
+
return new PajekParser(sink, report, resolved, firstVertex, draw ?? DEFAULT_WINDOW);
|
|
4274
|
+
};
|
|
4275
|
+
const close = (p) => {
|
|
4276
|
+
p.finish();
|
|
4277
|
+
const last = reports.at(-1);
|
|
4278
|
+
if (last !== void 0 && (draw !== null || p.voided.length > 0)) {
|
|
4279
|
+
last.keepForStyles({
|
|
4280
|
+
block: p.keptBlock,
|
|
4281
|
+
pajekDraw: draw ?? void 0,
|
|
4282
|
+
voided: p.voided
|
|
4283
|
+
});
|
|
4284
|
+
}
|
|
3103
4285
|
};
|
|
3104
4286
|
let parser = open();
|
|
3105
4287
|
const reader = new LineReader(input, reports[0], resolved);
|
|
@@ -3107,7 +4289,7 @@ const pajekImporter = Object.freeze({
|
|
|
3107
4289
|
for await (const raw of reader) {
|
|
3108
4290
|
const text = withoutStrayBom(raw);
|
|
3109
4291
|
if (parser.line(text, reader.line)) {
|
|
3110
|
-
parser
|
|
4292
|
+
close(parser);
|
|
3111
4293
|
reports.push(new ImportReportBuilder("pajek", resolved.errorLimit));
|
|
3112
4294
|
parser = open();
|
|
3113
4295
|
parser.line(text, reader.line);
|
|
@@ -3117,7 +4299,7 @@ const pajekImporter = Object.freeze({
|
|
|
3117
4299
|
throwIfAborted(resolved.signal);
|
|
3118
4300
|
}
|
|
3119
4301
|
}
|
|
3120
|
-
parser
|
|
4302
|
+
close(parser);
|
|
3121
4303
|
throwIfAborted(resolved.signal);
|
|
3122
4304
|
return reports.map((r) => r.finish());
|
|
3123
4305
|
}
|
|
@@ -3179,4 +4361,4 @@ export {
|
|
|
3179
4361
|
pajekImporter as d,
|
|
3180
4362
|
pajekExporter as p
|
|
3181
4363
|
};
|
|
3182
|
-
//# sourceMappingURL=importer-
|
|
4364
|
+
//# sourceMappingURL=importer-DgG4v1Ms.js.map
|