diagrams-js 0.3.1 → 0.5.0
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 +29 -0
- package/dist/index.d.ts +215 -6
- package/dist/index.js +242 -13
- package/package.json +1 -1
- package/skills/diagrams-js/diagram-diff/SKILL.md +356 -0
- package/skills/diagrams-js/diagrams-js-plugin-system/SKILL.md +5 -1
- package/skills/diagrams-js/json-serialization/SKILL.md +22 -5
- package/skills/diagrams-js/rendering-export/SKILL.md +35 -4
- package/skills/diagrams-js/svg-serialization/SKILL.md +212 -0
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
- **2000+ Node Classes**: Comprehensive coverage of cloud services and infrastructure components
|
|
19
19
|
- **Cross-Platform**: Works in browsers, Node.js, Deno and Bun
|
|
20
20
|
- **Multiple Output Formats**: SVG, PNG, JPG, and DOT
|
|
21
|
+
- **Visual Diff**: Compare diagram versions side-by-side with color-coded changes (added, removed, modified, renamed)
|
|
21
22
|
- **Type-Safe**: Full TypeScript support with comprehensive type definitions
|
|
22
23
|
- **WebAssembly Powered**: Uses a WebAssembly build of [Graphviz](https://graphviz.org) ([viz](https://github.com/mdaines/viz-js)) for fast, client-side rendering
|
|
23
24
|
- **Custom Nodes**: Support for external icons and images
|
|
@@ -68,6 +69,34 @@ api.to([db, storage]);
|
|
|
68
69
|
const svg = await diagram.render();
|
|
69
70
|
```
|
|
70
71
|
|
|
72
|
+
### Visual Diff
|
|
73
|
+
|
|
74
|
+
Compare two versions of a diagram to see what changed:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { Diagram } from "diagrams-js";
|
|
78
|
+
import { writeFileSync } from "fs";
|
|
79
|
+
|
|
80
|
+
// Load two versions (e.g., from git or saved JSON)
|
|
81
|
+
const before = JSON.parse(await fs.readFile("arch-v1.json", "utf8"));
|
|
82
|
+
const after = JSON.parse(await fs.readFile("arch-v2.json", "utf8"));
|
|
83
|
+
|
|
84
|
+
// Generate visual diff as self-contained HTML
|
|
85
|
+
const html = await Diagram.renderDiff(before, after, {
|
|
86
|
+
format: "html",
|
|
87
|
+
theme: "light",
|
|
88
|
+
showUnchanged: "show", // "show" (default), "dim", or "hide"
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
await fs.writeFile("diff.html", html);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The diff shows:
|
|
95
|
+
|
|
96
|
+
- 🟢 **Green**: Added elements
|
|
97
|
+
- 🔴 **Red**: Removed elements
|
|
98
|
+
- 🟠 **Amber**: Modified elements (including label changes)
|
|
99
|
+
|
|
71
100
|
### Browser
|
|
72
101
|
|
|
73
102
|
```html
|
package/dist/index.d.ts
CHANGED
|
@@ -210,6 +210,8 @@ interface RenderOptions {
|
|
|
210
210
|
scale?: number;
|
|
211
211
|
/** Whether to inject icons into SVG output */
|
|
212
212
|
injectIcons?: boolean;
|
|
213
|
+
/** Whether to embed diagram metadata into SVG output (default: true) */
|
|
214
|
+
embedData?: boolean;
|
|
213
215
|
/** Whether to return output as data URL */
|
|
214
216
|
dataUrl?: boolean;
|
|
215
217
|
}
|
|
@@ -794,9 +796,9 @@ interface DiagramNodeJSON {
|
|
|
794
796
|
/** Cloud provider identifier (e.g., 'aws', 'gcp', 'azure') */
|
|
795
797
|
provider?: string;
|
|
796
798
|
/** Service type within the provider (e.g., 'compute', 'storage') */
|
|
797
|
-
service?: string;
|
|
798
|
-
/** Specific resource type (e.g., 'EC2', 'S3', 'RDS') */
|
|
799
799
|
type?: string;
|
|
800
|
+
/** Specific resource type (e.g., 'EC2', 'S3', 'RDS') */
|
|
801
|
+
resource?: string;
|
|
800
802
|
/** Custom icon URL or data URI */
|
|
801
803
|
iconUrl?: string;
|
|
802
804
|
/** Additional Graphviz attributes */
|
|
@@ -919,8 +921,8 @@ interface DiagramJSON {
|
|
|
919
921
|
* name: "My Architecture",
|
|
920
922
|
* direction: "LR",
|
|
921
923
|
* nodes: [
|
|
922
|
-
* { id: "web", label: "Web Server", provider: "aws",
|
|
923
|
-
* { id: "db", label: "Database", provider: "aws",
|
|
924
|
+
* { id: "web", label: "Web Server", provider: "aws", type: "compute", resource: "EC2" },
|
|
925
|
+
* { id: "db", label: "Database", provider: "aws", type: "database", resource: "RDS" }
|
|
924
926
|
* ],
|
|
925
927
|
* edges: [
|
|
926
928
|
* { from: "web", to: "db", label: "SQL" }
|
|
@@ -933,6 +935,190 @@ interface DiagramJSON {
|
|
|
933
935
|
*/
|
|
934
936
|
declare function fromJSON(input: DiagramJSON | string, opts?: FromJSONOptions): Promise<Diagram>;
|
|
935
937
|
//#endregion
|
|
938
|
+
//#region src/diff.d.ts
|
|
939
|
+
/**
|
|
940
|
+
* Type of change detected during diff computation.
|
|
941
|
+
*/
|
|
942
|
+
type ChangeKind = "added" | "removed" | "modified" | "unchanged";
|
|
943
|
+
/**
|
|
944
|
+
* Diff result for a single node.
|
|
945
|
+
*/
|
|
946
|
+
interface NodeDiff {
|
|
947
|
+
/** The type of change */
|
|
948
|
+
kind: ChangeKind;
|
|
949
|
+
/** The node before changes (for removed, modified) */
|
|
950
|
+
before?: DiagramNodeJSON;
|
|
951
|
+
/** The node after changes (for added, modified) */
|
|
952
|
+
after?: DiagramNodeJSON;
|
|
953
|
+
/** Array of field paths that changed (for modified) */
|
|
954
|
+
changes?: string[];
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Diff result for a single edge.
|
|
958
|
+
*/
|
|
959
|
+
interface EdgeDiff {
|
|
960
|
+
/** The type of change */
|
|
961
|
+
kind: ChangeKind;
|
|
962
|
+
/** The edge before changes */
|
|
963
|
+
before?: DiagramEdgeJSON;
|
|
964
|
+
/** The edge after changes */
|
|
965
|
+
after?: DiagramEdgeJSON;
|
|
966
|
+
/** Array of field paths that changed */
|
|
967
|
+
changes?: string[];
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Diff result for a cluster (recursive).
|
|
971
|
+
*/
|
|
972
|
+
interface ClusterDiff {
|
|
973
|
+
/** The type of change */
|
|
974
|
+
kind: ChangeKind;
|
|
975
|
+
/** Cluster label */
|
|
976
|
+
label: string;
|
|
977
|
+
/** The cluster before changes */
|
|
978
|
+
before?: DiagramClusterJSON;
|
|
979
|
+
/** The cluster after changes */
|
|
980
|
+
after?: DiagramClusterJSON;
|
|
981
|
+
/** Array of field paths that changed */
|
|
982
|
+
changes?: string[];
|
|
983
|
+
/** Nested cluster diffs */
|
|
984
|
+
clusters?: ClusterDiff[];
|
|
985
|
+
/** Node IDs in this cluster and their diff status */
|
|
986
|
+
nodes?: Map<string, NodeDiff>;
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Summary of changes in the diff.
|
|
990
|
+
*/
|
|
991
|
+
interface DiffSummary {
|
|
992
|
+
/** Number of added nodes/edges/clusters */
|
|
993
|
+
added: number;
|
|
994
|
+
/** Number of removed nodes/edges/clusters */
|
|
995
|
+
removed: number;
|
|
996
|
+
/** Number of modified nodes/edges/clusters */
|
|
997
|
+
modified: number;
|
|
998
|
+
/** Number of unchanged nodes/edges/clusters */
|
|
999
|
+
unchanged: number;
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Metadata-level changes (diagram options, not individual elements).
|
|
1003
|
+
*/
|
|
1004
|
+
interface DiffMeta {
|
|
1005
|
+
/** Diagram name change */
|
|
1006
|
+
name?: {
|
|
1007
|
+
before?: string;
|
|
1008
|
+
after?: string;
|
|
1009
|
+
};
|
|
1010
|
+
/** Theme change */
|
|
1011
|
+
theme?: {
|
|
1012
|
+
before?: string;
|
|
1013
|
+
after?: string;
|
|
1014
|
+
};
|
|
1015
|
+
/** Direction change */
|
|
1016
|
+
direction?: {
|
|
1017
|
+
before?: string;
|
|
1018
|
+
after?: string;
|
|
1019
|
+
};
|
|
1020
|
+
/** Curve style change */
|
|
1021
|
+
curvestyle?: {
|
|
1022
|
+
before?: string;
|
|
1023
|
+
after?: string;
|
|
1024
|
+
};
|
|
1025
|
+
/** Graph attributes change */
|
|
1026
|
+
graphAttr?: {
|
|
1027
|
+
before?: Record<string, string>;
|
|
1028
|
+
after?: Record<string, string>;
|
|
1029
|
+
};
|
|
1030
|
+
/** Node attributes change */
|
|
1031
|
+
nodeAttr?: {
|
|
1032
|
+
before?: Record<string, string>;
|
|
1033
|
+
after?: Record<string, string>;
|
|
1034
|
+
};
|
|
1035
|
+
/** Edge attributes change */
|
|
1036
|
+
edgeAttr?: {
|
|
1037
|
+
before?: Record<string, string>;
|
|
1038
|
+
after?: Record<string, string>;
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Complete diff result for a diagram comparison.
|
|
1043
|
+
*/
|
|
1044
|
+
interface DiagramDiffResult {
|
|
1045
|
+
/** Node diffs by node ID */
|
|
1046
|
+
nodes: Map<string, NodeDiff>;
|
|
1047
|
+
/** Edge diffs by composite key "from->to[label]" */
|
|
1048
|
+
edges: Map<string, EdgeDiff>;
|
|
1049
|
+
/** Cluster diffs */
|
|
1050
|
+
clusters: ClusterDiff[];
|
|
1051
|
+
/** Summary counts */
|
|
1052
|
+
summary: DiffSummary;
|
|
1053
|
+
/** Metadata-level changes */
|
|
1054
|
+
meta: DiffMeta;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Options for computing a diff.
|
|
1058
|
+
*/
|
|
1059
|
+
interface DiffOptions {
|
|
1060
|
+
/** Fields to ignore during comparison */
|
|
1061
|
+
ignore?: {
|
|
1062
|
+
/** Ignore position/layout changes (default: true) */position?: boolean; /** Ignore metadata changes entirely, or specific metadata keys */
|
|
1063
|
+
metadata?: boolean | string[]; /** Ignore specific Graphviz attributes */
|
|
1064
|
+
attrs?: string[]; /** Ignore node ID changes - treat same-fingerprint nodes as unchanged (default: false) */
|
|
1065
|
+
nodeId?: boolean;
|
|
1066
|
+
};
|
|
1067
|
+
/** Custom node matching function (overrides default ID + fingerprint matching) */
|
|
1068
|
+
matchNodes?: (a: DiagramNodeJSON, b: DiagramNodeJSON) => boolean;
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* Options for rendering a diff.
|
|
1072
|
+
*/
|
|
1073
|
+
interface RenderDiffOptions {
|
|
1074
|
+
/** Output format: svg (combined) or html (self-contained page) */
|
|
1075
|
+
format?: "svg" | "html";
|
|
1076
|
+
/** Layout mode: side-by-side (default) or stacked */
|
|
1077
|
+
layout?: "side-by-side" | "stacked";
|
|
1078
|
+
/** Color theme: light (default) or dark */
|
|
1079
|
+
theme?: "light" | "dark";
|
|
1080
|
+
/** How to display unchanged elements: "show" | "dim" | "hide" (default: "show") */
|
|
1081
|
+
showUnchanged?: "show" | "dim" | "hide";
|
|
1082
|
+
/** Show legend in HTML output (default: true) */
|
|
1083
|
+
showLegend?: boolean;
|
|
1084
|
+
/** Show summary header in HTML output (default: true) */
|
|
1085
|
+
showSummary?: boolean;
|
|
1086
|
+
/** Enable hover tooltips in HTML output (default: true) */
|
|
1087
|
+
hoverDetails?: boolean;
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Compute the diff between two diagram versions.
|
|
1091
|
+
*
|
|
1092
|
+
* @param before - The original diagram (JSON or Diagram object)
|
|
1093
|
+
* @param after - The updated diagram (JSON or Diagram object)
|
|
1094
|
+
* @param opts - Options for diff computation
|
|
1095
|
+
* @returns Complete diff result with nodes, edges, clusters, and summary
|
|
1096
|
+
*
|
|
1097
|
+
* @example
|
|
1098
|
+
* ```typescript
|
|
1099
|
+
* const diff = computeDiff(diagramV1.toJSON(), diagramV2.toJSON());
|
|
1100
|
+
* console.log(diff.summary); // { added: 2, removed: 1, modified: 3, ... }
|
|
1101
|
+
* ```
|
|
1102
|
+
*/
|
|
1103
|
+
declare function computeDiff(before: DiagramJSON | Diagram, after: DiagramJSON | Diagram, opts?: DiffOptions): DiagramDiffResult;
|
|
1104
|
+
/**
|
|
1105
|
+
* Render a visual diff between two diagram versions.
|
|
1106
|
+
*
|
|
1107
|
+
* @param diff - The computed diff result from `computeDiff()`
|
|
1108
|
+
* @param before - The original diagram (JSON or Diagram object)
|
|
1109
|
+
* @param after - The updated diagram (JSON or Diagram object)
|
|
1110
|
+
* @param opts - Options for rendering the diff
|
|
1111
|
+
* @returns Promise resolving to SVG or HTML string
|
|
1112
|
+
*
|
|
1113
|
+
* @example
|
|
1114
|
+
* ```typescript
|
|
1115
|
+
* const diff = computeDiff(beforeJson, afterJson);
|
|
1116
|
+
* const html = await renderDiff(diff, beforeJson, afterJson, { format: "html" });
|
|
1117
|
+
* await fs.writeFile("diff.html", html);
|
|
1118
|
+
* ```
|
|
1119
|
+
*/
|
|
1120
|
+
declare function renderDiff(diff: DiagramDiffResult, before: DiagramJSON | Diagram, after: DiagramJSON | Diagram, opts?: RenderDiffOptions): Promise<string>;
|
|
1121
|
+
//#endregion
|
|
936
1122
|
//#region src/icons.d.ts
|
|
937
1123
|
/**
|
|
938
1124
|
* Maps a node to its icon information
|
|
@@ -1170,6 +1356,15 @@ declare function Diagram(name?: string, options?: DiagramOptions): Diagram;
|
|
|
1170
1356
|
declare namespace Diagram {
|
|
1171
1357
|
var fromJSON: typeof fromJSON;
|
|
1172
1358
|
}
|
|
1359
|
+
declare namespace Diagram {
|
|
1360
|
+
var fromSVG: (svg: string) => Promise<Diagram>;
|
|
1361
|
+
}
|
|
1362
|
+
declare namespace Diagram {
|
|
1363
|
+
var diff: (before: DiagramJSON | Diagram, after: DiagramJSON | Diagram, opts?: DiffOptions) => Promise<DiagramDiffResult>;
|
|
1364
|
+
}
|
|
1365
|
+
declare namespace Diagram {
|
|
1366
|
+
var renderDiff: (before: DiagramJSON | Diagram, after: DiagramJSON | Diagram, opts?: RenderDiffOptions) => Promise<string>;
|
|
1367
|
+
}
|
|
1173
1368
|
//#endregion
|
|
1174
1369
|
//#region src/Custom.d.ts
|
|
1175
1370
|
/**
|
|
@@ -1302,8 +1497,22 @@ declare function createJSONPlugin(): DiagramsPlugin;
|
|
|
1302
1497
|
* Exported for convenience
|
|
1303
1498
|
*/
|
|
1304
1499
|
declare const jsonPlugin: DiagramsPlugin;
|
|
1500
|
+
//#endregion
|
|
1501
|
+
//#region src/plugins/built-in/svg.d.ts
|
|
1502
|
+
/**
|
|
1503
|
+
* Create the built-in SVG plugin
|
|
1504
|
+
*
|
|
1505
|
+
* This plugin is automatically registered with every diagram and provides
|
|
1506
|
+
* SVG export/import with embedded metadata capabilities.
|
|
1507
|
+
*/
|
|
1508
|
+
declare function createSVGPlugin(): DiagramsPlugin;
|
|
1509
|
+
/**
|
|
1510
|
+
* Default SVG plugin instance
|
|
1511
|
+
* Exported for convenience
|
|
1512
|
+
*/
|
|
1513
|
+
declare const svgPlugin: DiagramsPlugin;
|
|
1305
1514
|
declare namespace index_d_exports {
|
|
1306
|
-
export { Cluster, CreatePlugin, Custom, DependencyError, Diagram, DiagramClusterJSON, DiagramEdgeJSON, DiagramJSON, DiagramNodeJSON, DiagramOptions, DiagramsPlugin, Edge, EdgeOptions, ExportContext, ExporterCapability, FromJSONOptions, HookCapability, HookContext, HookEvent, HookHandler, Iconify, ImportContext, ImporterCapability, MetadataCapability, MetadataContext, Node, NodeMetadata, NodeOptions, PluginCapability, PluginContext, PluginError, PluginRegistry, ProviderModule, RenderContext, RendererCapability, RuntimeError, RuntimeSupport, ThemeConfig, ThemeName, Yaml, createJSONPlugin, createPluginRegistry, jsonPlugin };
|
|
1515
|
+
export { ChangeKind, Cluster, ClusterDiff, CreatePlugin, Custom, DependencyError, Diagram, DiagramClusterJSON, DiagramDiffResult, DiagramEdgeJSON, DiagramJSON, DiagramNodeJSON, DiagramOptions, DiagramsPlugin, DiffMeta, DiffOptions, DiffSummary, Edge, EdgeDiff, EdgeOptions, ExportContext, ExporterCapability, FromJSONOptions, HookCapability, HookContext, HookEvent, HookHandler, Iconify, ImportContext, ImporterCapability, MetadataCapability, MetadataContext, Node, NodeDiff, NodeMetadata, NodeOptions, PluginCapability, PluginContext, PluginError, PluginRegistry, ProviderModule, RenderContext, RenderDiffOptions, RendererCapability, RuntimeError, RuntimeSupport, ThemeConfig, ThemeName, Yaml, computeDiff, createJSONPlugin, createPluginRegistry, createSVGPlugin, jsonPlugin, renderDiff, svgPlugin };
|
|
1307
1516
|
}
|
|
1308
1517
|
//#endregion
|
|
1309
|
-
export { Cluster, type CreatePlugin, Custom, DependencyError, Diagram, type DiagramClusterJSON, type DiagramEdgeJSON, type DiagramJSON, type DiagramNodeJSON, type DiagramOptions, type DiagramsPlugin, Edge, type EdgeOptions, type ExportContext, type ExporterCapability, type FromJSONOptions, type HookCapability, type HookContext, HookEvent, type HookHandler, Iconify, type ImportContext, type ImporterCapability, type MetadataCapability, type MetadataContext, type Node, type NodeMetadata, type NodeOptions, type PluginCapability, type PluginContext, PluginError, type PluginRegistry, type ProviderModule, type RenderContext, type RendererCapability, RuntimeError, type RuntimeSupport, type ThemeConfig, type ThemeName, type Yaml, createJSONPlugin, createPluginRegistry, jsonPlugin };
|
|
1518
|
+
export { type ChangeKind, Cluster, type ClusterDiff, type CreatePlugin, Custom, DependencyError, Diagram, type DiagramClusterJSON, type DiagramDiffResult, type DiagramEdgeJSON, type DiagramJSON, type DiagramNodeJSON, type DiagramOptions, type DiagramsPlugin, type DiffMeta, type DiffOptions, type DiffSummary, Edge, type EdgeDiff, type EdgeOptions, type ExportContext, type ExporterCapability, type FromJSONOptions, type HookCapability, type HookContext, HookEvent, type HookHandler, Iconify, type ImportContext, type ImporterCapability, type MetadataCapability, type MetadataContext, type Node, type NodeDiff, type NodeMetadata, type NodeOptions, type PluginCapability, type PluginContext, PluginError, type PluginRegistry, type ProviderModule, type RenderContext, type RenderDiffOptions, type RendererCapability, RuntimeError, type RuntimeSupport, type ThemeConfig, type ThemeName, type Yaml, computeDiff, createJSONPlugin, createPluginRegistry, createSVGPlugin, jsonPlugin, renderDiff, svgPlugin };
|