@graphty/graph-io 0.3.19 → 0.3.20
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/README.md +43 -0
- package/dist/chunks/{escape-CWExcecC.js → escape-B-tkk_Cl.js} +74 -16
- package/dist/chunks/escape-B-tkk_Cl.js.map +1 -0
- package/dist/chunks/{writer-DQiKgQJc.js → export-Bh60Dv-n.js} +5 -79
- package/dist/chunks/export-Bh60Dv-n.js.map +1 -0
- package/dist/chunks/{exporter-CbMZyVt-.js → exporter-BGrsWamJ.js} +7 -6
- package/dist/chunks/{exporter-CbMZyVt-.js.map → exporter-BGrsWamJ.js.map} +1 -1
- package/dist/chunks/exporter-DIeGJXAZ.js +834 -0
- package/dist/chunks/exporter-DIeGJXAZ.js.map +1 -0
- package/dist/chunks/{importer-BNFuV1-K.js → importer-BWY2FFc5.js} +28 -7
- package/dist/chunks/importer-BWY2FFc5.js.map +1 -0
- package/dist/chunks/{importer-BAP4PrxR.js → importer-BaQpCEcJ.js} +5 -5
- package/dist/chunks/{importer-BAP4PrxR.js.map → importer-BaQpCEcJ.js.map} +1 -1
- package/dist/chunks/importer-DD-xv9_Y.js +1471 -0
- package/dist/chunks/importer-DD-xv9_Y.js.map +1 -0
- package/dist/chunks/{importer-ByPGO-09.js → importer-DEcKhsmQ.js} +2 -2
- package/dist/chunks/{importer-ByPGO-09.js.map → importer-DEcKhsmQ.js.map} +1 -1
- package/dist/chunks/{importer-BW-Ft2ps.js → importer-DIrbbnAf.js} +6 -5
- package/dist/chunks/{importer-BW-Ft2ps.js.map → importer-DIrbbnAf.js.map} +1 -1
- package/dist/chunks/importer-D_e7e7LX.js +3055 -0
- package/dist/chunks/importer-D_e7e7LX.js.map +1 -0
- package/dist/chunks/{importer-Bm1_5vPS.js → importer-Wv4C4gaF.js} +9 -6
- package/dist/chunks/importer-Wv4C4gaF.js.map +1 -0
- package/dist/chunks/{importer-DOepkgnG.js → importer-vi3bSdtw.js} +4 -4
- package/dist/chunks/{importer-DOepkgnG.js.map → importer-vi3bSdtw.js.map} +1 -1
- package/dist/chunks/{importer-BVGtU1NA.js → importer-zGLo8Dg_.js} +6 -5
- package/dist/chunks/{importer-BVGtU1NA.js.map → importer-zGLo8Dg_.js.map} +1 -1
- package/dist/chunks/{json-elements-CZY1wiZh.js → json-elements-DDS8N2Dd.js} +2 -2
- package/dist/chunks/{json-elements-CZY1wiZh.js.map → json-elements-DDS8N2Dd.js.map} +1 -1
- package/dist/chunks/{records-BzNicMsf.js → records-dbRkxwaq.js} +2 -2
- package/dist/chunks/{records-BzNicMsf.js.map → records-dbRkxwaq.js.map} +1 -1
- package/dist/chunks/{report-BcWboivV.js → report-B1z4WT9e.js} +143 -111
- package/dist/chunks/{report-BcWboivV.js.map → report-B1z4WT9e.js.map} +1 -1
- package/dist/chunks/{weights-CwISIpCP.js → weights-Dzba96G3.js} +5 -5
- package/dist/chunks/{weights-CwISIpCP.js.map → weights-Dzba96G3.js.map} +1 -1
- package/dist/chunks/writer-C7flM-Ih.js +77 -0
- package/dist/chunks/writer-C7flM-Ih.js.map +1 -0
- package/dist/csv.js +6 -5
- package/dist/csv.js.map +1 -1
- package/dist/cx.js +1 -1
- package/dist/cx2.js +2 -2
- package/dist/cys.d.ts +1 -0
- package/dist/cys.js +6 -0
- package/dist/cys.js.map +1 -0
- package/dist/dot.js +1 -1
- package/dist/gexf.js +5 -4
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +12 -14
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +288 -141
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +1 -1
- package/dist/json.js +1 -1
- package/dist/neo4j.js +6 -5
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/src/common/cell-budget.d.ts +84 -0
- package/dist/src/common/cell-budget.d.ts.map +1 -0
- package/dist/src/common/cell-budget.js +138 -0
- package/dist/src/common/cell-budget.js.map +1 -0
- package/dist/src/common/input.d.ts +10 -0
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +39 -0
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/options.d.ts +6 -0
- package/dist/src/common/options.d.ts.map +1 -1
- package/dist/src/common/options.js +1 -1
- package/dist/src/common/options.js.map +1 -1
- package/dist/src/common/xml.d.ts +37 -3
- package/dist/src/common/xml.d.ts.map +1 -1
- package/dist/src/common/xml.js +86 -6
- package/dist/src/common/xml.js.map +1 -1
- package/dist/src/common/zip.d.ts +92 -0
- package/dist/src/common/zip.d.ts.map +1 -0
- package/dist/src/common/zip.js +399 -0
- package/dist/src/common/zip.js.map +1 -0
- package/dist/src/formats/cys/constants.d.ts +68 -0
- package/dist/src/formats/cys/constants.d.ts.map +1 -0
- package/dist/src/formats/cys/constants.js +76 -0
- package/dist/src/formats/cys/constants.js.map +1 -0
- package/dist/src/formats/cys/importer.d.ts +38 -0
- package/dist/src/formats/cys/importer.d.ts.map +1 -0
- package/dist/src/formats/cys/importer.js +830 -0
- package/dist/src/formats/cys/importer.js.map +1 -0
- package/dist/src/formats/cys/index.d.ts +7 -0
- package/dist/src/formats/cys/index.d.ts.map +1 -0
- package/dist/src/formats/cys/index.js +7 -0
- package/dist/src/formats/cys/index.js.map +1 -0
- package/dist/src/formats/cys/session.d.ts +132 -0
- package/dist/src/formats/cys/session.d.ts.map +1 -0
- package/dist/src/formats/cys/session.js +315 -0
- package/dist/src/formats/cys/session.js.map +1 -0
- package/dist/src/formats/cys/tables.d.ts +90 -0
- package/dist/src/formats/cys/tables.d.ts.map +1 -0
- package/dist/src/formats/cys/tables.js +293 -0
- package/dist/src/formats/cys/tables.js.map +1 -0
- package/dist/src/formats/dot/exporter.d.ts +2 -0
- package/dist/src/formats/dot/exporter.d.ts.map +1 -1
- package/dist/src/formats/dot/exporter.js +12 -0
- package/dist/src/formats/dot/exporter.js.map +1 -1
- package/dist/src/formats/dot/importer.js +6 -2
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/gexf/importer.d.ts +2 -2
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +1 -1
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gml/exporter.d.ts +0 -8
- package/dist/src/formats/gml/exporter.d.ts.map +1 -1
- package/dist/src/formats/gml/exporter.js +7 -17
- package/dist/src/formats/gml/exporter.js.map +1 -1
- package/dist/src/formats/xgmml/columns.d.ts +152 -0
- package/dist/src/formats/xgmml/columns.d.ts.map +1 -0
- package/dist/src/formats/xgmml/columns.js +593 -0
- package/dist/src/formats/xgmml/columns.js.map +1 -0
- package/dist/src/formats/xgmml/constants.d.ts +196 -0
- package/dist/src/formats/xgmml/constants.d.ts.map +1 -0
- package/dist/src/formats/xgmml/constants.js +197 -0
- package/dist/src/formats/xgmml/constants.js.map +1 -0
- package/dist/src/formats/xgmml/document.d.ts +361 -0
- package/dist/src/formats/xgmml/document.d.ts.map +1 -0
- package/dist/src/formats/xgmml/document.js +695 -0
- package/dist/src/formats/xgmml/document.js.map +1 -0
- package/dist/src/formats/xgmml/emit.d.ts +341 -0
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -0
- package/dist/src/formats/xgmml/emit.js +1275 -0
- package/dist/src/formats/xgmml/emit.js.map +1 -0
- package/dist/src/formats/xgmml/exporter.d.ts +24 -0
- package/dist/src/formats/xgmml/exporter.d.ts.map +1 -0
- package/dist/src/formats/xgmml/exporter.js +999 -0
- package/dist/src/formats/xgmml/exporter.js.map +1 -0
- package/dist/src/formats/xgmml/importer.d.ts +58 -0
- package/dist/src/formats/xgmml/importer.d.ts.map +1 -0
- package/dist/src/formats/xgmml/importer.js +360 -0
- package/dist/src/formats/xgmml/importer.js.map +1 -0
- package/dist/src/formats/xgmml/index.d.ts +8 -0
- package/dist/src/formats/xgmml/index.d.ts.map +1 -0
- package/dist/src/formats/xgmml/index.js +8 -0
- package/dist/src/formats/xgmml/index.js.map +1 -0
- package/dist/src/formats/xgmml/values.d.ts +60 -0
- package/dist/src/formats/xgmml/values.d.ts.map +1 -0
- package/dist/src/formats/xgmml/values.js +148 -0
- package/dist/src/formats/xgmml/values.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/registry.d.ts +7 -0
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +25 -10
- package/dist/src/registry.js.map +1 -1
- package/dist/src/sniff.d.ts +1 -1
- package/dist/src/sniff.d.ts.map +1 -1
- package/dist/src/sniff.js +2 -0
- package/dist/src/sniff.js.map +1 -1
- package/dist/xgmml.d.ts +1 -0
- package/dist/xgmml.js +9 -0
- package/dist/xgmml.js.map +1 -0
- package/package.json +15 -2
- package/src/common/cell-budget.ts +170 -0
- package/src/common/input.ts +40 -0
- package/src/common/options.ts +1 -1
- package/src/common/xml.ts +127 -6
- package/src/common/zip.ts +472 -0
- package/src/formats/cys/constants.ts +99 -0
- package/src/formats/cys/importer.ts +1100 -0
- package/src/formats/cys/index.ts +7 -0
- package/src/formats/cys/session.ts +428 -0
- package/src/formats/cys/tables.ts +400 -0
- package/src/formats/dot/exporter.ts +17 -0
- package/src/formats/dot/importer.ts +6 -2
- package/src/formats/gexf/importer.ts +0 -1
- package/src/formats/gml/exporter.ts +7 -18
- package/src/formats/xgmml/columns.ts +747 -0
- package/src/formats/xgmml/constants.ts +265 -0
- package/src/formats/xgmml/document.ts +975 -0
- package/src/formats/xgmml/emit.ts +1563 -0
- package/src/formats/xgmml/exporter.ts +1215 -0
- package/src/formats/xgmml/importer.ts +491 -0
- package/src/formats/xgmml/index.ts +8 -0
- package/src/formats/xgmml/values.ts +183 -0
- package/src/index.ts +9 -0
- package/src/registry.ts +41 -15
- package/src/sniff.ts +5 -1
- package/dist/chunks/escape-CWExcecC.js.map +0 -1
- package/dist/chunks/importer-BNFuV1-K.js.map +0 -1
- package/dist/chunks/importer-Bm1_5vPS.js.map +0 -1
- package/dist/chunks/writer-DQiKgQJc.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-Bh60Dv-n.js","sources":["../../src/common/export.ts"],"sourcesContent":["/**\n * The exporter-side machinery of design section 8.5: the ExportCapabilities table helper, the\n * generic check() that turns capability gaps into LossNotes with shared codes, and id sanitising\n * (`sanitizeIds: \"error\"` by default; an exporter never silently renames a node; \"mangle\" rewrites\n * the ids the format cannot hold and hands the exporter the originals to write into its\n * `graphty:originalId` attribute).\n *\n * Every exporter's check() calls checkCapabilities() first and appends its format-specific notes\n * (design section 8.5 names W_GML_RECORD_NUMBER_TYPE and W_OPEN_INTERVAL); export() calls\n * sanitizeIds() before writing anything.\n */\n\nimport {\n type Column,\n type Dtype,\n GraphFormatError,\n type GraphSnapshot,\n INVALID_INDEX,\n type NodeId,\n} from \"@graphty/graph-format\";\n\nimport { type ExportCapabilities, type LossNote } from \"../types.js\";\nimport {\n COLUMN_RENAMED_LOSS_CODE,\n EMPTY_COLUMN_DROPPED_CODE,\n ID_TEXT_COLLISION_CODE,\n ID_TEXT_TYPE_CODE,\n INTEGRAL_F64_CODE,\n MIXED_DIRECTION_CODE,\n MUTUAL_AS_UNDIRECTED_CODE,\n MUTUAL_EXPANDED_CODE,\n OPTIONS_GAINED_CODE,\n PARENTS_DROPPED_CODE,\n ROLE_ASSUMED_CODE,\n ROLE_DROPPED_CODE,\n STORAGE_CLASS_CODE,\n TEMPORAL_DROPPED_CODE,\n TEMPORAL_TEXT_DROPPED_CODE,\n TEXT_INFERRED_CODE,\n WEIGHT_KEY_CLASH_CODE,\n XML_ILLEGAL_CHAR_CODE,\n} from \"./codes.js\";\nimport { type ResolvedExportOptions } from \"./options.js\";\n\n/** The shared LossNote codes of checkCapabilities(). */\nexport const LOSS = Object.freeze({\n /** The format has no mixed direction; expanded pairs are written per onMixedDirection. */\n MIXED_DIRECTION: \"W_MIXED_DIRECTION\",\n /** The format has no mixed direction and onMixedDirection is \"error\": export() will throw E_DIRECTED. */\n MIXED_DIRECTION_ERROR: MIXED_DIRECTION_CODE,\n /** Parallel edges in a format without them. */\n MULTI_EDGES: \"W_MULTI_EDGES\",\n /** Self-loops in a format without them. */\n SELF_LOOPS: \"W_SELF_LOOPS\",\n /** The format requires edge ids and the snapshot has none; canonical e0..e{E-1} are generated. */\n EDGE_IDS_GENERATED: \"W_EDGE_IDS_GENERATED\",\n /** The snapshot has an edge id column and the format cannot write one. */\n EDGE_IDS_DROPPED: \"W_EDGE_IDS_DROPPED\",\n /** Ids outside the format's charset are rewritten (sanitizeIds \"mangle\"). */\n ID_MANGLED: \"W_ID_MANGLED\",\n /** Ids outside the format's charset and sanitizeIds \"error\": export() will throw E_INVALID_ID. */\n ID_CHARSET: \"E_ID_CHARSET\",\n /** The format numbers nodes 1..N; ids that are not their 1-based index are kept as labels only. */\n ID_RENUMBERED: \"W_ID_RENUMBERED\",\n /** A column dtype the format does not keep as declared. */\n DTYPE: \"W_DTYPE_UNSUPPORTED\",\n /** A multi-component column in a format without strides. */\n COMPONENTS: \"W_COMPONENTS_FLATTENED\",\n /** A list column in a format without lists. */\n LIST: \"W_LIST_UNSUPPORTED\",\n /** A json column in a format without nested values. */\n JSON: \"W_JSON_UNSUPPORTED\",\n /** A declared default in a format without defaults. */\n DEFAULT: \"W_DEFAULT_DROPPED\",\n /** Declared options in a format without enumerations. */\n OPTIONS: \"W_OPTIONS_DROPPED\",\n /** A parent / parents column in a format without containment. */\n HIERARCHY: \"W_HIERARCHY_DROPPED\",\n /** A start / end / timestamp column in a format without temporal support. */\n TEMPORAL: TEMPORAL_DROPPED_CODE,\n /** A `<column>.text` companion (design section 5.1) the format cannot carry. */\n TEMPORAL_TEXT: TEMPORAL_TEXT_DROPPED_CODE,\n /** A role column the format has no slot for; written as a plain attribute, the role lost. */\n ROLE: ROLE_DROPPED_CODE,\n /** A parents (multi-parent) column in a format with single containment only. */\n PARENTS: PARENTS_DROPPED_CODE,\n /** A mutual pair written as two directed edges without the mutual mark. */\n MUTUAL_EXPANDED: MUTUAL_EXPANDED_CODE,\n /** A mutual pair written as one undirected edge; the mark is lost and the pair reads back undirected. */\n MUTUAL_AS_UNDIRECTED: MUTUAL_AS_UNDIRECTED_CODE,\n /** Node ids whose written text reads back as the other type under the importer's id rule. */\n ID_TEXT_TYPE: ID_TEXT_TYPE_CODE,\n /** Two node ids share one written text; export() throws E_INVALID_ID. */\n ID_TEXT_COLLISION: ID_TEXT_COLLISION_CODE,\n /** A plain column named like the importer's weight key reads back as THE weight. */\n WEIGHT_KEY_CLASH: WEIGHT_KEY_CLASH_CODE,\n /** A role-less column whose written name the importer maps to a role. */\n ROLE_ASSUMED: ROLE_ASSUMED_CODE,\n /** A role column written into the format's slot reads back under the importer's fixed name. */\n COLUMN_NAME_CHANGED: COLUMN_RENAMED_LOSS_CODE,\n /** A declared column whose every row is unset vanishes through a format without declarations. */\n EMPTY_COLUMN: EMPTY_COLUMN_DROPPED_CODE,\n /** A string / dict column that reads back as the other storage class (the dictionary heuristic). */\n STORAGE_CLASS: STORAGE_CLASS_CODE,\n /** An f64 column whose set values are all integral reads back as i32 through an untyped format. */\n INTEGRAL_F64: INTEGRAL_F64_CODE,\n /** Text cells that read back as numbers or booleans under the 5.1 grammar. */\n TEXT_INFERRED: TEXT_INFERRED_CODE,\n /** A string cell holding a character XML 1.0 forbids; export() throws E_COLUMN_TYPE. */\n XML_ILLEGAL_CHAR: XML_ILLEGAL_CHAR_CODE,\n /** A dict column without declared options gains one on re-import. */\n OPTIONS_GAINED: OPTIONS_GAINED_CODE,\n /** A spells column in a format without spells. */\n SPELLS: \"W_SPELLS_DROPPED\",\n /** Dynamic attribute values (extension tables) in a format without them. */\n DYNAMIC_VALUES: \"W_DYNAMIC_VALUES_DROPPED\",\n /** An open-interval column in a format without open intervals (design section 5.1). */\n OPEN_INTERVAL: \"W_OPEN_INTERVAL\",\n /** Graph-level attributes in a format without them. */\n GRAPH_ATTRIBUTES: \"W_GRAPH_ATTRIBUTES_DROPPED\",\n /** A position column in a format without positions. */\n POSITIONS: \"W_POSITIONS_DROPPED\",\n /** Visual columns in a format without them. */\n VIZ: \"W_VIZ_DROPPED\",\n /** An extension table the format cannot carry. */\n EXTENSION_TABLE: \"W_EXTENSION_TABLE_DROPPED\",\n});\n\n/** The capabilities of a format that keeps nothing beyond plain topology; the base every exporter overrides. */\nexport const NO_CAPABILITIES: ExportCapabilities = Object.freeze({\n mixedDirection: false,\n multiEdges: false,\n selfLoops: false,\n edgeIds: \"none\",\n idCharset: \"any\",\n dtypes: Object.freeze([]),\n components: false,\n lists: false,\n json: false,\n defaults: false,\n options: false,\n hierarchy: false,\n temporal: \"none\",\n graphAttributes: false,\n positions: false,\n viz: false,\n});\n\n/**\n * Build a capabilities table from the fields a format supports; every field left out is the\n * conservative NO_CAPABILITIES value, so an exporter states what it keeps and nothing is assumed.\n * @param supported - the fields the format supports\n * @returns a frozen table\n */\nexport function capabilities(supported: Partial<ExportCapabilities>): ExportCapabilities {\n return Object.freeze({ ...NO_CAPABILITIES, ...supported, dtypes: Object.freeze([...(supported.dtypes ?? [])]) });\n}\n\n/**\n * Format facts checkCapabilities() needs that the 12.4 table does not carry.\n * Consumed by the per-format importers and exporters under src/formats.\n * @public\n */\nexport interface CheckExtras {\n /** Whether the format can write open intervals (GEXF 1.2 startopen / endopen); default false. */\n readonly openIntervals?: boolean | undefined;\n /**\n * Whether the format carries the `<column>.text` companions of design section 5.1 (the lexical\n * form of a temporal value); default false, and every companion is then reported as\n * W_TEMPORAL_TEXT_DROPPED.\n */\n readonly temporalText?: boolean | undefined;\n /**\n * The dtype the format's importer gives a position column; an f32 / f64 position of the other\n * dtype is reported as W_DTYPE_UNSUPPORTED because its values differ at the other precision.\n * Undefined skips the check.\n */\n readonly positionDtype?: Dtype | undefined;\n /**\n * The roles beyond the structural, position, viz, hierarchy and temporal ones that the format\n * has a slot for (`label`, `kind`, `labels`, `idSpace`, `sourcePort`, `targetPort`, ...); a\n * column with any other role is written as a plain attribute and reported as W_ROLE_DROPPED.\n * Defaults to none.\n */\n readonly roles?: ReadonlySet<string> | undefined;\n /**\n * Roles the format writes into a fixed slot whose importer reads them back under a fixed name;\n * a role column named otherwise is reported as W_COLUMN_NAME_CHANGED (role -> the name the\n * importer gives it). Defaults to none.\n */\n readonly roleNames?: Readonly<Record<string, string>> | undefined;\n}\n\n/** The roles checkCapabilities() treats structurally rather than as attribute columns. */\nconst STRUCTURAL_ROLES: ReadonlySet<string> = new Set([\"directed\", \"pair\", \"mutual\", \"weight\", \"originalId\"]);\nconst VIZ_ROLES: ReadonlySet<string> = new Set([\"color\", \"size\", \"shape\", \"thickness\"]);\nconst TEMPORAL_ROLES: ReadonlySet<string> = new Set([\"start\", \"end\", \"timestamp\", \"timestamps\"]);\nconst HIERARCHY_ROLES: ReadonlySet<string> = new Set([\"parent\", \"parents\"]);\n\n/**\n * The generic pre-flight of design section 8.5: compare a snapshot with a format's capabilities\n * and return one LossNote per gap, with the shared codes of LOSS. Format-specific notes are the\n * exporter's to append.\n * @param snapshot - the snapshot about to be exported\n * @param caps - the exporter's capabilities\n * @param options - the resolved common export options\n * @param extras - format facts the capabilities table does not carry\n * @returns the notes, empty when the export is exact\n */\nexport function checkCapabilities(\n snapshot: GraphSnapshot,\n caps: ExportCapabilities,\n options: ResolvedExportOptions,\n extras: CheckExtras = {},\n): LossNote[] {\n const notes: LossNote[] = [];\n const note = (code: string, message: string, column: string | null = null, count: number | null = null): void => {\n notes.push(Object.freeze({ code, message, column, count }));\n };\n\n // mixed direction (design section 3.6): an expanded snapshot carries the pair / directed roles\n const mixed = countMixedEdges(snapshot);\n if (mixed > 0 && !caps.mixedDirection) {\n if (options.onMixedDirection === \"error\") {\n note(\n LOSS.MIXED_DIRECTION_ERROR,\n `${mixed} undirected edge(s) in a directed graph; the format has no mixed direction and onMixedDirection is \"error\"`,\n null,\n mixed,\n );\n } else {\n note(\n LOSS.MIXED_DIRECTION,\n `${mixed} undirected edge(s) in a directed graph written as ${options.onMixedDirection}`,\n null,\n mixed,\n );\n }\n }\n\n if (snapshot.flags.multigraph && !caps.multiEdges) {\n const parallel = countParallelArcs(snapshot);\n note(LOSS.MULTI_EDGES, `${parallel} parallel edge(s); the format has no parallel edges`, null, parallel);\n }\n if (snapshot.selfLoopCount > 0 && !caps.selfLoops) {\n note(\n LOSS.SELF_LOOPS,\n `${snapshot.selfLoopCount} self-loop(s); the format has no self-loops`,\n null,\n snapshot.selfLoopCount,\n );\n }\n\n const edgeIds = snapshot.edges.byRole(\"id\");\n if (caps.edgeIds === \"required\" && edgeIds === null && snapshot.edgeCount > 0) {\n note(\n LOSS.EDGE_IDS_GENERATED,\n \"the format requires edge ids; canonical e0..e{E-1} are generated and not written back\",\n null,\n snapshot.edgeCount,\n );\n } else if (caps.edgeIds === \"none\" && edgeIds !== null) {\n note(\n LOSS.EDGE_IDS_DROPPED,\n `edge id column \"${edgeIds.meta.name}\" cannot be written`,\n edgeIds.meta.name,\n snapshot.edgeCount,\n );\n }\n\n const unrepresentable = countUnrepresentableIds(snapshot, caps.idCharset);\n if (unrepresentable > 0) {\n if (caps.idCharset === \"dense-1-based\") {\n note(\n LOSS.ID_RENUMBERED,\n options.sanitizeIds === \"mangle\"\n ? `${unrepresentable} node id(s) are not their 1-based index; nodes are numbered 1..N, the originals kept in the exporter's originalId attribute (restored by restoreMangledIds) and as labels of the nodes without a label value`\n : `${unrepresentable} node id(s) are not their 1-based index; nodes are numbered 1..N and ids kept as labels of the nodes without a label value (a node with one loses its id)`,\n null,\n unrepresentable,\n );\n } else if (options.sanitizeIds === \"mangle\") {\n note(\n LOSS.ID_MANGLED,\n `${unrepresentable} node id(s) outside the ${caps.idCharset} charset are rewritten; originals kept in the originalId attribute`,\n null,\n unrepresentable,\n );\n } else {\n note(\n LOSS.ID_CHARSET,\n `${unrepresentable} node id(s) outside the ${caps.idCharset} charset; export() will throw unless sanitizeIds is \"mangle\"`,\n null,\n unrepresentable,\n );\n }\n }\n\n checkColumns(snapshot.nodes, \"node\", caps, extras, note);\n checkColumns(snapshot.edges, \"edge\", caps, extras, note);\n const graphColumns = snapshot.graph.names();\n if (graphColumns.length > 0) {\n if (caps.graphAttributes) {\n checkColumns(snapshot.graph, \"graph\", caps, extras, note);\n } else {\n note(\n LOSS.GRAPH_ATTRIBUTES,\n `${graphColumns.length} graph attribute(s) cannot be written`,\n null,\n graphColumns.length,\n );\n }\n }\n\n for (const [name, table] of snapshot.extensions) {\n if (name.startsWith(\"temporal:\")) {\n if (caps.temporal !== \"dynamic-values\") {\n note(\n LOSS.DYNAMIC_VALUES,\n `dynamic values of \"${name}\" (${table.rowCount} row(s)) cannot be written`,\n name,\n table.rowCount,\n );\n }\n } else {\n note(\n LOSS.EXTENSION_TABLE,\n `extension table \"${name}\" (${table.rowCount} row(s)) cannot be written`,\n name,\n table.rowCount,\n );\n }\n }\n return notes;\n}\n\n/** A note-recording callback. */\ntype NoteFn = (code: string, message: string, column?: string | null, count?: number | null) => void;\n\n/**\n * The per-column checks of checkCapabilities().\n * @param table - the table\n * @param domain - the domain, for messages\n * @param caps - the capabilities\n * @param extras - format extras\n * @param note - the recorder\n */\nfunction checkColumns(\n table: Iterable<Column>,\n domain: string,\n caps: ExportCapabilities,\n extras: CheckExtras,\n note: NoteFn,\n): void {\n for (const column of table) {\n const { meta } = column;\n const { name, role } = meta;\n if (role !== null && STRUCTURAL_ROLES.has(role)) {\n continue;\n }\n const label = `${domain} column \"${name}\"`;\n if (role !== null && extras.roleNames !== undefined) {\n const fixed = extras.roleNames[role];\n if (fixed !== undefined && fixed !== name) {\n note(\n LOSS.COLUMN_NAME_CHANGED,\n `${label} (${role}) is written into the format's ${role} slot and reads back as \"${fixed}\"`,\n name,\n column.length - column.nullCount,\n );\n }\n }\n if (domain === \"edge\" && role === \"id\") {\n continue;\n }\n if (role === \"timeText\") {\n if (extras.temporalText !== true) {\n note(\n LOSS.TEMPORAL_TEXT,\n `${label} (the lexical form of a temporal column, design section 5.1) cannot be written`,\n name,\n column.length - column.nullCount,\n );\n }\n continue;\n }\n if (role === \"position\") {\n if (!caps.positions) {\n note(LOSS.POSITIONS, `${label} (positions) cannot be written`, name, column.length - column.nullCount);\n } else if (extras.positionDtype !== undefined && meta.dtype !== extras.positionDtype) {\n note(\n LOSS.DTYPE,\n `${label} (positions) is ${meta.dtype}; the format reads positions back as ${extras.positionDtype}`,\n name,\n column.length - column.nullCount,\n );\n }\n continue;\n }\n if (role !== null && VIZ_ROLES.has(role)) {\n if (!caps.viz) {\n note(LOSS.VIZ, `${label} (${role}) cannot be written`, name, column.length - column.nullCount);\n }\n continue;\n }\n if (role !== null && HIERARCHY_ROLES.has(role)) {\n if (!caps.hierarchy) {\n note(LOSS.HIERARCHY, `${label} (${role}) cannot be written`, name, column.length - column.nullCount);\n }\n continue;\n }\n if (role !== null && TEMPORAL_ROLES.has(role)) {\n if (caps.temporal === \"none\") {\n note(LOSS.TEMPORAL, `${label} (${role}) cannot be written`, name, column.length - column.nullCount);\n }\n continue;\n }\n if (role === \"spells\") {\n if (caps.temporal !== \"spells\" && caps.temporal !== \"dynamic-values\") {\n note(LOSS.SPELLS, `${label} (spells) cannot be written`, name, column.length - column.nullCount);\n }\n continue;\n }\n if (role === \"open\" || role === \"spellsOpen\") {\n // The open bits are written by the format's own temporal syntax when it has one; the\n // column's u8 storage is never an attribute dtype, so no dtype note either way.\n if (extras.openIntervals !== true) {\n note(\n LOSS.OPEN_INTERVAL,\n `${label} (open intervals) cannot be written`,\n name,\n column.length - column.nullCount,\n );\n }\n continue;\n }\n if (role !== null && !(extras.roles?.has(role) ?? false)) {\n note(\n LOSS.ROLE,\n `${label} (${role}) is written as a plain attribute; the format has no ${role} slot and the role is lost`,\n name,\n column.length - column.nullCount,\n );\n }\n if (meta.dynamic && caps.temporal !== \"dynamic-values\") {\n note(LOSS.DYNAMIC_VALUES, `${label} is dynamic; only its static value can be written`, name, null);\n }\n checkDtype(column, label, caps, note);\n if (meta.default !== undefined && !caps.defaults) {\n note(LOSS.DEFAULT, `${label} declares a default; the format has no defaults`, name, null);\n }\n if (meta.options !== null && !caps.options) {\n note(LOSS.OPTIONS, `${label} declares options; the format has no enumerations`, name, null);\n }\n }\n}\n\n/**\n * The dtype checks of one attribute column: lists, nested values, scalar dtypes and strides\n * against the capability table.\n * @param column - the column\n * @param label - the column's label for messages\n * @param caps - the capabilities\n * @param note - the recorder\n */\nfunction checkDtype(column: Column, label: string, caps: ExportCapabilities, note: NoteFn): void {\n const { meta } = column;\n const { name } = meta;\n const set = column.length - column.nullCount;\n switch (meta.dtype) {\n case \"list\":\n if (!caps.lists) {\n note(LOSS.LIST, `${label} is a list; the format has no lists`, name, set);\n } else if (meta.itemDtype !== null && !caps.dtypes.includes(meta.itemDtype)) {\n note(\n LOSS.DTYPE,\n `${label} holds ${meta.itemDtype} items; the format cannot keep that dtype`,\n name,\n set,\n );\n } else if (meta.itemDtype === \"dict\") {\n // no format declares an enumeration for list items: they read back as strings\n note(LOSS.DTYPE, `${label} holds dict items; list items read back as string`, name, set);\n }\n break;\n case \"json\":\n if (!caps.json) {\n note(LOSS.JSON, `${label} holds nested values; the format has no nested values`, name, set);\n }\n break;\n default:\n if (!caps.dtypes.includes(meta.dtype)) {\n note(LOSS.DTYPE, `${label} is ${meta.dtype}; the format cannot keep that dtype`, name, set);\n }\n if (meta.components > 1 && !caps.components) {\n note(\n LOSS.COMPONENTS,\n `${label} has ${meta.components} components; the format has no strides`,\n name,\n set,\n );\n }\n break;\n }\n}\n\n/**\n * The number of source edges that were undirected in a directed snapshot (the halves of an\n * expanded pair count once; an expanded self-loop has no mirror and counts once).\n * @param snapshot - the snapshot\n * @returns the count; 0 for an undirected snapshot or one without the directed role\n */\nexport function countMixedEdges(snapshot: GraphSnapshot): number {\n if (!snapshot.directed) {\n return 0;\n }\n const directed = snapshot.edges.byRole(\"directed\");\n if (directed === null || directed.dtype !== \"bool\") {\n return 0;\n }\n const pair = snapshot.edges.byRole(\"pair\");\n let undirectedRows = 0;\n let paired = 0;\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (directed.isSet(e) && directed.value(e) === false) {\n undirectedRows++;\n if (pair !== null && pair.dtype === \"u32\" && pair.isSet(e) && pair.data[e] !== INVALID_INDEX) {\n paired++;\n }\n }\n }\n return paired / 2 + (undirectedRows - paired);\n}\n\n/**\n * The number of arcs that repeat the previous arc's target within a row (parallel edges), counted\n * over the forward CSR; an undirected parallel edge is counted in both rows.\n * @param snapshot - the snapshot\n * @returns the count\n */\nexport function countParallelArcs(snapshot: GraphSnapshot): number {\n const { rowPtr, colIdx, nodeCount } = snapshot;\n let count = 0;\n for (let u = 0; u < nodeCount; u++) {\n for (let a = rowPtr[u] + 1; a < rowPtr[u + 1]; a++) {\n if (colIdx[a] === colIdx[a - 1]) {\n count++;\n }\n }\n }\n return snapshot.directed ? count : Math.ceil(count / 2);\n}\n\n// ============================================================ id sanitising\n\n/**\n * The id charsets of ExportCapabilities.\n * Consumed by the per-format importers and exporters under src/formats.\n * @public\n */\nexport type IdCharset = ExportCapabilities[\"idCharset\"];\n\n/**\n * The ids to write for every node after sanitising (design section 8.5).\n * Consumed by the per-format importers and exporters under src/formats.\n * @public\n */\nexport interface SanitizedIds {\n /** The charset applied. */\n readonly charset: IdCharset;\n /** How many ids differ from the snapshot's. */\n readonly changed: number;\n /**\n * The id to write for a node.\n * @param index - the node index\n * @returns the id as the format will read it back\n */\n idAt(index: number): NodeId;\n /**\n * Whether a node's written id differs from its original.\n * @param index - the node index\n * @returns true when the exporter must record the original\n */\n isChanged(index: number): boolean;\n /**\n * The original id of a node.\n * @param index - the node index\n * @returns the snapshot's id\n */\n originalAt(index: number): NodeId;\n}\n\n/** XML NameChar ranges (XML 1.0 fifth edition), as inclusive code point pairs. */\nconst NAME_CHAR_RANGES: readonly (readonly [number, number])[] = [\n [0x2d, 0x2e],\n [0x30, 0x3a],\n [0x41, 0x5a],\n [0x5f, 0x5f],\n [0x61, 0x7a],\n [0xb7, 0xb7],\n [0xc0, 0xd6],\n [0xd8, 0xf6],\n [0xf8, 0x37d],\n [0x37f, 0x1fff],\n [0x200c, 0x200d],\n [0x203f, 0x2040],\n [0x2070, 0x218f],\n [0x2c00, 0x2fef],\n [0x3001, 0xd7ff],\n [0xf900, 0xfdcf],\n [0xfdf0, 0xfffd],\n [0x10000, 0xeffff],\n];\n\n/**\n * Whether a code point is an XML NameChar.\n * @param cp - the code point\n * @returns true when it may appear in an NMTOKEN\n */\nexport function isNameChar(cp: number): boolean {\n for (const [lo, hi] of NAME_CHAR_RANGES) {\n if (cp < lo) {\n return false;\n }\n if (cp <= hi) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Whether a text is an XML NMTOKEN (one or more NameChars; GraphML node and edge ids).\n * @param text - the text\n * @returns true for a non-empty text of NameChars\n */\nexport function isNmtoken(text: string): boolean {\n if (text.length === 0) {\n return false;\n }\n for (const ch of text) {\n const cp = ch.codePointAt(0);\n if (cp === undefined || !isNameChar(cp)) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Whether an id can be written unchanged under a charset.\n * @param id - the id\n * @param charset - the charset\n * @returns true when the id needs no rewriting (\"dense-1-based\" is never true: see sanitizeIds)\n */\nexport function isRepresentableId(id: NodeId, charset: IdCharset): boolean {\n switch (charset) {\n case \"any\":\n return true;\n case \"nmtoken\":\n return isNmtoken(String(id));\n case \"integer\":\n return typeof id === \"number\" && Number.isSafeInteger(id);\n case \"dense-1-based\":\n return false;\n default: {\n const name: string = charset;\n throw new GraphFormatError(\"E_UNSUPPORTED\", `unknown id charset ${name}`, { charset: name });\n }\n }\n}\n\n/**\n * How many node ids a charset cannot hold as they are (for check()); under \"dense-1-based\" the\n * ids that are not their own 1-based index.\n * @param snapshot - the snapshot\n * @param charset - the charset\n * @returns the count\n */\nexport function countUnrepresentableIds(snapshot: GraphSnapshot, charset: IdCharset): number {\n const { ids } = snapshot;\n if (charset === \"any\") {\n return 0;\n }\n if (charset === \"dense-1-based\") {\n if (ids.kind === \"identity\" && ids.offset === 1) {\n return 0;\n }\n let changed = 0;\n for (let i = 0; i < ids.size; i++) {\n if (ids.idOf(i) !== i + 1) {\n changed++;\n }\n }\n return changed;\n }\n let count = 0;\n for (let i = 0; i < ids.size; i++) {\n if (!isRepresentableId(ids.idOf(i), charset)) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Sanitise the node ids for a charset (design section 8.5). Under \"error\" any id the charset\n * cannot hold is E_INVALID_ID (details.reason \"charset\") and nothing is written; under \"mangle\"\n * such ids are rewritten deterministically and uniquely: NMTOKEN by replacing every other\n * character with `_` (an empty result becomes `_`) and suffixing `_2`, `_3`... on collision;\n * integer by the smallest unused non-negative integers in index order. \"dense-1-based\" always\n * writes the 1-based index (Pajek numbers vertices; the exporter writes the original id as the\n * label), which is a renumbering rather than a mangling, so it never throws under \"error\"; under\n * \"mangle\" the exporter also writes the original id under its originalId attribute.\n * @param snapshot - the snapshot\n * @param charset - the charset\n * @param mode - the resolved sanitizeIds option\n * @returns the ids to write\n */\nexport function sanitizeIds(snapshot: GraphSnapshot, charset: IdCharset, mode: \"error\" | \"mangle\"): SanitizedIds {\n const { ids } = snapshot;\n const n = ids.size;\n if (charset === \"dense-1-based\") {\n const changed = countUnrepresentableIds(snapshot, charset);\n return {\n charset,\n changed,\n idAt: (i: number): NodeId => i + 1,\n isChanged: (i: number): boolean => ids.idOf(i) !== i + 1,\n originalAt: (i: number): NodeId => ids.idOf(i),\n };\n }\n const unchanged: SanitizedIds = {\n charset,\n changed: 0,\n idAt: (i: number): NodeId => ids.idOf(i),\n isChanged: (): boolean => false,\n originalAt: (i: number): NodeId => ids.idOf(i),\n };\n if (charset === \"any\") {\n return unchanged;\n }\n const bad: number[] = [];\n for (let i = 0; i < n; i++) {\n if (!isRepresentableId(ids.idOf(i), charset)) {\n bad.push(i);\n }\n }\n if (bad.length === 0) {\n return unchanged;\n }\n if (mode === \"error\") {\n const first = ids.idOf(bad[0]);\n throw new GraphFormatError(\n \"E_INVALID_ID\",\n `${bad.length} node id(s) cannot be written as ${charset} (first: ${JSON.stringify(first)} at index ${bad[0]}); pass sanitizeIds: \"mangle\" to rewrite them`,\n { reason: \"charset\", charset, count: bad.length, id: first, index: bad[0] },\n );\n }\n const written = new Map<number, NodeId>();\n if (charset === \"nmtoken\") {\n const used = new Set<string>();\n for (let i = 0; i < n; i++) {\n const id = ids.idOf(i);\n if (isRepresentableId(id, charset)) {\n used.add(String(id));\n }\n }\n for (const i of bad) {\n const base = mangleNmtoken(String(ids.idOf(i)));\n let candidate = base;\n for (let k = 2; used.has(candidate); k++) {\n candidate = `${base}_${k}`;\n }\n used.add(candidate);\n written.set(i, candidate);\n }\n } else {\n const used = new Set<number>();\n for (let i = 0; i < n; i++) {\n const id = ids.idOf(i);\n if (typeof id === \"number\" && Number.isSafeInteger(id)) {\n used.add(id);\n }\n }\n let next = 0;\n for (const i of bad) {\n while (used.has(next)) {\n next++;\n }\n used.add(next);\n written.set(i, next);\n next++;\n }\n }\n return {\n charset,\n changed: bad.length,\n idAt: (i: number): NodeId => written.get(i) ?? ids.idOf(i),\n isChanged: (i: number): boolean => written.has(i),\n originalAt: (i: number): NodeId => ids.idOf(i),\n };\n}\n\n/**\n * Rewrite a text as an NMTOKEN: every character that is not a NameChar becomes `_`.\n * @param text - the text\n * @returns a non-empty NMTOKEN\n */\nexport function mangleNmtoken(text: string): string {\n let out = \"\";\n for (const ch of text) {\n const cp = ch.codePointAt(0);\n out += cp !== undefined && isNameChar(cp) ? ch : \"_\";\n }\n return out.length === 0 ? \"_\" : out;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { GraphFormatError } from "@graphty/graph-format";
|
|
2
|
-
import {
|
|
3
|
-
import { c as capabilities, L as LOSS,
|
|
4
|
-
import { i as isRecord, P as POSITION_COLUMN } from "./json-elements-
|
|
5
|
-
import { e as explicitWeights } from "./weights-
|
|
6
|
-
import {
|
|
2
|
+
import { V as resolveExportOptions, X as pairFolding } from "./report-B1z4WT9e.js";
|
|
3
|
+
import { c as capabilities, L as LOSS, a as checkCapabilities } from "./export-Bh60Dv-n.js";
|
|
4
|
+
import { i as isRecord, P as POSITION_COLUMN } from "./json-elements-DDS8N2Dd.js";
|
|
5
|
+
import { e as explicitWeights } from "./weights-Dzba96G3.js";
|
|
6
|
+
import { j as joinText, e as encodeChunks } from "./writer-C7flM-Ih.js";
|
|
7
|
+
import { a as CX2_FORMAT, O as ORIGINAL_ID_ATTRIBUTE, b as cx2Type, B as BYPASS_NAMESPACE } from "./importer-vi3bSdtw.js";
|
|
7
8
|
const CX2_LOSS = Object.freeze({
|
|
8
9
|
/** Every edge is written directed: an undirected snapshot, or the undirected pairs of a mixed one. */
|
|
9
10
|
UNDIRECTED_AS_DIRECTED: "W_CX2_UNDIRECTED_AS_DIRECTED",
|
|
@@ -732,4 +733,4 @@ export {
|
|
|
732
733
|
CX2_LOSS as a,
|
|
733
734
|
cx2Exporter as c
|
|
734
735
|
};
|
|
735
|
-
//# sourceMappingURL=exporter-
|
|
736
|
+
//# sourceMappingURL=exporter-BGrsWamJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exporter-CbMZyVt-.js","sources":["../../src/formats/cx2/exporter.ts"],"sourcesContent":["/**\n * The CX2 exporter (design/graph-io/cytoscape-and-obo/design.md section 1.3; graphty issue #307):\n * writes a snapshot as one CX2 document -- the descriptor, the pre-metadata, one\n * `attributeDeclarations` block (aliases from `origin.id`, defaults from `meta.default`),\n * `networkAttributes`, `nodes` (x / y from the position with y flipped back to screen coordinates,\n * `z` from the `z` column), `edges`, the `cx2.bypass` columns as `nodeBypasses` / `edgeBypasses`,\n * the opaque aspects a CX2 import kept (which returns its own style rules) and `status`.\n *\n * What CX2 cannot hold is announced by check() before anything is written: every edge is\n * directed (W_CX2_UNDIRECTED_AS_DIRECTED, W_MUTUAL_EXPANDED), node ids are integers (E_ID_CHARSET\n * unless `sanitizeIds: \"mangle\"`, which keeps the original in the `graphty:originalId` attribute\n * the importer restores), nested values are written as JSON text (W_CX2_JSON_AS_STRING), NaN and\n * the infinities as null (W_CX2_NONFINITE_AS_NULL), and the generic notes of checkCapabilities().\n */\n\nimport { type Column, GraphFormatError, type GraphSnapshot, type NodeId } from \"@graphty/graph-format\";\n\nimport { type PairFolding, pairFolding } from \"../../common/direction.js\";\nimport { capabilities, checkCapabilities, LOSS } from \"../../common/export.js\";\nimport { isRecord, POSITION_COLUMN } from \"../../common/json-elements.js\";\nimport { type ResolvedExportOptions, resolveExportOptions } from \"../../common/options.js\";\nimport { type ExplicitWeights, explicitWeights } from \"../../common/weights.js\";\nimport { encodeChunks, joinText } from \"../../common/writer.js\";\nimport { type CommonExportOptions, type ExportCapabilities, type GraphExporter, type LossNote } from \"../../types.js\";\nimport { BYPASS_NAMESPACE, CX2_FORMAT, cx2Type, ORIGINAL_ID_ATTRIBUTE } from \"./importer.js\";\n\n/** The format-specific options of the CX2 exporter: none yet. */\nexport type Cx2ExportOptions = Readonly<Record<never, never>>;\n\n/**\n * The loss notes the CX2 exporter's check() returns (design section 1.3), by name. A key is the\n * code without its severity and format prefixes.\n */\nexport const CX2_LOSS = Object.freeze({\n /** Every edge is written directed: an undirected snapshot, or the undirected pairs of a mixed one. */\n UNDIRECTED_AS_DIRECTED: \"W_CX2_UNDIRECTED_AS_DIRECTED\",\n /** A nested (json) column is written as a string attribute holding its JSON text. */\n JSON_AS_STRING: \"W_CX2_JSON_AS_STRING\",\n /** NaN and the infinities cannot be written; they are written as null and read back unset. */\n NONFINITE_AS_NULL: \"W_CX2_NONFINITE_AS_NULL\",\n /** A mutual pair is written as two directed edges without its mark. */\n MUTUAL_EXPANDED: LOSS.MUTUAL_EXPANDED,\n /** A plain edge column named like the weight key reads back as THE weight (or is skipped when weights are written). */\n WEIGHT_KEY_CLASH: LOSS.WEIGHT_KEY_CLASH,\n /** A parent / parents column: CX2 has no containment. */\n HIERARCHY_DROPPED: LOSS.HIERARCHY,\n /** A start / end / timestamp column: CX2 has no time. */\n TEMPORAL_DROPPED: LOSS.TEMPORAL,\n /** A role column written as a plain attribute. */\n ROLE_DROPPED: LOSS.ROLE,\n /** A dtype CX2 declares as another (f32 as double, u32 as long, dict as string, ...). */\n DTYPE_UNSUPPORTED: LOSS.DTYPE,\n /** Node ids that are not integers under the default sanitizeIds \"error\": export() throws E_INVALID_ID. */\n ID_CHARSET: LOSS.ID_CHARSET,\n /** Node ids that are not integers under sanitizeIds \"mangle\": renumbered, originals kept. */\n ID_MANGLED: LOSS.ID_MANGLED,\n /** Edges without a usable id get generated integer ids. */\n EDGE_IDS_GENERATED: LOSS.EDGE_IDS_GENERATED,\n});\n\n/**\n * What CX2 keeps (design section 1.3): directed multigraphs with self-loops, integer node ids,\n * required integer edge ids, declared string / double / integer / boolean columns and lists of\n * them, declared defaults, network attributes and the position role. f32, u32, u8 and dict columns\n * are written as the nearest declared type and read back as it.\n */\nexport const CX2_CAPABILITIES: ExportCapabilities = capabilities({\n mixedDirection: false,\n multiEdges: true,\n selfLoops: true,\n edgeIds: \"required\",\n idCharset: \"integer\",\n dtypes: [\"string\", \"f64\", \"i32\", \"bool\"],\n components: false,\n lists: true,\n json: false,\n defaults: true,\n options: false,\n hierarchy: false,\n temporal: \"none\",\n graphAttributes: true,\n positions: true,\n viz: false,\n});\n\n/** The roles CX2 has a slot for, and the column names its importer gives them. */\nconst SLOT_ROLES: ReadonlySet<string> = new Set([\"label\", \"position\", \"id\"]);\nconst ROLE_NAMES: Readonly<Record<string, string>> = Object.freeze({\n label: \"name\",\n position: POSITION_COLUMN,\n});\n\n/** Roles whose columns are never written as attributes. */\nconst SKIPPED_ROLES: ReadonlySet<string> = new Set([\n \"directed\",\n \"pair\",\n \"mutual\",\n \"weight\",\n \"timeText\",\n \"originalId\",\n \"parent\",\n \"parents\",\n \"start\",\n \"end\",\n \"timestamp\",\n \"timestamps\",\n \"spells\",\n \"open\",\n \"spellsOpen\",\n \"position\",\n \"color\",\n \"size\",\n \"shape\",\n \"thickness\",\n]);\n\n/** The aspects the exporter writes itself; an opaque aspect of the same name is not written again. */\nconst CORE_ASPECTS: ReadonlySet<string> = new Set([\n \"nodes\",\n \"edges\",\n \"attributeDeclarations\",\n \"networkAttributes\",\n \"nodeBypasses\",\n \"edgeBypasses\",\n \"metaData\",\n \"status\",\n]);\n\n/** The weight attribute name. */\nconst WEIGHT_ATTRIBUTE = \"weight\";\n\n/**\n * The prefix of a string that stands for a raw number literal in the output: -0 (which\n * JSON.stringify writes as 0) and an integer id beyond 2^53 (kept as its digits).\n */\nconst RAW = `${String.fromCharCode(0)}cx2:`;\n\n/** A raw literal as JSON.stringify writes it, to be unquoted. */\nconst RAW_JSON = /\"\\\\u0000cx2:(-?[0-9]+)\"/g;\n\n/** An integer literal beyond 2^53 as text: a CX2 id graph-io keeps as its digits. */\nconst BIG_INTEGER_TEXT = /^-?[1-9][0-9]{15,}$/;\n\n/** The node ids as written: the original, a renumbered one, or a raw big integer. */\ninterface WrittenIds {\n /** How many ids were renumbered (sanitizeIds \"mangle\"). */\n readonly changed: number;\n /** The written id of node i (a number, or a RAW string for a big integer). */\n idAt(i: number): NodeId;\n /** Whether node i was renumbered. */\n isChanged(i: number): boolean;\n /** The original id of node i. */\n originalAt(i: number): NodeId;\n}\n\n/**\n * Whether an id can be written as a CX2 id unchanged: a safe integer, or the digits of an integer\n * beyond 2^53 (the CX2 importer reads those back as the same digits).\n * @param id - the id\n * @returns true when writable\n */\nfunction writableId(id: NodeId): boolean {\n return typeof id === \"number\"\n ? Number.isSafeInteger(id)\n : BIG_INTEGER_TEXT.test(id) && !Number.isSafeInteger(Number(id));\n}\n\n/**\n * The written node ids; under \"error\" an id that is not writable throws E_INVALID_ID, under\n * \"mangle\" it gets the next unused integer.\n * @param snapshot - the snapshot\n * @param mode - the sanitizeIds option\n * @returns the ids\n */\nfunction writtenIds(snapshot: GraphSnapshot, mode: \"error\" | \"mangle\"): WrittenIds {\n const { ids } = snapshot;\n const bad: number[] = [];\n const used = new Set<number>();\n for (let i = 0; i < ids.size; i++) {\n const id = ids.idOf(i);\n if (!writableId(id)) {\n bad.push(i);\n } else if (typeof id === \"number\") {\n used.add(id);\n }\n }\n if (bad.length > 0 && mode === \"error\") {\n const first = ids.idOf(bad[0]);\n throw new GraphFormatError(\n \"E_INVALID_ID\",\n `${bad.length} node id(s) cannot be written as CX2 integers (first: ${JSON.stringify(first)} at index ${bad[0]}); pass sanitizeIds: \"mangle\" to rewrite them`,\n { reason: \"charset\", charset: \"integer\", count: bad.length, index: bad[0] },\n );\n }\n const renumbered = new Map<number, number>();\n let next = 0;\n for (const i of bad) {\n while (used.has(next)) {\n next++;\n }\n used.add(next);\n renumbered.set(i, next);\n }\n return {\n changed: bad.length,\n idAt: (i: number): NodeId => {\n const id = renumbered.get(i) ?? ids.idOf(i);\n return typeof id === \"string\" ? `${RAW}${id}` : id;\n },\n isChanged: (i: number): boolean => renumbered.has(i),\n originalAt: (i: number): NodeId => ids.idOf(i),\n };\n}\n\n/**\n * How many node ids are not writable unchanged.\n * @param snapshot - the snapshot\n * @returns the count\n */\nfunction unwritableIds(snapshot: GraphSnapshot): number {\n let count = 0;\n for (let i = 0; i < snapshot.ids.size; i++) {\n if (!writableId(snapshot.ids.idOf(i))) {\n count++;\n }\n }\n return count;\n}\n\n/** One attribute column as it will be written. */\ninterface AttributePlan {\n readonly column: Column;\n /** The full attribute name. */\n readonly name: string;\n /** The key used in v (the alias, or the name). */\n readonly key: string;\n /** The declared type text. */\n readonly d: string;\n /** Whether values are written as their JSON text (a json column). */\n readonly jsonText: boolean;\n}\n\n/** Everything export() and check() need, computed once. */\ninterface Plan {\n readonly notes: LossNote[];\n readonly fatal: GraphFormatError | null;\n readonly ids: WrittenIds | null;\n readonly folding: PairFolding;\n readonly weights: ExplicitWeights;\n readonly nodeAttrs: readonly AttributePlan[];\n readonly edgeAttrs: readonly AttributePlan[];\n readonly graphAttrs: readonly AttributePlan[];\n readonly nodeBypasses: readonly Column[];\n readonly edgeBypasses: readonly Column[];\n readonly position: Column | null;\n readonly positionZ: boolean;\n readonly z: Column | null;\n readonly edgeIds: readonly number[];\n readonly originalIds: boolean;\n}\n\n/**\n * Whether a column is a bypass column of a CX2 import.\n * @param column - the column\n * @returns true for the cx2.bypass namespace\n */\nfunction isBypass(column: Column): boolean {\n return column.meta.origin?.namespace === BYPASS_NAMESPACE;\n}\n\n/**\n * Whether a column is the z (stacking order) column.\n * @param column - the column\n * @returns true for the column marked by a Cytoscape-family importer\n */\nfunction isZ(column: Column): boolean {\n return column.meta.extra.cytoscape === \"z\";\n}\n\n/**\n * The CX2 type of a scalar dtype.\n * @param dtype - the dtype\n * @param longOrigin - whether the source declared the column long\n * @returns the type text\n */\nfunction scalarType(dtype: string, longOrigin: boolean): string {\n switch (dtype) {\n case \"f64\":\n return longOrigin ? \"long\" : \"double\";\n case \"f32\":\n return \"double\";\n case \"i32\":\n case \"u8\":\n return \"integer\";\n case \"u32\":\n return \"long\";\n case \"bool\":\n return \"boolean\";\n default:\n return \"string\";\n }\n}\n\n/**\n * Whether every set value of an f64 column is integral (so a declared long stays long).\n * @param column - the column\n * @returns true when every set value is a safe integer\n */\nfunction allIntegral(column: Column): boolean {\n for (let i = 0; i < column.length; i++) {\n if (column.isSet(i) && !Number.isSafeInteger(column.value(i))) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * The declared type of a column.\n * @param column - the column\n * @returns the CX2 type text\n */\nfunction declaredType(column: Column): string {\n const { meta } = column;\n const origin = meta.origin?.type ?? null;\n const longOrigin = origin !== null && /long$/.test(origin) && (meta.dtype !== \"f64\" || allIntegral(column));\n if (meta.dtype === \"list\") {\n return meta.itemDtype === null || meta.itemDtype === \"json\"\n ? \"string\"\n : `list_of_${scalarType(meta.itemDtype, longOrigin)}`;\n }\n // a multi-component column (a color, a 3D vector) is written as a list of its components\n return meta.components > 1 ? `list_of_${scalarType(meta.dtype, false)}` : scalarType(meta.dtype, longOrigin);\n}\n\n/**\n * Count the non-finite numbers of a column.\n * @param column - the column\n * @returns how many set cells (or list items) are NaN or infinite\n */\nfunction nonFiniteCount(column: Column): number {\n const { dtype, itemDtype } = column.meta;\n const numeric =\n dtype === \"f32\" || dtype === \"f64\" || (dtype === \"list\" && (itemDtype === \"f32\" || itemDtype === \"f64\"));\n if (!numeric) {\n return 0;\n }\n let count = 0;\n for (let i = 0; i < column.length; i++) {\n if (!column.isSet(i)) {\n continue;\n }\n const value = column.value(i);\n if (dtype === \"list\") {\n if ((value as readonly number[]).some((v) => !Number.isFinite(v))) {\n count++;\n }\n } else if (!Number.isFinite(value as number)) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Plan the attribute columns of one table.\n * @param table - the table\n * @param skip - columns not written as attributes\n * @param rename - the written name of a column, when it differs (the label as `name`)\n * @param reserved - keys already used in v\n * @returns the plans\n */\nfunction planAttributes(\n table: Iterable<Column>,\n skip: (column: Column) => boolean,\n rename: (column: Column) => string,\n reserved: ReadonlySet<string> = new Set(),\n): AttributePlan[] {\n const plans: AttributePlan[] = [];\n const used = new Set<string>(reserved);\n const candidates = [...table].filter((c) => !skip(c));\n for (const column of candidates) {\n used.add(rename(column));\n }\n for (const column of candidates) {\n const name = rename(column);\n const { origin } = column.meta;\n let key = name;\n const alias = origin?.format === CX2_FORMAT && typeof origin.id === \"string\" ? origin.id : null;\n if (alias !== null && alias.length > 0 && alias !== name && !used.has(alias)) {\n key = alias;\n used.add(alias);\n }\n plans.push({ column, name, key, d: declaredType(column), jsonText: column.meta.dtype === \"json\" });\n }\n return plans;\n}\n\n/**\n * Plan an export: the notes, the fatal condition and what is written.\n * @param snapshot - the snapshot\n * @param common - the resolved common options\n * @returns the plan\n */\nfunction plan(snapshot: GraphSnapshot, common: ResolvedExportOptions): Plan {\n const notes: LossNote[] = [];\n let fatal: GraphFormatError | null = null;\n const note = (code: string, message: string, column: string | null = null, count: number | null = null): void => {\n notes.push(Object.freeze({ code, message, column, count }));\n };\n // bypass columns are written as bypasses, which hold any JSON value\n const bypassNames = new Set(\n [...snapshot.nodes, ...snapshot.edges].filter((c) => isBypass(c) || isZ(c)).map((c) => c.meta.name),\n );\n for (const gen of checkCapabilities(snapshot, CX2_CAPABILITIES, common, {\n roles: SLOT_ROLES,\n roleNames: ROLE_NAMES,\n })) {\n if (gen.column !== null && bypassNames.has(gen.column) && (gen.code === LOSS.JSON || gen.code === LOSS.DTYPE)) {\n continue;\n }\n if (gen.code === LOSS.ID_CHARSET || gen.code === LOSS.ID_MANGLED) {\n // counted below: CX2 also keeps integer ids beyond 2^53, which the generic rule refuses\n continue;\n }\n if (gen.code === LOSS.JSON) {\n note(\n CX2_LOSS.JSON_AS_STRING,\n `${gen.column === null ? \"a column\" : `column \"${gen.column}\"`} holds nested values; written as a string attribute holding their JSON text`,\n gen.column,\n gen.count,\n );\n continue;\n }\n if (gen.code === LOSS.MIXED_DIRECTION_ERROR && fatal === null) {\n fatal = new GraphFormatError(\"E_DIRECTED\", gen.message, { reason: \"mixed direction\" });\n }\n notes.push(gen);\n }\n\n const folding = pairFolding(snapshot);\n directionNotes(snapshot, folding, common, note);\n\n const unwritable = unwritableIds(snapshot);\n if (unwritable > 0) {\n note(\n common.sanitizeIds === \"mangle\" ? LOSS.ID_MANGLED : LOSS.ID_CHARSET,\n common.sanitizeIds === \"mangle\"\n ? `${unwritable} node id(s) that are not integers are renumbered; the originals are kept in the ${ORIGINAL_ID_ATTRIBUTE} attribute (restored by restoreMangledIds)`\n : `${unwritable} node id(s) that are not integers; export() will throw unless sanitizeIds is \"mangle\"`,\n null,\n unwritable,\n );\n }\n let ids: WrittenIds | null = null;\n try {\n ids = writtenIds(snapshot, common.sanitizeIds);\n } catch (err) {\n if (!(err instanceof GraphFormatError)) {\n throw err;\n }\n fatal ??= err;\n }\n\n const weights = explicitWeights(snapshot);\n const label = snapshot.nodes.byRole(\"label\");\n const nodeAttrs = planAttributes(\n snapshot.nodes,\n (c) => (c.meta.role !== null && SKIPPED_ROLES.has(c.meta.role)) || isBypass(c) || isZ(c),\n (c) => (c === label && !snapshot.nodes.has(\"name\") ? \"name\" : c.meta.name),\n ids !== null && ids.changed > 0 ? new Set([ORIGINAL_ID_ATTRIBUTE]) : new Set(),\n );\n const plainWeight = snapshot.edges.get(WEIGHT_ATTRIBUTE);\n const weightColumnClash = plainWeight !== null && plainWeight.meta.role === null;\n if (weightColumnClash) {\n note(\n LOSS.WEIGHT_KEY_CLASH,\n weights.weighted\n ? `edge column \"${WEIGHT_ATTRIBUTE}\" is not written: the explicit weights are written under that name`\n : `edge column \"${WEIGHT_ATTRIBUTE}\" reads back as the edge weight`,\n WEIGHT_ATTRIBUTE,\n null,\n );\n }\n const edgeAttrs = planAttributes(\n snapshot.edges,\n (c) =>\n (c.meta.role !== null && (SKIPPED_ROLES.has(c.meta.role) || c.meta.role === \"id\")) ||\n isBypass(c) ||\n (weights.weighted && c === plainWeight),\n (c) => c.meta.name,\n weights.weighted ? new Set([WEIGHT_ATTRIBUTE]) : new Set(),\n );\n const graphAttrs = planAttributes(\n snapshot.graph,\n () => false,\n (c) => c.meta.name,\n ).map((p) => ({ ...p, key: p.name }));\n\n let nonfinite = 0;\n for (const p of [...nodeAttrs, ...edgeAttrs, ...graphAttrs]) {\n nonfinite += nonFiniteCount(p.column);\n }\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (weights.isExplicit(e) && !Number.isFinite(weights.value(e))) {\n nonfinite++;\n }\n }\n const position = snapshot.nodes.byRole(\"position\");\n if (position !== null) {\n nonfinite += nonFinitePositions(position);\n }\n if (nonfinite > 0) {\n note(\n CX2_LOSS.NONFINITE_AS_NULL,\n `${nonfinite} NaN or infinite value(s) cannot be written in CX2; written as null, they read back unset`,\n null,\n nonfinite,\n );\n }\n\n const edgeIds = planEdgeIds(snapshot, note);\n const idColumn = snapshot.edges.byRole(\"id\");\n if (idColumn !== null && idColumn.dtype !== \"f64\") {\n note(\n LOSS.DTYPE,\n `edge id column \"${idColumn.meta.name}\" is ${idColumn.dtype}; CX2 edge ids are integers and read back as f64`,\n idColumn.meta.name,\n snapshot.edgeCount - idColumn.nullCount,\n );\n }\n const z = [...snapshot.nodes].find(isZ) ?? null;\n const positionZ = position !== null && z === null && position.meta.extra.sourceDims === 3;\n return {\n notes,\n fatal,\n ids,\n folding,\n weights,\n nodeAttrs,\n edgeAttrs,\n graphAttrs,\n nodeBypasses: [...snapshot.nodes].filter(isBypass),\n edgeBypasses: [...snapshot.edges].filter(isBypass),\n position,\n positionZ,\n z,\n edgeIds,\n originalIds: ids !== null && ids.changed > 0,\n };\n}\n\n/**\n * The direction notes: every CX2 edge is directed, so an undirected snapshot (or the undirected\n * pairs of a mixed one, folded under onMixedDirection) is written directed, and a mutual pair as\n * two edges without its mark.\n * @param snapshot - the snapshot\n * @param folding - the pair folding\n * @param common - the resolved common options\n * @param note - records a note\n */\nfunction directionNotes(\n snapshot: GraphSnapshot,\n folding: PairFolding,\n common: ResolvedExportOptions,\n note: (code: string, message: string, column?: string | null, count?: number | null) => void,\n): void {\n if (!snapshot.directed) {\n note(\n CX2_LOSS.UNDIRECTED_AS_DIRECTED,\n `the snapshot is undirected; every edge is written as a directed CX2 edge (${snapshot.edgeCount} edge(s))`,\n null,\n snapshot.edgeCount,\n );\n } else if (common.onMixedDirection !== \"error\") {\n let undirected = 0;\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (!folding.folded(e) && !folding.sourceDirected(e)) {\n undirected++;\n }\n }\n if (undirected > 0) {\n note(\n CX2_LOSS.UNDIRECTED_AS_DIRECTED,\n `${undirected} undirected edge(s) are written as one directed edge each (a pair folded to its primary); CX2 has no undirected edge`,\n null,\n undirected,\n );\n }\n }\n if (folding.mutualCount > 0) {\n note(\n LOSS.MUTUAL_EXPANDED,\n `${folding.mutualCount} mutual pair(s) are written as two directed edges; the mutual mark is lost`,\n null,\n folding.mutualCount,\n );\n }\n}\n\n/**\n * Count the positions with a non-finite x or y.\n * @param position - the position column\n * @returns the count\n */\nfunction nonFinitePositions(position: Column): number {\n let count = 0;\n for (let i = 0; i < position.length; i++) {\n if (position.isSet(i)) {\n const p = position.value(i) as ArrayLike<number>;\n if (!Number.isFinite(p[0]) || !Number.isFinite(p[1])) {\n count++;\n }\n }\n }\n return count;\n}\n\n/**\n * The edge ids to write: the id role column's values when they are distinct safe integers,\n * next unused integers for edges without one.\n * @param snapshot - the snapshot\n * @param note - records a note\n * @returns one id per edge\n */\nfunction planEdgeIds(\n snapshot: GraphSnapshot,\n note: (code: string, message: string, column?: string | null, count?: number | null) => void,\n): number[] {\n const column = snapshot.edges.byRole(\"id\");\n const ids: (number | null)[] = new Array<number | null>(snapshot.edgeCount).fill(null);\n const used = new Set<number>();\n let generated = 0;\n if (column !== null) {\n for (let e = 0; e < snapshot.edgeCount; e++) {\n const value = column.isSet(e) ? column.value(e) : undefined;\n let n = NaN;\n if (typeof value === \"number\") {\n n = value;\n } else if (typeof value === \"string\") {\n n = Number(value);\n }\n if (Number.isSafeInteger(n) && !used.has(n)) {\n ids[e] = n === 0 ? 0 : n;\n used.add(n);\n }\n }\n }\n let next = 0;\n const out: number[] = [];\n for (let e = 0; e < snapshot.edgeCount; e++) {\n let id = ids[e];\n if (id === null) {\n while (used.has(next)) {\n next++;\n }\n id = next;\n used.add(next);\n generated++;\n }\n out.push(id);\n }\n if (column !== null && generated > 0) {\n note(\n LOSS.EDGE_IDS_GENERATED,\n `${generated} edge(s) have no distinct integer id in \"${column.meta.name}\"; they are written with generated ids`,\n column.meta.name,\n generated,\n );\n }\n return out;\n}\n\n// ============================================================ writing\n\n/**\n * The JSON text of a value, keeping -0.\n * @param value - the value\n * @returns the text\n */\nfunction stringify(value: unknown): string {\n const text = JSON.stringify(value, (_key, v: unknown) => (Object.is(v, -0) ? `${RAW}-0` : v));\n return text.includes(\"\\\\u0000cx2:\") ? text.replace(RAW_JSON, \"$1\") : text;\n}\n\n/**\n * The value written for one cell.\n * @param p - the attribute plan\n * @param row - the row\n * @returns the value, or undefined for an unset cell\n */\nfunction cellValue(p: AttributePlan, row: number): unknown {\n const { column } = p;\n if (!column.isSet(row)) {\n return undefined;\n }\n const value = column.value(row);\n if (p.jsonText) {\n return JSON.stringify(value);\n }\n if (column.meta.dtype === \"list\" || column.meta.components > 1) {\n const items = Array.from(value as ArrayLike<unknown>);\n if (p.d === \"string\") {\n return JSON.stringify(items);\n }\n return items.some((v) => typeof v === \"number\" && !Number.isFinite(v)) ? null : items;\n }\n if (typeof value === \"number\" && !Number.isFinite(value)) {\n return null;\n }\n return value;\n}\n\n/**\n * The declarations of one table.\n * @param plans - the attribute plans\n * @param defaults - whether defaults and aliases may be written (not for network attributes)\n * @returns the declaration object\n */\nfunction declarations(plans: readonly AttributePlan[], defaults: boolean): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const p of plans) {\n const decl: Record<string, unknown> = { d: p.d };\n if (defaults && p.key !== p.name) {\n decl.a = p.key;\n }\n const fallback = p.column.meta.default;\n if (defaults && fallback !== undefined && fallback !== null) {\n if (defaultFits(cx2Type(p.d), fallback)) {\n decl.v = fallback;\n }\n }\n out[p.name] = decl;\n }\n return out;\n}\n\n/**\n * Whether a declared default can be written as the value of a declared type.\n * @param type - the type\n * @param fallback - the default\n * @returns true when it matches\n */\nfunction defaultFits(type: ReturnType<typeof cx2Type>, fallback: unknown): boolean {\n if (type === null) {\n return false;\n }\n if (type.list) {\n return Array.isArray(fallback);\n }\n switch (type.scalar) {\n case \"string\":\n return typeof fallback === \"string\";\n case \"boolean\":\n return typeof fallback === \"boolean\";\n default:\n return typeof fallback === \"number\" && Number.isFinite(fallback);\n }\n}\n\n/**\n * The v object of one element.\n * @param plans - the attribute plans\n * @param row - the row\n * @returns the object, or null when empty\n */\nfunction attributesOf(plans: readonly AttributePlan[], row: number): Record<string, unknown> | null {\n let out: Record<string, unknown> | null = null;\n for (const p of plans) {\n const value = cellValue(p, row);\n if (value !== undefined) {\n out ??= {};\n out[p.key] = value;\n }\n }\n return out;\n}\n\n/**\n * Write the document as text parts.\n * @param snapshot - the snapshot\n * @param p - the plan\n * @yields the document's text\n * @returns nothing\n */\nfunction* write(snapshot: GraphSnapshot, p: Plan): Generator<string, void, undefined> {\n if (p.fatal !== null) {\n throw p.fatal;\n }\n const { ids } = p;\n if (ids === null) {\n throw new GraphFormatError(\"E_INVALID_ID\", \"node ids cannot be written as CX2 integers\", { reason: \"charset\" });\n }\n const { src, dst } = snapshot.edgeList();\n const edges: number[] = [];\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (!p.folding.folded(e)) {\n edges.push(e);\n }\n }\n\n const nodeDecls = declarations(p.nodeAttrs, true);\n if (p.originalIds) {\n nodeDecls[ORIGINAL_ID_ATTRIBUTE] = { d: \"string\" };\n }\n const edgeDecls = declarations(p.edgeAttrs, true);\n if (p.weights.weighted) {\n edgeDecls[WEIGHT_ATTRIBUTE] = { d: \"double\" };\n }\n const networkDecls = declarations(p.graphAttrs, false);\n const network: Record<string, unknown> = {};\n for (const a of p.graphAttrs) {\n const value = cellValue(a, 0);\n if (value !== undefined) {\n network[a.name] = value;\n }\n }\n const { meta } = snapshot;\n for (const [key, value] of [\n [\"name\", meta.name],\n [\"description\", meta.description],\n ] as const) {\n if (value !== null && !(key in network) && !(key in networkDecls)) {\n network[key] = value;\n networkDecls[key] = { d: \"string\" };\n }\n }\n const kept = isRecord(meta.extra.cx2) ? meta.extra.cx2 : {};\n const otherDecls = isRecord(kept.declarations) ? kept.declarations : {};\n const opaque = meta.sourceFormat === CX2_FORMAT && isRecord(kept.opaque) ? kept.opaque : {};\n const declarationsElement: Record<string, unknown> = { ...otherDecls };\n for (const [key, table] of [\n [\"networkAttributes\", networkDecls],\n [\"nodes\", nodeDecls],\n [\"edges\", edgeDecls],\n ] as const) {\n if (Object.keys(table).length > 0) {\n declarationsElement[key] = table;\n }\n }\n const nodeBypassRows = bypassRows(p.nodeBypasses, snapshot.nodeCount);\n const edgeBypassRows = bypassRows(p.edgeBypasses, snapshot.edgeCount).filter((e) => !p.folding.folded(e));\n const opaqueAspects = Object.entries(opaque).filter(\n (entry): entry is [string, unknown[]] => !CORE_ASPECTS.has(entry[0]) && Array.isArray(entry[1]),\n );\n\n const counts: [string, number][] = [];\n const hasDeclarations = Object.keys(declarationsElement).length > 0;\n if (hasDeclarations) {\n counts.push([\"attributeDeclarations\", 1]);\n }\n if (Object.keys(network).length > 0) {\n counts.push([\"networkAttributes\", 1]);\n }\n counts.push([\"nodes\", snapshot.nodeCount], [\"edges\", edges.length]);\n if (nodeBypassRows.length > 0) {\n counts.push([\"nodeBypasses\", nodeBypassRows.length]);\n }\n if (edgeBypassRows.length > 0) {\n counts.push([\"edgeBypasses\", edgeBypassRows.length]);\n }\n for (const [name, elements] of opaqueAspects) {\n counts.push([name, elements.length]);\n }\n\n yield '[{\"CXVersion\":\"2.0\",\"hasFragments\":false},\\n';\n yield `{\"metaData\":${stringify(counts.map(([name, elementCount]) => ({ name, elementCount })))}},\\n`;\n if (hasDeclarations) {\n yield `{\"attributeDeclarations\":[${stringify(declarationsElement)}]},\\n`;\n }\n if (Object.keys(network).length > 0) {\n yield `{\"networkAttributes\":[${stringify(network)}]},\\n`;\n }\n yield* block(\"nodes\", snapshot.nodeCount, (i) => stringify(nodeElement(p, ids, i)));\n yield* block(\"edges\", edges.length, (k) => {\n const e = edges[k];\n const element: Record<string, unknown> = {\n id: p.edgeIds[e],\n s: ids.idAt(src[e]),\n t: ids.idAt(dst[e]),\n };\n let v = attributesOf(p.edgeAttrs, e);\n if (p.weights.isExplicit(e)) {\n const w = p.weights.value(e);\n v ??= {};\n v[WEIGHT_ATTRIBUTE] = Number.isFinite(w) ? w : null;\n }\n if (v !== null) {\n element.v = v;\n }\n return stringify(element);\n });\n if (nodeBypassRows.length > 0) {\n yield* block(\"nodeBypasses\", nodeBypassRows.length, (k) => {\n const i = nodeBypassRows[k];\n return stringify({ id: ids.idAt(i), v: bypassValues(p.nodeBypasses, i) });\n });\n }\n if (edgeBypassRows.length > 0) {\n yield* block(\"edgeBypasses\", edgeBypassRows.length, (k) => {\n const e = edgeBypassRows[k];\n return stringify({ id: p.edgeIds[e], v: bypassValues(p.edgeBypasses, e) });\n });\n }\n for (const [name, elements] of opaqueAspects) {\n yield* block(name, elements.length, (k) => stringify(elements[k]));\n }\n yield '{\"status\":[{\"error\":\"\",\"success\":true}]}]\\n';\n}\n\n/**\n * The text of one aspect block, element by element.\n * @param aspect - the aspect name\n * @param count - its element count\n * @param element - the JSON text of element k\n * @yields the block's text\n * @returns nothing\n */\nfunction* block(aspect: string, count: number, element: (k: number) => string): Generator<string, void, undefined> {\n yield `{${JSON.stringify(aspect)}:[`;\n for (let k = 0; k < count; k++) {\n yield k === 0 ? `\\n${element(k)}` : `,\\n${element(k)}`;\n }\n yield \"]},\\n\";\n}\n\n/**\n * The element of node i.\n * @param p - the plan\n * @param ids - the written ids\n * @param i - the node index\n * @returns the element\n */\nfunction nodeElement(p: Plan, ids: WrittenIds, i: number): Record<string, unknown> {\n const element: Record<string, unknown> = { id: ids.idAt(i) };\n if (p.position?.isSet(i) === true) {\n const point = p.position.value(i) as ArrayLike<number>;\n if (Number.isFinite(point[0]) && Number.isFinite(point[1])) {\n element.x = point[0];\n element.y = point[1] === 0 ? 0 : -point[1];\n if (p.positionZ && Number.isFinite(point[2])) {\n element.z = point[2];\n }\n }\n }\n if (p.z?.isSet(i) === true) {\n const z = p.z.value(i);\n if (typeof z === \"number\" && Number.isFinite(z)) {\n element.z = z;\n }\n }\n let v = attributesOf(p.nodeAttrs, i);\n if (p.originalIds && ids.isChanged(i)) {\n v ??= {};\n v[ORIGINAL_ID_ATTRIBUTE] = String(ids.originalAt(i));\n }\n if (v !== null) {\n element.v = v;\n }\n return element;\n}\n\n/**\n * The rows with at least one bypass value.\n * @param columns - the bypass columns\n * @param rows - the row count\n * @returns the rows, ascending\n */\nfunction bypassRows(columns: readonly Column[], rows: number): number[] {\n const out: number[] = [];\n if (columns.length === 0) {\n return out;\n }\n for (let i = 0; i < rows; i++) {\n if (columns.some((c) => c.isSet(i))) {\n out.push(i);\n }\n }\n return out;\n}\n\n/**\n * The bypass values of one row.\n * @param columns - the bypass columns\n * @param row - the row\n * @returns property -> value\n */\nfunction bypassValues(columns: readonly Column[], row: number): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const column of columns) {\n if (column.isSet(row)) {\n // the visual property's own name: a column renamed for a clash with an attribute keeps it in origin.id\n const property = column.meta.origin?.id;\n out[typeof property === \"string\" && property.length > 0 ? property : column.meta.name] = column.value(row);\n }\n }\n return out;\n}\n\n/**\n * The CX2 exporter plugin (design section 1.3).\n */\nexport const cx2Exporter: GraphExporter<Cx2ExportOptions> = Object.freeze({\n format: CX2_FORMAT,\n capabilities: CX2_CAPABILITIES,\n\n /**\n * Pre-flight: what export() would lose, without writing anything.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the notes, empty when the export is exact\n */\n check(snapshot: GraphSnapshot, options?: Cx2ExportOptions & CommonExportOptions): readonly LossNote[] {\n return Object.freeze([...plan(snapshot, resolveExportOptions(options)).notes]);\n },\n\n /**\n * Write the document as UTF-8 chunks.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the chunks\n */\n export(snapshot: GraphSnapshot, options?: Cx2ExportOptions & CommonExportOptions): AsyncIterable<Uint8Array> {\n return encodeChunks(write(snapshot, plan(snapshot, resolveExportOptions(options))));\n },\n\n /**\n * Write the document as one string.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the document\n */\n exportToString(snapshot: GraphSnapshot, options?: Cx2ExportOptions & CommonExportOptions): Promise<string> {\n return joinText(write(snapshot, plan(snapshot, resolveExportOptions(options))));\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"exporter-BGrsWamJ.js","sources":["../../src/formats/cx2/exporter.ts"],"sourcesContent":["/**\n * The CX2 exporter (design/graph-io/cytoscape-and-obo/design.md section 1.3; graphty issue #307):\n * writes a snapshot as one CX2 document -- the descriptor, the pre-metadata, one\n * `attributeDeclarations` block (aliases from `origin.id`, defaults from `meta.default`),\n * `networkAttributes`, `nodes` (x / y from the position with y flipped back to screen coordinates,\n * `z` from the `z` column), `edges`, the `cx2.bypass` columns as `nodeBypasses` / `edgeBypasses`,\n * the opaque aspects a CX2 import kept (which returns its own style rules) and `status`.\n *\n * What CX2 cannot hold is announced by check() before anything is written: every edge is\n * directed (W_CX2_UNDIRECTED_AS_DIRECTED, W_MUTUAL_EXPANDED), node ids are integers (E_ID_CHARSET\n * unless `sanitizeIds: \"mangle\"`, which keeps the original in the `graphty:originalId` attribute\n * the importer restores), nested values are written as JSON text (W_CX2_JSON_AS_STRING), NaN and\n * the infinities as null (W_CX2_NONFINITE_AS_NULL), and the generic notes of checkCapabilities().\n */\n\nimport { type Column, GraphFormatError, type GraphSnapshot, type NodeId } from \"@graphty/graph-format\";\n\nimport { type PairFolding, pairFolding } from \"../../common/direction.js\";\nimport { capabilities, checkCapabilities, LOSS } from \"../../common/export.js\";\nimport { isRecord, POSITION_COLUMN } from \"../../common/json-elements.js\";\nimport { type ResolvedExportOptions, resolveExportOptions } from \"../../common/options.js\";\nimport { type ExplicitWeights, explicitWeights } from \"../../common/weights.js\";\nimport { encodeChunks, joinText } from \"../../common/writer.js\";\nimport { type CommonExportOptions, type ExportCapabilities, type GraphExporter, type LossNote } from \"../../types.js\";\nimport { BYPASS_NAMESPACE, CX2_FORMAT, cx2Type, ORIGINAL_ID_ATTRIBUTE } from \"./importer.js\";\n\n/** The format-specific options of the CX2 exporter: none yet. */\nexport type Cx2ExportOptions = Readonly<Record<never, never>>;\n\n/**\n * The loss notes the CX2 exporter's check() returns (design section 1.3), by name. A key is the\n * code without its severity and format prefixes.\n */\nexport const CX2_LOSS = Object.freeze({\n /** Every edge is written directed: an undirected snapshot, or the undirected pairs of a mixed one. */\n UNDIRECTED_AS_DIRECTED: \"W_CX2_UNDIRECTED_AS_DIRECTED\",\n /** A nested (json) column is written as a string attribute holding its JSON text. */\n JSON_AS_STRING: \"W_CX2_JSON_AS_STRING\",\n /** NaN and the infinities cannot be written; they are written as null and read back unset. */\n NONFINITE_AS_NULL: \"W_CX2_NONFINITE_AS_NULL\",\n /** A mutual pair is written as two directed edges without its mark. */\n MUTUAL_EXPANDED: LOSS.MUTUAL_EXPANDED,\n /** A plain edge column named like the weight key reads back as THE weight (or is skipped when weights are written). */\n WEIGHT_KEY_CLASH: LOSS.WEIGHT_KEY_CLASH,\n /** A parent / parents column: CX2 has no containment. */\n HIERARCHY_DROPPED: LOSS.HIERARCHY,\n /** A start / end / timestamp column: CX2 has no time. */\n TEMPORAL_DROPPED: LOSS.TEMPORAL,\n /** A role column written as a plain attribute. */\n ROLE_DROPPED: LOSS.ROLE,\n /** A dtype CX2 declares as another (f32 as double, u32 as long, dict as string, ...). */\n DTYPE_UNSUPPORTED: LOSS.DTYPE,\n /** Node ids that are not integers under the default sanitizeIds \"error\": export() throws E_INVALID_ID. */\n ID_CHARSET: LOSS.ID_CHARSET,\n /** Node ids that are not integers under sanitizeIds \"mangle\": renumbered, originals kept. */\n ID_MANGLED: LOSS.ID_MANGLED,\n /** Edges without a usable id get generated integer ids. */\n EDGE_IDS_GENERATED: LOSS.EDGE_IDS_GENERATED,\n});\n\n/**\n * What CX2 keeps (design section 1.3): directed multigraphs with self-loops, integer node ids,\n * required integer edge ids, declared string / double / integer / boolean columns and lists of\n * them, declared defaults, network attributes and the position role. f32, u32, u8 and dict columns\n * are written as the nearest declared type and read back as it.\n */\nexport const CX2_CAPABILITIES: ExportCapabilities = capabilities({\n mixedDirection: false,\n multiEdges: true,\n selfLoops: true,\n edgeIds: \"required\",\n idCharset: \"integer\",\n dtypes: [\"string\", \"f64\", \"i32\", \"bool\"],\n components: false,\n lists: true,\n json: false,\n defaults: true,\n options: false,\n hierarchy: false,\n temporal: \"none\",\n graphAttributes: true,\n positions: true,\n viz: false,\n});\n\n/** The roles CX2 has a slot for, and the column names its importer gives them. */\nconst SLOT_ROLES: ReadonlySet<string> = new Set([\"label\", \"position\", \"id\"]);\nconst ROLE_NAMES: Readonly<Record<string, string>> = Object.freeze({\n label: \"name\",\n position: POSITION_COLUMN,\n});\n\n/** Roles whose columns are never written as attributes. */\nconst SKIPPED_ROLES: ReadonlySet<string> = new Set([\n \"directed\",\n \"pair\",\n \"mutual\",\n \"weight\",\n \"timeText\",\n \"originalId\",\n \"parent\",\n \"parents\",\n \"start\",\n \"end\",\n \"timestamp\",\n \"timestamps\",\n \"spells\",\n \"open\",\n \"spellsOpen\",\n \"position\",\n \"color\",\n \"size\",\n \"shape\",\n \"thickness\",\n]);\n\n/** The aspects the exporter writes itself; an opaque aspect of the same name is not written again. */\nconst CORE_ASPECTS: ReadonlySet<string> = new Set([\n \"nodes\",\n \"edges\",\n \"attributeDeclarations\",\n \"networkAttributes\",\n \"nodeBypasses\",\n \"edgeBypasses\",\n \"metaData\",\n \"status\",\n]);\n\n/** The weight attribute name. */\nconst WEIGHT_ATTRIBUTE = \"weight\";\n\n/**\n * The prefix of a string that stands for a raw number literal in the output: -0 (which\n * JSON.stringify writes as 0) and an integer id beyond 2^53 (kept as its digits).\n */\nconst RAW = `${String.fromCharCode(0)}cx2:`;\n\n/** A raw literal as JSON.stringify writes it, to be unquoted. */\nconst RAW_JSON = /\"\\\\u0000cx2:(-?[0-9]+)\"/g;\n\n/** An integer literal beyond 2^53 as text: a CX2 id graph-io keeps as its digits. */\nconst BIG_INTEGER_TEXT = /^-?[1-9][0-9]{15,}$/;\n\n/** The node ids as written: the original, a renumbered one, or a raw big integer. */\ninterface WrittenIds {\n /** How many ids were renumbered (sanitizeIds \"mangle\"). */\n readonly changed: number;\n /** The written id of node i (a number, or a RAW string for a big integer). */\n idAt(i: number): NodeId;\n /** Whether node i was renumbered. */\n isChanged(i: number): boolean;\n /** The original id of node i. */\n originalAt(i: number): NodeId;\n}\n\n/**\n * Whether an id can be written as a CX2 id unchanged: a safe integer, or the digits of an integer\n * beyond 2^53 (the CX2 importer reads those back as the same digits).\n * @param id - the id\n * @returns true when writable\n */\nfunction writableId(id: NodeId): boolean {\n return typeof id === \"number\"\n ? Number.isSafeInteger(id)\n : BIG_INTEGER_TEXT.test(id) && !Number.isSafeInteger(Number(id));\n}\n\n/**\n * The written node ids; under \"error\" an id that is not writable throws E_INVALID_ID, under\n * \"mangle\" it gets the next unused integer.\n * @param snapshot - the snapshot\n * @param mode - the sanitizeIds option\n * @returns the ids\n */\nfunction writtenIds(snapshot: GraphSnapshot, mode: \"error\" | \"mangle\"): WrittenIds {\n const { ids } = snapshot;\n const bad: number[] = [];\n const used = new Set<number>();\n for (let i = 0; i < ids.size; i++) {\n const id = ids.idOf(i);\n if (!writableId(id)) {\n bad.push(i);\n } else if (typeof id === \"number\") {\n used.add(id);\n }\n }\n if (bad.length > 0 && mode === \"error\") {\n const first = ids.idOf(bad[0]);\n throw new GraphFormatError(\n \"E_INVALID_ID\",\n `${bad.length} node id(s) cannot be written as CX2 integers (first: ${JSON.stringify(first)} at index ${bad[0]}); pass sanitizeIds: \"mangle\" to rewrite them`,\n { reason: \"charset\", charset: \"integer\", count: bad.length, index: bad[0] },\n );\n }\n const renumbered = new Map<number, number>();\n let next = 0;\n for (const i of bad) {\n while (used.has(next)) {\n next++;\n }\n used.add(next);\n renumbered.set(i, next);\n }\n return {\n changed: bad.length,\n idAt: (i: number): NodeId => {\n const id = renumbered.get(i) ?? ids.idOf(i);\n return typeof id === \"string\" ? `${RAW}${id}` : id;\n },\n isChanged: (i: number): boolean => renumbered.has(i),\n originalAt: (i: number): NodeId => ids.idOf(i),\n };\n}\n\n/**\n * How many node ids are not writable unchanged.\n * @param snapshot - the snapshot\n * @returns the count\n */\nfunction unwritableIds(snapshot: GraphSnapshot): number {\n let count = 0;\n for (let i = 0; i < snapshot.ids.size; i++) {\n if (!writableId(snapshot.ids.idOf(i))) {\n count++;\n }\n }\n return count;\n}\n\n/** One attribute column as it will be written. */\ninterface AttributePlan {\n readonly column: Column;\n /** The full attribute name. */\n readonly name: string;\n /** The key used in v (the alias, or the name). */\n readonly key: string;\n /** The declared type text. */\n readonly d: string;\n /** Whether values are written as their JSON text (a json column). */\n readonly jsonText: boolean;\n}\n\n/** Everything export() and check() need, computed once. */\ninterface Plan {\n readonly notes: LossNote[];\n readonly fatal: GraphFormatError | null;\n readonly ids: WrittenIds | null;\n readonly folding: PairFolding;\n readonly weights: ExplicitWeights;\n readonly nodeAttrs: readonly AttributePlan[];\n readonly edgeAttrs: readonly AttributePlan[];\n readonly graphAttrs: readonly AttributePlan[];\n readonly nodeBypasses: readonly Column[];\n readonly edgeBypasses: readonly Column[];\n readonly position: Column | null;\n readonly positionZ: boolean;\n readonly z: Column | null;\n readonly edgeIds: readonly number[];\n readonly originalIds: boolean;\n}\n\n/**\n * Whether a column is a bypass column of a CX2 import.\n * @param column - the column\n * @returns true for the cx2.bypass namespace\n */\nfunction isBypass(column: Column): boolean {\n return column.meta.origin?.namespace === BYPASS_NAMESPACE;\n}\n\n/**\n * Whether a column is the z (stacking order) column.\n * @param column - the column\n * @returns true for the column marked by a Cytoscape-family importer\n */\nfunction isZ(column: Column): boolean {\n return column.meta.extra.cytoscape === \"z\";\n}\n\n/**\n * The CX2 type of a scalar dtype.\n * @param dtype - the dtype\n * @param longOrigin - whether the source declared the column long\n * @returns the type text\n */\nfunction scalarType(dtype: string, longOrigin: boolean): string {\n switch (dtype) {\n case \"f64\":\n return longOrigin ? \"long\" : \"double\";\n case \"f32\":\n return \"double\";\n case \"i32\":\n case \"u8\":\n return \"integer\";\n case \"u32\":\n return \"long\";\n case \"bool\":\n return \"boolean\";\n default:\n return \"string\";\n }\n}\n\n/**\n * Whether every set value of an f64 column is integral (so a declared long stays long).\n * @param column - the column\n * @returns true when every set value is a safe integer\n */\nfunction allIntegral(column: Column): boolean {\n for (let i = 0; i < column.length; i++) {\n if (column.isSet(i) && !Number.isSafeInteger(column.value(i))) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * The declared type of a column.\n * @param column - the column\n * @returns the CX2 type text\n */\nfunction declaredType(column: Column): string {\n const { meta } = column;\n const origin = meta.origin?.type ?? null;\n const longOrigin = origin !== null && /long$/.test(origin) && (meta.dtype !== \"f64\" || allIntegral(column));\n if (meta.dtype === \"list\") {\n return meta.itemDtype === null || meta.itemDtype === \"json\"\n ? \"string\"\n : `list_of_${scalarType(meta.itemDtype, longOrigin)}`;\n }\n // a multi-component column (a color, a 3D vector) is written as a list of its components\n return meta.components > 1 ? `list_of_${scalarType(meta.dtype, false)}` : scalarType(meta.dtype, longOrigin);\n}\n\n/**\n * Count the non-finite numbers of a column.\n * @param column - the column\n * @returns how many set cells (or list items) are NaN or infinite\n */\nfunction nonFiniteCount(column: Column): number {\n const { dtype, itemDtype } = column.meta;\n const numeric =\n dtype === \"f32\" || dtype === \"f64\" || (dtype === \"list\" && (itemDtype === \"f32\" || itemDtype === \"f64\"));\n if (!numeric) {\n return 0;\n }\n let count = 0;\n for (let i = 0; i < column.length; i++) {\n if (!column.isSet(i)) {\n continue;\n }\n const value = column.value(i);\n if (dtype === \"list\") {\n if ((value as readonly number[]).some((v) => !Number.isFinite(v))) {\n count++;\n }\n } else if (!Number.isFinite(value as number)) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Plan the attribute columns of one table.\n * @param table - the table\n * @param skip - columns not written as attributes\n * @param rename - the written name of a column, when it differs (the label as `name`)\n * @param reserved - keys already used in v\n * @returns the plans\n */\nfunction planAttributes(\n table: Iterable<Column>,\n skip: (column: Column) => boolean,\n rename: (column: Column) => string,\n reserved: ReadonlySet<string> = new Set(),\n): AttributePlan[] {\n const plans: AttributePlan[] = [];\n const used = new Set<string>(reserved);\n const candidates = [...table].filter((c) => !skip(c));\n for (const column of candidates) {\n used.add(rename(column));\n }\n for (const column of candidates) {\n const name = rename(column);\n const { origin } = column.meta;\n let key = name;\n const alias = origin?.format === CX2_FORMAT && typeof origin.id === \"string\" ? origin.id : null;\n if (alias !== null && alias.length > 0 && alias !== name && !used.has(alias)) {\n key = alias;\n used.add(alias);\n }\n plans.push({ column, name, key, d: declaredType(column), jsonText: column.meta.dtype === \"json\" });\n }\n return plans;\n}\n\n/**\n * Plan an export: the notes, the fatal condition and what is written.\n * @param snapshot - the snapshot\n * @param common - the resolved common options\n * @returns the plan\n */\nfunction plan(snapshot: GraphSnapshot, common: ResolvedExportOptions): Plan {\n const notes: LossNote[] = [];\n let fatal: GraphFormatError | null = null;\n const note = (code: string, message: string, column: string | null = null, count: number | null = null): void => {\n notes.push(Object.freeze({ code, message, column, count }));\n };\n // bypass columns are written as bypasses, which hold any JSON value\n const bypassNames = new Set(\n [...snapshot.nodes, ...snapshot.edges].filter((c) => isBypass(c) || isZ(c)).map((c) => c.meta.name),\n );\n for (const gen of checkCapabilities(snapshot, CX2_CAPABILITIES, common, {\n roles: SLOT_ROLES,\n roleNames: ROLE_NAMES,\n })) {\n if (gen.column !== null && bypassNames.has(gen.column) && (gen.code === LOSS.JSON || gen.code === LOSS.DTYPE)) {\n continue;\n }\n if (gen.code === LOSS.ID_CHARSET || gen.code === LOSS.ID_MANGLED) {\n // counted below: CX2 also keeps integer ids beyond 2^53, which the generic rule refuses\n continue;\n }\n if (gen.code === LOSS.JSON) {\n note(\n CX2_LOSS.JSON_AS_STRING,\n `${gen.column === null ? \"a column\" : `column \"${gen.column}\"`} holds nested values; written as a string attribute holding their JSON text`,\n gen.column,\n gen.count,\n );\n continue;\n }\n if (gen.code === LOSS.MIXED_DIRECTION_ERROR && fatal === null) {\n fatal = new GraphFormatError(\"E_DIRECTED\", gen.message, { reason: \"mixed direction\" });\n }\n notes.push(gen);\n }\n\n const folding = pairFolding(snapshot);\n directionNotes(snapshot, folding, common, note);\n\n const unwritable = unwritableIds(snapshot);\n if (unwritable > 0) {\n note(\n common.sanitizeIds === \"mangle\" ? LOSS.ID_MANGLED : LOSS.ID_CHARSET,\n common.sanitizeIds === \"mangle\"\n ? `${unwritable} node id(s) that are not integers are renumbered; the originals are kept in the ${ORIGINAL_ID_ATTRIBUTE} attribute (restored by restoreMangledIds)`\n : `${unwritable} node id(s) that are not integers; export() will throw unless sanitizeIds is \"mangle\"`,\n null,\n unwritable,\n );\n }\n let ids: WrittenIds | null = null;\n try {\n ids = writtenIds(snapshot, common.sanitizeIds);\n } catch (err) {\n if (!(err instanceof GraphFormatError)) {\n throw err;\n }\n fatal ??= err;\n }\n\n const weights = explicitWeights(snapshot);\n const label = snapshot.nodes.byRole(\"label\");\n const nodeAttrs = planAttributes(\n snapshot.nodes,\n (c) => (c.meta.role !== null && SKIPPED_ROLES.has(c.meta.role)) || isBypass(c) || isZ(c),\n (c) => (c === label && !snapshot.nodes.has(\"name\") ? \"name\" : c.meta.name),\n ids !== null && ids.changed > 0 ? new Set([ORIGINAL_ID_ATTRIBUTE]) : new Set(),\n );\n const plainWeight = snapshot.edges.get(WEIGHT_ATTRIBUTE);\n const weightColumnClash = plainWeight !== null && plainWeight.meta.role === null;\n if (weightColumnClash) {\n note(\n LOSS.WEIGHT_KEY_CLASH,\n weights.weighted\n ? `edge column \"${WEIGHT_ATTRIBUTE}\" is not written: the explicit weights are written under that name`\n : `edge column \"${WEIGHT_ATTRIBUTE}\" reads back as the edge weight`,\n WEIGHT_ATTRIBUTE,\n null,\n );\n }\n const edgeAttrs = planAttributes(\n snapshot.edges,\n (c) =>\n (c.meta.role !== null && (SKIPPED_ROLES.has(c.meta.role) || c.meta.role === \"id\")) ||\n isBypass(c) ||\n (weights.weighted && c === plainWeight),\n (c) => c.meta.name,\n weights.weighted ? new Set([WEIGHT_ATTRIBUTE]) : new Set(),\n );\n const graphAttrs = planAttributes(\n snapshot.graph,\n () => false,\n (c) => c.meta.name,\n ).map((p) => ({ ...p, key: p.name }));\n\n let nonfinite = 0;\n for (const p of [...nodeAttrs, ...edgeAttrs, ...graphAttrs]) {\n nonfinite += nonFiniteCount(p.column);\n }\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (weights.isExplicit(e) && !Number.isFinite(weights.value(e))) {\n nonfinite++;\n }\n }\n const position = snapshot.nodes.byRole(\"position\");\n if (position !== null) {\n nonfinite += nonFinitePositions(position);\n }\n if (nonfinite > 0) {\n note(\n CX2_LOSS.NONFINITE_AS_NULL,\n `${nonfinite} NaN or infinite value(s) cannot be written in CX2; written as null, they read back unset`,\n null,\n nonfinite,\n );\n }\n\n const edgeIds = planEdgeIds(snapshot, note);\n const idColumn = snapshot.edges.byRole(\"id\");\n if (idColumn !== null && idColumn.dtype !== \"f64\") {\n note(\n LOSS.DTYPE,\n `edge id column \"${idColumn.meta.name}\" is ${idColumn.dtype}; CX2 edge ids are integers and read back as f64`,\n idColumn.meta.name,\n snapshot.edgeCount - idColumn.nullCount,\n );\n }\n const z = [...snapshot.nodes].find(isZ) ?? null;\n const positionZ = position !== null && z === null && position.meta.extra.sourceDims === 3;\n return {\n notes,\n fatal,\n ids,\n folding,\n weights,\n nodeAttrs,\n edgeAttrs,\n graphAttrs,\n nodeBypasses: [...snapshot.nodes].filter(isBypass),\n edgeBypasses: [...snapshot.edges].filter(isBypass),\n position,\n positionZ,\n z,\n edgeIds,\n originalIds: ids !== null && ids.changed > 0,\n };\n}\n\n/**\n * The direction notes: every CX2 edge is directed, so an undirected snapshot (or the undirected\n * pairs of a mixed one, folded under onMixedDirection) is written directed, and a mutual pair as\n * two edges without its mark.\n * @param snapshot - the snapshot\n * @param folding - the pair folding\n * @param common - the resolved common options\n * @param note - records a note\n */\nfunction directionNotes(\n snapshot: GraphSnapshot,\n folding: PairFolding,\n common: ResolvedExportOptions,\n note: (code: string, message: string, column?: string | null, count?: number | null) => void,\n): void {\n if (!snapshot.directed) {\n note(\n CX2_LOSS.UNDIRECTED_AS_DIRECTED,\n `the snapshot is undirected; every edge is written as a directed CX2 edge (${snapshot.edgeCount} edge(s))`,\n null,\n snapshot.edgeCount,\n );\n } else if (common.onMixedDirection !== \"error\") {\n let undirected = 0;\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (!folding.folded(e) && !folding.sourceDirected(e)) {\n undirected++;\n }\n }\n if (undirected > 0) {\n note(\n CX2_LOSS.UNDIRECTED_AS_DIRECTED,\n `${undirected} undirected edge(s) are written as one directed edge each (a pair folded to its primary); CX2 has no undirected edge`,\n null,\n undirected,\n );\n }\n }\n if (folding.mutualCount > 0) {\n note(\n LOSS.MUTUAL_EXPANDED,\n `${folding.mutualCount} mutual pair(s) are written as two directed edges; the mutual mark is lost`,\n null,\n folding.mutualCount,\n );\n }\n}\n\n/**\n * Count the positions with a non-finite x or y.\n * @param position - the position column\n * @returns the count\n */\nfunction nonFinitePositions(position: Column): number {\n let count = 0;\n for (let i = 0; i < position.length; i++) {\n if (position.isSet(i)) {\n const p = position.value(i) as ArrayLike<number>;\n if (!Number.isFinite(p[0]) || !Number.isFinite(p[1])) {\n count++;\n }\n }\n }\n return count;\n}\n\n/**\n * The edge ids to write: the id role column's values when they are distinct safe integers,\n * next unused integers for edges without one.\n * @param snapshot - the snapshot\n * @param note - records a note\n * @returns one id per edge\n */\nfunction planEdgeIds(\n snapshot: GraphSnapshot,\n note: (code: string, message: string, column?: string | null, count?: number | null) => void,\n): number[] {\n const column = snapshot.edges.byRole(\"id\");\n const ids: (number | null)[] = new Array<number | null>(snapshot.edgeCount).fill(null);\n const used = new Set<number>();\n let generated = 0;\n if (column !== null) {\n for (let e = 0; e < snapshot.edgeCount; e++) {\n const value = column.isSet(e) ? column.value(e) : undefined;\n let n = NaN;\n if (typeof value === \"number\") {\n n = value;\n } else if (typeof value === \"string\") {\n n = Number(value);\n }\n if (Number.isSafeInteger(n) && !used.has(n)) {\n ids[e] = n === 0 ? 0 : n;\n used.add(n);\n }\n }\n }\n let next = 0;\n const out: number[] = [];\n for (let e = 0; e < snapshot.edgeCount; e++) {\n let id = ids[e];\n if (id === null) {\n while (used.has(next)) {\n next++;\n }\n id = next;\n used.add(next);\n generated++;\n }\n out.push(id);\n }\n if (column !== null && generated > 0) {\n note(\n LOSS.EDGE_IDS_GENERATED,\n `${generated} edge(s) have no distinct integer id in \"${column.meta.name}\"; they are written with generated ids`,\n column.meta.name,\n generated,\n );\n }\n return out;\n}\n\n// ============================================================ writing\n\n/**\n * The JSON text of a value, keeping -0.\n * @param value - the value\n * @returns the text\n */\nfunction stringify(value: unknown): string {\n const text = JSON.stringify(value, (_key, v: unknown) => (Object.is(v, -0) ? `${RAW}-0` : v));\n return text.includes(\"\\\\u0000cx2:\") ? text.replace(RAW_JSON, \"$1\") : text;\n}\n\n/**\n * The value written for one cell.\n * @param p - the attribute plan\n * @param row - the row\n * @returns the value, or undefined for an unset cell\n */\nfunction cellValue(p: AttributePlan, row: number): unknown {\n const { column } = p;\n if (!column.isSet(row)) {\n return undefined;\n }\n const value = column.value(row);\n if (p.jsonText) {\n return JSON.stringify(value);\n }\n if (column.meta.dtype === \"list\" || column.meta.components > 1) {\n const items = Array.from(value as ArrayLike<unknown>);\n if (p.d === \"string\") {\n return JSON.stringify(items);\n }\n return items.some((v) => typeof v === \"number\" && !Number.isFinite(v)) ? null : items;\n }\n if (typeof value === \"number\" && !Number.isFinite(value)) {\n return null;\n }\n return value;\n}\n\n/**\n * The declarations of one table.\n * @param plans - the attribute plans\n * @param defaults - whether defaults and aliases may be written (not for network attributes)\n * @returns the declaration object\n */\nfunction declarations(plans: readonly AttributePlan[], defaults: boolean): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const p of plans) {\n const decl: Record<string, unknown> = { d: p.d };\n if (defaults && p.key !== p.name) {\n decl.a = p.key;\n }\n const fallback = p.column.meta.default;\n if (defaults && fallback !== undefined && fallback !== null) {\n if (defaultFits(cx2Type(p.d), fallback)) {\n decl.v = fallback;\n }\n }\n out[p.name] = decl;\n }\n return out;\n}\n\n/**\n * Whether a declared default can be written as the value of a declared type.\n * @param type - the type\n * @param fallback - the default\n * @returns true when it matches\n */\nfunction defaultFits(type: ReturnType<typeof cx2Type>, fallback: unknown): boolean {\n if (type === null) {\n return false;\n }\n if (type.list) {\n return Array.isArray(fallback);\n }\n switch (type.scalar) {\n case \"string\":\n return typeof fallback === \"string\";\n case \"boolean\":\n return typeof fallback === \"boolean\";\n default:\n return typeof fallback === \"number\" && Number.isFinite(fallback);\n }\n}\n\n/**\n * The v object of one element.\n * @param plans - the attribute plans\n * @param row - the row\n * @returns the object, or null when empty\n */\nfunction attributesOf(plans: readonly AttributePlan[], row: number): Record<string, unknown> | null {\n let out: Record<string, unknown> | null = null;\n for (const p of plans) {\n const value = cellValue(p, row);\n if (value !== undefined) {\n out ??= {};\n out[p.key] = value;\n }\n }\n return out;\n}\n\n/**\n * Write the document as text parts.\n * @param snapshot - the snapshot\n * @param p - the plan\n * @yields the document's text\n * @returns nothing\n */\nfunction* write(snapshot: GraphSnapshot, p: Plan): Generator<string, void, undefined> {\n if (p.fatal !== null) {\n throw p.fatal;\n }\n const { ids } = p;\n if (ids === null) {\n throw new GraphFormatError(\"E_INVALID_ID\", \"node ids cannot be written as CX2 integers\", { reason: \"charset\" });\n }\n const { src, dst } = snapshot.edgeList();\n const edges: number[] = [];\n for (let e = 0; e < snapshot.edgeCount; e++) {\n if (!p.folding.folded(e)) {\n edges.push(e);\n }\n }\n\n const nodeDecls = declarations(p.nodeAttrs, true);\n if (p.originalIds) {\n nodeDecls[ORIGINAL_ID_ATTRIBUTE] = { d: \"string\" };\n }\n const edgeDecls = declarations(p.edgeAttrs, true);\n if (p.weights.weighted) {\n edgeDecls[WEIGHT_ATTRIBUTE] = { d: \"double\" };\n }\n const networkDecls = declarations(p.graphAttrs, false);\n const network: Record<string, unknown> = {};\n for (const a of p.graphAttrs) {\n const value = cellValue(a, 0);\n if (value !== undefined) {\n network[a.name] = value;\n }\n }\n const { meta } = snapshot;\n for (const [key, value] of [\n [\"name\", meta.name],\n [\"description\", meta.description],\n ] as const) {\n if (value !== null && !(key in network) && !(key in networkDecls)) {\n network[key] = value;\n networkDecls[key] = { d: \"string\" };\n }\n }\n const kept = isRecord(meta.extra.cx2) ? meta.extra.cx2 : {};\n const otherDecls = isRecord(kept.declarations) ? kept.declarations : {};\n const opaque = meta.sourceFormat === CX2_FORMAT && isRecord(kept.opaque) ? kept.opaque : {};\n const declarationsElement: Record<string, unknown> = { ...otherDecls };\n for (const [key, table] of [\n [\"networkAttributes\", networkDecls],\n [\"nodes\", nodeDecls],\n [\"edges\", edgeDecls],\n ] as const) {\n if (Object.keys(table).length > 0) {\n declarationsElement[key] = table;\n }\n }\n const nodeBypassRows = bypassRows(p.nodeBypasses, snapshot.nodeCount);\n const edgeBypassRows = bypassRows(p.edgeBypasses, snapshot.edgeCount).filter((e) => !p.folding.folded(e));\n const opaqueAspects = Object.entries(opaque).filter(\n (entry): entry is [string, unknown[]] => !CORE_ASPECTS.has(entry[0]) && Array.isArray(entry[1]),\n );\n\n const counts: [string, number][] = [];\n const hasDeclarations = Object.keys(declarationsElement).length > 0;\n if (hasDeclarations) {\n counts.push([\"attributeDeclarations\", 1]);\n }\n if (Object.keys(network).length > 0) {\n counts.push([\"networkAttributes\", 1]);\n }\n counts.push([\"nodes\", snapshot.nodeCount], [\"edges\", edges.length]);\n if (nodeBypassRows.length > 0) {\n counts.push([\"nodeBypasses\", nodeBypassRows.length]);\n }\n if (edgeBypassRows.length > 0) {\n counts.push([\"edgeBypasses\", edgeBypassRows.length]);\n }\n for (const [name, elements] of opaqueAspects) {\n counts.push([name, elements.length]);\n }\n\n yield '[{\"CXVersion\":\"2.0\",\"hasFragments\":false},\\n';\n yield `{\"metaData\":${stringify(counts.map(([name, elementCount]) => ({ name, elementCount })))}},\\n`;\n if (hasDeclarations) {\n yield `{\"attributeDeclarations\":[${stringify(declarationsElement)}]},\\n`;\n }\n if (Object.keys(network).length > 0) {\n yield `{\"networkAttributes\":[${stringify(network)}]},\\n`;\n }\n yield* block(\"nodes\", snapshot.nodeCount, (i) => stringify(nodeElement(p, ids, i)));\n yield* block(\"edges\", edges.length, (k) => {\n const e = edges[k];\n const element: Record<string, unknown> = {\n id: p.edgeIds[e],\n s: ids.idAt(src[e]),\n t: ids.idAt(dst[e]),\n };\n let v = attributesOf(p.edgeAttrs, e);\n if (p.weights.isExplicit(e)) {\n const w = p.weights.value(e);\n v ??= {};\n v[WEIGHT_ATTRIBUTE] = Number.isFinite(w) ? w : null;\n }\n if (v !== null) {\n element.v = v;\n }\n return stringify(element);\n });\n if (nodeBypassRows.length > 0) {\n yield* block(\"nodeBypasses\", nodeBypassRows.length, (k) => {\n const i = nodeBypassRows[k];\n return stringify({ id: ids.idAt(i), v: bypassValues(p.nodeBypasses, i) });\n });\n }\n if (edgeBypassRows.length > 0) {\n yield* block(\"edgeBypasses\", edgeBypassRows.length, (k) => {\n const e = edgeBypassRows[k];\n return stringify({ id: p.edgeIds[e], v: bypassValues(p.edgeBypasses, e) });\n });\n }\n for (const [name, elements] of opaqueAspects) {\n yield* block(name, elements.length, (k) => stringify(elements[k]));\n }\n yield '{\"status\":[{\"error\":\"\",\"success\":true}]}]\\n';\n}\n\n/**\n * The text of one aspect block, element by element.\n * @param aspect - the aspect name\n * @param count - its element count\n * @param element - the JSON text of element k\n * @yields the block's text\n * @returns nothing\n */\nfunction* block(aspect: string, count: number, element: (k: number) => string): Generator<string, void, undefined> {\n yield `{${JSON.stringify(aspect)}:[`;\n for (let k = 0; k < count; k++) {\n yield k === 0 ? `\\n${element(k)}` : `,\\n${element(k)}`;\n }\n yield \"]},\\n\";\n}\n\n/**\n * The element of node i.\n * @param p - the plan\n * @param ids - the written ids\n * @param i - the node index\n * @returns the element\n */\nfunction nodeElement(p: Plan, ids: WrittenIds, i: number): Record<string, unknown> {\n const element: Record<string, unknown> = { id: ids.idAt(i) };\n if (p.position?.isSet(i) === true) {\n const point = p.position.value(i) as ArrayLike<number>;\n if (Number.isFinite(point[0]) && Number.isFinite(point[1])) {\n element.x = point[0];\n element.y = point[1] === 0 ? 0 : -point[1];\n if (p.positionZ && Number.isFinite(point[2])) {\n element.z = point[2];\n }\n }\n }\n if (p.z?.isSet(i) === true) {\n const z = p.z.value(i);\n if (typeof z === \"number\" && Number.isFinite(z)) {\n element.z = z;\n }\n }\n let v = attributesOf(p.nodeAttrs, i);\n if (p.originalIds && ids.isChanged(i)) {\n v ??= {};\n v[ORIGINAL_ID_ATTRIBUTE] = String(ids.originalAt(i));\n }\n if (v !== null) {\n element.v = v;\n }\n return element;\n}\n\n/**\n * The rows with at least one bypass value.\n * @param columns - the bypass columns\n * @param rows - the row count\n * @returns the rows, ascending\n */\nfunction bypassRows(columns: readonly Column[], rows: number): number[] {\n const out: number[] = [];\n if (columns.length === 0) {\n return out;\n }\n for (let i = 0; i < rows; i++) {\n if (columns.some((c) => c.isSet(i))) {\n out.push(i);\n }\n }\n return out;\n}\n\n/**\n * The bypass values of one row.\n * @param columns - the bypass columns\n * @param row - the row\n * @returns property -> value\n */\nfunction bypassValues(columns: readonly Column[], row: number): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const column of columns) {\n if (column.isSet(row)) {\n // the visual property's own name: a column renamed for a clash with an attribute keeps it in origin.id\n const property = column.meta.origin?.id;\n out[typeof property === \"string\" && property.length > 0 ? property : column.meta.name] = column.value(row);\n }\n }\n return out;\n}\n\n/**\n * The CX2 exporter plugin (design section 1.3).\n */\nexport const cx2Exporter: GraphExporter<Cx2ExportOptions> = Object.freeze({\n format: CX2_FORMAT,\n capabilities: CX2_CAPABILITIES,\n\n /**\n * Pre-flight: what export() would lose, without writing anything.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the notes, empty when the export is exact\n */\n check(snapshot: GraphSnapshot, options?: Cx2ExportOptions & CommonExportOptions): readonly LossNote[] {\n return Object.freeze([...plan(snapshot, resolveExportOptions(options)).notes]);\n },\n\n /**\n * Write the document as UTF-8 chunks.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the chunks\n */\n export(snapshot: GraphSnapshot, options?: Cx2ExportOptions & CommonExportOptions): AsyncIterable<Uint8Array> {\n return encodeChunks(write(snapshot, plan(snapshot, resolveExportOptions(options))));\n },\n\n /**\n * Write the document as one string.\n * @param snapshot - the snapshot\n * @param options - the common options\n * @returns the document\n */\n exportToString(snapshot: GraphSnapshot, options?: Cx2ExportOptions & CommonExportOptions): Promise<string> {\n return joinText(write(snapshot, plan(snapshot, resolveExportOptions(options))));\n },\n});\n"],"names":[],"mappings":"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"}
|