@graphty/graph-io 0.3.48 → 0.3.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{approximations-C2riR4NT.js → approximations-Bzn3L-je.js} +2 -2
- package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-Bzn3L-je.js.map} +1 -1
- package/dist/chunks/bends-BGXjv_U4.js +129 -0
- package/dist/chunks/bends-BGXjv_U4.js.map +1 -0
- package/dist/chunks/{block-Cu22ewuS.js → block-iptrlMBb.js} +906 -164
- package/dist/chunks/block-iptrlMBb.js.map +1 -0
- package/dist/chunks/choose-CczZJaX_.js +717 -0
- package/dist/chunks/choose-CczZJaX_.js.map +1 -0
- package/dist/chunks/{codes-CV_Bhcyi.js → codes-BE2xir2k.js} +6 -2
- package/dist/chunks/codes-BE2xir2k.js.map +1 -0
- package/dist/chunks/{constants-D0LqcsLJ.js → constants-CKkYLPtt.js} +2 -2
- package/dist/chunks/{constants-D0LqcsLJ.js.map → constants-CKkYLPtt.js.map} +1 -1
- package/dist/chunks/{context-cgmmOxZ2.js → context-C3p0RQxR.js} +5 -4
- package/dist/chunks/{context-cgmmOxZ2.js.map → context-C3p0RQxR.js.map} +1 -1
- package/dist/chunks/{convert-BcQ8_jMo.js → convert-Ct2zelbQ.js} +7 -2
- package/dist/chunks/convert-Ct2zelbQ.js.map +1 -0
- package/dist/chunks/{credentials-BiQsnMTb.js → credentials-DXHx7nwR.js} +16 -14
- package/dist/chunks/credentials-DXHx7nwR.js.map +1 -0
- package/dist/chunks/{cx-export-BEeF6ymo.js → cx-export-Bt6NoqTQ.js} +3 -3
- package/dist/chunks/{cx-export-BEeF6ymo.js.map → cx-export-Bt6NoqTQ.js.map} +1 -1
- package/dist/chunks/descriptor-B28U25x4.js +60 -0
- package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
- package/dist/chunks/{descriptor-BJ-W0Jd-.js → descriptor-DLA5kINx.js} +7 -2
- package/dist/chunks/descriptor-DLA5kINx.js.map +1 -0
- package/dist/chunks/{emit-CD8xnY8s.js → emit-BwHQkZle.js} +1660 -133
- package/dist/chunks/emit-BwHQkZle.js.map +1 -0
- package/dist/chunks/{escape-DH2Egt-l.js → escape-CuCIzNMB.js} +8 -8
- package/dist/chunks/{escape-DH2Egt-l.js.map → escape-CuCIzNMB.js.map} +1 -1
- package/dist/chunks/{export-CZ7VRm4I.js → export-Cha4dRFz.js} +45 -387
- package/dist/chunks/export-Cha4dRFz.js.map +1 -0
- package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
- package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
- package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-D2CETOMK.js} +1222 -156
- package/dist/chunks/exporter-D2CETOMK.js.map +1 -0
- package/dist/chunks/{exporter-BIdaoIgh.js → exporter-D9yMtocA.js} +7 -7
- package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-D9yMtocA.js.map} +1 -1
- package/dist/chunks/{exporter-DtVU80Fa.js → exporter-_jrBTnos.js} +9 -8
- package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-_jrBTnos.js.map} +1 -1
- package/dist/chunks/{exporter-ChjL5fmP.js → exporter-nDfxIK5D.js} +9 -8
- package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-nDfxIK5D.js.map} +1 -1
- package/dist/chunks/format-BXiAb-1h.js +408 -0
- package/dist/chunks/format-BXiAb-1h.js.map +1 -0
- package/dist/chunks/{generic-CP6YD34u.js → generic-ymWCETAJ.js} +387 -31
- package/dist/chunks/generic-ymWCETAJ.js.map +1 -0
- package/dist/chunks/{importer-e3huMZbm.js → importer-B92x1xY5.js} +14 -10
- package/dist/chunks/importer-B92x1xY5.js.map +1 -0
- package/dist/chunks/{importer-B87_fmVx.js → importer-CT9mJ1nn.js} +326 -84
- package/dist/chunks/importer-CT9mJ1nn.js.map +1 -0
- package/dist/chunks/{importer-CB_zV5_L.js → importer-DaLTjbds.js} +116 -1102
- package/dist/chunks/importer-DaLTjbds.js.map +1 -0
- package/dist/chunks/{importer-DPZDN40-.js → importer-GREKMdIf.js} +25 -17
- package/dist/chunks/importer-GREKMdIf.js.map +1 -0
- package/dist/chunks/{importer-Bji2MeWr.js → importer-PqaaKKnY.js} +13 -10
- package/dist/chunks/{importer-Bji2MeWr.js.map → importer-PqaaKKnY.js.map} +1 -1
- package/dist/chunks/{importer-Cyy6UseH.js → importer-Vn5QvmmJ.js} +66 -13
- package/dist/chunks/importer-Vn5QvmmJ.js.map +1 -0
- package/dist/chunks/{importer-CVT-JyDE.js → importer-vRq4h3j5.js} +1469 -356
- package/dist/chunks/importer-vRq4h3j5.js.map +1 -0
- package/dist/chunks/{input-Ccg9I22A.js → input-CAxt_aV-.js} +4 -4
- package/dist/chunks/{input-Ccg9I22A.js.map → input-CAxt_aV-.js.map} +1 -1
- package/dist/chunks/{json-elements-By172SVq.js → json-elements-Cq76WjnZ.js} +4 -4
- package/dist/chunks/{json-elements-By172SVq.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
- package/dist/chunks/{lexicon-u2SI5xcx.js → lexicon-Clf4QIyl.js} +282 -74
- package/dist/chunks/lexicon-Clf4QIyl.js.map +1 -0
- package/dist/chunks/{ontology-export-BwgMyuF0.js → ontology-export-OMo91mb0.js} +4 -4
- package/dist/chunks/{ontology-export-BwgMyuF0.js.map → ontology-export-OMo91mb0.js.map} +1 -1
- package/dist/chunks/{records-Cgvxz-Vx.js → records-NJiYvekn.js} +2 -2
- package/dist/chunks/{records-Cgvxz-Vx.js.map → records-NJiYvekn.js.map} +1 -1
- package/dist/chunks/{report-CgdsL9Hb.js → report-CwMfYa9J.js} +23 -23
- package/dist/chunks/{report-CgdsL9Hb.js.map → report-CwMfYa9J.js.map} +1 -1
- package/dist/chunks/round-trip-Zm3_ivgq.js +79 -0
- package/dist/chunks/round-trip-Zm3_ivgq.js.map +1 -0
- package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-EokFic1V.js} +5 -5
- package/dist/chunks/sigv4-EokFic1V.js.map +1 -0
- package/dist/chunks/{styles-CaABMoO1.js → styles-CCs214_3.js} +1237 -138
- package/dist/chunks/styles-CCs214_3.js.map +1 -0
- package/dist/chunks/styles-Cm62yyQX.js +2812 -0
- package/dist/chunks/styles-Cm62yyQX.js.map +1 -0
- package/dist/chunks/styles-DPQQIig4.js +1928 -0
- package/dist/chunks/styles-DPQQIig4.js.map +1 -0
- package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-UMFdNqze.js} +503 -172
- package/dist/chunks/styles-yed-UMFdNqze.js.map +1 -0
- package/dist/chunks/{text-BuKQVMz2.js → text-ystE2bYi.js} +2 -2
- package/dist/chunks/{text-BuKQVMz2.js.map → text-ystE2bYi.js.map} +1 -1
- package/dist/csv.js +7 -7
- package/dist/cx.js +2 -2
- package/dist/cx2.js +2 -2
- package/dist/cys.js +1 -1
- package/dist/dot.js +5 -4
- package/dist/dot.js.map +1 -1
- package/dist/gexf.js +42 -12
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +847 -193
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +232 -220
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +3 -3
- package/dist/json.js +3 -2
- package/dist/neo4j.js +6 -6
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/positions.js +45 -3
- package/dist/positions.js.map +1 -1
- package/dist/sources-cypher.js +138 -23
- package/dist/sources-cypher.js.map +1 -1
- package/dist/sources-ndex.js +2 -2
- package/dist/sources-rest.js +16 -6
- package/dist/sources-rest.js.map +1 -1
- package/dist/sources-sparql.d.ts +1 -0
- package/dist/sources-sparql.js +405 -0
- package/dist/sources-sparql.js.map +1 -0
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +5 -1
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx/styles.d.ts +24 -1
- package/dist/src/formats/cx/styles.d.ts.map +1 -1
- package/dist/src/formats/cx/styles.js +117 -11
- package/dist/src/formats/cx/styles.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +1 -0
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/cx2/styles.d.ts.map +1 -1
- package/dist/src/formats/cx2/styles.js +3 -1
- package/dist/src/formats/cx2/styles.js.map +1 -1
- package/dist/src/formats/cys/importer.d.ts.map +1 -1
- package/dist/src/formats/cys/importer.js +1 -0
- package/dist/src/formats/cys/importer.js.map +1 -1
- package/dist/src/formats/cys/styles.d.ts +2 -0
- package/dist/src/formats/cys/styles.d.ts.map +1 -1
- package/dist/src/formats/cys/styles.js +15 -7
- package/dist/src/formats/cys/styles.js.map +1 -1
- package/dist/src/formats/dot/drawing.d.ts +98 -0
- package/dist/src/formats/dot/drawing.d.ts.map +1 -0
- package/dist/src/formats/dot/drawing.js +734 -0
- package/dist/src/formats/dot/drawing.js.map +1 -0
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +108 -31
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/label-places.d.ts +34 -0
- package/dist/src/formats/dot/label-places.d.ts.map +1 -0
- package/dist/src/formats/dot/label-places.js +179 -0
- package/dist/src/formats/dot/label-places.js.map +1 -0
- package/dist/src/formats/dot/record.d.ts +50 -0
- package/dist/src/formats/dot/record.d.ts.map +1 -0
- package/dist/src/formats/dot/record.js +275 -0
- package/dist/src/formats/dot/record.js.map +1 -0
- package/dist/src/formats/dot/styles.d.ts +62 -2
- package/dist/src/formats/dot/styles.d.ts.map +1 -1
- package/dist/src/formats/dot/styles.js +1454 -119
- package/dist/src/formats/dot/styles.js.map +1 -1
- package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
- package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
- package/dist/src/formats/gexf/dialog-metrics.js +59 -0
- package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
- package/dist/src/formats/gexf/importer.d.ts +7 -0
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +41 -5
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/preview.d.ts +77 -0
- package/dist/src/formats/gexf/preview.d.ts.map +1 -0
- package/dist/src/formats/gexf/preview.js +191 -0
- package/dist/src/formats/gexf/preview.js.map +1 -0
- package/dist/src/formats/gexf/schema.d.ts.map +1 -1
- package/dist/src/formats/gexf/schema.js +2 -1
- package/dist/src/formats/gexf/schema.js.map +1 -1
- package/dist/src/formats/gexf/styles.d.ts +58 -31
- package/dist/src/formats/gexf/styles.d.ts.map +1 -1
- package/dist/src/formats/gexf/styles.js +848 -225
- package/dist/src/formats/gexf/styles.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts +5 -2
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +258 -71
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/index.d.ts +1 -1
- package/dist/src/formats/gml/index.d.ts.map +1 -1
- package/dist/src/formats/gml/index.js +1 -1
- package/dist/src/formats/gml/index.js.map +1 -1
- package/dist/src/formats/gml/positions.d.ts +7 -0
- package/dist/src/formats/gml/positions.d.ts.map +1 -1
- package/dist/src/formats/gml/positions.js +29 -7
- package/dist/src/formats/gml/positions.js.map +1 -1
- package/dist/src/formats/gml/styles.d.ts.map +1 -1
- package/dist/src/formats/gml/styles.js +753 -101
- package/dist/src/formats/gml/styles.js.map +1 -1
- package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-plain.js +6 -10
- package/dist/src/formats/graphml/styles-plain.js.map +1 -1
- package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
- package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-yed.js +692 -161
- package/dist/src/formats/graphml/styles-yed.js.map +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.js +429 -64
- package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts +3 -3
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +16 -6
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/dialect.d.ts +3 -2
- package/dist/src/formats/json/dialect.d.ts.map +1 -1
- package/dist/src/formats/json/dialect.js +39 -5
- package/dist/src/formats/json/dialect.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts +13 -2
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +42 -6
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/index.d.ts +1 -1
- package/dist/src/formats/json/index.d.ts.map +1 -1
- package/dist/src/formats/json/index.js +1 -1
- package/dist/src/formats/json/index.js.map +1 -1
- package/dist/src/formats/json/positions.d.ts +5 -2
- package/dist/src/formats/json/positions.d.ts.map +1 -1
- package/dist/src/formats/json/positions.js +20 -4
- package/dist/src/formats/json/positions.js.map +1 -1
- package/dist/src/formats/json/styles.d.ts +12 -1
- package/dist/src/formats/json/styles.d.ts.map +1 -1
- package/dist/src/formats/json/styles.js +1755 -136
- package/dist/src/formats/json/styles.js.map +1 -1
- package/dist/src/formats/pajek/draw.d.ts +96 -0
- package/dist/src/formats/pajek/draw.d.ts.map +1 -0
- package/dist/src/formats/pajek/draw.js +372 -0
- package/dist/src/formats/pajek/draw.js.map +1 -0
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +70 -51
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts +9 -0
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +233 -102
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/index.d.ts +1 -0
- package/dist/src/formats/pajek/index.d.ts.map +1 -1
- package/dist/src/formats/pajek/index.js.map +1 -1
- package/dist/src/formats/pajek/styles.d.ts +15 -7
- package/dist/src/formats/pajek/styles.d.ts.map +1 -1
- package/dist/src/formats/pajek/styles.js +1278 -114
- package/dist/src/formats/pajek/styles.js.map +1 -1
- package/dist/src/formats/pajek/syntax.d.ts +10 -1
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +26 -2
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts +1 -0
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +65 -5
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/styles.d.ts +23 -3
- package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
- package/dist/src/formats/xgmml/styles.js +277 -60
- package/dist/src/formats/xgmml/styles.js.map +1 -1
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/positions/convert.d.ts.map +1 -1
- package/dist/src/positions/convert.js +11 -1
- package/dist/src/positions/convert.js.map +1 -1
- package/dist/src/positions/extract.d.ts.map +1 -1
- package/dist/src/positions/extract.js +53 -1
- package/dist/src/positions/extract.js.map +1 -1
- package/dist/src/positions/index.d.ts +1 -1
- package/dist/src/positions/index.d.ts.map +1 -1
- package/dist/src/positions/types.d.ts +59 -0
- package/dist/src/positions/types.d.ts.map +1 -1
- package/dist/src/sources/builtins.d.ts +1 -1
- package/dist/src/sources/builtins.d.ts.map +1 -1
- package/dist/src/sources/builtins.js +8 -2
- package/dist/src/sources/builtins.js.map +1 -1
- package/dist/src/sources/context.d.ts.map +1 -1
- package/dist/src/sources/context.js +1 -0
- package/dist/src/sources/context.js.map +1 -1
- package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
- package/dist/src/sources/cypher/descriptor.js +5 -0
- package/dist/src/sources/cypher/descriptor.js.map +1 -1
- package/dist/src/sources/cypher/index.d.ts.map +1 -1
- package/dist/src/sources/cypher/index.js +124 -18
- package/dist/src/sources/cypher/index.js.map +1 -1
- package/dist/src/sources/cypher/params.d.ts +1 -1
- package/dist/src/sources/cypher/params.d.ts.map +1 -1
- package/dist/src/sources/cypher/query-builder.d.ts +17 -0
- package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
- package/dist/src/sources/cypher/query-builder.js +31 -0
- package/dist/src/sources/cypher/query-builder.js.map +1 -1
- package/dist/src/sources/ids.d.ts +5 -0
- package/dist/src/sources/ids.d.ts.map +1 -1
- package/dist/src/sources/ids.js +5 -0
- package/dist/src/sources/ids.js.map +1 -1
- package/dist/src/sources/params.d.ts +3 -0
- package/dist/src/sources/params.d.ts.map +1 -1
- package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
- package/dist/src/sources/rest/descriptor.js +5 -0
- package/dist/src/sources/rest/descriptor.js.map +1 -1
- package/dist/src/sources/rest/source.d.ts.map +1 -1
- package/dist/src/sources/rest/source.js +15 -0
- package/dist/src/sources/rest/source.js.map +1 -1
- package/dist/src/sources/sigv4.d.ts +5 -3
- package/dist/src/sources/sigv4.d.ts.map +1 -1
- package/dist/src/sources/sigv4.js +6 -4
- package/dist/src/sources/sigv4.js.map +1 -1
- package/dist/src/sources/sparql/descriptor.d.ts +10 -0
- package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
- package/dist/src/sources/sparql/descriptor.js +64 -0
- package/dist/src/sources/sparql/descriptor.js.map +1 -0
- package/dist/src/sources/sparql/index.d.ts +28 -0
- package/dist/src/sources/sparql/index.d.ts.map +1 -0
- package/dist/src/sources/sparql/index.js +314 -0
- package/dist/src/sources/sparql/index.js.map +1 -0
- package/dist/src/sources/sparql/ntriples.d.ts +69 -0
- package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
- package/dist/src/sources/sparql/ntriples.js +180 -0
- package/dist/src/sources/sparql/ntriples.js.map +1 -0
- package/dist/src/sources/sparql/params.d.ts +27 -0
- package/dist/src/sources/sparql/params.d.ts.map +1 -0
- package/dist/src/sources/sparql/params.js +5 -0
- package/dist/src/sources/sparql/params.js.map +1 -0
- package/dist/src/sources/sparql/query.d.ts +72 -0
- package/dist/src/sources/sparql/query.d.ts.map +1 -0
- package/dist/src/sources/sparql/query.js +113 -0
- package/dist/src/sources/sparql/query.js.map +1 -0
- package/dist/src/sources/types.d.ts +31 -0
- package/dist/src/sources/types.d.ts.map +1 -1
- package/dist/src/styles/annotations.d.ts +61 -5
- package/dist/src/styles/annotations.d.ts.map +1 -1
- package/dist/src/styles/annotations.js +130 -22
- package/dist/src/styles/annotations.js.map +1 -1
- package/dist/src/styles/canon/bends.d.ts +46 -0
- package/dist/src/styles/canon/bends.d.ts.map +1 -1
- package/dist/src/styles/canon/bends.js +123 -0
- package/dist/src/styles/canon/bends.js.map +1 -1
- package/dist/src/styles/canon/color-tables.d.ts +6 -1
- package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
- package/dist/src/styles/canon/color-tables.js +10 -4
- package/dist/src/styles/canon/color-tables.js.map +1 -1
- package/dist/src/styles/canon/color.d.ts +3 -1
- package/dist/src/styles/canon/color.d.ts.map +1 -1
- package/dist/src/styles/canon/color.js +103 -3
- package/dist/src/styles/canon/color.js.map +1 -1
- package/dist/src/styles/canon/enums.d.ts +2 -2
- package/dist/src/styles/canon/enums.d.ts.map +1 -1
- package/dist/src/styles/canon/enums.js +81 -7
- package/dist/src/styles/canon/enums.js.map +1 -1
- package/dist/src/styles/canon/graphviz.d.ts +12 -3
- package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
- package/dist/src/styles/canon/graphviz.js +57 -9
- package/dist/src/styles/canon/graphviz.js.map +1 -1
- package/dist/src/styles/canon/number.d.ts +8 -0
- package/dist/src/styles/canon/number.d.ts.map +1 -1
- package/dist/src/styles/canon/number.js +18 -0
- package/dist/src/styles/canon/number.js.map +1 -1
- package/dist/src/styles/canon/text.d.ts +29 -2
- package/dist/src/styles/canon/text.d.ts.map +1 -1
- package/dist/src/styles/canon/text.js +156 -16
- package/dist/src/styles/canon/text.js.map +1 -1
- package/dist/src/styles/codes.d.ts +2 -0
- package/dist/src/styles/codes.d.ts.map +1 -1
- package/dist/src/styles/codes.js +2 -0
- package/dist/src/styles/codes.js.map +1 -1
- package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
- package/dist/src/styles/cyjs/cascade.js +1015 -79
- package/dist/src/styles/cyjs/cascade.js.map +1 -1
- package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
- package/dist/src/styles/cyjs/defaults-table.js +3 -0
- package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
- package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
- package/dist/src/styles/cyjs/emit.js +202 -9
- package/dist/src/styles/cyjs/emit.js.map +1 -1
- package/dist/src/styles/cyjs/face.d.ts +20 -0
- package/dist/src/styles/cyjs/face.d.ts.map +1 -0
- package/dist/src/styles/cyjs/face.js +332 -0
- package/dist/src/styles/cyjs/face.js.map +1 -0
- package/dist/src/styles/cyjs/mappers.d.ts +44 -1
- package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
- package/dist/src/styles/cyjs/mappers.js +461 -26
- package/dist/src/styles/cyjs/mappers.js.map +1 -1
- package/dist/src/styles/cyjs/routes.d.ts +53 -0
- package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
- package/dist/src/styles/cyjs/routes.js +360 -0
- package/dist/src/styles/cyjs/routes.js.map +1 -0
- package/dist/src/styles/cytoscape/charts.d.ts +23 -0
- package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/charts.js +560 -0
- package/dist/src/styles/cytoscape/charts.js.map +1 -0
- package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/emit.js +156 -48
- package/dist/src/styles/cytoscape/emit.js.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
- package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.js +387 -77
- package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
- package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
- package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/mappings.js +92 -0
- package/dist/src/styles/cytoscape/mappings.js.map +1 -1
- package/dist/src/styles/cytoscape/resolve.d.ts +42 -2
- package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/resolve.js +623 -17
- package/dist/src/styles/cytoscape/resolve.js.map +1 -1
- package/dist/src/styles/defaults.d.ts +46 -26
- package/dist/src/styles/defaults.d.ts.map +1 -1
- package/dist/src/styles/defaults.js +308 -71
- package/dist/src/styles/defaults.js.map +1 -1
- package/dist/src/styles/index.d.ts +4 -3
- package/dist/src/styles/index.d.ts.map +1 -1
- package/dist/src/styles/index.js +3 -2
- package/dist/src/styles/index.js.map +1 -1
- package/dist/src/styles/internal.d.ts +1 -0
- package/dist/src/styles/internal.d.ts.map +1 -1
- package/dist/src/styles/internal.js +1 -0
- package/dist/src/styles/internal.js.map +1 -1
- package/dist/src/styles/io/generic.d.ts.map +1 -1
- package/dist/src/styles/io/generic.js +56 -16
- package/dist/src/styles/io/generic.js.map +1 -1
- package/dist/src/styles/io/round-trip.d.ts +56 -0
- package/dist/src/styles/io/round-trip.d.ts.map +1 -0
- package/dist/src/styles/io/round-trip.js +138 -0
- package/dist/src/styles/io/round-trip.js.map +1 -0
- package/dist/src/styles/io/writer.d.ts.map +1 -1
- package/dist/src/styles/io/writer.js +6 -1
- package/dist/src/styles/io/writer.js.map +1 -1
- package/dist/src/styles/notes.d.ts.map +1 -1
- package/dist/src/styles/notes.js +1 -0
- package/dist/src/styles/notes.js.map +1 -1
- package/dist/src/styles/plan/features.d.ts +1 -1
- package/dist/src/styles/plan/features.d.ts.map +1 -1
- package/dist/src/styles/plan/features.js +22 -2
- package/dist/src/styles/plan/features.js.map +1 -1
- package/dist/src/styles/plan/index.d.ts +1 -1
- package/dist/src/styles/plan/index.d.ts.map +1 -1
- package/dist/src/styles/plan/index.js +1 -1
- package/dist/src/styles/plan/index.js.map +1 -1
- package/dist/src/styles/plan/plan.d.ts.map +1 -1
- package/dist/src/styles/plan/plan.js +61 -4
- package/dist/src/styles/plan/plan.js.map +1 -1
- package/dist/src/styles/plan/resolve.d.ts +11 -0
- package/dist/src/styles/plan/resolve.d.ts.map +1 -1
- package/dist/src/styles/plan/resolve.js +40 -4
- package/dist/src/styles/plan/resolve.js.map +1 -1
- package/dist/src/styles/slots.d.ts +14 -0
- package/dist/src/styles/slots.d.ts.map +1 -0
- package/dist/src/styles/slots.js +20 -0
- package/dist/src/styles/slots.js.map +1 -0
- package/dist/src/styles/types.d.ts +622 -6
- package/dist/src/styles/types.d.ts.map +1 -1
- package/dist/src/styles/vocabulary.d.ts +3 -2
- package/dist/src/styles/vocabulary.d.ts.map +1 -1
- package/dist/src/styles/vocabulary.js +203 -0
- package/dist/src/styles/vocabulary.js.map +1 -1
- package/dist/styles.js +30 -239
- package/dist/styles.js.map +1 -1
- package/dist/xgmml.js +3 -3
- package/package.json +27 -7
- package/src/formats/cx/importer.ts +6 -1
- package/src/formats/cx/styles.ts +143 -9
- package/src/formats/cx2/importer.ts +1 -0
- package/src/formats/cx2/styles.ts +3 -1
- package/src/formats/cys/importer.ts +1 -0
- package/src/formats/cys/styles.ts +27 -5
- package/src/formats/dot/drawing.ts +799 -0
- package/src/formats/dot/importer.ts +120 -35
- package/src/formats/dot/label-places.ts +228 -0
- package/src/formats/dot/record.ts +336 -0
- package/src/formats/dot/styles.ts +1654 -153
- package/src/formats/gexf/dialog-metrics.ts +61 -0
- package/src/formats/gexf/importer.ts +50 -5
- package/src/formats/gexf/preview.ts +217 -0
- package/src/formats/gexf/schema.ts +2 -1
- package/src/formats/gexf/styles.ts +1099 -245
- package/src/formats/gml/importer.ts +291 -76
- package/src/formats/gml/index.ts +1 -1
- package/src/formats/gml/positions.ts +29 -7
- package/src/formats/gml/styles.ts +851 -109
- package/src/formats/graphml/styles-plain.ts +6 -15
- package/src/formats/graphml/styles-yed.ts +762 -173
- package/src/formats/graphml/styles-yfiles3.ts +485 -63
- package/src/formats/graphml/yfiles.ts +19 -6
- package/src/formats/json/dialect.ts +41 -5
- package/src/formats/json/importer.ts +59 -7
- package/src/formats/json/index.ts +1 -0
- package/src/formats/json/positions.ts +22 -5
- package/src/formats/json/styles.ts +2041 -185
- package/src/formats/pajek/draw.ts +458 -0
- package/src/formats/pajek/exporter.ts +81 -49
- package/src/formats/pajek/importer.ts +278 -103
- package/src/formats/pajek/index.ts +1 -0
- package/src/formats/pajek/styles.ts +1381 -133
- package/src/formats/pajek/syntax.ts +27 -2
- package/src/formats/xgmml/emit.ts +73 -5
- package/src/formats/xgmml/styles.ts +330 -71
- package/src/index.ts +5 -1
- package/src/positions/convert.ts +12 -1
- package/src/positions/extract.ts +55 -1
- package/src/positions/index.ts +1 -0
- package/src/positions/types.ts +60 -0
- package/src/sources/builtins.ts +8 -1
- package/src/sources/context.ts +1 -0
- package/src/sources/cypher/descriptor.ts +7 -1
- package/src/sources/cypher/index.ts +148 -18
- package/src/sources/cypher/params.ts +1 -1
- package/src/sources/cypher/query-builder.ts +33 -0
- package/src/sources/ids.ts +6 -0
- package/src/sources/params.ts +3 -0
- package/src/sources/rest/descriptor.ts +5 -0
- package/src/sources/rest/source.ts +16 -0
- package/src/sources/sigv4.ts +6 -4
- package/src/sources/sparql/descriptor.ts +67 -0
- package/src/sources/sparql/index.ts +356 -0
- package/src/sources/sparql/ntriples.ts +219 -0
- package/src/sources/sparql/params.ts +28 -0
- package/src/sources/sparql/query.ts +162 -0
- package/src/sources/types.ts +35 -0
- package/src/styles/annotations.ts +201 -27
- package/src/styles/canon/bends.ts +137 -0
- package/src/styles/canon/color-tables.ts +10 -4
- package/src/styles/canon/color.ts +105 -3
- package/src/styles/canon/enums.ts +98 -8
- package/src/styles/canon/graphviz.ts +71 -10
- package/src/styles/canon/number.ts +19 -0
- package/src/styles/canon/text.ts +187 -16
- package/src/styles/codes.ts +2 -0
- package/src/styles/cyjs/cascade.ts +1160 -84
- package/src/styles/cyjs/defaults-table.ts +3 -0
- package/src/styles/cyjs/emit.ts +233 -13
- package/src/styles/cyjs/face.ts +372 -0
- package/src/styles/cyjs/mappers.ts +492 -27
- package/src/styles/cyjs/routes.ts +432 -0
- package/src/styles/cytoscape/charts.ts +684 -0
- package/src/styles/cytoscape/emit.ts +170 -48
- package/src/styles/cytoscape/lexicon.ts +431 -78
- package/src/styles/cytoscape/mappings.ts +108 -0
- package/src/styles/cytoscape/resolve.ts +741 -17
- package/src/styles/defaults.ts +417 -108
- package/src/styles/index.ts +5 -0
- package/src/styles/internal.ts +1 -0
- package/src/styles/io/generic.ts +79 -23
- package/src/styles/io/round-trip.ts +202 -0
- package/src/styles/io/writer.ts +6 -1
- package/src/styles/notes.ts +1 -0
- package/src/styles/plan/features.ts +23 -2
- package/src/styles/plan/index.ts +1 -1
- package/src/styles/plan/plan.ts +69 -5
- package/src/styles/plan/resolve.ts +47 -4
- package/src/styles/slots.ts +25 -0
- package/src/styles/types.ts +633 -5
- package/src/styles/vocabulary.ts +211 -2
- package/dist/chunks/block-Cu22ewuS.js.map +0 -1
- package/dist/chunks/choose-Cdx6Enl2.js +0 -57
- package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
- package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
- package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
- package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
- package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
- package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
- package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
- package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
- package/dist/chunks/format-BMS-1Nxb.js +0 -64
- package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
- package/dist/chunks/generic-CP6YD34u.js.map +0 -1
- package/dist/chunks/importer-B87_fmVx.js.map +0 -1
- package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
- package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
- package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
- package/dist/chunks/importer-DPZDN40-.js.map +0 -1
- package/dist/chunks/importer-e3huMZbm.js.map +0 -1
- package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
- package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
- package/dist/chunks/styles-CaABMoO1.js.map +0 -1
- package/dist/chunks/styles-P_gmFAOi.js +0 -770
- package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
- package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
- package/dist/chunks/writer-DvHTl36J.js +0 -449
- package/dist/chunks/writer-DvHTl36J.js.map +0 -1
|
@@ -1,15 +1,269 @@
|
|
|
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-iptrlMBb.js";
|
|
11
|
+
import { S as StyleApproximations } from "./approximations-Bzn3L-je.js";
|
|
12
|
+
import { e as elementValues, t as takeFromBlock } from "./round-trip-Zm3_ivgq.js";
|
|
13
|
+
import { v as valueColumns } from "./styles-yed-UMFdNqze.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 iniNumber(draw, name) {
|
|
63
|
+
const v = draw.ini.get(name);
|
|
64
|
+
const n = v === void 0 || v.trim() === "" ? Number.NaN : Number(v);
|
|
65
|
+
return Number.isFinite(n) ? n : null;
|
|
66
|
+
}
|
|
67
|
+
const PARTITION_COLORS = [
|
|
68
|
+
"#00ffff",
|
|
69
|
+
"#ffff00",
|
|
70
|
+
"#7fff00",
|
|
71
|
+
"#ff0000",
|
|
72
|
+
"#0000ff",
|
|
73
|
+
"#ffd8f2",
|
|
74
|
+
"#ffffff",
|
|
75
|
+
"#ff6321",
|
|
76
|
+
"#8c23ff",
|
|
77
|
+
"#606dc4",
|
|
78
|
+
"#1ef9a3",
|
|
79
|
+
"#009900",
|
|
80
|
+
"#7f7f7f",
|
|
81
|
+
"#000000",
|
|
82
|
+
"#ad0000",
|
|
83
|
+
"#ccffb2",
|
|
84
|
+
"#ffff99",
|
|
85
|
+
"#ff00ff",
|
|
86
|
+
"#007091",
|
|
87
|
+
"#ffb528",
|
|
88
|
+
"#ff0a9b",
|
|
89
|
+
"#00e000",
|
|
90
|
+
"#ff779e",
|
|
91
|
+
"#d8f2ff",
|
|
92
|
+
"#d8ff4f",
|
|
93
|
+
"#ff84ff",
|
|
94
|
+
"#e5ffcc",
|
|
95
|
+
"#ccccff",
|
|
96
|
+
"#59ddff",
|
|
97
|
+
"#ffd9bc",
|
|
98
|
+
"#db9370",
|
|
99
|
+
"#ccffff",
|
|
100
|
+
"#d8d8d8",
|
|
101
|
+
"#666666",
|
|
102
|
+
"#a5a5a5",
|
|
103
|
+
"#3f3f3f",
|
|
104
|
+
"#e5e5e5",
|
|
105
|
+
"#262626",
|
|
106
|
+
"#bfbfbf",
|
|
107
|
+
"#595959"
|
|
108
|
+
];
|
|
109
|
+
const VERTEX_SIZE = 20;
|
|
110
|
+
const VERTEX_FILL = "#ffd9bc";
|
|
111
|
+
const SIZE_OF_VERTICES = 8;
|
|
112
|
+
function objectValues(snapshot, kind, n) {
|
|
113
|
+
if (n < 1) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const pajek = snapshot.meta.extra.pajek;
|
|
117
|
+
const name = pajek?.objects?.filter((o) => o.kind === kind)[n - 1]?.column;
|
|
118
|
+
if (name === void 0 || !snapshot.nodes.has(name)) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
return (i) => {
|
|
122
|
+
const v = snapshot.nodes.value(name, i);
|
|
123
|
+
return typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function column(values, property, n) {
|
|
127
|
+
values[property] ??= new Array(n).fill(null);
|
|
128
|
+
return values[property];
|
|
129
|
+
}
|
|
130
|
+
function drawVertices(draw, snapshot, node) {
|
|
131
|
+
const n = snapshot.nodeCount;
|
|
132
|
+
const width = column(node, "width", n);
|
|
133
|
+
const height = column(node, "height", n);
|
|
134
|
+
scaleVertexSizes(draw, width, height);
|
|
135
|
+
sizeByVectors(draw, snapshot, width, height);
|
|
136
|
+
colorByPartition(draw, snapshot, node);
|
|
137
|
+
const opacity = iniNumber(draw, "TransparencyofVertices");
|
|
138
|
+
if (opacity !== null && opacity < 1) {
|
|
139
|
+
const o = Math.max(0, opacity);
|
|
140
|
+
const fill = column(node, "fillOpacity", n);
|
|
141
|
+
fill.forEach((v, i) => {
|
|
142
|
+
fill[i] = (typeof v === "number" ? v : 1) * o;
|
|
143
|
+
});
|
|
144
|
+
column(node, "borderOpacity", n).fill(o * o);
|
|
145
|
+
}
|
|
146
|
+
if (flag(draw, "Form10.effect3d")) {
|
|
147
|
+
effect3d(snapshot, node);
|
|
148
|
+
}
|
|
149
|
+
markVertices(draw, node, n);
|
|
150
|
+
for (const property of ["width", "height"]) {
|
|
151
|
+
if (node[property].every((v) => v === null)) {
|
|
152
|
+
Reflect.deleteProperty(node, property);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function scaleVertexSizes(draw, width, height) {
|
|
157
|
+
const size = iniNumber(draw, "Form8.SizeofVertices");
|
|
158
|
+
if (size === null || size === SIZE_OF_VERTICES) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const f = size / SIZE_OF_VERTICES;
|
|
162
|
+
const scaled = (v) => typeof v === "number" ? v * f : VERTEX_SIZE * f * f;
|
|
163
|
+
for (let i = 0; i < width.length; i++) {
|
|
164
|
+
width[i] = scaled(width[i]);
|
|
165
|
+
height[i] = scaled(height[i]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function colorByPartition(draw, snapshot, node) {
|
|
169
|
+
const partition = objectValues(snapshot, "partition", draw.partition);
|
|
170
|
+
if (partition === null) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const fill = column(node, "fill", snapshot.nodeCount);
|
|
174
|
+
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
175
|
+
const k = partition(i);
|
|
176
|
+
if (k !== null) {
|
|
177
|
+
fill[i] = PARTITION_COLORS[Math.abs(k) % PARTITION_COLORS.length];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function markVertices(draw, node, n) {
|
|
182
|
+
const mark = iniNumber(draw, "Form8.MarkVerticesUsing");
|
|
183
|
+
if (mark === 2) {
|
|
184
|
+
column(node, "label", n).forEach((_, i, a) => {
|
|
185
|
+
a[i] = String(i + 1);
|
|
186
|
+
});
|
|
187
|
+
} else if (mark === 3 || mark === 4) {
|
|
188
|
+
column(node, "label", n).fill("");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function effect3d(snapshot, node) {
|
|
192
|
+
const n = snapshot.nodeCount;
|
|
193
|
+
const fill = column(node, "fill", n);
|
|
194
|
+
const end = column(node, "fillGradient", n);
|
|
195
|
+
const angle = column(node, "fillGradientAngle", n);
|
|
196
|
+
const half = (v) => {
|
|
197
|
+
const h = v / 2;
|
|
198
|
+
const f = Math.floor(h);
|
|
199
|
+
return h - f === 0.5 && f % 2 === 0 ? f : Math.round(h);
|
|
200
|
+
};
|
|
201
|
+
for (let i = 0; i < n; i++) {
|
|
202
|
+
const color = typeof fill[i] === "string" ? String(fill[i]) : VERTEX_FILL;
|
|
203
|
+
end[i] = `#${[1, 3, 5].map(
|
|
204
|
+
(k) => half(Number.parseInt(color.slice(k, k + 2), 16)).toString(16).padStart(2, "0")
|
|
205
|
+
).join("")}`;
|
|
206
|
+
const phi = snapshot.nodes.has("phi") ? Number(snapshot.nodes.value("phi", i)) : 0;
|
|
207
|
+
angle[i] = Number.isFinite(phi) ? ((90 - phi) % 360 + 360) % 360 : 90;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function sizeByVectors(draw, snapshot, width, height) {
|
|
211
|
+
const first = objectValues(snapshot, "vector", draw.vector);
|
|
212
|
+
if (first === null) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const second = objectValues(snapshot, "vector", draw.vector2);
|
|
216
|
+
const scale = (sizes, i, v) => {
|
|
217
|
+
if (v !== null && v >= 0) {
|
|
218
|
+
sizes[i] = (typeof sizes[i] === "number" ? sizes[i] : VERTEX_SIZE) * v;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
222
|
+
const v = first(i);
|
|
223
|
+
if (second === null) {
|
|
224
|
+
const root = v === null || v < 0 ? null : Math.sqrt(v);
|
|
225
|
+
scale(width, i, root);
|
|
226
|
+
scale(height, i, root);
|
|
227
|
+
} else {
|
|
228
|
+
scale(width, i, v);
|
|
229
|
+
scale(height, i, second(i));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function drawLines(draw, snapshot, node, edge) {
|
|
234
|
+
const m = snapshot.edgeCount;
|
|
235
|
+
const opacity = iniNumber(draw, "TransparencyofLines");
|
|
236
|
+
if (opacity !== null && opacity < 1) {
|
|
237
|
+
const o = column(edge, "opacity", m);
|
|
238
|
+
o.forEach((v, e) => {
|
|
239
|
+
o[e] = (typeof v === "number" ? v : 1) * Math.max(0, opacity);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (flag(draw, "Form10.StraightLinesOnly1")) {
|
|
243
|
+
const curved = column(edge, "curved", m);
|
|
244
|
+
for (let e = 0; e < m; e++) {
|
|
245
|
+
const bends = edge.bends?.[e];
|
|
246
|
+
if (bends === null || bends === void 0) {
|
|
247
|
+
curved[e] = false;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (flag(draw, "Form10.ColorGradientLines")) {
|
|
252
|
+
const fill = node.fill;
|
|
253
|
+
const fillOf = (i) => typeof fill?.[i] === "string" ? fill[i] : VERTEX_FILL;
|
|
254
|
+
const colors = column(edge, "gradientColors", m);
|
|
255
|
+
const kind = column(edge, "gradientKind", m);
|
|
256
|
+
const sourceArrow = column(edge, "sourceArrowColor", m);
|
|
257
|
+
const targetArrow = column(edge, "targetArrowColor", m);
|
|
258
|
+
for (let e = 0; e < m; e++) {
|
|
259
|
+
const [s, t] = [fillOf(snapshot.edgeSource(e)), fillOf(snapshot.edgeTarget(e))];
|
|
260
|
+
colors[e] = `${s} ${t}`;
|
|
261
|
+
kind[e] = "linear";
|
|
262
|
+
sourceArrow[e] = s;
|
|
263
|
+
targetArrow[e] = t;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
13
267
|
const LABEL_COLUMN = "label";
|
|
14
268
|
const POSITION_COLUMN = "position";
|
|
15
269
|
const SHAPE_COLUMN = "shape";
|
|
@@ -256,7 +510,7 @@ function parseIntervals(token) {
|
|
|
256
510
|
return [];
|
|
257
511
|
}
|
|
258
512
|
const spells = [];
|
|
259
|
-
for (const part of body.split(
|
|
513
|
+
for (const part of body.split(/[,/]/)) {
|
|
260
514
|
spells.push(parseSpell(token, part));
|
|
261
515
|
}
|
|
262
516
|
return spells;
|
|
@@ -328,6 +582,20 @@ function isParameterKey(text) {
|
|
|
328
582
|
}
|
|
329
583
|
return !/^[+-]?(\.\d|\d)/.test(text) && !/^[+-]?(?:nan|inf|infinity)$/i.test(text);
|
|
330
584
|
}
|
|
585
|
+
const VOIDING_KEYS = /* @__PURE__ */ new Set([
|
|
586
|
+
"bc",
|
|
587
|
+
"bw",
|
|
588
|
+
"s_size",
|
|
589
|
+
"phi",
|
|
590
|
+
"r",
|
|
591
|
+
"q",
|
|
592
|
+
"lc",
|
|
593
|
+
"la",
|
|
594
|
+
"lr",
|
|
595
|
+
"lphi",
|
|
596
|
+
"fos",
|
|
597
|
+
"font"
|
|
598
|
+
]);
|
|
331
599
|
const PAJEK_STYLE_CAPABILITIES = Object.freeze({
|
|
332
600
|
tool: "pajek",
|
|
333
601
|
node: Object.freeze([
|
|
@@ -338,22 +606,93 @@ const PAJEK_STYLE_CAPABILITIES = Object.freeze({
|
|
|
338
606
|
"borderColor",
|
|
339
607
|
"borderWidth",
|
|
340
608
|
"shape",
|
|
609
|
+
"shapePoints",
|
|
341
610
|
"width",
|
|
342
611
|
"height",
|
|
343
612
|
"labelColor",
|
|
344
|
-
"labelSize"
|
|
613
|
+
"labelSize",
|
|
614
|
+
"labelFont",
|
|
615
|
+
"labelPosition",
|
|
616
|
+
"labelOffsetX",
|
|
617
|
+
"labelOffsetY",
|
|
618
|
+
"labelShiftX"
|
|
619
|
+
]),
|
|
620
|
+
edge: Object.freeze([
|
|
621
|
+
"color",
|
|
622
|
+
"opacity",
|
|
623
|
+
"width",
|
|
624
|
+
"lineStyle",
|
|
625
|
+
"sourceArrow",
|
|
626
|
+
"targetArrow",
|
|
627
|
+
"arrowPosition",
|
|
628
|
+
"label",
|
|
629
|
+
"labelColor",
|
|
630
|
+
"labelSize",
|
|
631
|
+
"labelFont"
|
|
345
632
|
]),
|
|
346
|
-
edge: Object.freeze(["color", "opacity", "width", "lineStyle", "sourceArrow", "targetArrow"]),
|
|
347
633
|
block: "native"
|
|
348
634
|
});
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
|
|
635
|
+
const PAJEK_VERTEX_SIZE = 20;
|
|
636
|
+
const PAJEK_FIGURES = /* @__PURE__ */ new Map([
|
|
637
|
+
["other:man", [2.502, 6.487]],
|
|
638
|
+
["other:woman", [3.003, 6.478]]
|
|
639
|
+
]);
|
|
640
|
+
const PAJEK_POINTS_PER_UNIT = 500;
|
|
641
|
+
const NODE_KEYS = [
|
|
642
|
+
"ic",
|
|
643
|
+
"bc",
|
|
644
|
+
"bw",
|
|
645
|
+
"s_size",
|
|
646
|
+
"x_fact",
|
|
647
|
+
"y_fact",
|
|
648
|
+
"phi",
|
|
649
|
+
"q",
|
|
650
|
+
"lc",
|
|
651
|
+
"fos",
|
|
652
|
+
"font",
|
|
653
|
+
"lr",
|
|
654
|
+
"lphi",
|
|
655
|
+
"la"
|
|
656
|
+
];
|
|
657
|
+
const EDGE_KEYS = ["c", "w", "p", "s", "ap", "l", "lc", "fos", "font"];
|
|
658
|
+
const CARRIED = {
|
|
659
|
+
node: [SHAPE_COLUMN, ...NODE_KEYS],
|
|
660
|
+
edge: ["c", "w", "p", "s", "ap"]
|
|
661
|
+
};
|
|
662
|
+
const CARRIED_LINE = CARRIED.edge.filter((key) => key !== "p");
|
|
663
|
+
const EDGE_WIDTH_PER_W = 2;
|
|
664
|
+
const ARC_DEFAULTS = { color: "#999999", width: 1 };
|
|
665
|
+
function carriedParams(keys, whole) {
|
|
666
|
+
let last = /* @__PURE__ */ new Map();
|
|
667
|
+
return (get) => {
|
|
668
|
+
const own = /* @__PURE__ */ new Map();
|
|
669
|
+
for (const key of keys) {
|
|
670
|
+
const v = get(key);
|
|
671
|
+
if (v !== null) {
|
|
672
|
+
own.set(key, v);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
if (whole) {
|
|
676
|
+
if (own.size > 0) {
|
|
677
|
+
last = own;
|
|
678
|
+
return get;
|
|
679
|
+
}
|
|
680
|
+
} else {
|
|
681
|
+
for (const [key, v] of own) {
|
|
682
|
+
last.set(key, v);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
const carried = last;
|
|
686
|
+
return (key) => get(key) ?? (keys.includes(key) ? carried.get(key) ?? null : null);
|
|
687
|
+
};
|
|
688
|
+
}
|
|
352
689
|
const DIRECTED_KEY = "directed";
|
|
353
690
|
const READ = {
|
|
354
691
|
node: [
|
|
355
692
|
"label",
|
|
356
693
|
"shape",
|
|
694
|
+
"shapePoints",
|
|
695
|
+
"shapePointsStretch",
|
|
357
696
|
"fill",
|
|
358
697
|
"fillOpacity",
|
|
359
698
|
"borderColor",
|
|
@@ -361,9 +700,26 @@ const READ = {
|
|
|
361
700
|
"width",
|
|
362
701
|
"height",
|
|
363
702
|
"labelColor",
|
|
364
|
-
"labelSize"
|
|
703
|
+
"labelSize",
|
|
704
|
+
"labelFont",
|
|
705
|
+
"labelPosition",
|
|
706
|
+
"labelOffsetX",
|
|
707
|
+
"labelOffsetY",
|
|
708
|
+
"labelShiftX",
|
|
709
|
+
"labelRotation"
|
|
365
710
|
],
|
|
366
|
-
edge: [
|
|
711
|
+
edge: [
|
|
712
|
+
"color",
|
|
713
|
+
"opacity",
|
|
714
|
+
"width",
|
|
715
|
+
"lineStyle",
|
|
716
|
+
"arrowSize",
|
|
717
|
+
"arrowPosition",
|
|
718
|
+
"label",
|
|
719
|
+
"labelColor",
|
|
720
|
+
"labelSize",
|
|
721
|
+
"labelFont"
|
|
722
|
+
]
|
|
367
723
|
};
|
|
368
724
|
function readColor(raw, property, opacity, put, at) {
|
|
369
725
|
if (raw === null) {
|
|
@@ -371,6 +727,10 @@ function readColor(raw, property, opacity, put, at) {
|
|
|
371
727
|
}
|
|
372
728
|
const c = canonColor(raw, "dvips", at(property));
|
|
373
729
|
if (c === null) {
|
|
730
|
+
const unknown = UNKNOWN_COLORS.get(property);
|
|
731
|
+
if (unknown !== void 0 && typeof raw === "string" && /^[A-Za-z]\w*$/.test(raw.trim())) {
|
|
732
|
+
put(property, unknown);
|
|
733
|
+
}
|
|
374
734
|
return;
|
|
375
735
|
}
|
|
376
736
|
put(property, c.color);
|
|
@@ -379,43 +739,437 @@ function readColor(raw, property, opacity, put, at) {
|
|
|
379
739
|
put(opacity, alpha);
|
|
380
740
|
}
|
|
381
741
|
}
|
|
742
|
+
const UNKNOWN_COLORS = /* @__PURE__ */ new Map([
|
|
743
|
+
["fill", "#ffffff"],
|
|
744
|
+
["color", "#000000"]
|
|
745
|
+
]);
|
|
382
746
|
function readNumber(raw, property, put, at) {
|
|
383
747
|
if (raw !== null) {
|
|
384
748
|
put(property, canonNumber(raw, at(property)));
|
|
385
749
|
}
|
|
386
750
|
}
|
|
387
|
-
function readVertex(get, put, at) {
|
|
751
|
+
function readVertex(get, put, at, place = null) {
|
|
388
752
|
const label = get(LABEL_COLUMN);
|
|
389
753
|
if (label !== null && label !== "") {
|
|
390
754
|
put("label", canonText(label, at("label")));
|
|
391
755
|
}
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
756
|
+
const raw = get(SHAPE_COLUMN);
|
|
757
|
+
const shape = raw === null ? null : canonEnum("shape", raw, "dvips", at("shape"));
|
|
758
|
+
if (raw !== null) {
|
|
759
|
+
put("shape", shape);
|
|
395
760
|
}
|
|
396
761
|
readColor(get("ic"), "fill", "fillOpacity", put, at);
|
|
397
762
|
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);
|
|
763
|
+
readNumber(get("bw"), "borderWidth", put, at);
|
|
764
|
+
readSize(get, put, at, PAJEK_FIGURES.get(String(shape)));
|
|
765
|
+
readOutline(get, put, shape);
|
|
405
766
|
readColor(get("lc"), "labelColor", null, put, at);
|
|
406
767
|
readNumber(get("fos"), "labelSize", put, at);
|
|
768
|
+
readFont(get("font"), put, at);
|
|
769
|
+
readLabelPosition(get, put, at);
|
|
770
|
+
readLabelAngle(get("la"), put, at, place);
|
|
771
|
+
if (shape === "none") {
|
|
772
|
+
for (const [property, value] of EMPTY_LABEL) {
|
|
773
|
+
put(property, value);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
const PAJEK_OUTLINES = /* @__PURE__ */ new Map([
|
|
778
|
+
[
|
|
779
|
+
"rectangle",
|
|
780
|
+
[
|
|
781
|
+
[-1, 1],
|
|
782
|
+
[1, 1],
|
|
783
|
+
[1, -1],
|
|
784
|
+
[-1, -1]
|
|
785
|
+
]
|
|
786
|
+
],
|
|
787
|
+
[
|
|
788
|
+
"triangle",
|
|
789
|
+
[
|
|
790
|
+
[1, -1],
|
|
791
|
+
[0, 1],
|
|
792
|
+
[-1, -1]
|
|
793
|
+
]
|
|
794
|
+
],
|
|
795
|
+
[
|
|
796
|
+
"other:house",
|
|
797
|
+
[
|
|
798
|
+
[-0.7, -1],
|
|
799
|
+
[0.7, -1],
|
|
800
|
+
[0.7, 0.3],
|
|
801
|
+
[1, 0.3],
|
|
802
|
+
[1, 0.4],
|
|
803
|
+
[0, 1],
|
|
804
|
+
[-1, 0.4],
|
|
805
|
+
[-1, 0.3],
|
|
806
|
+
[-0.7, 0.3]
|
|
807
|
+
]
|
|
808
|
+
]
|
|
809
|
+
]);
|
|
810
|
+
const PAJEK_DIAMOND_Q = 1e-3;
|
|
811
|
+
function readOutline(get, put, shape) {
|
|
812
|
+
const phi = numberOrNull(get("phi")) ?? 0;
|
|
813
|
+
const q = numberOrNull(get("q")) ?? PAJEK_DIAMOND_Q;
|
|
814
|
+
const diamond = [
|
|
815
|
+
[-1, 0],
|
|
816
|
+
[-q, 1],
|
|
817
|
+
[q, 1],
|
|
818
|
+
[1, 0],
|
|
819
|
+
[q, -1],
|
|
820
|
+
[-q, -1]
|
|
821
|
+
];
|
|
822
|
+
const corners = shape === "diamond" ? diamond : PAJEK_OUTLINES.get(String(shape));
|
|
823
|
+
if (corners === void 0 || shape !== "diamond" && phi % 360 === 0) {
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
const [w, h] = [numberOrNull(get("x_fact")) || 1, numberOrNull(get("y_fact")) || 1];
|
|
827
|
+
const [c, s] = [Math.cos(phi * Math.PI / 180), Math.sin(phi * Math.PI / 180)];
|
|
828
|
+
const round = (v) => String(Number(v.toFixed(4)) + 0);
|
|
829
|
+
const points = corners.map(([x, y]) => {
|
|
830
|
+
const [px, py] = [x * w, y * h];
|
|
831
|
+
return `${round((px * c - py * s) / w)},${round((px * s + py * c) / h)}`;
|
|
832
|
+
});
|
|
833
|
+
put("shape", "polygon");
|
|
834
|
+
put("shapePoints", points.join(" "));
|
|
835
|
+
put("shapePointsStretch", false);
|
|
836
|
+
}
|
|
837
|
+
const EMPTY_LABEL = [
|
|
838
|
+
["labelSize", 1],
|
|
839
|
+
["labelColor", "#ffffff"],
|
|
840
|
+
["labelPosition", "center"],
|
|
841
|
+
["labelOffsetX", 0],
|
|
842
|
+
["labelOffsetY", 0],
|
|
843
|
+
["labelShiftX", 0]
|
|
844
|
+
];
|
|
845
|
+
function readFont(raw, put, at) {
|
|
846
|
+
if (raw === null || raw === "") {
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
const ps = typeof raw === "string" ? postscriptFont(raw.trim()) : null;
|
|
850
|
+
if (ps === null) {
|
|
851
|
+
readText(raw, "labelFont", put, at);
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
put("labelFont", ps.family);
|
|
407
855
|
}
|
|
408
|
-
function
|
|
856
|
+
function readLabelAngle(raw, put, at, place) {
|
|
857
|
+
let a = raw === null ? null : canonNumber(raw, at("labelRotation"));
|
|
858
|
+
if (a !== null && a >= 360) {
|
|
859
|
+
a = place === null ? null : Math.atan2(0.5 - place[1], place[0] - 0.5) * 180 / Math.PI + a - 360;
|
|
860
|
+
}
|
|
861
|
+
if (a !== null) {
|
|
862
|
+
put("labelRotation", Number((((360 - a) % 360 + 360) % 360).toPrecision(12)));
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
function readSize(get, put, at, figure) {
|
|
866
|
+
for (const [key, property, k] of [
|
|
867
|
+
["x_fact", "width", 0],
|
|
868
|
+
["y_fact", "height", 1]
|
|
869
|
+
]) {
|
|
870
|
+
const f = get(key);
|
|
871
|
+
if (f === null && figure === void 0) {
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
const factor = f === null ? 1 : canonNumber(f, at(property));
|
|
875
|
+
const over = figure?.[k] ?? 1;
|
|
876
|
+
put(property, factor === null ? null : Number((PAJEK_VERTEX_SIZE * factor * over).toPrecision(15)));
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
function readText(raw, property, put, at) {
|
|
880
|
+
if (raw !== null && raw !== "") {
|
|
881
|
+
put(property, canonText(raw, at(property)));
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
const SIDE_ANGLES = /* @__PURE__ */ new Map([
|
|
885
|
+
["right", 0],
|
|
886
|
+
["top-right", 90],
|
|
887
|
+
["left", 180],
|
|
888
|
+
["bottom-right", 285]
|
|
889
|
+
]);
|
|
890
|
+
const NEAREST_SIDES = /* @__PURE__ */ new Map([
|
|
891
|
+
["top", "top-right"],
|
|
892
|
+
["top-left", "top-right"],
|
|
893
|
+
["bottom", "bottom-right"],
|
|
894
|
+
["bottom-left", "bottom-right"]
|
|
895
|
+
]);
|
|
896
|
+
function readLabelPosition(get, put, at) {
|
|
897
|
+
const [lr, lphi, fos] = [get("lr"), get("lphi"), get("fos")];
|
|
898
|
+
if (lr === null && lphi === null && fos === null) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
const radius = lr === null ? PAJEK_LABEL_RADIUS : canonNumber(lr, at("labelPosition"));
|
|
902
|
+
const angle = lphi === null ? PAJEK_LABEL_ANGLE : canonNumber(lphi, at("labelPosition"));
|
|
903
|
+
const size = fos === null ? PAJEK_LABEL_SIZE : canonNumber(fos, at("labelSize"));
|
|
904
|
+
if (radius === null || angle === null || size === null) {
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
const [x, y] = labelOffset(radius, angle, size);
|
|
908
|
+
put("labelPosition", "center");
|
|
909
|
+
put("labelOffsetX", x);
|
|
910
|
+
put("labelOffsetY", y);
|
|
911
|
+
put("labelShiftX", radius === 0 ? 0 : 0.5);
|
|
912
|
+
}
|
|
913
|
+
function labelOffset(radius, angle, size) {
|
|
914
|
+
if (radius === 0) {
|
|
915
|
+
return [0, 0];
|
|
916
|
+
}
|
|
917
|
+
const t = angle * Math.PI / 180;
|
|
918
|
+
const round = (v) => Number(v.toFixed(9)) + 0;
|
|
919
|
+
return [round(radius * Math.cos(t)), round(-radius * Math.sin(t) - PAJEK_BASELINE_TO_MIDDLE * size)];
|
|
920
|
+
}
|
|
921
|
+
const PAJEK_LABEL_RADIUS = 20;
|
|
922
|
+
const PAJEK_LABEL_ANGLE = 285;
|
|
923
|
+
const PAJEK_LABEL_SIZE = 15;
|
|
924
|
+
const PAJEK_BASELINE_TO_MIDDLE = 0.3465;
|
|
925
|
+
function readLine(get, put, at, directed, labels = true, run = null, loop = null) {
|
|
409
926
|
readColor(get("c"), "color", "opacity", put, at);
|
|
410
|
-
readNumber(
|
|
927
|
+
readNumber(
|
|
928
|
+
get("w"),
|
|
929
|
+
"width",
|
|
930
|
+
(property, value) => {
|
|
931
|
+
put(property, typeof value === "number" && !directed ? value * EDGE_WIDTH_PER_W : value);
|
|
932
|
+
},
|
|
933
|
+
at
|
|
934
|
+
);
|
|
411
935
|
const p = get("p");
|
|
412
|
-
if (p
|
|
413
|
-
put("lineStyle",
|
|
936
|
+
if (p === "Dots") {
|
|
937
|
+
put("lineStyle", pajekDash(get, directed));
|
|
938
|
+
} else if (p === "Solid") {
|
|
939
|
+
put("lineStyle", "solid");
|
|
940
|
+
} else if (p !== null) {
|
|
941
|
+
noteAt(at("lineStyle"), STYLE_ISSUE.UNKNOWN_VALUE, typeof p === "string" ? p : JSON.stringify(p));
|
|
942
|
+
put("lineStyle", "solid");
|
|
943
|
+
}
|
|
944
|
+
readNumber(get("s"), "arrowSize", put, at);
|
|
945
|
+
readArrowPosition(get("ap"), put, at);
|
|
946
|
+
const line = loop === null ? get : loopParam(get);
|
|
947
|
+
const controls = loop === null ? null : readLoop(line, put, loop);
|
|
948
|
+
if (labels) {
|
|
949
|
+
readText(get("l"), "label", put, at);
|
|
950
|
+
if (controls === null) {
|
|
951
|
+
readLineLabelPlace(get, put, at, run);
|
|
952
|
+
} else {
|
|
953
|
+
readLineLabelPlace(line, put, at, [PAJEK_POINTS_PER_UNIT, 0], loopTop(controls));
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
if (loop === null) {
|
|
957
|
+
readBezier(get, put, run);
|
|
958
|
+
}
|
|
959
|
+
readColor(get("lc"), "labelColor", null, put, at);
|
|
960
|
+
readNumber(get("fos"), "labelSize", put, at);
|
|
961
|
+
readFont(get("font"), put, at);
|
|
962
|
+
}
|
|
963
|
+
const LOOP_DEFAULTS = { a1: -70, k1: 0.3, a2: -70, k2: 0.3 };
|
|
964
|
+
function loopParam(get) {
|
|
965
|
+
return (key) => get(key) ?? (key in LOOP_DEFAULTS ? LOOP_DEFAULTS[key] : null);
|
|
966
|
+
}
|
|
967
|
+
function readLoop(get, put, loop) {
|
|
968
|
+
const run = [PAJEK_POINTS_PER_UNIT, 0];
|
|
969
|
+
const controls = bezierControls(get, run);
|
|
970
|
+
if (controls === null) {
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
const [[a1, l1], [a2, l2]] = controls;
|
|
974
|
+
const L = PAJEK_POINTS_PER_UNIT;
|
|
975
|
+
const [c1, c2] = [
|
|
976
|
+
[a1 * L, -l1 * L],
|
|
977
|
+
[(a2 - 1) * L, -l2 * L]
|
|
978
|
+
];
|
|
979
|
+
loop([c1, c2]);
|
|
980
|
+
put("curved", true);
|
|
981
|
+
put("bendCurve", "bezier");
|
|
982
|
+
put("targetArrow", "none");
|
|
983
|
+
return [c1, c2];
|
|
984
|
+
}
|
|
985
|
+
function loopTop(controls) {
|
|
986
|
+
const [c1, c2] = controls;
|
|
987
|
+
return Math.atan2(c2[1] - c1[1], c2[0] - c1[0]) * 180 / Math.PI;
|
|
988
|
+
}
|
|
989
|
+
function layLoops(snapshot, loops, node, edge) {
|
|
990
|
+
const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
|
|
991
|
+
for (const [e, controls] of loops) {
|
|
992
|
+
const v = snapshot.edgeSource(e);
|
|
993
|
+
const half = (property) => {
|
|
994
|
+
const size = node[property]?.[v];
|
|
995
|
+
return (typeof size === "number" && size > 0 ? size : PAJEK_VERTEX_SIZE) / 2;
|
|
996
|
+
};
|
|
997
|
+
const [hw, hh] = [half("width"), half("height")];
|
|
998
|
+
const column2 = (property) => edge[property] ??= new Array(snapshot.edgeCount).fill(null);
|
|
999
|
+
column2("bends")[e] = controls.map(([x, y]) => `${fraction(x / hw)},${fraction(-y / hh)}`).join(" ");
|
|
1000
|
+
column2("curved")[e] = true;
|
|
1001
|
+
column2("bendCurve")[e] = "bezier";
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
function readLineLabelPlace(get, put, at, run, direction) {
|
|
1005
|
+
const length = run === null ? 0 : Math.hypot(run[0], run[1]);
|
|
1006
|
+
if (run === null || length === 0) {
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
const n = (key, fallback, property) => {
|
|
1010
|
+
const v = get(key);
|
|
1011
|
+
return v === null ? fallback : canonNumber(v, at(property));
|
|
1012
|
+
};
|
|
1013
|
+
const [lp, lr, lphi, la] = [
|
|
1014
|
+
n("lp", 0.5, "labelOffsetX"),
|
|
1015
|
+
n("lr", 0, "labelOffsetX"),
|
|
1016
|
+
n("lphi", 0, "labelOffsetX"),
|
|
1017
|
+
n("la", 0, "labelRotation")
|
|
1018
|
+
];
|
|
1019
|
+
const size = n("fos", PAJEK_LABEL_SIZE, "labelSize");
|
|
1020
|
+
if (lp === null || lr === null || lphi === null || la === null || size === null) {
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
const along = 0.5 - (lp <= 1 ? lp : lp / length);
|
|
1024
|
+
const t = lphi * Math.PI / 180;
|
|
1025
|
+
const round = (v) => Number(v.toFixed(9)) + 0;
|
|
1026
|
+
const turn = ((direction ?? lineDirection(get, run, along + 0.5)) - la) % 360 + 360;
|
|
1027
|
+
const up = turn * Math.PI / 180;
|
|
1028
|
+
const rise = PAJEK_BASELINE_TO_MIDDLE * size;
|
|
1029
|
+
put("labelPosition", "center");
|
|
1030
|
+
put("labelOffsetX", round(along * run[0] + lr * Math.cos(t) + rise * Math.sin(up)));
|
|
1031
|
+
put("labelOffsetY", round(along * run[1] - lr * Math.sin(t) - rise * Math.cos(up)));
|
|
1032
|
+
put("labelRotation", round(turn % 360));
|
|
1033
|
+
}
|
|
1034
|
+
function readBezier(get, put, run) {
|
|
1035
|
+
const controls = bezierControls(get, run);
|
|
1036
|
+
if (controls === null) {
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
|
|
1040
|
+
put("curved", true);
|
|
1041
|
+
put("bendCurve", "bezier");
|
|
1042
|
+
put("bends", controls.map(([along, across]) => `${fraction(along)},${fraction(across)}`).join(" "));
|
|
1043
|
+
}
|
|
1044
|
+
function readArcEnd(get, put, run, target) {
|
|
1045
|
+
const ap = numberOrNull(get("ap")) ?? 0;
|
|
1046
|
+
const length = Math.hypot(run[0], run[1]);
|
|
1047
|
+
if (ap !== 0 || length === 0 || bezierControls(get, run) === null) {
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
const [ux, uy] = [run[0] / length, run[1] / length];
|
|
1051
|
+
const r = 1 / Math.hypot(ux / (target[0] / 2), uy / (target[1] / 2));
|
|
1052
|
+
const back = 1.5 + 5 * (numberOrNull(get("s")) ?? 1);
|
|
1053
|
+
const turn = -(numberOrNull(get("a2")) ?? 0) * Math.PI / 180;
|
|
1054
|
+
const [c, s] = [Math.cos(turn), Math.sin(turn)];
|
|
1055
|
+
const end = [run[0] - r * ux - back * (ux * c - uy * s), run[1] - r * uy - back * (ux * s + uy * c)];
|
|
1056
|
+
const controls = bezierControls(get, end);
|
|
1057
|
+
if (controls === null) {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
const L2 = length * length;
|
|
1061
|
+
const fraction = (x) => String(Math.round(x * 1e4) / 1e4 || 0);
|
|
1062
|
+
const bends = controls.map(([along, left]) => {
|
|
1063
|
+
const [x, y] = [along * end[0] + left * end[1], along * end[1] - left * end[0]];
|
|
1064
|
+
return `${fraction((x * run[0] + y * run[1]) / L2)},${fraction((x * run[1] - y * run[0]) / L2)}`;
|
|
1065
|
+
});
|
|
1066
|
+
put("bends", bends.join(" "));
|
|
1067
|
+
}
|
|
1068
|
+
function bezierControls(get, run) {
|
|
1069
|
+
const [a1, k1, a2, k2] = ["a1", "k1", "a2", "k2"].map((key) => numberOrNull(get(key)));
|
|
1070
|
+
if (a1 === null && k1 === null && a2 === null && k2 === null || run === null || run[0] === 0 && run[1] === 0) {
|
|
1071
|
+
return null;
|
|
1072
|
+
}
|
|
1073
|
+
const [s, t] = [k1 ?? 1, k2 ?? 1];
|
|
1074
|
+
if (s < 0 || t < 0) {
|
|
1075
|
+
return null;
|
|
1076
|
+
}
|
|
1077
|
+
const rad = Math.PI / 180;
|
|
1078
|
+
const [u, v] = [(a1 ?? 0) * rad, (a2 ?? 0) * rad];
|
|
1079
|
+
return [
|
|
1080
|
+
[s / 2 * Math.cos(u), -s / 2 * Math.sin(u)],
|
|
1081
|
+
[1 - t / 2 * Math.cos(v), -t / 2 * Math.sin(v)]
|
|
1082
|
+
];
|
|
1083
|
+
}
|
|
1084
|
+
function lineDirection(get, run, along) {
|
|
1085
|
+
const controls = bezierControls(get, run);
|
|
1086
|
+
let [dx, dy] = run;
|
|
1087
|
+
if (controls !== null) {
|
|
1088
|
+
const t = Math.min(1, Math.max(0, along));
|
|
1089
|
+
const p = [[0, 0], ...controls, [1, 0]];
|
|
1090
|
+
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]);
|
|
1091
|
+
const [a, l] = [d(0), d(1)];
|
|
1092
|
+
[dx, dy] = [a * run[0] + l * run[1], a * run[1] - l * run[0]];
|
|
1093
|
+
}
|
|
1094
|
+
return Math.atan2(dy, dx) * 180 / Math.PI;
|
|
1095
|
+
}
|
|
1096
|
+
function readLineValue(value, get, put, directed = true) {
|
|
1097
|
+
if (value === 0) {
|
|
1098
|
+
put("visible", false);
|
|
1099
|
+
} else if (value !== null && value < 0 && get("p") === null) {
|
|
1100
|
+
put("lineStyle", pajekDash(get, directed));
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
const PAJEK_DASH = 5;
|
|
1104
|
+
function pajekDash(get, directed) {
|
|
1105
|
+
const w = numberOrNull(get("w"));
|
|
1106
|
+
const width = (w ?? 1) * (directed ? 1 : EDGE_WIDTH_PER_W);
|
|
1107
|
+
return PAJEK_DASH <= 1.5 * Math.max(1, width) ? "dotted" : "dashed";
|
|
1108
|
+
}
|
|
1109
|
+
function readHooks(get, put, source, target) {
|
|
1110
|
+
for (const [key, property, shape] of [
|
|
1111
|
+
["h1", "sourcePort", source],
|
|
1112
|
+
["h2", "targetPort", target]
|
|
1113
|
+
]) {
|
|
1114
|
+
const hook = numberOrNull(get(key));
|
|
1115
|
+
const port = hook === null ? null : hookPort(shape, hook);
|
|
1116
|
+
if (port !== null) {
|
|
1117
|
+
const round = (v) => String(Number(v.toFixed(4)) + 0);
|
|
1118
|
+
put(property, `${round(port[0])},${round(port[1])}`);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
function hookPort(shape, hook) {
|
|
1123
|
+
if (!Number.isInteger(hook) || hook < 1) {
|
|
1124
|
+
return null;
|
|
1125
|
+
}
|
|
1126
|
+
const keyword = typeof shape === "string" ? shape.toLowerCase() : "ellipse";
|
|
1127
|
+
if (keyword === "ellipse" || keyword === "cross") {
|
|
1128
|
+
const a = hook * Math.PI / 180;
|
|
1129
|
+
return [Math.cos(a), Math.sin(a)];
|
|
1130
|
+
}
|
|
1131
|
+
if (keyword !== "box" || hook > 400) {
|
|
1132
|
+
return null;
|
|
1133
|
+
}
|
|
1134
|
+
const d = hook * 0.02;
|
|
1135
|
+
if (hook <= 50) {
|
|
1136
|
+
return [1, d];
|
|
1137
|
+
}
|
|
1138
|
+
if (hook <= 150) {
|
|
1139
|
+
return [2 - d, 1];
|
|
1140
|
+
}
|
|
1141
|
+
if (hook <= 250) {
|
|
1142
|
+
return [-1, 4 - d];
|
|
1143
|
+
}
|
|
1144
|
+
return hook <= 350 ? [d - 6, -1] : [1, d - 8];
|
|
1145
|
+
}
|
|
1146
|
+
function numberOrNull(raw) {
|
|
1147
|
+
if (typeof raw === "string" && raw.trim() !== "") {
|
|
1148
|
+
raw = Number(raw);
|
|
1149
|
+
}
|
|
1150
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : null;
|
|
1151
|
+
}
|
|
1152
|
+
function readArrowPosition(raw, put, at) {
|
|
1153
|
+
if (raw === null) {
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
const ap = canonNumber(raw, at("arrowPosition"));
|
|
1157
|
+
if (ap !== null && ap > 1) {
|
|
1158
|
+
noteAt(at("arrowPosition"), STYLE_ISSUE.NOT_CARRIED, `ap ${String(ap)}`);
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
if (ap !== 0) {
|
|
1162
|
+
put("arrowPosition", ap);
|
|
414
1163
|
}
|
|
415
1164
|
}
|
|
416
1165
|
function cells(table, i) {
|
|
417
|
-
return (key) =>
|
|
1166
|
+
return (key) => {
|
|
1167
|
+
const v = table.has(key) ? plainCell(table.value(key, i)) : null;
|
|
1168
|
+
return COLOR_PARAMS.has(key) && typeof v === "string" && NUMERIC_COLOR.test(v) ? null : v;
|
|
1169
|
+
};
|
|
418
1170
|
}
|
|
1171
|
+
const COLOR_PARAMS = /* @__PURE__ */ new Set(["ic", "bc", "lc", "c"]);
|
|
1172
|
+
const NUMERIC_COLOR = /^[\d.]+(?: [\d.]+)*$/;
|
|
419
1173
|
function directedEdges(snapshot) {
|
|
420
1174
|
const out = new Array(snapshot.edgeCount).fill(snapshot.directed);
|
|
421
1175
|
const col = snapshot.directed ? snapshot.edges.byRole("directed") : null;
|
|
@@ -431,32 +1185,72 @@ function styleColumns(table, keys) {
|
|
|
431
1185
|
}
|
|
432
1186
|
function pajekStyles(snapshot, context) {
|
|
433
1187
|
const notes = new StyleNotes();
|
|
1188
|
+
const { block, draw, voided } = keptOf(context.kept);
|
|
1189
|
+
const labels = drawsLineLabels(draw);
|
|
1190
|
+
const place = places(snapshot);
|
|
1191
|
+
const window = draw ?? { width: PAJEK_POINTS_PER_UNIT, height: PAJEK_POINTS_PER_UNIT };
|
|
1192
|
+
const loops = /* @__PURE__ */ new Map();
|
|
1193
|
+
const runOf = (e) => {
|
|
1194
|
+
const [s, t] = [place(snapshot.edgeSource(e)), place(snapshot.edgeTarget(e))];
|
|
1195
|
+
return s === null || t === null ? null : [(t[0] - s[0]) * window.width, (t[1] - s[1]) * window.height];
|
|
1196
|
+
};
|
|
434
1197
|
const read = (target) => {
|
|
435
1198
|
const table = target === "node" ? snapshot.nodes : snapshot.edges;
|
|
436
1199
|
const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
|
|
437
1200
|
const out = valueColumns(n);
|
|
1201
|
+
const carry = carriedParams(target === "node" ? CARRIED.node : CARRIED_LINE, target === "node");
|
|
438
1202
|
for (let i = 0; i < n; i++) {
|
|
439
1203
|
context.budget.spend(target, 1);
|
|
440
1204
|
const at = (property) => ({ notes, target, property, element: i, budget: context.budget });
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
1205
|
+
const put = (property, value) => {
|
|
1206
|
+
out.put(i, property, value);
|
|
1207
|
+
};
|
|
1208
|
+
const own = cells(table, i);
|
|
1209
|
+
const get = target === "node" && voided.has(i) ? voidedParams(own, keywords[i - 1] ?? null) : carry(own);
|
|
1210
|
+
if (target === "node") {
|
|
1211
|
+
readVertex(get, put, at, place(i));
|
|
1212
|
+
keywords[i] = get(SHAPE_COLUMN);
|
|
1213
|
+
} else {
|
|
1214
|
+
readEdge(i, get, put, at);
|
|
1215
|
+
}
|
|
448
1216
|
}
|
|
449
1217
|
return out.values;
|
|
450
1218
|
};
|
|
1219
|
+
const readEdge = (i, get, put, at) => {
|
|
1220
|
+
const run = runOf(i);
|
|
1221
|
+
const loop = run !== null && block === null && snapshot.edgeSource(i) === snapshot.edgeTarget(i) ? (controls) => {
|
|
1222
|
+
loops.set(i, controls);
|
|
1223
|
+
} : null;
|
|
1224
|
+
readLine(get, put, at, directed[i], labels, run, loop);
|
|
1225
|
+
if (directed[i] && loop === null && run !== null) {
|
|
1226
|
+
readArcEnd(get, put, run, targetSize(snapshot.edgeTarget(i)));
|
|
1227
|
+
}
|
|
1228
|
+
readLineValue(lineValue(i), get, put, directed[i]);
|
|
1229
|
+
readHooks(get, put, keywords[snapshot.edgeSource(i)], keywords[snapshot.edgeTarget(i)]);
|
|
1230
|
+
};
|
|
1231
|
+
const directed = directedEdges(snapshot);
|
|
1232
|
+
const keywords = [];
|
|
1233
|
+
const weights = explicitWeights(snapshot);
|
|
1234
|
+
const lineValue = (e) => weights.isExplicit(e) ? weights.value(e) : numberOrNull(cells(snapshot.edges, e)(VALUE_COLUMN));
|
|
451
1235
|
const node = read("node");
|
|
1236
|
+
const targetSize = (v) => {
|
|
1237
|
+
const size = (property) => {
|
|
1238
|
+
const s = node[property]?.[v];
|
|
1239
|
+
return typeof s === "number" && s > 0 ? s : PAJEK_VERTEX_SIZE;
|
|
1240
|
+
};
|
|
1241
|
+
return [size("width"), size("height")];
|
|
1242
|
+
};
|
|
452
1243
|
const edge = read("edge");
|
|
453
|
-
|
|
1244
|
+
if (draw !== null) {
|
|
1245
|
+
drawVertices(draw, snapshot, node);
|
|
1246
|
+
drawLines(draw, snapshot, node, edge);
|
|
1247
|
+
}
|
|
1248
|
+
layLoops(snapshot, loops, node, edge);
|
|
454
1249
|
if (block !== null) {
|
|
455
|
-
exactFromBlock(snapshot, block, { node, edge });
|
|
1250
|
+
exactFromBlock(snapshot, block, { node, edge }, labels);
|
|
456
1251
|
}
|
|
457
1252
|
const rules = [];
|
|
458
1253
|
const columns = /* @__PURE__ */ new Map();
|
|
459
|
-
const directed = directedEdges(snapshot);
|
|
460
1254
|
if (directed.some(Boolean)) {
|
|
461
1255
|
columns.set(
|
|
462
1256
|
DIRECTED_KEY,
|
|
@@ -468,14 +1262,14 @@ function pajekStyles(snapshot, context) {
|
|
|
468
1262
|
role: "group",
|
|
469
1263
|
origin: "tool",
|
|
470
1264
|
where: { has: { style: DIRECTED_KEY } },
|
|
471
|
-
set: { targetArrow: "triangle" }
|
|
1265
|
+
set: { targetArrow: "triangle", color: ARC_DEFAULTS.color, width: ARC_DEFAULTS.width }
|
|
472
1266
|
});
|
|
473
1267
|
}
|
|
474
1268
|
return {
|
|
475
1269
|
canonical: true,
|
|
476
1270
|
dialect: "dvips",
|
|
477
1271
|
tool: "pajek",
|
|
478
|
-
units: "
|
|
1272
|
+
units: "px",
|
|
479
1273
|
node: { values: node },
|
|
480
1274
|
edge: { values: edge, rules, columns },
|
|
481
1275
|
notes: notes.list(),
|
|
@@ -486,6 +1280,39 @@ function pajekStyles(snapshot, context) {
|
|
|
486
1280
|
}
|
|
487
1281
|
};
|
|
488
1282
|
}
|
|
1283
|
+
function places(snapshot) {
|
|
1284
|
+
const col = snapshot.nodes.byRole("position");
|
|
1285
|
+
return (i) => {
|
|
1286
|
+
const v = col === null || col === void 0 ? null : col.value(i);
|
|
1287
|
+
if (v === null || typeof v !== "object" || !("length" in v)) {
|
|
1288
|
+
return null;
|
|
1289
|
+
}
|
|
1290
|
+
const [x, y] = v;
|
|
1291
|
+
return typeof x === "number" && typeof y === "number" ? [x, y] : null;
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
function keptOf(kept) {
|
|
1295
|
+
if (typeof kept === "string") {
|
|
1296
|
+
return { block: kept, draw: null, voided: /* @__PURE__ */ new Set() };
|
|
1297
|
+
}
|
|
1298
|
+
if (typeof kept === "object" && kept !== null) {
|
|
1299
|
+
const { block, pajekDraw, voided } = kept;
|
|
1300
|
+
return {
|
|
1301
|
+
block: typeof block === "string" ? block : null,
|
|
1302
|
+
draw: pajekDraw ?? null,
|
|
1303
|
+
voided: new Set(voided ?? [])
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
return { block: null, draw: null, voided: /* @__PURE__ */ new Set() };
|
|
1307
|
+
}
|
|
1308
|
+
function voidedParams(own, before) {
|
|
1309
|
+
return (key) => {
|
|
1310
|
+
if (key === LABEL_COLUMN) {
|
|
1311
|
+
return own(key);
|
|
1312
|
+
}
|
|
1313
|
+
return key === SHAPE_COLUMN ? before : null;
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
489
1316
|
const SHAPES = /* @__PURE__ */ new Map([
|
|
490
1317
|
["ellipse", "ellipse"],
|
|
491
1318
|
["rectangle", "box"],
|
|
@@ -526,9 +1353,37 @@ function shapeKeyword(get, approximate) {
|
|
|
526
1353
|
if (keyword !== void 0) {
|
|
527
1354
|
return keyword;
|
|
528
1355
|
}
|
|
1356
|
+
if (shape === "polygon" && diamondQ(get) !== null) {
|
|
1357
|
+
return "diamond";
|
|
1358
|
+
}
|
|
529
1359
|
approximate("shape", shape);
|
|
1360
|
+
const points = get("shapePoints");
|
|
1361
|
+
if (shape === "polygon" && points !== null) {
|
|
1362
|
+
approximate("shapePoints", points);
|
|
1363
|
+
}
|
|
530
1364
|
return NEAREST_SHAPES.get(shape) ?? "ellipse";
|
|
531
1365
|
}
|
|
1366
|
+
function diamondQ(get) {
|
|
1367
|
+
const points = get("shapePoints");
|
|
1368
|
+
const corners = typeof points === "string" ? points.trim().split(/\s+/).map((p) => p.split(",").map(Number)) : [];
|
|
1369
|
+
if (corners.length !== 6) {
|
|
1370
|
+
return null;
|
|
1371
|
+
}
|
|
1372
|
+
const q = corners[2][0];
|
|
1373
|
+
const want = [
|
|
1374
|
+
[-1, 0],
|
|
1375
|
+
[-q, 1],
|
|
1376
|
+
[q, 1],
|
|
1377
|
+
[1, 0],
|
|
1378
|
+
[q, -1],
|
|
1379
|
+
[-q, -1]
|
|
1380
|
+
];
|
|
1381
|
+
return want.every(([x, y], k) => corners[k][0] === x && corners[k][1] === y) ? q : null;
|
|
1382
|
+
}
|
|
1383
|
+
function pajekDefault(target, property) {
|
|
1384
|
+
const values = toolDefaults("pajek")?.[target];
|
|
1385
|
+
return values?.[property]?.value;
|
|
1386
|
+
}
|
|
532
1387
|
function vertexParams(get, approximate) {
|
|
533
1388
|
const out = /* @__PURE__ */ new Map();
|
|
534
1389
|
opaque(get, ["fillOpacity", "opacity"], approximate);
|
|
@@ -536,54 +1391,117 @@ function vertexParams(get, approximate) {
|
|
|
536
1391
|
if (keyword !== "ellipse") {
|
|
537
1392
|
out.set(SHAPE_COLUMN, keyword);
|
|
538
1393
|
}
|
|
1394
|
+
const q = diamondQ(get);
|
|
1395
|
+
if (q !== null && q !== PAJEK_DIAMOND_Q) {
|
|
1396
|
+
out.set("q", q);
|
|
1397
|
+
}
|
|
1398
|
+
vertexColorParams(get, out);
|
|
1399
|
+
vertexSizeParams(get, out);
|
|
1400
|
+
const bw = get("borderWidth");
|
|
1401
|
+
if (typeof bw === "number" && bw !== pajekDefault("node", "borderWidth")) {
|
|
1402
|
+
out.set("bw", bw);
|
|
1403
|
+
}
|
|
1404
|
+
fontParam(get, out, pajekDefault("node", "labelFont"));
|
|
1405
|
+
labelPositionParams(get, out, approximate);
|
|
1406
|
+
return out;
|
|
1407
|
+
}
|
|
1408
|
+
function vertexColorParams(get, out) {
|
|
539
1409
|
const colors = [
|
|
540
1410
|
["fill", "ic"],
|
|
541
1411
|
["borderColor", "bc"],
|
|
542
1412
|
["labelColor", "lc"]
|
|
543
1413
|
];
|
|
544
|
-
const numbers = [
|
|
545
|
-
["width", "x_fact"],
|
|
546
|
-
["height", "y_fact"],
|
|
547
|
-
["labelSize", "fos"]
|
|
548
|
-
];
|
|
549
1414
|
for (const [property, key] of colors) {
|
|
550
1415
|
const v = get(property);
|
|
551
|
-
if (typeof v === "string" &&
|
|
1416
|
+
if (typeof v === "string" && v !== pajekDefault("node", property)) {
|
|
552
1417
|
out.set(key, pajekColorText(v));
|
|
553
1418
|
}
|
|
554
1419
|
}
|
|
555
|
-
|
|
1420
|
+
}
|
|
1421
|
+
function vertexSizeParams(get, out) {
|
|
1422
|
+
const numbers = [
|
|
1423
|
+
["width", "x_fact", PAJEK_VERTEX_SIZE],
|
|
1424
|
+
["height", "y_fact", PAJEK_VERTEX_SIZE],
|
|
1425
|
+
["labelSize", "fos", 1]
|
|
1426
|
+
];
|
|
1427
|
+
const figure = PAJEK_FIGURES.get(String(get("shape")));
|
|
1428
|
+
for (const [property, key, per] of numbers) {
|
|
556
1429
|
const v = get(property);
|
|
557
|
-
|
|
558
|
-
|
|
1430
|
+
let over = 1;
|
|
1431
|
+
if (figure !== void 0 && key !== "fos") {
|
|
1432
|
+
over = figure[key === "x_fact" ? 0 : 1];
|
|
1433
|
+
}
|
|
1434
|
+
if (typeof v === "number" && (over !== 1 || v !== pajekDefault("node", property))) {
|
|
1435
|
+
out.set(key, Number((v / (per * over)).toPrecision(15)));
|
|
559
1436
|
}
|
|
560
1437
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
1438
|
+
}
|
|
1439
|
+
function fontParam(get, out, skip) {
|
|
1440
|
+
const font = get("labelFont");
|
|
1441
|
+
const name = typeof font === "string" && font !== "" ? graphvizFontName(font, false, false) : null;
|
|
1442
|
+
if (name !== null && name !== skip) {
|
|
1443
|
+
out.set("font", name);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
function labelPositionParams(get, out, approximate) {
|
|
1447
|
+
const position = get("labelPosition");
|
|
1448
|
+
if (typeof position !== "string") {
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
if (position === "center") {
|
|
1452
|
+
const polar = polarOf(get);
|
|
1453
|
+
if (polar === null) {
|
|
1454
|
+
out.set("lr", 0);
|
|
1455
|
+
} else if (polar[0] !== PAJEK_LABEL_RADIUS || polar[1] !== PAJEK_LABEL_ANGLE) {
|
|
1456
|
+
out.set("lr", polar[0]);
|
|
1457
|
+
out.set("lphi", polar[1]);
|
|
568
1458
|
}
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1461
|
+
const nearest = NEAREST_SIDES.get(position);
|
|
1462
|
+
if (nearest !== void 0) {
|
|
1463
|
+
approximate("labelPosition", position);
|
|
1464
|
+
}
|
|
1465
|
+
const angle = SIDE_ANGLES.get(nearest ?? position);
|
|
1466
|
+
if (angle !== void 0 && angle !== PAJEK_LABEL_ANGLE) {
|
|
1467
|
+
out.set("lphi", angle);
|
|
569
1468
|
}
|
|
570
|
-
|
|
1469
|
+
}
|
|
1470
|
+
function polarOf(get) {
|
|
1471
|
+
const [x, y, shift] = [get("labelOffsetX"), get("labelOffsetY"), get("labelShiftX")];
|
|
1472
|
+
if (typeof x !== "number" || typeof y !== "number" || shift !== 0.5) {
|
|
1473
|
+
return null;
|
|
1474
|
+
}
|
|
1475
|
+
const size = get("labelSize");
|
|
1476
|
+
const up = y + PAJEK_BASELINE_TO_MIDDLE * (typeof size === "number" ? size : PAJEK_LABEL_SIZE);
|
|
1477
|
+
const round = (v) => Number(v.toFixed(6)) + 0;
|
|
1478
|
+
const lr = round(Math.hypot(x, up));
|
|
1479
|
+
return lr === 0 ? null : [lr, round((Math.atan2(-up, x) * 180 / Math.PI % 360 + 360) % 360)];
|
|
1480
|
+
}
|
|
1481
|
+
function lineDefaults(directed) {
|
|
1482
|
+
return directed ? ARC_DEFAULTS : { color: pajekDefault("edge", "color"), width: pajekDefault("edge", "width") };
|
|
571
1483
|
}
|
|
572
1484
|
function lineParams(get, directed, approximate) {
|
|
573
1485
|
const out = /* @__PURE__ */ new Map();
|
|
574
1486
|
opaque(get, ["opacity"], approximate);
|
|
1487
|
+
const defaults = lineDefaults(directed);
|
|
575
1488
|
const color = get("color");
|
|
576
|
-
if (typeof color === "string" && color !==
|
|
1489
|
+
if (typeof color === "string" && color !== defaults.color) {
|
|
577
1490
|
out.set("c", pajekColorText(color));
|
|
578
1491
|
}
|
|
579
1492
|
const width = get("width");
|
|
580
|
-
if (typeof width === "number") {
|
|
581
|
-
out.set("w", width);
|
|
1493
|
+
if (typeof width === "number" && width !== defaults.width) {
|
|
1494
|
+
out.set("w", directed ? width : Number((width / EDGE_WIDTH_PER_W).toPrecision(15)));
|
|
582
1495
|
}
|
|
583
1496
|
const lineStyle = get("lineStyle");
|
|
584
|
-
if (typeof lineStyle === "string" && lineStyle !== "solid" && pajekDots(lineStyle, approximate)) {
|
|
1497
|
+
if (typeof lineStyle === "string" && lineStyle !== "solid" && pajekDots(lineStyle, out, directed, approximate)) {
|
|
585
1498
|
out.set("p", "Dots");
|
|
586
1499
|
}
|
|
1500
|
+
const position = get("arrowPosition");
|
|
1501
|
+
if (typeof position === "number" && position > 0) {
|
|
1502
|
+
out.set("ap", position);
|
|
1503
|
+
}
|
|
1504
|
+
lineLabelParams(get, out, approximate);
|
|
587
1505
|
const target = get("targetArrow");
|
|
588
1506
|
if (target !== null && target !== (directed ? "triangle" : "none")) {
|
|
589
1507
|
approximate("targetArrow", target);
|
|
@@ -594,47 +1512,50 @@ function lineParams(get, directed, approximate) {
|
|
|
594
1512
|
}
|
|
595
1513
|
return out;
|
|
596
1514
|
}
|
|
597
|
-
function
|
|
598
|
-
|
|
599
|
-
|
|
1515
|
+
function lineLabelParams(get, out, approximate) {
|
|
1516
|
+
const label = get("label");
|
|
1517
|
+
if (typeof label === "string" && label !== "") {
|
|
1518
|
+
const text = pajekLabelText(label);
|
|
1519
|
+
if (text !== label) {
|
|
1520
|
+
approximate("label", label);
|
|
1521
|
+
}
|
|
1522
|
+
out.set("l", text);
|
|
600
1523
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
1524
|
+
const labelColor = get("labelColor");
|
|
1525
|
+
if (typeof labelColor === "string") {
|
|
1526
|
+
out.set("lc", pajekColorText(labelColor));
|
|
1527
|
+
}
|
|
1528
|
+
const labelSize = get("labelSize");
|
|
1529
|
+
if (typeof labelSize === "number") {
|
|
1530
|
+
out.set("fos", labelSize);
|
|
608
1531
|
}
|
|
609
|
-
|
|
1532
|
+
fontParam(get, out);
|
|
610
1533
|
}
|
|
611
|
-
function
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
if (ex === null) {
|
|
615
|
-
return;
|
|
1534
|
+
function pajekDots(lineStyle, params, directed, approximate) {
|
|
1535
|
+
if (lineStyle === pajekDash((key) => params.get(key) ?? null, directed)) {
|
|
1536
|
+
return true;
|
|
616
1537
|
}
|
|
1538
|
+
approximate("lineStyle", lineStyle);
|
|
1539
|
+
return ["dashed", "dotted", "dash-dot", "long-dash"].includes(lineStyle);
|
|
1540
|
+
}
|
|
1541
|
+
function exactFromBlock(snapshot, text, read, labels) {
|
|
617
1542
|
const notes = new StyleNotes();
|
|
618
1543
|
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
|
-
}
|
|
1544
|
+
takeFromBlock(snapshot, text, "pajek", (target) => ({
|
|
1545
|
+
values: read[target],
|
|
1546
|
+
properties: READ[target],
|
|
1547
|
+
writes: PAJEK_STYLE_CAPABILITIES[target],
|
|
1548
|
+
readBack: (i, want) => {
|
|
1549
|
+
const back = writtenAndReadBack(target, want, directed[i], notes, labels);
|
|
1550
|
+
return (property) => back.get(property) ?? null;
|
|
1551
|
+
},
|
|
1552
|
+
// a label the block places by a side clears the offsets its `lphi` reads back as
|
|
1553
|
+
take: (property, wanted) => wanted !== null || LABEL_PLACE.has(property) || OUTLINE.has(property)
|
|
1554
|
+
}));
|
|
636
1555
|
}
|
|
637
|
-
|
|
1556
|
+
const OUTLINE = /* @__PURE__ */ new Set(["shapePoints", "shapePointsStretch"]);
|
|
1557
|
+
const LABEL_PLACE = /* @__PURE__ */ new Set(["labelOffsetX", "labelOffsetY", "labelShiftX"]);
|
|
1558
|
+
function writtenAndReadBack(target, want, directed, notes, labels) {
|
|
638
1559
|
const ignore = () => void 0;
|
|
639
1560
|
const params = target === "node" ? vertexParams(want, ignore) : lineParams(want, directed, ignore);
|
|
640
1561
|
const back = /* @__PURE__ */ new Map();
|
|
@@ -642,15 +1563,26 @@ function writtenAndReadBack(target, want, directed, notes) {
|
|
|
642
1563
|
if (typeof label === "string") {
|
|
643
1564
|
params.set(LABEL_COLUMN, pajekLabelText(label));
|
|
644
1565
|
}
|
|
645
|
-
(target === "node"
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
);
|
|
1566
|
+
if (target === "node" && [...params.keys()].every((key) => key === LABEL_COLUMN)) {
|
|
1567
|
+
params.set(SHAPE_COLUMN, "ellipse");
|
|
1568
|
+
}
|
|
1569
|
+
for (const key of target === "edge" ? CARRIED.edge : []) {
|
|
1570
|
+
if (!params.has(key)) {
|
|
1571
|
+
params.set(key, lineRestated(key, directed));
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
const get = (key) => params.get(key) ?? null;
|
|
1575
|
+
const put = (property, value) => {
|
|
1576
|
+
if (value !== null) {
|
|
1577
|
+
back.set(property, value);
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
const at = (property) => ({ notes, target, property });
|
|
1581
|
+
if (target === "node") {
|
|
1582
|
+
readVertex(get, put, at);
|
|
1583
|
+
} else {
|
|
1584
|
+
readLine(get, put, at, directed, labels);
|
|
1585
|
+
}
|
|
654
1586
|
return back;
|
|
655
1587
|
}
|
|
656
1588
|
function pajekStyledExport(snapshot, input) {
|
|
@@ -665,14 +1597,15 @@ function pajekStyledExport(snapshot, input) {
|
|
|
665
1597
|
const approximate = (property, value) => {
|
|
666
1598
|
approximated.add(target, property, value);
|
|
667
1599
|
};
|
|
668
|
-
const get =
|
|
1600
|
+
const get = elementValues((t, p) => input.picture(t, p), target, PAJEK_STYLE_CAPABILITIES[target]);
|
|
669
1601
|
const n = target === "node" ? snapshot.nodeCount : snapshot.edgeCount;
|
|
670
1602
|
const params = (i) => target === "node" ? vertexParams(get(i), approximate) : lineParams(get(i), directed[i], approximate);
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
);
|
|
1603
|
+
const columns = paramColumns(n, params);
|
|
1604
|
+
if (target === "edge") {
|
|
1605
|
+
keepLineLabels(snapshot, columns);
|
|
1606
|
+
}
|
|
1607
|
+
restateCarried(target, columns, directed);
|
|
1608
|
+
replaceParamColumns(table, target === "node" ? [SHAPE_COLUMN, ...NODE_KEYS] : EDGE_KEYS, columns);
|
|
676
1609
|
}
|
|
677
1610
|
out.nodes.set(
|
|
678
1611
|
LABEL_COLUMN,
|
|
@@ -687,6 +1620,23 @@ function pajekStyledExport(snapshot, input) {
|
|
|
687
1620
|
notes.push(...styleBlockLosses(block, input.rules.styles.rules.length, "size"));
|
|
688
1621
|
return { snapshot: out, comment: PAJEK_STYLE_COMMENT + block, notes };
|
|
689
1622
|
}
|
|
1623
|
+
function keepLineLabels(snapshot, columns) {
|
|
1624
|
+
if (!snapshot.edges.has("l")) {
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
const own = (e) => plainCell(snapshot.edges.value("l", e));
|
|
1628
|
+
let col = columns.get("l");
|
|
1629
|
+
for (let e = 0; e < snapshot.edgeCount; e++) {
|
|
1630
|
+
const v = own(e);
|
|
1631
|
+
if (typeof v === "string" && v !== "" && (col?.[e] ?? null) === null) {
|
|
1632
|
+
col ??= new Array(snapshot.edgeCount).fill(null);
|
|
1633
|
+
col[e] = pajekLabelText(v);
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
if (col !== void 0) {
|
|
1637
|
+
columns.set("l", col);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
690
1640
|
function drawnLabels(input, n, approximated) {
|
|
691
1641
|
const drawn = input.picture("node", "label");
|
|
692
1642
|
const out = new Array(n).fill("");
|
|
@@ -715,6 +1665,45 @@ function replaceParamColumns(table, keys, columns) {
|
|
|
715
1665
|
table.set(key, col, { dtype: numeric ? "f64" : "string" });
|
|
716
1666
|
}
|
|
717
1667
|
}
|
|
1668
|
+
function restateCarried(target, columns, directed) {
|
|
1669
|
+
if (target === "node") {
|
|
1670
|
+
const all = [...columns.values()];
|
|
1671
|
+
if (all.length === 0) {
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1674
|
+
const n = all[0].length;
|
|
1675
|
+
const shape = columns.get(SHAPE_COLUMN) ?? new Array(n).fill(null);
|
|
1676
|
+
for (let i = 0; i < n; i++) {
|
|
1677
|
+
if (all.every((col) => col[i] === null)) {
|
|
1678
|
+
shape[i] = "ellipse";
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
columns.set(SHAPE_COLUMN, shape);
|
|
1682
|
+
return;
|
|
1683
|
+
}
|
|
1684
|
+
for (const key of CARRIED.edge) {
|
|
1685
|
+
const col = columns.get(key);
|
|
1686
|
+
if (col === void 0) {
|
|
1687
|
+
continue;
|
|
1688
|
+
}
|
|
1689
|
+
for (let i = 0; i < col.length; i++) {
|
|
1690
|
+
col[i] ??= lineRestated(key, directed[i]);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
function lineRestated(key, directed) {
|
|
1695
|
+
const defaults = lineDefaults(directed);
|
|
1696
|
+
switch (key) {
|
|
1697
|
+
case "c":
|
|
1698
|
+
return pajekColorText(String(defaults.color));
|
|
1699
|
+
case "w":
|
|
1700
|
+
return directed ? Number(defaults.width) : Number(defaults.width) / EDGE_WIDTH_PER_W;
|
|
1701
|
+
case "p":
|
|
1702
|
+
return "Solid";
|
|
1703
|
+
default:
|
|
1704
|
+
return 0;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
718
1707
|
function paramColumns(n, params) {
|
|
719
1708
|
const columns = /* @__PURE__ */ new Map();
|
|
720
1709
|
for (let i = 0; i < n; i++) {
|
|
@@ -815,58 +1804,58 @@ const CAPABILITIES = capabilities({
|
|
|
815
1804
|
});
|
|
816
1805
|
function plan(table, domain, notes) {
|
|
817
1806
|
const planned = [];
|
|
818
|
-
for (const
|
|
819
|
-
const slot = columnSlot(
|
|
1807
|
+
for (const column2 of table) {
|
|
1808
|
+
const slot = columnSlot(column2, domain, notes);
|
|
820
1809
|
if (slot !== null) {
|
|
821
|
-
planned.push({ column, slot });
|
|
1810
|
+
planned.push({ column: column2, slot });
|
|
822
1811
|
}
|
|
823
1812
|
}
|
|
824
1813
|
return planned;
|
|
825
1814
|
}
|
|
826
|
-
function columnNote(notes, code, message,
|
|
827
|
-
notes?.push(note(code, message,
|
|
1815
|
+
function columnNote(notes, code, message, column2) {
|
|
1816
|
+
notes?.push(note(code, message, column2.meta.name, column2.length - column2.nullCount));
|
|
828
1817
|
}
|
|
829
|
-
function columnSlot(
|
|
830
|
-
const { role, name } =
|
|
1818
|
+
function columnSlot(column2, domain, notes) {
|
|
1819
|
+
const { role, name } = column2.meta;
|
|
831
1820
|
if (role === "label" && domain === "node") {
|
|
832
|
-
return labelSlot(
|
|
1821
|
+
return labelSlot(column2, notes);
|
|
833
1822
|
}
|
|
834
1823
|
if (role === "position") {
|
|
835
|
-
return positionSlot(
|
|
1824
|
+
return positionSlot(column2, domain, notes);
|
|
836
1825
|
}
|
|
837
1826
|
if (role === "spells") {
|
|
838
|
-
return spellsSlot(
|
|
1827
|
+
return spellsSlot(column2, domain, notes);
|
|
839
1828
|
}
|
|
840
1829
|
if (role !== null && DROPPED_TEMPORAL_ROLES.has(role)) {
|
|
841
1830
|
columnNote(
|
|
842
1831
|
notes,
|
|
843
1832
|
PAJEK_LOSS.TEMPORAL_DROPPED,
|
|
844
1833
|
`${domain} column "${name}" (${role}) cannot be written; Pajek intervals come from the spells role`,
|
|
845
|
-
|
|
1834
|
+
column2
|
|
846
1835
|
);
|
|
847
1836
|
return null;
|
|
848
1837
|
}
|
|
849
|
-
if (writtenElsewhere(
|
|
1838
|
+
if (writtenElsewhere(column2, domain)) {
|
|
850
1839
|
return null;
|
|
851
1840
|
}
|
|
852
|
-
return namedSlot(
|
|
1841
|
+
return namedSlot(column2, domain, notes);
|
|
853
1842
|
}
|
|
854
|
-
function labelSlot(
|
|
855
|
-
const { name, dtype } =
|
|
1843
|
+
function labelSlot(column2, notes) {
|
|
1844
|
+
const { name, dtype } = column2.meta;
|
|
856
1845
|
if (dtype !== "string" && dtype !== "dict") {
|
|
857
1846
|
columnNote(
|
|
858
1847
|
notes,
|
|
859
1848
|
PAJEK_LOSS.LABEL_AS_TEXT,
|
|
860
1849
|
`node column "${name}" (label) is ${dtype}; labels are text and re-import as string`,
|
|
861
|
-
|
|
1850
|
+
column2
|
|
862
1851
|
);
|
|
863
1852
|
}
|
|
864
1853
|
return "label";
|
|
865
1854
|
}
|
|
866
|
-
function positionSlot(
|
|
867
|
-
const { name, components } =
|
|
1855
|
+
function positionSlot(column2, domain, notes) {
|
|
1856
|
+
const { name, components } = column2.meta;
|
|
868
1857
|
if (domain === "edge") {
|
|
869
|
-
columnNote(notes, LOSS.POSITIONS, `edge column "${name}" (position) cannot be written`,
|
|
1858
|
+
columnNote(notes, LOSS.POSITIONS, `edge column "${name}" (position) cannot be written`, column2);
|
|
870
1859
|
return null;
|
|
871
1860
|
}
|
|
872
1861
|
if (components === 2 || components === 3) {
|
|
@@ -876,12 +1865,12 @@ function positionSlot(column, domain, notes) {
|
|
|
876
1865
|
notes,
|
|
877
1866
|
PAJEK_LOSS.POSITION_STRIDE,
|
|
878
1867
|
`node column "${name}" (position) has ${components} components; Pajek coordinates are x y [z]`,
|
|
879
|
-
|
|
1868
|
+
column2
|
|
880
1869
|
);
|
|
881
1870
|
return null;
|
|
882
1871
|
}
|
|
883
|
-
function spellsSlot(
|
|
884
|
-
const { name, dtype, itemDtype } =
|
|
1872
|
+
function spellsSlot(column2, domain, notes) {
|
|
1873
|
+
const { name, dtype, itemDtype } = column2.meta;
|
|
885
1874
|
if (dtype === "list" && (itemDtype === "f64" || itemDtype === "i32" || itemDtype === "f32")) {
|
|
886
1875
|
return "spells";
|
|
887
1876
|
}
|
|
@@ -889,22 +1878,22 @@ function spellsSlot(column, domain, notes) {
|
|
|
889
1878
|
notes,
|
|
890
1879
|
LOSS.SPELLS,
|
|
891
1880
|
`${domain} column "${name}" (spells) is not a list of number pairs; it cannot be written`,
|
|
892
|
-
|
|
1881
|
+
column2
|
|
893
1882
|
);
|
|
894
1883
|
return null;
|
|
895
1884
|
}
|
|
896
|
-
function writtenElsewhere(
|
|
897
|
-
const { role, dtype } =
|
|
1885
|
+
function writtenElsewhere(column2, domain) {
|
|
1886
|
+
const { role, dtype } = column2.meta;
|
|
898
1887
|
if (role !== null && (STRUCTURAL_ROLES.has(role) || CHECKED_ROLES.has(role))) {
|
|
899
1888
|
return true;
|
|
900
1889
|
}
|
|
901
1890
|
return domain === "edge" && role === "id" || dtype === "list" || dtype === "json";
|
|
902
1891
|
}
|
|
903
|
-
function namedSlot(
|
|
904
|
-
const { name, dtype } =
|
|
1892
|
+
function namedSlot(column2, domain, notes) {
|
|
1893
|
+
const { name, dtype } = column2.meta;
|
|
905
1894
|
const text = dtype === "dict" || dtype === "string";
|
|
906
1895
|
if (text && domain === "node" && name === SHAPE_COLUMN) {
|
|
907
|
-
return shapeSlot(
|
|
1896
|
+
return shapeSlot(column2, notes);
|
|
908
1897
|
}
|
|
909
1898
|
if (text && domain === "edge" && name === RELATION_COLUMN) {
|
|
910
1899
|
return "relation";
|
|
@@ -914,22 +1903,22 @@ function namedSlot(column, domain, notes) {
|
|
|
914
1903
|
notes,
|
|
915
1904
|
PAJEK_LOSS.KEY_DROPPED,
|
|
916
1905
|
`${domain} column "${name}" cannot be a Pajek parameter key; it is not written`,
|
|
917
|
-
|
|
1906
|
+
column2
|
|
918
1907
|
);
|
|
919
1908
|
return null;
|
|
920
1909
|
}
|
|
921
1910
|
return "param";
|
|
922
1911
|
}
|
|
923
|
-
function shapeSlot(
|
|
924
|
-
if (allShapeKeywords(
|
|
1912
|
+
function shapeSlot(column2, notes) {
|
|
1913
|
+
if (allShapeKeywords(column2)) {
|
|
925
1914
|
return "shape";
|
|
926
1915
|
}
|
|
927
|
-
if (
|
|
1916
|
+
if (column2.meta.dtype === "dict") {
|
|
928
1917
|
columnNote(
|
|
929
1918
|
notes,
|
|
930
1919
|
PAJEK_LOSS.SHAPE_AS_PARAMETER,
|
|
931
|
-
`node column "${
|
|
932
|
-
|
|
1920
|
+
`node column "${column2.meta.name}" holds values outside the Pajek shape keywords; it is written as a parameter and reads back as string`,
|
|
1921
|
+
column2
|
|
933
1922
|
);
|
|
934
1923
|
}
|
|
935
1924
|
return "param";
|
|
@@ -937,9 +1926,9 @@ function shapeSlot(column, notes) {
|
|
|
937
1926
|
function labelNotes(snapshot, nodePlan, notes) {
|
|
938
1927
|
let labels = null;
|
|
939
1928
|
let carried = 0;
|
|
940
|
-
for (const { column, slot } of nodePlan) {
|
|
1929
|
+
for (const { column: column2, slot } of nodePlan) {
|
|
941
1930
|
if (slot === "label") {
|
|
942
|
-
labels =
|
|
1931
|
+
labels = column2;
|
|
943
1932
|
} else if (slot !== "skip" && slot !== "relation") {
|
|
944
1933
|
carried++;
|
|
945
1934
|
}
|
|
@@ -986,16 +1975,16 @@ function unlabeled(nodeCount, labels) {
|
|
|
986
1975
|
}
|
|
987
1976
|
return count;
|
|
988
1977
|
}
|
|
989
|
-
function allShapeKeywords(
|
|
990
|
-
for (let r = 0; r <
|
|
991
|
-
if (
|
|
1978
|
+
function allShapeKeywords(column2) {
|
|
1979
|
+
for (let r = 0; r < column2.length; r++) {
|
|
1980
|
+
if (column2.isSet(r) && !SHAPES$1.has(column2.value(r))) {
|
|
992
1981
|
return false;
|
|
993
1982
|
}
|
|
994
1983
|
}
|
|
995
1984
|
return true;
|
|
996
1985
|
}
|
|
997
|
-
function note(code, message,
|
|
998
|
-
return Object.freeze({ code, message, column, count });
|
|
1986
|
+
function note(code, message, column2 = null, count = null) {
|
|
1987
|
+
return Object.freeze({ code, message, column: column2, count });
|
|
999
1988
|
}
|
|
1000
1989
|
function numberText(value, dtype) {
|
|
1001
1990
|
switch (dtype) {
|
|
@@ -1013,53 +2002,53 @@ function numberText(value, dtype) {
|
|
|
1013
2002
|
}
|
|
1014
2003
|
}
|
|
1015
2004
|
}
|
|
1016
|
-
function cellText(
|
|
1017
|
-
switch (
|
|
2005
|
+
function cellText(column2, row) {
|
|
2006
|
+
switch (column2.dtype) {
|
|
1018
2007
|
case "f32":
|
|
1019
2008
|
case "f64":
|
|
1020
2009
|
case "i32":
|
|
1021
2010
|
case "u32":
|
|
1022
2011
|
case "u8": {
|
|
1023
|
-
const value =
|
|
2012
|
+
const value = column2.value(row);
|
|
1024
2013
|
if (typeof value === "number") {
|
|
1025
|
-
return numberText(value,
|
|
2014
|
+
return numberText(value, column2.dtype);
|
|
1026
2015
|
}
|
|
1027
2016
|
const parts = [];
|
|
1028
2017
|
const vector = value;
|
|
1029
2018
|
for (let k = 0; k < vector.length; k++) {
|
|
1030
|
-
parts.push(numberText(vector[k],
|
|
2019
|
+
parts.push(numberText(vector[k], column2.dtype));
|
|
1031
2020
|
}
|
|
1032
2021
|
return parts.join(" ");
|
|
1033
2022
|
}
|
|
1034
2023
|
case "bool":
|
|
1035
|
-
return
|
|
2024
|
+
return column2.value(row) === true ? "true" : "false";
|
|
1036
2025
|
case "dict":
|
|
1037
2026
|
case "string":
|
|
1038
|
-
return
|
|
2027
|
+
return column2.value(row);
|
|
1039
2028
|
case "list":
|
|
1040
2029
|
case "json":
|
|
1041
|
-
return JSON.stringify(
|
|
2030
|
+
return JSON.stringify(column2.value(row));
|
|
1042
2031
|
default: {
|
|
1043
|
-
const name =
|
|
2032
|
+
const name = column2.dtype;
|
|
1044
2033
|
throw new Error(`unknown dtype ${name}`);
|
|
1045
2034
|
}
|
|
1046
2035
|
}
|
|
1047
2036
|
}
|
|
1048
2037
|
function checkCells(planned, domain, notes) {
|
|
1049
|
-
for (const { column, slot } of planned) {
|
|
2038
|
+
for (const { column: column2, slot } of planned) {
|
|
1050
2039
|
if (slot === "position" || slot === "spells") {
|
|
1051
2040
|
continue;
|
|
1052
2041
|
}
|
|
1053
|
-
const { name } =
|
|
2042
|
+
const { name } = column2.meta;
|
|
1054
2043
|
let badText = 0;
|
|
1055
2044
|
let nonFinite = 0;
|
|
1056
2045
|
let typed = 0;
|
|
1057
|
-
for (let r = 0; r <
|
|
1058
|
-
if (!
|
|
2046
|
+
for (let r = 0; r < column2.length; r++) {
|
|
2047
|
+
if (!column2.isSet(r)) {
|
|
1059
2048
|
continue;
|
|
1060
2049
|
}
|
|
1061
|
-
if (
|
|
1062
|
-
const value =
|
|
2050
|
+
if (column2.dtype === "f64" || column2.dtype === "f32") {
|
|
2051
|
+
const value = column2.value(r);
|
|
1063
2052
|
if (typeof value === "number") {
|
|
1064
2053
|
if (!Number.isFinite(value)) {
|
|
1065
2054
|
nonFinite++;
|
|
@@ -1067,8 +2056,8 @@ function checkCells(planned, domain, notes) {
|
|
|
1067
2056
|
} else if (value !== void 0 && !Array.from(value).every((v) => Number.isFinite(v))) {
|
|
1068
2057
|
nonFinite++;
|
|
1069
2058
|
}
|
|
1070
|
-
} else if (
|
|
1071
|
-
const text =
|
|
2059
|
+
} else if (column2.dtype === "string" || column2.dtype === "dict") {
|
|
2060
|
+
const text = column2.value(r);
|
|
1072
2061
|
if (!isPajekLabel(text)) {
|
|
1073
2062
|
badText++;
|
|
1074
2063
|
} else if (slot === "param" && inferTextDtype(text) !== "string") {
|
|
@@ -1131,11 +2120,11 @@ function labelOf(labels, ids, i, needed) {
|
|
|
1131
2120
|
}
|
|
1132
2121
|
return null;
|
|
1133
2122
|
}
|
|
1134
|
-
function spellsText(
|
|
1135
|
-
if (
|
|
2123
|
+
function spellsText(column2, row) {
|
|
2124
|
+
if (column2.dtype !== "list" || !column2.isSet(row)) {
|
|
1136
2125
|
return null;
|
|
1137
2126
|
}
|
|
1138
|
-
const items =
|
|
2127
|
+
const items = column2.sliceOf(row);
|
|
1139
2128
|
if (items.length === 0) {
|
|
1140
2129
|
return null;
|
|
1141
2130
|
}
|
|
@@ -1146,29 +2135,29 @@ function spellsText(column, row) {
|
|
|
1146
2135
|
}
|
|
1147
2136
|
return formatIntervals(pairs);
|
|
1148
2137
|
}
|
|
1149
|
-
function coordinatesText(
|
|
1150
|
-
if (!
|
|
2138
|
+
function coordinatesText(column2, i, writeZ) {
|
|
2139
|
+
if (!column2.isSet(i)) {
|
|
1151
2140
|
return null;
|
|
1152
2141
|
}
|
|
1153
|
-
const dtype =
|
|
1154
|
-
const vector =
|
|
2142
|
+
const dtype = column2.dtype;
|
|
2143
|
+
const vector = column2.value(i);
|
|
1155
2144
|
const x = formatNumber(vector[0], dtype);
|
|
1156
2145
|
const y = formatNumber(vector[1], dtype);
|
|
1157
|
-
if (
|
|
2146
|
+
if (column2.meta.components === 3 && writeZ) {
|
|
1158
2147
|
return `${x} ${y} ${formatNumber(vector[2], dtype)}`;
|
|
1159
2148
|
}
|
|
1160
2149
|
return `${x} ${y}`;
|
|
1161
2150
|
}
|
|
1162
|
-
function needsZ(
|
|
1163
|
-
if (
|
|
2151
|
+
function needsZ(column2) {
|
|
2152
|
+
if (column2.meta.components !== 3) {
|
|
1164
2153
|
return false;
|
|
1165
2154
|
}
|
|
1166
|
-
if (
|
|
2155
|
+
if (column2.meta.extra.sourceDims !== 2) {
|
|
1167
2156
|
return true;
|
|
1168
2157
|
}
|
|
1169
|
-
for (let i = 0; i <
|
|
1170
|
-
if (
|
|
1171
|
-
const vector =
|
|
2158
|
+
for (let i = 0; i < column2.length; i++) {
|
|
2159
|
+
if (column2.isSet(i)) {
|
|
2160
|
+
const vector = column2.value(i);
|
|
1172
2161
|
if (vector[2] !== 0) {
|
|
1173
2162
|
return true;
|
|
1174
2163
|
}
|
|
@@ -1251,27 +2240,49 @@ function checkIdTexts(nodeCount, ids, mangle, notes) {
|
|
|
1251
2240
|
}
|
|
1252
2241
|
}
|
|
1253
2242
|
function* writeVertices(snapshot, ids, nodePlan, mangle) {
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
let
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
2243
|
+
const slots = vertexSlots(nodePlan);
|
|
2244
|
+
const writeZ = slots.position !== null && needsZ(slots.position);
|
|
2245
|
+
for (let i = 0; i < snapshot.nodeCount; i++) {
|
|
2246
|
+
const parts = vertexParts(slots, i, writeZ);
|
|
2247
|
+
if (mangle && ids.isChanged(i)) {
|
|
2248
|
+
parts.push(`${ORIGINAL_ID_KEY} ${quotePajekLabel(idText(ids.originalAt(i)))}`);
|
|
2249
|
+
}
|
|
2250
|
+
if (slots.spells !== null) {
|
|
2251
|
+
const spells = spellsText(slots.spells, i);
|
|
2252
|
+
if (spells !== null) {
|
|
2253
|
+
parts.push(spells);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
const label = labelOf(slots.labels, ids, i, parts.length > 0);
|
|
2257
|
+
let line = String(i + 1);
|
|
2258
|
+
if (label !== null) {
|
|
2259
|
+
line += ` ${quotePajekLabel(encodeCharacterReferences(label))}`;
|
|
2260
|
+
}
|
|
2261
|
+
if (parts.length > 0) {
|
|
2262
|
+
line += ` ${parts.join(" ")}`;
|
|
2263
|
+
}
|
|
2264
|
+
yield `${line}
|
|
2265
|
+
`;
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
function vertexSlots(nodePlan) {
|
|
2269
|
+
const slots = { labels: null, position: null, shape: null, spells: null, params: [] };
|
|
2270
|
+
for (const { column: column2, slot } of nodePlan) {
|
|
1260
2271
|
switch (slot) {
|
|
1261
2272
|
case "label":
|
|
1262
|
-
labels =
|
|
2273
|
+
slots.labels = column2;
|
|
1263
2274
|
break;
|
|
1264
2275
|
case "position":
|
|
1265
|
-
position =
|
|
2276
|
+
slots.position = column2;
|
|
1266
2277
|
break;
|
|
1267
2278
|
case "shape":
|
|
1268
|
-
shape =
|
|
2279
|
+
slots.shape = column2;
|
|
1269
2280
|
break;
|
|
1270
2281
|
case "spells":
|
|
1271
|
-
|
|
2282
|
+
slots.spells = column2;
|
|
1272
2283
|
break;
|
|
1273
2284
|
case "param":
|
|
1274
|
-
|
|
2285
|
+
slots.params.push(column2);
|
|
1275
2286
|
break;
|
|
1276
2287
|
case "relation":
|
|
1277
2288
|
case "skip":
|
|
@@ -1282,48 +2293,32 @@ function* writeVertices(snapshot, ids, nodePlan, mangle) {
|
|
|
1282
2293
|
}
|
|
1283
2294
|
}
|
|
1284
2295
|
}
|
|
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))}`;
|
|
2296
|
+
return slots;
|
|
2297
|
+
}
|
|
2298
|
+
function vertexParts(slots, i, writeZ) {
|
|
2299
|
+
const { position, shape } = slots;
|
|
2300
|
+
const parts = [];
|
|
2301
|
+
const coordinates = position === null ? null : coordinatesText(position, i, writeZ);
|
|
2302
|
+
if (coordinates !== null) {
|
|
2303
|
+
parts.push(coordinates);
|
|
2304
|
+
}
|
|
2305
|
+
const placed = parts.length > 0;
|
|
2306
|
+
const shaped = shape?.isSet(i) === true;
|
|
2307
|
+
if (shaped) {
|
|
2308
|
+
const keyword = cellText(shape, i);
|
|
2309
|
+
parts.push(SHAPES$1.has(keyword) ? keyword : `${SHAPE_COLUMN} ${quotePajekLabel(keyword)}`);
|
|
2310
|
+
}
|
|
2311
|
+
const named = parts.length;
|
|
2312
|
+
for (const column2 of slots.params) {
|
|
2313
|
+
if (!column2.isSet(i)) {
|
|
2314
|
+
continue;
|
|
1320
2315
|
}
|
|
1321
|
-
if (parts.length
|
|
1322
|
-
|
|
2316
|
+
if (placed && !shaped && parts.length === named && VOIDING_KEYS.has(column2.meta.name)) {
|
|
2317
|
+
parts.push("ellipse");
|
|
1323
2318
|
}
|
|
1324
|
-
|
|
1325
|
-
`;
|
|
2319
|
+
parts.push(`${column2.meta.name} ${quotePajekLabel(cellText(column2, i))}`);
|
|
1326
2320
|
}
|
|
2321
|
+
return parts;
|
|
1327
2322
|
}
|
|
1328
2323
|
function* writeLines(snapshot, edgePlan) {
|
|
1329
2324
|
const folding = pairFolding(snapshot, { foldMutual: true });
|
|
@@ -1332,16 +2327,16 @@ function* writeLines(snapshot, edgePlan) {
|
|
|
1332
2327
|
let relation = null;
|
|
1333
2328
|
let edgeSpells = null;
|
|
1334
2329
|
const edgeParams = [];
|
|
1335
|
-
for (const { column, slot } of edgePlan) {
|
|
2330
|
+
for (const { column: column2, slot } of edgePlan) {
|
|
1336
2331
|
switch (slot) {
|
|
1337
2332
|
case "relation":
|
|
1338
|
-
relation =
|
|
2333
|
+
relation = column2;
|
|
1339
2334
|
break;
|
|
1340
2335
|
case "spells":
|
|
1341
|
-
edgeSpells =
|
|
2336
|
+
edgeSpells = column2;
|
|
1342
2337
|
break;
|
|
1343
2338
|
case "param":
|
|
1344
|
-
edgeParams.push(
|
|
2339
|
+
edgeParams.push(column2);
|
|
1345
2340
|
break;
|
|
1346
2341
|
case "label":
|
|
1347
2342
|
case "position":
|
|
@@ -1388,9 +2383,9 @@ function* writeLines(snapshot, edgePlan) {
|
|
|
1388
2383
|
if (weight !== null) {
|
|
1389
2384
|
line += ` ${weight}`;
|
|
1390
2385
|
}
|
|
1391
|
-
for (const
|
|
1392
|
-
if (
|
|
1393
|
-
line += ` ${
|
|
2386
|
+
for (const column2 of edgeParams) {
|
|
2387
|
+
if (column2.isSet(e)) {
|
|
2388
|
+
line += ` ${column2.meta.name} ${quotePajekLabel(cellText(column2, e))}`;
|
|
1394
2389
|
}
|
|
1395
2390
|
}
|
|
1396
2391
|
if (edgeSpells !== null) {
|
|
@@ -1478,16 +2473,16 @@ function withOriginalIds(options) {
|
|
|
1478
2473
|
}
|
|
1479
2474
|
function ownedColumns(snapshot, planned) {
|
|
1480
2475
|
const owned = /* @__PURE__ */ new Set();
|
|
1481
|
-
const key = (
|
|
1482
|
-
for (const { column, slot } of planned) {
|
|
1483
|
-
const shapeParam = slot === "param" &&
|
|
2476
|
+
const key = (column2) => `${column2.meta.domain}:${column2.meta.name}`;
|
|
2477
|
+
for (const { column: column2, slot } of planned) {
|
|
2478
|
+
const shapeParam = slot === "param" && column2.meta.domain === "node" && column2.meta.name === SHAPE_COLUMN;
|
|
1484
2479
|
if (slot === "shape" || slot === "relation" || shapeParam) {
|
|
1485
|
-
owned.add(key(
|
|
2480
|
+
owned.add(key(column2));
|
|
1486
2481
|
}
|
|
1487
2482
|
}
|
|
1488
|
-
for (const
|
|
1489
|
-
if (
|
|
1490
|
-
owned.add(key(
|
|
2483
|
+
for (const column2 of [...snapshot.nodes, ...snapshot.edges]) {
|
|
2484
|
+
if (column2.meta.role === "spells") {
|
|
2485
|
+
owned.add(key(column2));
|
|
1491
2486
|
}
|
|
1492
2487
|
}
|
|
1493
2488
|
return owned;
|
|
@@ -1530,13 +2525,13 @@ function checkPlain(snapshot, options) {
|
|
|
1530
2525
|
const owned = ownedColumns(snapshot, [...nodePlan, ...edgePlan]);
|
|
1531
2526
|
notes.push(...capabilityNotes(snapshot, resolved, owned));
|
|
1532
2527
|
labelNotes(snapshot, nodePlan, notes);
|
|
1533
|
-
for (const
|
|
2528
|
+
for (const column2 of [...snapshot.edges].filter((c) => c.meta.role === "label")) {
|
|
1534
2529
|
notes.push(
|
|
1535
2530
|
note(
|
|
1536
2531
|
LOSS.ROLE,
|
|
1537
|
-
`edge column "${
|
|
1538
|
-
|
|
1539
|
-
|
|
2532
|
+
`edge column "${column2.meta.name}" (label) is written as a plain parameter; Pajek labels vertices only and the role is lost`,
|
|
2533
|
+
column2.meta.name,
|
|
2534
|
+
column2.length - column2.nullCount
|
|
1540
2535
|
)
|
|
1541
2536
|
);
|
|
1542
2537
|
}
|
|
@@ -1731,7 +2726,7 @@ function spellsDecl() {
|
|
|
1731
2726
|
origin: { format: "pajek", id: "interval" }
|
|
1732
2727
|
};
|
|
1733
2728
|
}
|
|
1734
|
-
function positionDecl(sourceDims) {
|
|
2729
|
+
function positionDecl(sourceDims, window) {
|
|
1735
2730
|
return {
|
|
1736
2731
|
name: POSITION_COLUMN,
|
|
1737
2732
|
dtype: "f64",
|
|
@@ -1740,10 +2735,21 @@ function positionDecl(sourceDims) {
|
|
|
1740
2735
|
role: "position",
|
|
1741
2736
|
origin: { format: "pajek", id: "coordinates" },
|
|
1742
2737
|
// 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
|
-
|
|
2738
|
+
// centers depth on 0.5, and NetworkX writes "0.0 0.0" for a node with no position; one unit
|
|
2739
|
+
// is the Draw window's width in points across and its height down (500 each by default,
|
|
2740
|
+
// PAJEK_POINTS_PER_UNIT): Pajek stretches 0..1 to the window one axis at a time
|
|
2741
|
+
extra: {
|
|
2742
|
+
sourceDims,
|
|
2743
|
+
units: "file",
|
|
2744
|
+
pxPerUnit: window.width,
|
|
2745
|
+
...window.height === window.width ? {} : { pxPerUnitY: window.height },
|
|
2746
|
+
yAxis: "down",
|
|
2747
|
+
zOrigin: 0.5,
|
|
2748
|
+
zeroUnplaced: true
|
|
2749
|
+
}
|
|
1745
2750
|
};
|
|
1746
2751
|
}
|
|
2752
|
+
const DEFAULT_WINDOW = { width: PAJEK_POINTS_PER_UNIT, height: PAJEK_POINTS_PER_UNIT };
|
|
1747
2753
|
class LineError extends Error {
|
|
1748
2754
|
/**
|
|
1749
2755
|
* Create a line error.
|
|
@@ -1770,8 +2776,11 @@ class PajekParser {
|
|
|
1770
2776
|
* @param report - the report
|
|
1771
2777
|
* @param options - the resolved common options
|
|
1772
2778
|
* @param firstVertex - the firstVertex format option
|
|
2779
|
+
* @param window - the Draw window the coordinates are stretched to
|
|
1773
2780
|
*/
|
|
1774
|
-
constructor(sink, report, options, firstVertex) {
|
|
2781
|
+
constructor(sink, report, options, firstVertex, window = DEFAULT_WINDOW) {
|
|
2782
|
+
this.keptBlock = null;
|
|
2783
|
+
this.voided = [];
|
|
1775
2784
|
this.section = "none";
|
|
1776
2785
|
this.kind = "directed";
|
|
1777
2786
|
this.relation = null;
|
|
@@ -1808,6 +2817,7 @@ class PajekParser {
|
|
|
1808
2817
|
this.ended = false;
|
|
1809
2818
|
this.edgeParams = /* @__PURE__ */ new Map();
|
|
1810
2819
|
this.styleBlockKept = false;
|
|
2820
|
+
this.window = window;
|
|
1811
2821
|
this.sink = sink;
|
|
1812
2822
|
this.report = report;
|
|
1813
2823
|
this.options = options;
|
|
@@ -1827,7 +2837,8 @@ class PajekParser {
|
|
|
1827
2837
|
const trimmed = text.trimStart();
|
|
1828
2838
|
if (trimmed.startsWith(PAJEK_STYLE_COMMENT)) {
|
|
1829
2839
|
this.styleBlockKept = true;
|
|
1830
|
-
this.
|
|
2840
|
+
this.keptBlock = trimmed.slice(PAJEK_STYLE_COMMENT.length);
|
|
2841
|
+
this.report.keepForStyles(this.keptBlock);
|
|
1831
2842
|
}
|
|
1832
2843
|
}
|
|
1833
2844
|
/**
|
|
@@ -2290,6 +3301,55 @@ class PajekParser {
|
|
|
2290
3301
|
*/
|
|
2291
3302
|
vertexLine(text, line) {
|
|
2292
3303
|
const tokens = this.tokens(text, "node", line);
|
|
3304
|
+
const { k, pos } = this.vertexNumber(tokens, line);
|
|
3305
|
+
let i = 1;
|
|
3306
|
+
let label = null;
|
|
3307
|
+
if (tokens.length > 1 && !startsWithCoordinates(text, tokens)) {
|
|
3308
|
+
label = this.labelOf(tokens[1], k, line);
|
|
3309
|
+
i = 2;
|
|
3310
|
+
}
|
|
3311
|
+
const { xyz, dims, next } = this.vertexCoordinates(tokens, i, k);
|
|
3312
|
+
i = next;
|
|
3313
|
+
this.checkCoordinates(text, tokens, i, dims === 2 && label !== null, k, line);
|
|
3314
|
+
let shape = null;
|
|
3315
|
+
if (i < tokens.length && isShapeKeyword(tokens[i])) {
|
|
3316
|
+
shape = tokens[i].toLowerCase();
|
|
3317
|
+
i++;
|
|
3318
|
+
}
|
|
3319
|
+
const extras = this.extras(tokens, i, "node", line);
|
|
3320
|
+
shape = extras.shape ?? shape;
|
|
3321
|
+
const restored = this.restoredId(extras);
|
|
3322
|
+
this.createNodes();
|
|
3323
|
+
const repeated = this.markVertexSeen(pos, k, line);
|
|
3324
|
+
const index = this.vertexIndex(pos, k, label, restored, repeated, line);
|
|
3325
|
+
if (shape === null && dims > 0 && extras.keys.length > 0 && VOIDING_KEYS.has(extras.keys[0])) {
|
|
3326
|
+
this.voided.push(index);
|
|
3327
|
+
}
|
|
3328
|
+
if (label !== null) {
|
|
3329
|
+
this.labelHandle = this.nodeHandle(this.labelHandle, LABEL_DECL, line);
|
|
3330
|
+
this.sink.setNodeValue(this.labelHandle, index, label);
|
|
3331
|
+
}
|
|
3332
|
+
if (dims > 0) {
|
|
3333
|
+
this.writePosition(index, dims, xyz, k, line);
|
|
3334
|
+
}
|
|
3335
|
+
if (shape !== null) {
|
|
3336
|
+
this.writeShape(index, shape, line);
|
|
3337
|
+
}
|
|
3338
|
+
for (let p = 0; p < extras.keys.length; p++) {
|
|
3339
|
+
this.writeParameter("node", extras.keys[p], index, extras.values[p]);
|
|
3340
|
+
}
|
|
3341
|
+
if (extras.spells !== null) {
|
|
3342
|
+
this.nodeSpellsHandle = this.nodeHandle(this.nodeSpellsHandle, spellsDecl(), line);
|
|
3343
|
+
this.sink.setNodeValue(this.nodeSpellsHandle, index, extras.spells);
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
/**
|
|
3347
|
+
* A vertex line's number, checked: it starts the line and is in the declared range.
|
|
3348
|
+
* @param tokens - the line's tokens
|
|
3349
|
+
* @param line - the line number
|
|
3350
|
+
* @returns the vertex number and its position
|
|
3351
|
+
*/
|
|
3352
|
+
vertexNumber(tokens, line) {
|
|
2293
3353
|
if (!isVertexNumber(tokens[0])) {
|
|
2294
3354
|
this.report.counts.skippedNodes++;
|
|
2295
3355
|
throw new LineError(
|
|
@@ -2312,27 +3372,25 @@ class PajekParser {
|
|
|
2312
3372
|
`vertex ${k} is outside ${this.base}..${this.base + this.vertexCount - 1}`
|
|
2313
3373
|
);
|
|
2314
3374
|
}
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
3375
|
+
return { k, pos };
|
|
3376
|
+
}
|
|
3377
|
+
/**
|
|
3378
|
+
* A vertex line's coordinates: two or three numbers, or none; a single one is an error.
|
|
3379
|
+
* @param tokens - the line's tokens
|
|
3380
|
+
* @param i - where the coordinates would start
|
|
3381
|
+
* @param k - the vertex number
|
|
3382
|
+
* @returns x, y and z (0 when absent), how many were read, and the index after them
|
|
3383
|
+
*/
|
|
3384
|
+
vertexCoordinates(tokens, i, k) {
|
|
2325
3385
|
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;
|
|
3386
|
+
const x = Number(tokens[i]);
|
|
3387
|
+
const y = Number(tokens[i + 1]);
|
|
3388
|
+
if (i + 2 < tokens.length && isNumericText(tokens[i + 2])) {
|
|
3389
|
+
return { xyz: [x, y, Number(tokens[i + 2])], dims: 3, next: i + 3 };
|
|
2334
3390
|
}
|
|
2335
|
-
|
|
3391
|
+
return { xyz: [x, y, 0], dims: 2, next: i + 2 };
|
|
3392
|
+
}
|
|
3393
|
+
if (i < tokens.length && isNumericText(tokens[i])) {
|
|
2336
3394
|
this.report.counts.skippedNodes++;
|
|
2337
3395
|
throw new LineError(
|
|
2338
3396
|
"parse-error",
|
|
@@ -2340,81 +3398,88 @@ class PajekParser {
|
|
|
2340
3398
|
`vertex ${k}: a single coordinate "${tokens[i]}"; coordinates are x y [z]`
|
|
2341
3399
|
);
|
|
2342
3400
|
}
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
if (repeated) {
|
|
3401
|
+
return { xyz: [0, 0, 0], dims: 0, next: i };
|
|
3402
|
+
}
|
|
3403
|
+
/**
|
|
3404
|
+
* Marks a vertex's position as having a line, warning when it already had one.
|
|
3405
|
+
* @param pos - the vertex's position
|
|
3406
|
+
* @param k - the vertex number
|
|
3407
|
+
* @param line - the line number
|
|
3408
|
+
* @returns whether the vertex already had a line
|
|
3409
|
+
*/
|
|
3410
|
+
markVertexSeen(pos, k, line) {
|
|
3411
|
+
if (this.seen[pos] !== 0) {
|
|
2355
3412
|
this.report.warning(
|
|
2356
3413
|
"merged",
|
|
2357
3414
|
PAJEK_ISSUE.DUPLICATE_NODE,
|
|
2358
3415
|
`vertex ${k} has more than one line; the later values overwrite`,
|
|
2359
3416
|
{ line, element: String(k) }
|
|
2360
3417
|
);
|
|
2361
|
-
|
|
2362
|
-
this.seen[pos] = 1;
|
|
2363
|
-
this.seenCount++;
|
|
3418
|
+
return true;
|
|
2364
3419
|
}
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
3420
|
+
this.seen[pos] = 1;
|
|
3421
|
+
this.seenCount++;
|
|
3422
|
+
return false;
|
|
3423
|
+
}
|
|
3424
|
+
/**
|
|
3425
|
+
* The node index a vertex line writes to, creating the node when its id is deferred to its line.
|
|
3426
|
+
* @param pos - the vertex's position
|
|
3427
|
+
* @param k - the vertex number
|
|
3428
|
+
* @param label - the line's label, or null
|
|
3429
|
+
* @param restored - the original id the line carries, or null
|
|
3430
|
+
* @param repeated - whether the vertex already had a line
|
|
3431
|
+
* @param line - the line number
|
|
3432
|
+
* @returns the node index
|
|
3433
|
+
*/
|
|
3434
|
+
vertexIndex(pos, k, label, restored, repeated, line) {
|
|
3435
|
+
const { idOfPos } = this;
|
|
3436
|
+
if (idOfPos !== null && !repeated && this.options.nodeIdFrom === "label") {
|
|
3437
|
+
return this.deferredNode(idOfPos, pos, k, label, line, "label");
|
|
3438
|
+
}
|
|
3439
|
+
if (idOfPos !== null && idOfPos[pos] === void 0) {
|
|
2369
3440
|
for (let p = this.filledBelow; p < pos; p++) {
|
|
2370
|
-
if (
|
|
2371
|
-
this.numberedNode(
|
|
3441
|
+
if (idOfPos[p] === void 0) {
|
|
3442
|
+
this.numberedNode(idOfPos, p);
|
|
2372
3443
|
}
|
|
2373
3444
|
}
|
|
2374
3445
|
if (pos > this.filledBelow) {
|
|
2375
3446
|
this.filledBelow = pos;
|
|
2376
3447
|
}
|
|
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);
|
|
3448
|
+
return this.deferredNode(idOfPos, pos, k, restored, line, "originalId");
|
|
2395
3449
|
}
|
|
2396
|
-
if (
|
|
2397
|
-
this.
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
if (this.shapeHandle === INVALID_INDEX) {
|
|
2404
|
-
this.shapeHandle = declareResolved(sink, "node", SHAPE_DECL, this.report, { line }).handle;
|
|
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]);
|
|
3450
|
+
if (restored !== null && !repeated) {
|
|
3451
|
+
this.report.warning(
|
|
3452
|
+
"coercion",
|
|
3453
|
+
PAJEK_ISSUE.ORIGINAL_ID_UNRESTORED,
|
|
3454
|
+
`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`,
|
|
3455
|
+
{ line, element: String(k) }
|
|
3456
|
+
);
|
|
2411
3457
|
}
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
3458
|
+
return this.indexOfPos[pos];
|
|
3459
|
+
}
|
|
3460
|
+
/**
|
|
3461
|
+
* A node column's handle, declared on first use.
|
|
3462
|
+
* @param handle - the handle so far, or INVALID_INDEX
|
|
3463
|
+
* @param decl - the column's declaration
|
|
3464
|
+
* @param line - the line number
|
|
3465
|
+
* @returns the handle
|
|
3466
|
+
*/
|
|
3467
|
+
nodeHandle(handle, decl, line) {
|
|
3468
|
+
return handle === INVALID_INDEX ? declareResolved(this.sink, "node", decl, this.report, { line }).handle : handle;
|
|
3469
|
+
}
|
|
3470
|
+
/**
|
|
3471
|
+
* Writes a vertex's shape keyword: to the shape column, or to an earlier `shape "<text>"` parameter's column.
|
|
3472
|
+
* @param index - the node index
|
|
3473
|
+
* @param shape - the keyword
|
|
3474
|
+
* @param line - the line number
|
|
3475
|
+
*/
|
|
3476
|
+
writeShape(index, shape, line) {
|
|
3477
|
+
if (this.shapeHandle === INVALID_INDEX && this.nodeParams.has(SHAPE_COLUMN)) {
|
|
3478
|
+
this.writeParameter("node", SHAPE_COLUMN, index, shape);
|
|
3479
|
+
return;
|
|
2417
3480
|
}
|
|
3481
|
+
this.shapeHandle = this.nodeHandle(this.shapeHandle, SHAPE_DECL, line);
|
|
3482
|
+
this.sink.setNodeValue(this.shapeHandle, index, shape);
|
|
2418
3483
|
}
|
|
2419
3484
|
/**
|
|
2420
3485
|
* A vertex label as written, its character references decoded.
|
|
@@ -2475,7 +3540,9 @@ class PajekParser {
|
|
|
2475
3540
|
writePosition(index, dims, point, k, line) {
|
|
2476
3541
|
if (this.positionHandle === INVALID_INDEX) {
|
|
2477
3542
|
this.coordDims = dims;
|
|
2478
|
-
this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims), this.report, {
|
|
3543
|
+
this.positionHandle = declareResolved(this.sink, "node", positionDecl(dims, this.window), this.report, {
|
|
3544
|
+
line
|
|
3545
|
+
}).handle;
|
|
2479
3546
|
} else if (dims !== this.coordDims) {
|
|
2480
3547
|
this.report.warnOnce(
|
|
2481
3548
|
"validation-error",
|
|
@@ -2862,7 +3929,7 @@ class PajekParser {
|
|
|
2862
3929
|
for (let i = start; i < tokens.length; ) {
|
|
2863
3930
|
const token = tokens[i];
|
|
2864
3931
|
if (token.startsWith("[")) {
|
|
2865
|
-
extras.spells = this.intervals(token, domain);
|
|
3932
|
+
extras.spells = this.intervals(token, domain, line);
|
|
2866
3933
|
i++;
|
|
2867
3934
|
continue;
|
|
2868
3935
|
}
|
|
@@ -2885,8 +3952,9 @@ class PajekParser {
|
|
|
2885
3952
|
}
|
|
2886
3953
|
seen.add(token);
|
|
2887
3954
|
extras.keys.push(token);
|
|
2888
|
-
|
|
2889
|
-
i
|
|
3955
|
+
const triple = COLOR_KEYS.has(token) ? colorTriple(tokens, i + 1) : null;
|
|
3956
|
+
extras.values.push(triple ?? tokens[i + 1]);
|
|
3957
|
+
i += triple === null ? 2 : 4;
|
|
2890
3958
|
}
|
|
2891
3959
|
return extras;
|
|
2892
3960
|
}
|
|
@@ -2915,12 +3983,15 @@ class PajekParser {
|
|
|
2915
3983
|
);
|
|
2916
3984
|
}
|
|
2917
3985
|
/**
|
|
2918
|
-
* The spells of a row's interval token
|
|
3986
|
+
* The spells of a row's interval token. A token not closed by "]" skips the row; a closed one
|
|
3987
|
+
* whose times cannot be read (`[287-?]`, lin-rel4.net) is reported and dropped, and the rest of
|
|
3988
|
+
* the row (its label, coordinates and parameters) is kept.
|
|
2919
3989
|
* @param token - the token, starting with "["
|
|
2920
|
-
* @param domain - what is skipped when the token is
|
|
2921
|
-
* @
|
|
3990
|
+
* @param domain - what is skipped when the token is not closed
|
|
3991
|
+
* @param line - the line number
|
|
3992
|
+
* @returns the spells, or null for an empty `[]`, which is no spell at all, and for a dropped one
|
|
2922
3993
|
*/
|
|
2923
|
-
intervals(token, domain) {
|
|
3994
|
+
intervals(token, domain, line) {
|
|
2924
3995
|
if (!isIntervalToken(token)) {
|
|
2925
3996
|
this.skip(domain);
|
|
2926
3997
|
throw new LineError(
|
|
@@ -2933,12 +4004,13 @@ class PajekParser {
|
|
|
2933
4004
|
const spells = parseIntervals(token);
|
|
2934
4005
|
return spells.length === 0 ? null : spells;
|
|
2935
4006
|
} catch (err) {
|
|
2936
|
-
this.
|
|
2937
|
-
throw new LineError(
|
|
4007
|
+
this.report.error(
|
|
2938
4008
|
"validation-error",
|
|
2939
4009
|
PAJEK_ISSUE.INTERVAL,
|
|
2940
|
-
err instanceof Error ? err.message : String(err)
|
|
4010
|
+
`${err instanceof Error ? err.message : String(err)}; the interval is dropped and the rest of the line kept`,
|
|
4011
|
+
{ line }
|
|
2941
4012
|
);
|
|
4013
|
+
return null;
|
|
2942
4014
|
}
|
|
2943
4015
|
}
|
|
2944
4016
|
/**
|
|
@@ -2976,6 +4048,12 @@ class PajekParser {
|
|
|
2976
4048
|
writer.write(row, text);
|
|
2977
4049
|
}
|
|
2978
4050
|
}
|
|
4051
|
+
const COLOR_KEYS = /* @__PURE__ */ new Set(["ic", "bc", "lc", "c"]);
|
|
4052
|
+
function colorTriple(tokens, at) {
|
|
4053
|
+
const parts = tokens.slice(at, at + 3);
|
|
4054
|
+
const fraction = (t) => /^[01]?(?:\.\d+)?$/.test(t) && t !== "" && Number(t) <= 1;
|
|
4055
|
+
return parts.length === 3 && parts.every(fraction) ? parts.join(" ") : null;
|
|
4056
|
+
}
|
|
2979
4057
|
function startsWithCoordinates(text, tokens) {
|
|
2980
4058
|
if (quotedAfterNumber(text, tokens)) {
|
|
2981
4059
|
return false;
|
|
@@ -3015,10 +4093,29 @@ function headSection(text) {
|
|
|
3015
4093
|
}
|
|
3016
4094
|
const pajekImporter = Object.freeze({
|
|
3017
4095
|
format: "pajek",
|
|
3018
|
-
options: Object.freeze(["firstVertex"]),
|
|
4096
|
+
options: Object.freeze(["firstVertex", "pajekDraw"]),
|
|
3019
4097
|
extensions: Object.freeze([".net", ".paj"]),
|
|
3020
4098
|
mimeTypes: Object.freeze(["text/x-pajek", "text/plain"]),
|
|
3021
4099
|
styles: pajekStyles,
|
|
4100
|
+
/**
|
|
4101
|
+
* Where Pajek 6.02 draws a network whose vertices have no coordinates: round a circle in vertex order, the first
|
|
4102
|
+
* on the left, the rest going clockwise on screen (y down), at radius 0.4 about the middle of the Draw window
|
|
4103
|
+
* (pajek-iliad: 311 vertices 200 points from the middle of its 500-point window). A file with coordinates is read
|
|
4104
|
+
* from its position column.
|
|
4105
|
+
* @param snapshot - the imported graph
|
|
4106
|
+
* @returns the circle for a file with no coordinates, else null
|
|
4107
|
+
*/
|
|
4108
|
+
positions(snapshot) {
|
|
4109
|
+
if (snapshot.nodes.byRole("position") !== null) {
|
|
4110
|
+
return null;
|
|
4111
|
+
}
|
|
4112
|
+
return {
|
|
4113
|
+
units: "file",
|
|
4114
|
+
pxPerUnit: PAJEK_POINTS_PER_UNIT,
|
|
4115
|
+
yAxis: "down",
|
|
4116
|
+
unplacedCircle: { center: [0.5, 0.5], radius: 0.4, startDegrees: 180, direction: 1 }
|
|
4117
|
+
};
|
|
4118
|
+
},
|
|
3022
4119
|
/**
|
|
3023
4120
|
* Confidence that the input is a Pajek network: it starts with `*Vertices` (or `*Network`),
|
|
3024
4121
|
* after any `%` comment lines.
|
|
@@ -3046,10 +4143,11 @@ const pajekImporter = Object.freeze({
|
|
|
3046
4143
|
}
|
|
3047
4144
|
const resolved = resolveImportOptions(options, DEFAULTS);
|
|
3048
4145
|
const firstVertex = firstVertexOption(options?.firstVertex);
|
|
4146
|
+
const draw = resolvePajekDraw(options?.pajekDraw);
|
|
3049
4147
|
const report = new ImportReportBuilder("pajek", resolved.errorLimit);
|
|
3050
4148
|
reportSinkOptions(sink, options, report);
|
|
3051
4149
|
reportUnusedOptions(options, report, USED_OPTIONS);
|
|
3052
|
-
const parser = new PajekParser(sink, report, resolved, firstVertex);
|
|
4150
|
+
const parser = new PajekParser(sink, report, resolved, firstVertex, draw ?? DEFAULT_WINDOW);
|
|
3053
4151
|
const reader = new LineReader(input, report, resolved);
|
|
3054
4152
|
let rest = null;
|
|
3055
4153
|
let restLine = 0;
|
|
@@ -3069,6 +4167,9 @@ const pajekImporter = Object.freeze({
|
|
|
3069
4167
|
}
|
|
3070
4168
|
}
|
|
3071
4169
|
parser.finish();
|
|
4170
|
+
if (draw !== null || parser.voided.length > 0) {
|
|
4171
|
+
report.keepForStyles({ block: parser.keptBlock, pajekDraw: draw ?? void 0, voided: parser.voided });
|
|
4172
|
+
}
|
|
3072
4173
|
if (rest !== null) {
|
|
3073
4174
|
const objects = rest.objects > 0 ? `; ${rest.objects} *Partition / *Vector object(s) after them are not read` : "";
|
|
3074
4175
|
report.warning(
|
|
@@ -3093,13 +4194,25 @@ const pajekImporter = Object.freeze({
|
|
|
3093
4194
|
async importAll(input, sinkFor, options) {
|
|
3094
4195
|
const resolved = resolveImportOptions(options, DEFAULTS);
|
|
3095
4196
|
const firstVertex = firstVertexOption(options?.firstVertex);
|
|
4197
|
+
const draw = resolvePajekDraw(options?.pajekDraw);
|
|
3096
4198
|
const reports = [new ImportReportBuilder("pajek", resolved.errorLimit)];
|
|
3097
4199
|
reportUnusedOptions(options, reports[0], USED_OPTIONS);
|
|
3098
4200
|
const open = () => {
|
|
3099
4201
|
const report = reports[reports.length - 1];
|
|
3100
4202
|
const sink = sinkFor(reports.length - 1);
|
|
3101
4203
|
reportSinkOptions(sink, options, report);
|
|
3102
|
-
return new PajekParser(sink, report, resolved, firstVertex);
|
|
4204
|
+
return new PajekParser(sink, report, resolved, firstVertex, draw ?? DEFAULT_WINDOW);
|
|
4205
|
+
};
|
|
4206
|
+
const close = (p) => {
|
|
4207
|
+
p.finish();
|
|
4208
|
+
const last = reports.at(-1);
|
|
4209
|
+
if (last !== void 0 && (draw !== null || p.voided.length > 0)) {
|
|
4210
|
+
last.keepForStyles({
|
|
4211
|
+
block: p.keptBlock,
|
|
4212
|
+
pajekDraw: draw ?? void 0,
|
|
4213
|
+
voided: p.voided
|
|
4214
|
+
});
|
|
4215
|
+
}
|
|
3103
4216
|
};
|
|
3104
4217
|
let parser = open();
|
|
3105
4218
|
const reader = new LineReader(input, reports[0], resolved);
|
|
@@ -3107,7 +4220,7 @@ const pajekImporter = Object.freeze({
|
|
|
3107
4220
|
for await (const raw of reader) {
|
|
3108
4221
|
const text = withoutStrayBom(raw);
|
|
3109
4222
|
if (parser.line(text, reader.line)) {
|
|
3110
|
-
parser
|
|
4223
|
+
close(parser);
|
|
3111
4224
|
reports.push(new ImportReportBuilder("pajek", resolved.errorLimit));
|
|
3112
4225
|
parser = open();
|
|
3113
4226
|
parser.line(text, reader.line);
|
|
@@ -3117,7 +4230,7 @@ const pajekImporter = Object.freeze({
|
|
|
3117
4230
|
throwIfAborted(resolved.signal);
|
|
3118
4231
|
}
|
|
3119
4232
|
}
|
|
3120
|
-
parser
|
|
4233
|
+
close(parser);
|
|
3121
4234
|
throwIfAborted(resolved.signal);
|
|
3122
4235
|
return reports.map((r) => r.finish());
|
|
3123
4236
|
}
|
|
@@ -3179,4 +4292,4 @@ export {
|
|
|
3179
4292
|
pajekImporter as d,
|
|
3180
4293
|
pajekExporter as p
|
|
3181
4294
|
};
|
|
3182
|
-
//# sourceMappingURL=importer-
|
|
4295
|
+
//# sourceMappingURL=importer-vRq4h3j5.js.map
|