@weasel-js/labkit 1.6.1 → 1.7.1
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 +3 -3
- package/dist/_dts/{CanvasStackContext-Wo6OwIVM.d.ts → CanvasStackContext-Cjy6I-Iv.d.ts} +4 -1
- package/dist/_dts/{Stage-DWBBi8IU.d.ts → Stage-D6t7o0pF.d.ts} +59 -18
- package/dist/_dts/{index-CKyX0ME_.d.ts → index-BTmaRy6a.d.ts} +10 -6
- package/dist/_dts/{types-B7yBTTF9.d.ts → index-DCMA4Fy1.d.ts} +59 -113
- package/dist/_dts/{types-DTuViBvc.d.ts → types-BUBSIZuV.d.ts} +18 -8
- package/dist/_dts/{useTrialState-CMaV6UD4.d.ts → useTrialState-Bh8bzFgE.d.ts} +1 -1
- package/dist/canvas/index.d.ts +8 -6
- package/dist/canvas/index.js +6 -6
- package/dist/chrome/index.d.ts +6 -4
- package/dist/chrome/index.js +11 -10
- package/dist/chunk-2ES4W47N.js +8 -0
- package/dist/chunk-2ES4W47N.js.map +1 -0
- package/dist/{chunk-WPLAANH4.js → chunk-2N7UBSS2.js} +12 -12
- package/dist/chunk-2N7UBSS2.js.map +1 -0
- package/dist/chunk-4KSC7NXL.js +15491 -0
- package/dist/chunk-4KSC7NXL.js.map +1 -0
- package/dist/{chunk-SLAQPUI4.js → chunk-CEGFXTBD.js} +10 -63
- package/dist/chunk-CEGFXTBD.js.map +1 -0
- package/dist/chunk-CZZPXUOU.js +3 -0
- package/dist/{chunk-SBXNQW4G.js.map → chunk-CZZPXUOU.js.map} +1 -1
- package/dist/{chunk-QGMOA2YE.js → chunk-E23Q6A3Y.js} +296 -104
- package/dist/chunk-E23Q6A3Y.js.map +1 -0
- package/dist/{chunk-GHGO52SO.js → chunk-E6NARGU7.js} +5 -5
- package/dist/{chunk-GHGO52SO.js.map → chunk-E6NARGU7.js.map} +1 -1
- package/dist/{chunk-IJJUK4FU.js → chunk-EESJUSYR.js} +5 -6
- package/dist/chunk-EESJUSYR.js.map +1 -0
- package/dist/{chunk-HXXTULDN.js → chunk-EFXRM6XQ.js} +8 -11
- package/dist/chunk-EFXRM6XQ.js.map +1 -0
- package/dist/chunk-F4ACIK7Z.js +210 -0
- package/dist/chunk-F4ACIK7Z.js.map +1 -0
- package/dist/{chunk-6FLXL3I7.js → chunk-FB4MIZOO.js} +77 -45
- package/dist/chunk-FB4MIZOO.js.map +1 -0
- package/dist/{chunk-AWQG7FCC.js → chunk-FG3EXZDV.js} +3 -3
- package/dist/{chunk-AWQG7FCC.js.map → chunk-FG3EXZDV.js.map} +1 -1
- package/dist/{chunk-4TT3PNPR.js → chunk-GAHELLJT.js} +95 -95
- package/dist/chunk-GAHELLJT.js.map +1 -0
- package/dist/{chunk-HKV7LRHY.js → chunk-IBVRMHW5.js} +5 -5
- package/dist/{chunk-HKV7LRHY.js.map → chunk-IBVRMHW5.js.map} +1 -1
- package/dist/{chunk-ASOK76ZH.js → chunk-JFOJESJF.js} +72 -29
- package/dist/chunk-JFOJESJF.js.map +1 -0
- package/dist/{chunk-RWNDDKOH.js → chunk-PMLZP7RT.js} +18 -15
- package/dist/chunk-PMLZP7RT.js.map +1 -0
- package/dist/{chunk-TJ77A4A3.js → chunk-READTDQX.js} +5 -9
- package/dist/chunk-READTDQX.js.map +1 -0
- package/dist/{chunk-JVBYV6TL.js → chunk-ROGJWDQA.js} +3 -3
- package/dist/{chunk-JVBYV6TL.js.map → chunk-ROGJWDQA.js.map} +1 -1
- package/dist/{chunk-CGHF6RZV.js → chunk-T6DLGEJB.js} +18 -18
- package/dist/chunk-T6DLGEJB.js.map +1 -0
- package/dist/{chunk-24W5VEJW.js → chunk-ULYYNWGP.js} +2 -2
- package/dist/{chunk-24W5VEJW.js.map → chunk-ULYYNWGP.js.map} +1 -1
- package/dist/{chunk-DWMSB4CA.js → chunk-VYVGVBGY.js} +95 -32
- package/dist/chunk-VYVGVBGY.js.map +1 -0
- package/dist/{chunk-IRTGUQ5O.js → chunk-WLMDTI2Q.js} +16 -6
- package/dist/chunk-WLMDTI2Q.js.map +1 -0
- package/dist/{chunk-NEXR37YJ.js → chunk-XE5HJOPL.js} +6 -8
- package/dist/chunk-XE5HJOPL.js.map +1 -0
- package/dist/chunk-XVUKDSYV.js +38 -0
- package/dist/chunk-XVUKDSYV.js.map +1 -0
- package/dist/{chunk-O6FFFOHS.js → chunk-YCFKW5RX.js} +16 -8
- package/dist/chunk-YCFKW5RX.js.map +1 -0
- package/dist/{chunk-CQLQPQ4P.js → chunk-ZQIHJXP4.js} +2 -2
- package/dist/chunk-ZQIHJXP4.js.map +1 -0
- package/dist/config/index.d.ts +28 -13
- package/dist/config/index.js +4 -4
- package/dist/controls/index.d.ts +4 -7
- package/dist/controls/index.js +6 -5
- package/dist/dragdrop/index.d.ts +23 -3
- package/dist/dragdrop/index.js +4 -3
- package/dist/fonts/oswald-tabular-digits.woff2 +0 -0
- package/dist/index.d.ts +72 -487
- package/dist/index.js +603 -441
- package/dist/index.js.map +1 -1
- package/dist/job/index.d.ts +8 -0
- package/dist/job/index.js +1 -1
- package/dist/layers/index.d.ts +6 -5
- package/dist/layers/index.js +3 -2
- package/dist/loupe/index.d.ts +100 -30
- package/dist/loupe/index.js +585 -6
- package/dist/loupe/index.js.map +1 -1
- package/dist/overview/index.d.ts +4 -2
- package/dist/overview/index.js +20 -18
- package/dist/overview/index.js.map +1 -1
- package/dist/passthrough/weasel-canvas.d.ts +2 -0
- package/dist/passthrough/weasel-ui.d.ts +2 -2701
- package/dist/passthrough/weasel-ui.js +4 -3
- package/dist/primitives/index.d.ts +37 -2
- package/dist/primitives/index.js +9 -8
- package/dist/state/index.d.ts +7 -5
- package/dist/state/index.js +6 -6
- package/dist/styles.css +150 -126
- package/dist/surface/index.d.ts +10 -2
- package/dist/surface/index.js +1 -1
- package/dist/undo/index.d.ts +5 -3
- package/package.json +14 -13
- package/src/annotations/AnnotationOverlay.abandon.test.tsx +143 -0
- package/src/annotations/AnnotationOverlay.tsx +52 -33
- package/src/annotations/Annotations.less +0 -10
- package/src/annotations/Annotations.overlay.test.tsx +31 -0
- package/src/annotations/MarkList.tsx +4 -8
- package/src/annotations/capture.browser.test.ts +41 -0
- package/src/annotations/capture.ts +14 -7
- package/src/annotations/drawOne.ts +2 -2
- package/src/annotations/frac.test.ts +44 -1
- package/src/annotations/frac.ts +46 -18
- package/src/annotations/index.ts +1 -0
- package/src/annotations/paint.test.ts +76 -46
- package/src/annotations/paint.ts +65 -43
- package/src/annotations/store.test.ts +212 -2
- package/src/annotations/store.ts +130 -27
- package/src/annotations/svgNodes.test.ts +28 -19
- package/src/annotations/svgNodes.ts +6 -6
- package/src/annotations/types.ts +29 -10
- package/src/canvas/AGENTS.md +1 -0
- package/src/canvas/CameraInput.test.tsx +30 -0
- package/src/canvas/CameraInput.tsx +60 -48
- package/src/canvas/CanvasStack.tsx +11 -6
- package/src/canvas/CanvasStackContext.ts +4 -1
- package/src/canvas/LinkedCursor.less +1 -1
- package/src/canvas/Stage.test.tsx +33 -4
- package/src/canvas/Stage.tsx +9 -4
- package/src/canvas/cameraRegistry.test.ts +55 -0
- package/src/canvas/cameraRegistry.ts +87 -0
- package/src/canvas/cameraZoom.test.ts +46 -0
- package/src/canvas/cameraZoom.ts +24 -0
- package/src/canvas/index.ts +14 -2
- package/src/canvas/sharedScope.test.tsx +94 -0
- package/src/canvas/worldSpec.ts +3 -1
- package/src/chrome/ChromeRegions.stories.tsx +1 -0
- package/src/chrome/builtins.test.ts +7 -6
- package/src/chrome/builtins.tsx +5 -1
- package/src/chrome/index.ts +1 -1
- package/src/chrome/merge.test.ts +5 -0
- package/src/chrome/merge.ts +4 -2
- package/src/chrome/regions/PaletteRegion.less +0 -7
- package/src/chrome/regions/PaletteRegion.test.tsx +2 -3
- package/src/chrome/regions/PaletteRegion.tsx +3 -4
- package/src/chrome/regions/SidebarRegion.less +12 -2
- package/src/chrome/regions/ViewportRegion.browser.test.less +6 -0
- package/src/chrome/regions/ViewportRegion.browser.test.tsx +38 -0
- package/src/chrome/regions/ViewportRegion.less +6 -0
- package/src/chrome/regions/ViewportRegion.tsx +10 -4
- package/src/chrome/types.ts +4 -2
- package/src/config/auto.ts +1 -0
- package/src/config/builder.test.ts +2 -1
- package/src/config/builder.ts +18 -5
- package/src/config/fromConfigField.test.ts +14 -0
- package/src/config/fromConfigField.ts +18 -4
- package/src/config/path.ts +2 -5
- package/src/config/resolve.ts +4 -0
- package/src/config/types.ts +14 -9
- package/src/controls/ControlPanel.less +1 -1
- package/src/controls/ControlPanel.stories.tsx +3 -2
- package/src/controls/ControlPanel.test.tsx +98 -11
- package/src/controls/ControlPanel.tsx +61 -2
- package/src/dragdrop/DragDropRuntime.tsx +22 -13
- package/src/dragdrop/DragGhost.tsx +3 -0
- package/src/dragdrop/Palette.tsx +2 -0
- package/src/index.test.ts +5 -0
- package/src/index.ts +16 -2
- package/src/instrument/types.ts +0 -6
- package/src/job/useJob.ts +14 -9
- package/src/lab/Lab.tsx +88 -73
- package/src/lab/{LabFit.stories.less → LabFit.browser.test.less} +1 -1
- package/src/lab/{LabFit.stories.tsx → LabFit.browser.test.tsx} +41 -63
- package/src/lab/LabFullChrome.stories.tsx +1 -0
- package/src/lab/LabHeader.test.tsx +24 -14
- package/src/lab/LabHeader.tsx +11 -12
- package/src/lab/LabShell.less +9 -17
- package/src/lab/LabSwitcher.browser.test.tsx +27 -0
- package/src/lab/LabSwitcher.less +8 -6
- package/src/lab/LabZoom.test.tsx +223 -0
- package/src/lab/LabZoom.tsx +170 -0
- package/src/lab/Workspace.tsx +48 -52
- package/src/lab/index.ts +1 -0
- package/src/loupe/AGENTS.md +28 -15
- package/src/loupe/CanvasLoupe.tsx +2 -3
- package/src/loupe/DomLoupe.tsx +1 -7
- package/src/loupe/Loupe.less +16 -0
- package/src/loupe/LoupeGestures.tsx +1 -1
- package/src/loupe/TrialLoupe.tsx +120 -57
- package/src/loupe/index.ts +1 -6
- package/src/loupe/types.test.ts +3 -3
- package/src/loupe/types.ts +24 -27
- package/src/loupe/useLoupe.test.tsx +29 -4
- package/src/loupe/useLoupe.ts +20 -17
- package/src/overview/OverviewMarks.tsx +12 -4
- package/src/overview/TrialOverview.tsx +10 -8
- package/src/passthrough/weasel-ui.test.ts +2 -0
- package/src/passthrough/weasel-ui.ts +17 -5
- package/src/primitives/FloatingPanel.test.tsx +11 -0
- package/src/primitives/FloatingPanel.tsx +8 -7
- package/src/primitives/JobProgress.less +2 -1
- package/src/primitives/Legend.stories.tsx +1 -0
- package/src/primitives/Readout.browser.test.tsx +137 -0
- package/src/primitives/Readout.less +12 -0
- package/src/primitives/Readout.stories.tsx +58 -0
- package/src/primitives/Readout.test.tsx +93 -0
- package/src/primitives/Readout.tsx +56 -0
- package/src/primitives/Split.tsx +69 -41
- package/src/primitives/Toolbar.tsx +3 -3
- package/src/primitives/ZoomControl.less +1 -2
- package/src/primitives/index.ts +2 -0
- package/src/specimen/Specimen.stories.tsx +1 -0
- package/src/specimen/Specimen.tsx +2 -3
- package/src/state/Persistence.browser.test.tsx +47 -0
- package/src/state/store.test.ts +5 -1
- package/src/state/undock.ts +3 -0
- package/src/state/useOpenOnce.ts +20 -16
- package/src/state/usePersistedState.test.tsx +1 -1
- package/src/state/view.ts +1 -0
- package/src/styles.less +1 -0
- package/src/surface/index.ts +1 -1
- package/src/surface/useTiledSurface.test.tsx +14 -0
- package/src/surface/useTiledSurface.ts +11 -3
- package/src/theme/Interstellar.stories.tsx +3 -1
- package/src/theme/base.less +21 -47
- package/src/theme/interstellar.test.ts +1 -1
- package/src/theme/interstellar.theme.json +10 -3
- package/src/trial/Trial.annotations.test.tsx +73 -0
- package/src/trial/Trial.less +0 -29
- package/src/trial/Trial.loupe.test.tsx +28 -11
- package/src/trial/Trial.tsx +85 -67
- package/src/trial/TrialChrome.tsx +27 -6
- package/src/trial/index.ts +2 -0
- package/src/trial/loupeSwitch.ts +15 -0
- package/dist/_dts/LayerList.d-BoELAMsM.d.ts +0 -83
- package/dist/_dts/PrefsRow.d-DFpPIeIC.d.ts +0 -39
- package/dist/_dts/PropertyField.d-D0ndfIIt.d.ts +0 -404
- package/dist/_dts/Select.d-Cr8-zoup.d.ts +0 -569
- package/dist/chunk-4TT3PNPR.js.map +0 -1
- package/dist/chunk-6FLXL3I7.js.map +0 -1
- package/dist/chunk-ASOK76ZH.js.map +0 -1
- package/dist/chunk-CGHF6RZV.js.map +0 -1
- package/dist/chunk-CQLQPQ4P.js.map +0 -1
- package/dist/chunk-DWMSB4CA.js.map +0 -1
- package/dist/chunk-HXXTULDN.js.map +0 -1
- package/dist/chunk-IJJUK4FU.js.map +0 -1
- package/dist/chunk-IRTGUQ5O.js.map +0 -1
- package/dist/chunk-KHK5FGER.js +0 -145
- package/dist/chunk-KHK5FGER.js.map +0 -1
- package/dist/chunk-NEXR37YJ.js.map +0 -1
- package/dist/chunk-O6FFFOHS.js.map +0 -1
- package/dist/chunk-QGMOA2YE.js.map +0 -1
- package/dist/chunk-RWNDDKOH.js.map +0 -1
- package/dist/chunk-S4NCI32V.js +0 -549
- package/dist/chunk-S4NCI32V.js.map +0 -1
- package/dist/chunk-SBXNQW4G.js +0 -3
- package/dist/chunk-SLAQPUI4.js.map +0 -1
- package/dist/chunk-TJ77A4A3.js.map +0 -1
- package/dist/chunk-TYN6MLXX.js +0 -13864
- package/dist/chunk-TYN6MLXX.js.map +0 -1
- package/dist/chunk-WPLAANH4.js.map +0 -1
- package/src/primitives/useRovingTabIndex.test.ts +0 -48
- package/src/primitives/useRovingTabIndex.ts +0 -88
- package/src/state/Persistence.stories.tsx +0 -75
|
@@ -1,22 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { identity, multiply } from './chunk-XVUKDSYV.js';
|
|
2
|
+
import { resolveScreenLength, scriptMetricsFor, boundsOfPath, getMarker, PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z, resolveAlign, resolveRunFace, resolveTextStyle, parseColor, rgbaToHex, getPaintKind, resolveMarkerSize } from '@weasel-js/core';
|
|
2
3
|
import { tileGeometry } from '@weasel-js/core/patterns-builtin';
|
|
3
4
|
|
|
4
|
-
// ../svg/dist/index.js
|
|
5
|
-
|
|
6
|
-
// ../geom/dist/index.js
|
|
7
|
-
function identity() {
|
|
8
|
-
return [1, 0, 0, 1, 0, 0];
|
|
9
|
-
}
|
|
10
|
-
function multiply(m, n) {
|
|
11
|
-
return [
|
|
12
|
-
m[0] * n[0] + m[2] * n[1],
|
|
13
|
-
m[1] * n[0] + m[3] * n[1],
|
|
14
|
-
m[0] * n[2] + m[2] * n[3],
|
|
15
|
-
m[1] * n[2] + m[3] * n[3],
|
|
16
|
-
m[0] * n[4] + m[2] * n[5] + m[4],
|
|
17
|
-
m[1] * n[4] + m[3] * n[5] + m[5]
|
|
18
|
-
];
|
|
19
|
-
}
|
|
20
5
|
var IDENTITY_MATRIX = identity();
|
|
21
6
|
function isIdentity(m, eps = 1e-9) {
|
|
22
7
|
return Math.abs(m[0] - 1) < eps && Math.abs(m[1]) < eps && Math.abs(m[2]) < eps && Math.abs(m[3] - 1) < eps && Math.abs(m[4]) < eps && Math.abs(m[5]) < eps;
|
|
@@ -31,10 +16,201 @@ function trimNumber(n) {
|
|
|
31
16
|
if (Number.isInteger(r)) return String(r);
|
|
32
17
|
return String(r);
|
|
33
18
|
}
|
|
34
|
-
function anchorOffset(style,
|
|
19
|
+
function anchorOffset(style, width2) {
|
|
35
20
|
const edge = resolveAlign(style?.align ?? "left", style?.direction ?? "ltr");
|
|
36
|
-
return edge === "center" ?
|
|
21
|
+
return edge === "center" ? width2 / 2 : edge === "right" ? width2 : 0;
|
|
22
|
+
}
|
|
23
|
+
function parsePaintAttr(raw) {
|
|
24
|
+
if (raw == null) return null;
|
|
25
|
+
const s = raw.trim();
|
|
26
|
+
if (s === "") return null;
|
|
27
|
+
if (s === "none") return { kind: "none" };
|
|
28
|
+
if (s.toLowerCase() === "currentcolor") {
|
|
29
|
+
return { kind: "solid", color: "#000000", alpha: 1 };
|
|
30
|
+
}
|
|
31
|
+
const urlMatch = /^url\(\s*#([^)\s]+)\s*\)(.*)$/.exec(s);
|
|
32
|
+
if (urlMatch) {
|
|
33
|
+
const out = { kind: "ref", id: urlMatch[1] };
|
|
34
|
+
const rest = urlMatch[2].trim();
|
|
35
|
+
if (rest !== "" && rest !== "none") {
|
|
36
|
+
const fallback = parsePaintAttr(rest);
|
|
37
|
+
if (fallback?.kind === "solid") {
|
|
38
|
+
out.fallback = { color: fallback.color, alpha: fallback.alpha };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const [r, g, b, a] = parseColor(s);
|
|
45
|
+
return { kind: "solid", color: rgbaToHex([r, g, b]), alpha: a };
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
var TEXT_TRANSFORMS = /* @__PURE__ */ new Set(["none", "uppercase", "lowercase", "capitalize"]);
|
|
51
|
+
var DIMENSION = /^([+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?)([a-z%]*)$/i;
|
|
52
|
+
function dimension(v) {
|
|
53
|
+
const m = DIMENSION.exec(v);
|
|
54
|
+
return m ? { n: Number(m[1]), unit: m[2].toLowerCase() } : void 0;
|
|
55
|
+
}
|
|
56
|
+
var clamp01 = (n) => n < 0 ? 0 : n > 1 ? 1 : n;
|
|
57
|
+
var length = (native, coercedAs) => (v, warn, prop) => {
|
|
58
|
+
const d = dimension(v);
|
|
59
|
+
if (!d) return void 0;
|
|
60
|
+
if (d.unit && !native.includes(d.unit)) {
|
|
61
|
+
warn(`${prop} "${v}" uses unit "${d.unit}", which is not converted; treated as ${d.n} ${coercedAs}`);
|
|
62
|
+
}
|
|
63
|
+
return d.n;
|
|
64
|
+
};
|
|
65
|
+
var worldLength = length(["px"], "world units");
|
|
66
|
+
var keyword2 = (...words) => (v) => words.includes(v) ? v : void 0;
|
|
67
|
+
var isCurrentColor = (v) => v.toLowerCase() === "currentcolor";
|
|
68
|
+
function readPaint(v) {
|
|
69
|
+
if (v === "context-fill") return { kind: "context", of: "fill" };
|
|
70
|
+
if (v === "context-stroke") return { kind: "context", of: "stroke" };
|
|
71
|
+
return parsePaintAttr(v) ?? void 0;
|
|
72
|
+
}
|
|
73
|
+
function readRatio(v) {
|
|
74
|
+
const d = dimension(v);
|
|
75
|
+
if (!d || d.unit !== "" && d.unit !== "%") return void 0;
|
|
76
|
+
return clamp01(d.unit === "%" ? d.n / 100 : d.n);
|
|
77
|
+
}
|
|
78
|
+
function readSolidColor(v, warn, prop) {
|
|
79
|
+
const parsed = parsePaintAttr(v);
|
|
80
|
+
if (parsed?.kind !== "solid") return void 0;
|
|
81
|
+
if (isCurrentColor(v)) warn(`${prop}="${v}" is read as black; it is not resolved against color`);
|
|
82
|
+
return parsed;
|
|
83
|
+
}
|
|
84
|
+
function readMarkerRef(v) {
|
|
85
|
+
if (v === "none") return null;
|
|
86
|
+
return /^url\(\s*#([^)\s]+)\s*\)$/.exec(v)?.[1];
|
|
87
|
+
}
|
|
88
|
+
function readLinecap(v, warn) {
|
|
89
|
+
const cap = keyword2("butt", "round", "square")(v);
|
|
90
|
+
if (!cap) warn(`unsupported stroke-linecap: ${v}`);
|
|
91
|
+
return cap;
|
|
92
|
+
}
|
|
93
|
+
function readLinejoin(v, warn) {
|
|
94
|
+
const join = keyword2("miter", "round", "bevel")(v);
|
|
95
|
+
if (join) return join;
|
|
96
|
+
if (v === "arcs" || v === "miter-clip") {
|
|
97
|
+
warn(`stroke-linejoin "${v}" not supported; falling back to miter`);
|
|
98
|
+
return "miter";
|
|
99
|
+
}
|
|
100
|
+
warn(`unsupported stroke-linejoin: ${v}`);
|
|
101
|
+
return void 0;
|
|
102
|
+
}
|
|
103
|
+
function readDashArray(v, warn) {
|
|
104
|
+
if (v === "none" || v === "") return null;
|
|
105
|
+
const nums = [];
|
|
106
|
+
for (const t of v.split(/[\s,]+/).filter(Boolean)) {
|
|
107
|
+
const d = dimension(t);
|
|
108
|
+
if (!d || d.unit !== "" && d.unit !== "px" || d.n < 0) {
|
|
109
|
+
warn(`unrecognized stroke-dasharray: ${v}`);
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
nums.push(d.n);
|
|
113
|
+
}
|
|
114
|
+
return nums.length % 2 === 1 ? [...nums, ...nums] : nums;
|
|
115
|
+
}
|
|
116
|
+
function readMiterLimit(v, warn) {
|
|
117
|
+
const d = dimension(v);
|
|
118
|
+
if (d && d.unit === "" && d.n >= 1) return d.n;
|
|
119
|
+
warn(`unrecognized stroke-miterlimit: ${v}`);
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
function readColor(v) {
|
|
123
|
+
return isCurrentColor(v) || parsePaintAttr(v)?.kind === "solid" ? v : void 0;
|
|
124
|
+
}
|
|
125
|
+
function readFontSize(v, warn, prop) {
|
|
126
|
+
const d = dimension(v);
|
|
127
|
+
if (d?.unit === "%") return { fontScale: d.n / 100 };
|
|
128
|
+
const n = worldLength(v, warn, prop);
|
|
129
|
+
return n == null ? void 0 : { fontSize: n };
|
|
130
|
+
}
|
|
131
|
+
function readFontWeight(v) {
|
|
132
|
+
if (v === "normal" || v === "bold" || v === "bolder") return v;
|
|
133
|
+
const d = dimension(v);
|
|
134
|
+
return d && d.unit === "" && d.n >= 1 && d.n <= 1e3 ? d.n : void 0;
|
|
135
|
+
}
|
|
136
|
+
function readFontStyle(v, warn) {
|
|
137
|
+
if (v === "normal" || v === "italic") return v;
|
|
138
|
+
if (v === "oblique") {
|
|
139
|
+
warn('font-style "oblique" is read as italic');
|
|
140
|
+
return "italic";
|
|
141
|
+
}
|
|
142
|
+
return void 0;
|
|
143
|
+
}
|
|
144
|
+
function readLetterSpacing(v, warn, prop) {
|
|
145
|
+
return v === "normal" ? null : worldLength(v, warn, prop);
|
|
146
|
+
}
|
|
147
|
+
function readDecoration(v, warn) {
|
|
148
|
+
const out = {};
|
|
149
|
+
for (const t of v.toLowerCase().split(/\s+/)) {
|
|
150
|
+
if (t === "underline") out.underline = true;
|
|
151
|
+
else if (t === "line-through") out.strikethrough = true;
|
|
152
|
+
else if (t === "overline") out.overline = true;
|
|
153
|
+
else if (t !== "none" && t !== "blink") warn(`text-decoration "${v}": "${t}" is not modeled; dropped`);
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
function readFontVariant(v, warn) {
|
|
158
|
+
let out;
|
|
159
|
+
for (const t of v.toLowerCase().split(/\s+/)) {
|
|
160
|
+
if (t === "small-caps" || t === "normal") out = t;
|
|
161
|
+
else if (t) warn(`font-variant "${v}": "${t}" is not modeled; dropped`);
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
37
164
|
}
|
|
165
|
+
function readTextTransform(v) {
|
|
166
|
+
const t = v.toLowerCase();
|
|
167
|
+
return TEXT_TRANSFORMS.has(t) ? t : void 0;
|
|
168
|
+
}
|
|
169
|
+
var emLength = length(["em"], "em");
|
|
170
|
+
function readBaselineShift(v, warn, prop) {
|
|
171
|
+
const k = v.toLowerCase();
|
|
172
|
+
if (k === "super" || k === "sub") return { script: k };
|
|
173
|
+
if (k === "baseline") return {};
|
|
174
|
+
const d = dimension(v);
|
|
175
|
+
if (d?.unit === "%") return d.n === 0 ? {} : { baselineShift: d.n / 100 };
|
|
176
|
+
const n = emLength(v, warn, prop);
|
|
177
|
+
if (n == null) return void 0;
|
|
178
|
+
return n === 0 ? {} : { baselineShift: n };
|
|
179
|
+
}
|
|
180
|
+
var inherited = (read) => ({ inherits: true, read });
|
|
181
|
+
var own = (read) => ({ inherits: false, read });
|
|
182
|
+
var PROPERTIES = {
|
|
183
|
+
"fill": inherited(readPaint),
|
|
184
|
+
"fill-opacity": inherited(readRatio),
|
|
185
|
+
"fill-rule": inherited(keyword2("nonzero", "evenodd")),
|
|
186
|
+
"stroke": inherited(readPaint),
|
|
187
|
+
"stroke-width": inherited(worldLength),
|
|
188
|
+
"stroke-opacity": inherited(readRatio),
|
|
189
|
+
"stroke-linecap": inherited(readLinecap),
|
|
190
|
+
"stroke-linejoin": inherited(readLinejoin),
|
|
191
|
+
"stroke-dasharray": inherited(readDashArray),
|
|
192
|
+
"stroke-miterlimit": inherited(readMiterLimit),
|
|
193
|
+
"marker-start": inherited(readMarkerRef),
|
|
194
|
+
"marker-mid": inherited(readMarkerRef),
|
|
195
|
+
"marker-end": inherited(readMarkerRef),
|
|
196
|
+
"color": inherited(readColor),
|
|
197
|
+
"font-size": inherited(readFontSize),
|
|
198
|
+
"font-family": inherited((v) => v.length > 0 ? v : void 0),
|
|
199
|
+
"font-weight": inherited(readFontWeight),
|
|
200
|
+
"font-style": inherited(readFontStyle),
|
|
201
|
+
"text-anchor": inherited(keyword2("start", "middle", "end")),
|
|
202
|
+
"letter-spacing": inherited(readLetterSpacing),
|
|
203
|
+
"text-decoration": inherited(readDecoration),
|
|
204
|
+
"direction": inherited(keyword2("ltr", "rtl")),
|
|
205
|
+
"text-transform": inherited(readTextTransform),
|
|
206
|
+
"font-variant": inherited(readFontVariant),
|
|
207
|
+
"opacity": own(readRatio),
|
|
208
|
+
"stop-color": own(readSolidColor),
|
|
209
|
+
"stop-opacity": own(readRatio),
|
|
210
|
+
"baseline-shift": own(readBaselineShift),
|
|
211
|
+
"vector-effect": own(keyword2("none", "non-scaling-stroke"))
|
|
212
|
+
};
|
|
213
|
+
Object.keys(PROPERTIES).filter((p) => PROPERTIES[p].inherits);
|
|
38
214
|
function patternSpecOf(paint) {
|
|
39
215
|
return "tile" in paint.pattern ? paint.pattern : null;
|
|
40
216
|
}
|
|
@@ -53,7 +229,11 @@ function patternXml(id, paint, onWarn) {
|
|
|
53
229
|
`width="${trimNumber(geometry.size)}"`,
|
|
54
230
|
`height="${trimNumber(geometry.size)}"`
|
|
55
231
|
];
|
|
56
|
-
|
|
232
|
+
const [a, b, c, d] = paint.transform ?? [1, 0, 0, 1];
|
|
233
|
+
const placement = formatMatrix([a, b, c, d, origin.x, origin.y]);
|
|
234
|
+
if (paint.transform && !isIdentity([a, b, c, d, 0, 0]) && placement) {
|
|
235
|
+
attrs.push(`patternTransform="${placement}"`);
|
|
236
|
+
} else if (origin.x !== 0 || origin.y !== 0) {
|
|
57
237
|
attrs.push(`x="${trimNumber(origin.x)}"`, `y="${trimNumber(origin.y)}"`);
|
|
58
238
|
}
|
|
59
239
|
attrs.push(`data-weasel-tile="${escapeAttr(JSON.stringify(spec))}"`);
|
|
@@ -90,8 +270,8 @@ function escapeAttr(s) {
|
|
|
90
270
|
}
|
|
91
271
|
function serializePathD(path) {
|
|
92
272
|
if (path.kind === "rect") {
|
|
93
|
-
const { x, y, width, height } = path;
|
|
94
|
-
return `M${trimNumber(x)} ${trimNumber(y)}h${trimNumber(
|
|
273
|
+
const { x, y, width: width2, height: height2 } = path;
|
|
274
|
+
return `M${trimNumber(x)} ${trimNumber(y)}h${trimNumber(width2)}v${trimNumber(height2)}h${trimNumber(-width2)}Z`;
|
|
95
275
|
}
|
|
96
276
|
const cmds = path.commands;
|
|
97
277
|
const xs = path.coords;
|
|
@@ -123,29 +303,35 @@ function serializePathD(path) {
|
|
|
123
303
|
}
|
|
124
304
|
var WEASEL_NS = "urn:weasel-js:svg";
|
|
125
305
|
var WEASEL_NS_PREFIX = "wzl";
|
|
126
|
-
function
|
|
127
|
-
const kind = paint.fill ?? "solid";
|
|
306
|
+
function nativeSvgKind(kind) {
|
|
128
307
|
return kind === "solid" || kind === "linear-gradient" || kind === "radial-gradient" || kind === "pattern";
|
|
129
308
|
}
|
|
309
|
+
function hasNativeSvgForm(paint) {
|
|
310
|
+
return nativeSvgKind(paint.fill ?? "solid");
|
|
311
|
+
}
|
|
130
312
|
var INTERPOLATE_SPACES = /* @__PURE__ */ new Set(["rgb", "oklab", "oklch"]);
|
|
313
|
+
function nativeSvgSpace(space) {
|
|
314
|
+
return !space || space === "rgb";
|
|
315
|
+
}
|
|
131
316
|
function interpolateAttr(space) {
|
|
132
|
-
if (
|
|
317
|
+
if (nativeSvgSpace(space)) return "";
|
|
133
318
|
return ` ${WEASEL_NS_PREFIX}:interpolate="${space}"`;
|
|
134
319
|
}
|
|
135
320
|
function usesInterpolateAttr(paint) {
|
|
136
321
|
const space = paint.interpolate;
|
|
137
|
-
return space
|
|
322
|
+
return !nativeSvgSpace(space) && INTERPOLATE_SPACES.has(space);
|
|
138
323
|
}
|
|
139
324
|
var PaintServerRegistry = class {
|
|
140
325
|
byPaint = /* @__PURE__ */ new Map();
|
|
141
326
|
order = [];
|
|
142
327
|
counter = 0;
|
|
143
|
-
// Marker
|
|
144
|
-
// id is the marker key itself, not a minted counter
|
|
145
|
-
// `marker-end="url(#id)"` fragment back as the marker
|
|
146
|
-
// registry knows it, so a synthetic id would come
|
|
147
|
-
|
|
148
|
-
|
|
328
|
+
// Marker defs referenced by any stroke, by `<defs>` id in first-use order.
|
|
329
|
+
// An unsized reference's id is the marker key itself, not a minted counter
|
|
330
|
+
// id: `parseSvg` reads a `marker-end="url(#id)"` fragment back as the marker
|
|
331
|
+
// key directly when the registry knows it, so a synthetic id would come
|
|
332
|
+
// back as a stranger. A sized one gets a def of its own, stamped with its
|
|
333
|
+
// key and size so the parser can read the reference back whole.
|
|
334
|
+
markers = /* @__PURE__ */ new Map();
|
|
149
335
|
// Clip paths, in first-use order. Identity, not value: two groups clipped by
|
|
150
336
|
// equal outlines get a def each, which costs bytes and misleads nobody.
|
|
151
337
|
clips = [];
|
|
@@ -170,22 +356,26 @@ var PaintServerRegistry = class {
|
|
|
170
356
|
if (hasNativeSvgForm(paint)) return `url(#${id})`;
|
|
171
357
|
return `url(#${id}) ${paintFallback(paint)}`;
|
|
172
358
|
}
|
|
359
|
+
/** The paint kind of each registered paint, once, in first-use order. */
|
|
360
|
+
paintKinds() {
|
|
361
|
+
return [...new Set(this.order.map((paint) => paint.fill ?? "solid"))];
|
|
362
|
+
}
|
|
173
363
|
/** Whether any registered paint serializes outside SVG's own vocabulary, so
|
|
174
364
|
* the root has to declare {@link WEASEL_NS}. */
|
|
175
365
|
usesPrivateNamespace() {
|
|
176
|
-
return this.order.some((paint) => !hasNativeSvgForm(paint) || usesInterpolateAttr(paint));
|
|
366
|
+
return this.order.some((paint) => !hasNativeSvgForm(paint) || usesInterpolateAttr(paint)) || [...this.markers.values()].some((m) => m.size !== void 0 || writesInset(getMarker(m.key)));
|
|
177
367
|
}
|
|
178
|
-
/** The `<defs>` id for a marker
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
* never be written. */
|
|
182
|
-
markerId(
|
|
368
|
+
/** The `<defs>` id for a marker reference — the key itself when it has no
|
|
369
|
+
* size, else the key suffixed with the size. `undefined` when nothing is
|
|
370
|
+
* registered under the key, so a caller emits no attribute at all rather
|
|
371
|
+
* than a `url(#…)` pointing at a def that will never be written. */
|
|
372
|
+
markerId(ref) {
|
|
373
|
+
const key = typeof ref === "string" ? ref : ref.key;
|
|
374
|
+
const size = typeof ref === "string" ? void 0 : ref.size;
|
|
183
375
|
if (getMarker(key) === void 0) return void 0;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
return key;
|
|
376
|
+
const id = size === void 0 ? key : `${key}-s${typeof size === "number" ? trimNumber(size) : `${trimNumber(size.px)}px`}`;
|
|
377
|
+
if (!this.markers.has(id)) this.markers.set(id, size === void 0 ? { key } : { key, size });
|
|
378
|
+
return id;
|
|
189
379
|
}
|
|
190
380
|
/** Mint (or recall) the `<defs>` id for a clip outline. */
|
|
191
381
|
clipId(path) {
|
|
@@ -199,17 +389,22 @@ var PaintServerRegistry = class {
|
|
|
199
389
|
/** Emit `<defs>...</defs>` XML for every registered paint server, marker
|
|
200
390
|
* and clip path. */
|
|
201
391
|
toDefsXml(onWarn) {
|
|
202
|
-
if (this.order.length === 0 && this.
|
|
392
|
+
if (this.order.length === 0 && this.markers.size === 0 && this.clips.length === 0) {
|
|
203
393
|
return "";
|
|
204
394
|
}
|
|
205
395
|
const parts = ["<defs>"];
|
|
206
396
|
for (const paint of this.order) {
|
|
207
397
|
parts.push(paintServerXml(this.byPaint.get(paint), paint, onWarn));
|
|
208
398
|
}
|
|
209
|
-
for (const key of this.
|
|
399
|
+
for (const [id, { key, size }] of this.markers) {
|
|
210
400
|
const entry = getMarker(key);
|
|
211
401
|
if (!entry) continue;
|
|
212
|
-
|
|
402
|
+
if (entry.toSvg) {
|
|
403
|
+
if (size !== void 0) onWarn?.(`marker "${key}" writes its own <marker> def, which cannot carry a reference's size; written at its own size`);
|
|
404
|
+
parts.push(entry.toSvg(id, entry));
|
|
405
|
+
} else {
|
|
406
|
+
parts.push(defaultMarkerXml(id, entry, onWarn, key, size));
|
|
407
|
+
}
|
|
213
408
|
}
|
|
214
409
|
for (const path of this.clips) {
|
|
215
410
|
parts.push(
|
|
@@ -220,13 +415,19 @@ var PaintServerRegistry = class {
|
|
|
220
415
|
return parts.join("");
|
|
221
416
|
}
|
|
222
417
|
};
|
|
223
|
-
function
|
|
224
|
-
|
|
418
|
+
function writesInset(entry) {
|
|
419
|
+
return entry !== void 0 && !entry.toSvg && (entry.inset ?? 0) !== 0;
|
|
420
|
+
}
|
|
421
|
+
function defaultMarkerXml(id, entry, onWarn, key, size) {
|
|
422
|
+
const unit = size === void 0 ? 1 : resolveMarkerSize({ key: key ?? id, size }, 1);
|
|
423
|
+
const path = entry.path({ size: unit, stroke: { paint: { fill: "solid", color: "#000" } } });
|
|
225
424
|
const d = serializePathD(path);
|
|
226
425
|
const fill = markerPaintAttrs("fill", entry.fill, id, onWarn);
|
|
227
|
-
const outline = entry.outline ? ` ${markerPaintAttrs("stroke", entry.outline.paint, id, onWarn)} stroke-width="${trimNumber(entry.outline.width)}" stroke-linecap="round" stroke-linejoin="round"` : "";
|
|
426
|
+
const outline = entry.outline ? ` ${markerPaintAttrs("stroke", entry.outline.paint, id, onWarn)} stroke-width="${trimNumber(entry.outline.width * unit)}" stroke-linecap="round" stroke-linejoin="round"` : "";
|
|
228
427
|
const orient = typeof entry.orient === "number" ? trimNumber(entry.orient * 180 / Math.PI) : "auto-start-reverse";
|
|
229
|
-
|
|
428
|
+
const units = size === void 0 ? 'markerUnits="strokeWidth" markerWidth="8" markerHeight="8"' : `markerUnits="userSpaceOnUse" markerWidth="${trimNumber(8 * unit)}" markerHeight="${trimNumber(8 * unit)}" ${WEASEL_NS_PREFIX}:key="${key}" ${WEASEL_NS_PREFIX}:size="${typeof size === "number" ? trimNumber(size) : `${trimNumber(size.px)}px`}"`;
|
|
429
|
+
const inset = writesInset(entry) ? ` ${WEASEL_NS_PREFIX}:inset="${trimNumber(entry.inset)}"` : "";
|
|
430
|
+
return `<marker id="${id}" ${units}${inset} refX="0" refY="0" orient="${orient}" overflow="visible"><path d="${d}" ${fill}${outline}/></marker>`;
|
|
230
431
|
}
|
|
231
432
|
function markerPaintAttrs(attr, paint, id, onWarn) {
|
|
232
433
|
if (paint === "none") return `${attr}="none"`;
|
|
@@ -241,9 +442,10 @@ function paintServerXml(id, paint, onWarn) {
|
|
|
241
442
|
if (paint.fill === "pattern") return patternXml(id, paint, onWarn);
|
|
242
443
|
const builtin = gradientXml(id, paint);
|
|
243
444
|
if (builtin) return builtin;
|
|
244
|
-
const
|
|
445
|
+
const kind = getPaintKind(paint.fill);
|
|
446
|
+
const custom = kind?.toSvg?.(id, paint);
|
|
245
447
|
if (custom) return custom;
|
|
246
|
-
onWarn?.(`${paint.fill} fill has no vector form \u2014 omitted from <defs>`);
|
|
448
|
+
onWarn?.(kind ? `${paint.fill} fill has no vector form \u2014 omitted from <defs>` : `${paint.fill} fill is not registered \u2014 omitted from <defs>; a kind loaded on demand needs \`await warmSvg(nodes)\` before a synchronous export`);
|
|
247
449
|
return "";
|
|
248
450
|
}
|
|
249
451
|
function gradientUnitsAttr(units) {
|
|
@@ -388,16 +590,10 @@ function registerPaintServers(nodes, registry) {
|
|
|
388
590
|
function registerTextPaint(paint, registry) {
|
|
389
591
|
if (paint && !("color" in paint)) registry.register(paint);
|
|
390
592
|
}
|
|
391
|
-
function markerKeyOfRef(ref) {
|
|
392
|
-
if (typeof ref === "string") return ref;
|
|
393
|
-
if (ref && typeof ref === "object" && "key" in ref) return String(ref.key);
|
|
394
|
-
return void 0;
|
|
395
|
-
}
|
|
396
593
|
function registerMarkers(stroke, registry) {
|
|
397
594
|
if (!stroke) return;
|
|
398
595
|
for (const ref of [stroke.markerStart, stroke.markerMid, stroke.markerEnd]) {
|
|
399
|
-
|
|
400
|
-
if (key) registry.markerId(key);
|
|
596
|
+
if (ref !== void 0) registry.markerId(ref);
|
|
401
597
|
}
|
|
402
598
|
}
|
|
403
599
|
function nodeXml(node, registry, namespaces, warn) {
|
|
@@ -486,35 +682,30 @@ function pathXml(node, registry, namespaces, warn) {
|
|
|
486
682
|
}
|
|
487
683
|
function paintAttrs(paint, name, registry, includeOpacity = true) {
|
|
488
684
|
if (paint.kind === "none") return [`${name}="none"`];
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
685
|
+
const out = [`${name}="${paint.kind === "solid" ? paint.color : registry.ref(paint.paint)}"`];
|
|
686
|
+
if (includeOpacity) out.push(...opacityAttr(`${name}-opacity`, svgPaintOpacity(paint)));
|
|
687
|
+
return out;
|
|
688
|
+
}
|
|
689
|
+
function svgPaintOpacity(paint) {
|
|
690
|
+
if (paint.kind === "solid") return paint.opacity;
|
|
691
|
+
return paint.kind === "gradient" ? paint.paint.opacity : void 0;
|
|
692
|
+
}
|
|
693
|
+
function opacityAttr(name, v) {
|
|
694
|
+
return v != null && v !== 1 ? [`${name}="${trimNumber(v)}"`] : [];
|
|
497
695
|
}
|
|
498
|
-
function strokeWidthAttrs(
|
|
499
|
-
if (typeof
|
|
500
|
-
return [`stroke-width="${trimNumber(
|
|
696
|
+
function strokeWidthAttrs(width2) {
|
|
697
|
+
if (typeof width2 === "number") return [`stroke-width="${trimNumber(width2)}"`];
|
|
698
|
+
return [`stroke-width="${trimNumber(width2.px)}"`, 'vector-effect="non-scaling-stroke"'];
|
|
501
699
|
}
|
|
502
700
|
function coreStrokeAttrs(stroke, registry, warn) {
|
|
503
701
|
const paint = stroke?.paint;
|
|
504
702
|
if (!stroke || !paint) return [];
|
|
505
|
-
const
|
|
506
|
-
if (!((typeof
|
|
703
|
+
const width2 = stroke.width ?? 1;
|
|
704
|
+
if (!((typeof width2 === "object" ? width2.px : width2) > 0)) return [];
|
|
507
705
|
warnStrokeAlign(stroke.align, warn);
|
|
508
|
-
const attrs = [];
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
if (paint.opacity != null && paint.opacity !== 1) {
|
|
512
|
-
attrs.push(`stroke-opacity="${trimNumber(paint.opacity)}"`);
|
|
513
|
-
}
|
|
514
|
-
} else {
|
|
515
|
-
attrs.push(`stroke="${registry.ref(paint)}"`);
|
|
516
|
-
}
|
|
517
|
-
attrs.push(...strokeWidthAttrs(width));
|
|
706
|
+
const attrs = [`stroke="${"color" in paint ? paint.color : registry.ref(paint)}"`];
|
|
707
|
+
attrs.push(...opacityAttr("stroke-opacity", paint.opacity));
|
|
708
|
+
attrs.push(...strokeWidthAttrs(width2));
|
|
518
709
|
if (stroke.cap) attrs.push(`stroke-linecap="${stroke.cap}"`);
|
|
519
710
|
if (stroke.join) attrs.push(`stroke-linejoin="${stroke.join}"`);
|
|
520
711
|
if (stroke.dash && stroke.dash.length > 0) {
|
|
@@ -528,8 +719,7 @@ function coreStrokeAttrs(stroke, registry, warn) {
|
|
|
528
719
|
]) {
|
|
529
720
|
const ref = stroke[field];
|
|
530
721
|
if (ref === void 0) continue;
|
|
531
|
-
const
|
|
532
|
-
const id = registry.markerId(key);
|
|
722
|
+
const id = registry.markerId(ref);
|
|
533
723
|
if (id === void 0) continue;
|
|
534
724
|
attrs.push(`${attr}="url(#${id})"`);
|
|
535
725
|
}
|
|
@@ -539,10 +729,7 @@ function strokeAttrsFor(stroke, registry, warn) {
|
|
|
539
729
|
warnStrokeAlign(stroke.align, warn);
|
|
540
730
|
const attrs = paintAttrs(stroke.paint, "stroke", registry, false);
|
|
541
731
|
attrs.push(...strokeWidthAttrs(stroke.width));
|
|
542
|
-
|
|
543
|
-
if (opacity != null && opacity !== 1) {
|
|
544
|
-
attrs.push(`stroke-opacity="${trimNumber(opacity)}"`);
|
|
545
|
-
}
|
|
732
|
+
attrs.push(...opacityAttr("stroke-opacity", stroke.opacity ?? svgPaintOpacity(stroke.paint)));
|
|
546
733
|
if (stroke.cap) {
|
|
547
734
|
attrs.push(`stroke-linecap="${stroke.cap}"`);
|
|
548
735
|
}
|
|
@@ -619,18 +806,21 @@ function textXml(node, registry, namespaces, warn) {
|
|
|
619
806
|
if (style?.fontFamily) attrs.push(`font-family="${escapeAttr2(style.fontFamily)}"`);
|
|
620
807
|
if (style?.fontWeight != null) attrs.push(`font-weight="${String(style.fontWeight)}"`);
|
|
621
808
|
if (style?.fontStyle && style.fontStyle !== "normal") attrs.push(`font-style="${style.fontStyle}"`);
|
|
809
|
+
if (style?.fontVariantCaps === "small-caps") attrs.push('font-variant="small-caps"');
|
|
622
810
|
const direction = style?.direction ?? "ltr";
|
|
623
811
|
if (direction === "rtl") attrs.push('direction="rtl"');
|
|
624
812
|
if (style?.align != null || direction === "rtl") {
|
|
625
813
|
const align = style?.align ?? "left";
|
|
626
|
-
const anchor = align === "center" ? "middle" : align === "start" ? "start" : align === "end" ? "end" : align === "left" === (direction === "ltr") ? "start" : "end";
|
|
814
|
+
const anchor = align === "center" ? "middle" : align === "start" || align === "justify" ? "start" : align === "end" ? "end" : align === "left" === (direction === "ltr") ? "start" : "end";
|
|
627
815
|
if (anchor !== "start") attrs.push(`text-anchor="${anchor}"`);
|
|
816
|
+
if (align === "justify") attrs.push('data-weasel-align="justify"');
|
|
628
817
|
}
|
|
629
818
|
if (style?.letterSpacing != null && style.letterSpacing !== 0) {
|
|
630
819
|
attrs.push(`letter-spacing="${trimNumber(resolveScreenLength(style.letterSpacing, 1))}"`);
|
|
631
820
|
}
|
|
632
821
|
const decoration = textDecorationValue(style?.underline, style?.strikethrough, style?.overline);
|
|
633
822
|
if (decoration) attrs.push(`text-decoration="${decoration}"`);
|
|
823
|
+
if (style?.script) attrs.push(`baseline-shift="${style.script}"`);
|
|
634
824
|
if (style?.textTransform && style.textTransform !== "none") {
|
|
635
825
|
attrs.push(`style="text-transform:${style.textTransform}"`);
|
|
636
826
|
}
|
|
@@ -645,14 +835,8 @@ function textXml(node, registry, namespaces, warn) {
|
|
|
645
835
|
if (node.fill === null) {
|
|
646
836
|
attrs.push('fill="none"');
|
|
647
837
|
} else if (node.fill) {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
if (node.fill.opacity != null && node.fill.opacity !== 1) {
|
|
651
|
-
attrs.push(`fill-opacity="${trimNumber(node.fill.opacity)}"`);
|
|
652
|
-
}
|
|
653
|
-
} else {
|
|
654
|
-
attrs.push(`fill="${registry.ref(node.fill)}"`);
|
|
655
|
-
}
|
|
838
|
+
attrs.push(`fill="${"color" in node.fill ? node.fill.color : registry.ref(node.fill)}"`);
|
|
839
|
+
attrs.push(...opacityAttr("fill-opacity", node.fill.opacity));
|
|
656
840
|
}
|
|
657
841
|
for (const a of coreStrokeAttrs(node.stroke, registry, warn)) attrs.push(a);
|
|
658
842
|
if (node.opacity != null && node.opacity !== 1) {
|
|
@@ -664,17 +848,25 @@ function textXml(node, registry, namespaces, warn) {
|
|
|
664
848
|
const deg = node.rotation * 180 / Math.PI;
|
|
665
849
|
attrs.push(`transform="rotate(${trimNumber(deg)} ${trimNumber(cx)} ${trimNumber(cy)})"`);
|
|
666
850
|
}
|
|
667
|
-
const body = node.runs && node.runs.length > 0 ? node.runs.map((r) => runXml(r, registry, warn)).join("") : escapeText(node.text);
|
|
851
|
+
const body = node.runs && node.runs.length > 0 ? node.runs.map((r) => runXml(r, style, registry, warn)).join("") : escapeText(node.text);
|
|
668
852
|
const metaAttrs = metaAttrsXml(node.meta, namespaces);
|
|
669
853
|
const metaEls = metaElementsXml(node.meta, namespaces);
|
|
670
854
|
return `<text ${attrs.join(" ")}${metaAttrs}>${body}${metaEls}</text>`;
|
|
671
855
|
}
|
|
672
|
-
function
|
|
856
|
+
function scriptSizeFace(run, style) {
|
|
857
|
+
if (run.script == null || run.baselineShift == null) return void 0;
|
|
858
|
+
const face = resolveRunFace(run, resolveTextStyle(style));
|
|
859
|
+
return { family: face.fontFamily, weight: face.fontWeight, style: face.fontStyle };
|
|
860
|
+
}
|
|
861
|
+
function runXml(run, style, registry, warn) {
|
|
673
862
|
const attrs = [];
|
|
674
|
-
if (run.
|
|
863
|
+
if (run.fontWeight != null) attrs.push(`font-weight="${run.fontWeight}"`);
|
|
864
|
+
else if (run.bold) attrs.push(`font-weight="700"`);
|
|
675
865
|
if (run.italic) attrs.push(`font-style="italic"`);
|
|
866
|
+
if (run.fontVariantCaps) attrs.push(`font-variant="${run.fontVariantCaps}"`);
|
|
676
867
|
if (run.fontFamily) attrs.push(`font-family="${escapeAttr2(run.fontFamily)}"`);
|
|
677
|
-
const
|
|
868
|
+
const face = scriptSizeFace(run, style);
|
|
869
|
+
const presetScale = face && run.script ? scriptMetricsFor(face.family, face.weight, face.style)[run.script].size : void 0;
|
|
678
870
|
const scale = run.fontScale ?? presetScale;
|
|
679
871
|
if (run.fontSize != null) attrs.push(`font-size="${trimNumber(resolveScreenLength(run.fontSize, 1))}"`);
|
|
680
872
|
else if (scale != null) attrs.push(`font-size="${trimNumber(scale * 100)}%"`);
|
|
@@ -726,6 +918,6 @@ function pathBounds(path) {
|
|
|
726
918
|
return { minX: b.x, minY: b.y, maxX: b.x + b.width, maxY: b.y + b.height };
|
|
727
919
|
}
|
|
728
920
|
|
|
729
|
-
export { serializeSvg, tilePreviewCssUrl };
|
|
730
|
-
//# sourceMappingURL=chunk-
|
|
731
|
-
//# sourceMappingURL=chunk-
|
|
921
|
+
export { nativeSvgKind, nativeSvgSpace, serializeSvg, tilePreviewCssUrl };
|
|
922
|
+
//# sourceMappingURL=chunk-E23Q6A3Y.js.map
|
|
923
|
+
//# sourceMappingURL=chunk-E23Q6A3Y.js.map
|