@diagrammo/dgmo 0.25.1 → 0.25.3
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 +69 -884
- package/dist/auto.cjs +1 -1
- package/dist/auto.js +122 -122
- package/dist/auto.mjs +1 -1
- package/dist/cli.cjs +158 -158
- package/dist/index.cjs +8 -4
- package/dist/index.js +8 -4
- package/package.json +17 -17
- package/src/utils/svg-embed.ts +48 -24
package/dist/index.cjs
CHANGED
|
@@ -58685,8 +58685,9 @@ function normalizeSvgForEmbed(input) {
|
|
|
58685
58685
|
const h = tight.height + pad2 * 2;
|
|
58686
58686
|
const canvas = readViewBox(svg);
|
|
58687
58687
|
const TOL = 2;
|
|
58688
|
-
const
|
|
58689
|
-
|
|
58688
|
+
const MIN_COVERAGE = 0.5;
|
|
58689
|
+
const trustworthy = !canvas || x >= canvas.x - TOL && y >= canvas.y - TOL && x + w <= canvas.x + canvas.width + TOL && y + h <= canvas.y + canvas.height + TOL && w >= canvas.width * MIN_COVERAGE && h >= canvas.height * MIN_COVERAGE;
|
|
58690
|
+
if (trustworthy) {
|
|
58690
58691
|
const vb = `${x} ${y} ${w} ${h}`;
|
|
58691
58692
|
svg = svg.replace(/(<svg[^>]*?)viewBox="[^"]*"/, `$1viewBox="${vb}"`);
|
|
58692
58693
|
}
|
|
@@ -58781,8 +58782,11 @@ function computeBBox(svg) {
|
|
|
58781
58782
|
const y = attr(tag, "y");
|
|
58782
58783
|
if (x !== null && y !== null) {
|
|
58783
58784
|
const w = text.length * 7;
|
|
58784
|
-
|
|
58785
|
-
|
|
58785
|
+
const anchor = tag.match(/\btext-anchor="([^"]*)"/)?.[1] ?? "start";
|
|
58786
|
+
const left = anchor === "middle" ? x - w / 2 : anchor === "end" ? x - w : x;
|
|
58787
|
+
const right = anchor === "middle" ? x + w / 2 : anchor === "end" ? x : x + w;
|
|
58788
|
+
push(left, y - 14);
|
|
58789
|
+
push(right, y + 4);
|
|
58786
58790
|
}
|
|
58787
58791
|
}
|
|
58788
58792
|
for (const m of svg.matchAll(/<path\b[^>]*?\bd="([^"]+)"/g)) {
|
package/dist/index.js
CHANGED
|
@@ -58690,8 +58690,9 @@ function normalizeSvgForEmbed(input) {
|
|
|
58690
58690
|
const h = tight.height + pad2 * 2;
|
|
58691
58691
|
const canvas = readViewBox(svg);
|
|
58692
58692
|
const TOL = 2;
|
|
58693
|
-
const
|
|
58694
|
-
|
|
58693
|
+
const MIN_COVERAGE = 0.5;
|
|
58694
|
+
const trustworthy = !canvas || x >= canvas.x - TOL && y >= canvas.y - TOL && x + w <= canvas.x + canvas.width + TOL && y + h <= canvas.y + canvas.height + TOL && w >= canvas.width * MIN_COVERAGE && h >= canvas.height * MIN_COVERAGE;
|
|
58695
|
+
if (trustworthy) {
|
|
58695
58696
|
const vb = `${x} ${y} ${w} ${h}`;
|
|
58696
58697
|
svg = svg.replace(/(<svg[^>]*?)viewBox="[^"]*"/, `$1viewBox="${vb}"`);
|
|
58697
58698
|
}
|
|
@@ -58786,8 +58787,11 @@ function computeBBox(svg) {
|
|
|
58786
58787
|
const y = attr(tag, "y");
|
|
58787
58788
|
if (x !== null && y !== null) {
|
|
58788
58789
|
const w = text.length * 7;
|
|
58789
|
-
|
|
58790
|
-
|
|
58790
|
+
const anchor = tag.match(/\btext-anchor="([^"]*)"/)?.[1] ?? "start";
|
|
58791
|
+
const left = anchor === "middle" ? x - w / 2 : anchor === "end" ? x - w : x;
|
|
58792
|
+
const right = anchor === "middle" ? x + w / 2 : anchor === "end" ? x : x + w;
|
|
58793
|
+
push(left, y - 14);
|
|
58794
|
+
push(right, y + 4);
|
|
58791
58795
|
}
|
|
58792
58796
|
}
|
|
58793
58797
|
for (const m of svg.matchAll(/<path\b[^>]*?\bd="([^"]+)"/g)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diagrammo/dgmo",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.3",
|
|
4
4
|
"description": "DGMO diagram markup language — parser, renderer, and color system",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -157,9 +157,9 @@
|
|
|
157
157
|
"d3-scale": "^4.0.2",
|
|
158
158
|
"d3-selection": "^3.0.0",
|
|
159
159
|
"d3-shape": "^3.2.0",
|
|
160
|
-
"echarts": "^6.
|
|
160
|
+
"echarts": "^6.1.0",
|
|
161
161
|
"elkjs": "^0.11.1",
|
|
162
|
-
"jsdom": "^29.
|
|
162
|
+
"jsdom": "^29.1.1",
|
|
163
163
|
"lz-string": "^1.5.0",
|
|
164
164
|
"topojson-client": "^3.1.0"
|
|
165
165
|
},
|
|
@@ -175,30 +175,30 @@
|
|
|
175
175
|
"@types/d3-scale": "^4.0.9",
|
|
176
176
|
"@types/d3-selection": "^3.0.11",
|
|
177
177
|
"@types/d3-shape": "^3.1.8",
|
|
178
|
-
"@types/jsdom": "^28.0.
|
|
178
|
+
"@types/jsdom": "^28.0.3",
|
|
179
179
|
"@types/topojson-client": "^3.1.5",
|
|
180
|
-
"@vitest/coverage-v8": "^4.1.
|
|
181
|
-
"axe-core": "^4.
|
|
182
|
-
"cspell": "^10.0.
|
|
180
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
181
|
+
"axe-core": "^4.12.0",
|
|
182
|
+
"cspell": "^10.0.1",
|
|
183
183
|
"depcheck": "^1.4.7",
|
|
184
184
|
"esbuild": "^0.28.0",
|
|
185
|
-
"eslint": "^10.
|
|
185
|
+
"eslint": "^10.4.1",
|
|
186
186
|
"eslint-plugin-security": "^4.0.0",
|
|
187
|
-
"fast-check": "^4.
|
|
187
|
+
"fast-check": "^4.8.0",
|
|
188
188
|
"fflate": "^0.8.3",
|
|
189
189
|
"husky": "^9.1.7",
|
|
190
|
-
"jscpd": "^4.
|
|
191
|
-
"knip": "^6.
|
|
192
|
-
"lint-staged": "^
|
|
190
|
+
"jscpd": "^4.2.4",
|
|
191
|
+
"knip": "^6.15.0",
|
|
192
|
+
"lint-staged": "^17.0.7",
|
|
193
193
|
"madge": "^8.0.0",
|
|
194
194
|
"mapshaper": "0.7.22",
|
|
195
|
-
"prettier": "^3.8.
|
|
196
|
-
"publint": "^0.3.
|
|
195
|
+
"prettier": "^3.8.3",
|
|
196
|
+
"publint": "^0.3.21",
|
|
197
197
|
"tsup": "^8.5.1",
|
|
198
198
|
"type-coverage": "^2.29.7",
|
|
199
|
-
"typescript": "^6.0.
|
|
200
|
-
"typescript-eslint": "^8.
|
|
201
|
-
"vitest": "^4.1.
|
|
199
|
+
"typescript": "^6.0.3",
|
|
200
|
+
"typescript-eslint": "^8.60.1",
|
|
201
|
+
"vitest": "^4.1.8"
|
|
202
202
|
},
|
|
203
203
|
"lint-staged": {
|
|
204
204
|
"*.ts": [
|
package/src/utils/svg-embed.ts
CHANGED
|
@@ -38,23 +38,30 @@ export function normalizeSvgForEmbed(input: string): string {
|
|
|
38
38
|
const y = tight.y - pad;
|
|
39
39
|
const w = tight.width + pad * 2;
|
|
40
40
|
const h = tight.height + pad * 2;
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
// it
|
|
45
|
-
//
|
|
46
|
-
// viewBox and CLIPS the diagram
|
|
47
|
-
//
|
|
48
|
-
//
|
|
41
|
+
// The renderer's viewBox is authoritative; computeBBox may only shave dead
|
|
42
|
+
// margins off it. computeBBox is a best-effort string parser with two
|
|
43
|
+
// failure modes, and the renderer's canvas bounds catch both:
|
|
44
|
+
// 1. OVER-shoot — it misreads path arc commands (`A rx ry rot … x y`) and
|
|
45
|
+
// yields a box that strays OUTSIDE the canvas (negative origin /
|
|
46
|
+
// over-wide). Applying it shifts the viewBox and CLIPS the diagram.
|
|
47
|
+
// 2. UNDER-shoot — it can't see elements positioned via `transform`
|
|
48
|
+
// (no x/y attrs), e.g. word-cloud words. It then measures only the
|
|
49
|
+
// stragglers (the title) and collapses the box to a tiny region,
|
|
50
|
+
// zooming that fragment to fill the frame.
|
|
51
|
+
// So only tighten when the computed box sits WITHIN the canvas AND still
|
|
52
|
+
// covers most of it; otherwise keep the renderer's correct bounds.
|
|
49
53
|
const canvas = readViewBox(svg);
|
|
50
54
|
const TOL = 2;
|
|
51
|
-
const
|
|
55
|
+
const MIN_COVERAGE = 0.5; // a real trim shaves margins, not the diagram
|
|
56
|
+
const trustworthy =
|
|
52
57
|
!canvas ||
|
|
53
58
|
(x >= canvas.x - TOL &&
|
|
54
59
|
y >= canvas.y - TOL &&
|
|
55
60
|
x + w <= canvas.x + canvas.width + TOL &&
|
|
56
|
-
y + h <= canvas.y + canvas.height + TOL
|
|
57
|
-
|
|
61
|
+
y + h <= canvas.y + canvas.height + TOL &&
|
|
62
|
+
w >= canvas.width * MIN_COVERAGE &&
|
|
63
|
+
h >= canvas.height * MIN_COVERAGE);
|
|
64
|
+
if (trustworthy) {
|
|
58
65
|
const vb = `${x} ${y} ${w} ${h}`;
|
|
59
66
|
svg = svg.replace(/(<svg[^>]*?)viewBox="[^"]*"/, `$1viewBox="${vb}"`);
|
|
60
67
|
}
|
|
@@ -87,26 +94,34 @@ export function getEmbedSvgViewBox(
|
|
|
87
94
|
};
|
|
88
95
|
}
|
|
89
96
|
|
|
90
|
-
/**
|
|
91
|
-
* Compute an approximate content bounding box from raw element coordinates.
|
|
92
|
-
*
|
|
93
|
-
* This is a regex walk, not a real SVG layout — it ignores `transform`
|
|
94
|
-
* attributes and uses a heuristic for text widths. dgmo's renderers mostly use
|
|
95
|
-
* absolute coordinates within their viewBox, so the approximation is close
|
|
96
|
-
* enough that the rendered output reliably fills the visible area.
|
|
97
|
-
*/
|
|
98
97
|
/** Read the root `<svg>` viewBox as numbers, if present and well-formed. */
|
|
99
98
|
function readViewBox(
|
|
100
99
|
svg: string
|
|
101
100
|
): { x: number; y: number; width: number; height: number } | null {
|
|
102
101
|
const m = svg.match(/<svg[^>]*?\bviewBox="([^"]+)"/);
|
|
103
102
|
if (!m) return null;
|
|
104
|
-
const n = m[1]
|
|
105
|
-
|
|
103
|
+
const n = m[1]!
|
|
104
|
+
.trim()
|
|
105
|
+
.split(/[\s,]+/)
|
|
106
|
+
.map(Number);
|
|
107
|
+
if (
|
|
108
|
+
n.length !== 4 ||
|
|
109
|
+
n.some((v) => !Number.isFinite(v)) ||
|
|
110
|
+
n[2]! <= 0 ||
|
|
111
|
+
n[3]! <= 0
|
|
112
|
+
)
|
|
106
113
|
return null;
|
|
107
114
|
return { x: n[0]!, y: n[1]!, width: n[2]!, height: n[3]! };
|
|
108
115
|
}
|
|
109
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Compute an approximate content bounding box from raw element coordinates.
|
|
119
|
+
*
|
|
120
|
+
* This is a regex walk, not a real SVG layout — it ignores `transform`
|
|
121
|
+
* attributes and uses a heuristic for text widths. dgmo's renderers mostly use
|
|
122
|
+
* absolute coordinates within their viewBox, so the approximation is close
|
|
123
|
+
* enough that the rendered output reliably fills the visible area.
|
|
124
|
+
*/
|
|
110
125
|
function computeBBox(
|
|
111
126
|
svg: string
|
|
112
127
|
): { x: number; y: number; width: number; height: number } | null {
|
|
@@ -189,9 +204,18 @@ function computeBBox(
|
|
|
189
204
|
const y = attr(tag, 'y');
|
|
190
205
|
if (x !== null && y !== null) {
|
|
191
206
|
const w = text.length * 7;
|
|
192
|
-
// text-anchor
|
|
193
|
-
|
|
194
|
-
|
|
207
|
+
// Honor text-anchor so the horizontal extent points the right way:
|
|
208
|
+
// `start` (SVG default) grows rightward from x, `end` grows leftward,
|
|
209
|
+
// `middle` straddles x. Assuming middle for everything under-measures
|
|
210
|
+
// start-anchored text (e.g. pyramid right-column descriptions), which
|
|
211
|
+
// collapses the tight viewBox and clips that text in embeds.
|
|
212
|
+
const anchor = tag.match(/\btext-anchor="([^"]*)"/)?.[1] ?? 'start';
|
|
213
|
+
const left =
|
|
214
|
+
anchor === 'middle' ? x - w / 2 : anchor === 'end' ? x - w : x;
|
|
215
|
+
const right =
|
|
216
|
+
anchor === 'middle' ? x + w / 2 : anchor === 'end' ? x : x + w;
|
|
217
|
+
push(left, y - 14);
|
|
218
|
+
push(right, y + 4);
|
|
195
219
|
}
|
|
196
220
|
}
|
|
197
221
|
|