domotion-svg 0.1.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/FEATURES.md +102 -0
- package/LICENSE +21 -0
- package/README.md +66 -0
- package/dist/animator.d.ts +158 -0
- package/dist/animator.js +424 -0
- package/dist/animator.test.d.ts +5 -0
- package/dist/animator.test.js +169 -0
- package/dist/border-radius.test.d.ts +1 -0
- package/dist/border-radius.test.js +148 -0
- package/dist/capture.d.ts +193 -0
- package/dist/capture.js +786 -0
- package/dist/chrome.d.ts +45 -0
- package/dist/chrome.js +107 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +512 -0
- package/dist/client/dom.d.ts +10 -0
- package/dist/client/dom.js +17 -0
- package/dist/conic-raster.d.ts +58 -0
- package/dist/conic-raster.js +292 -0
- package/dist/conic-raster.test.d.ts +1 -0
- package/dist/conic-raster.test.js +187 -0
- package/dist/coretext-extractor.test.d.ts +1 -0
- package/dist/coretext-extractor.test.js +94 -0
- package/dist/coretext-helper.d.ts +60 -0
- package/dist/coretext-helper.js +205 -0
- package/dist/cross-origin-font-face.test.d.ts +1 -0
- package/dist/cross-origin-font-face.test.js +107 -0
- package/dist/cursor-overlay.d.ts +123 -0
- package/dist/cursor-overlay.js +207 -0
- package/dist/cursor-overlay.test.d.ts +1 -0
- package/dist/cursor-overlay.test.js +88 -0
- package/dist/dark-mode-capture.test.d.ts +1 -0
- package/dist/dark-mode-capture.test.js +158 -0
- package/dist/dark-mode-form-controls.test.d.ts +1 -0
- package/dist/dark-mode-form-controls.test.js +218 -0
- package/dist/dom-to-svg.d.ts +1016 -0
- package/dist/dom-to-svg.js +7717 -0
- package/dist/embed-remote-images.test.d.ts +1 -0
- package/dist/embed-remote-images.test.js +424 -0
- package/dist/form-controls.d.ts +70 -0
- package/dist/form-controls.js +1151 -0
- package/dist/frame-merge.d.ts +95 -0
- package/dist/frame-merge.js +374 -0
- package/dist/frame-merge.test.d.ts +6 -0
- package/dist/frame-merge.test.js +144 -0
- package/dist/gradients.d.ts +184 -0
- package/dist/gradients.js +937 -0
- package/dist/gradients.test.d.ts +1 -0
- package/dist/gradients.test.js +150 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +7 -0
- package/dist/jsx-runtime.d.ts +27 -0
- package/dist/jsx-runtime.js +96 -0
- package/dist/jsx-runtime.test.d.ts +1 -0
- package/dist/jsx-runtime.test.js +41 -0
- package/dist/kerfjs-imports.test.d.ts +1 -0
- package/dist/kerfjs-imports.test.js +36 -0
- package/dist/mask.test.d.ts +1 -0
- package/dist/mask.test.js +206 -0
- package/dist/optimize.d.ts +12 -0
- package/dist/optimize.js +32 -0
- package/dist/preserve-aspect-ratio.test.d.ts +1 -0
- package/dist/preserve-aspect-ratio.test.js +38 -0
- package/dist/resize-embedded-images.d.ts +33 -0
- package/dist/resize-embedded-images.js +164 -0
- package/dist/resize-embedded-images.test.d.ts +9 -0
- package/dist/resize-embedded-images.test.js +255 -0
- package/dist/stacking-context.test.d.ts +1 -0
- package/dist/stacking-context.test.js +927 -0
- package/dist/text-renderer.d.ts +42 -0
- package/dist/text-renderer.js +608 -0
- package/dist/text-renderer.test.d.ts +1 -0
- package/dist/text-renderer.test.js +150 -0
- package/dist/text-to-path.d.ts +265 -0
- package/dist/text-to-path.js +1800 -0
- package/dist/text-to-path.test.d.ts +1 -0
- package/dist/text-to-path.test.js +570 -0
- package/dist/utils/escapeHtml.d.ts +2 -0
- package/dist/utils/escapeHtml.js +15 -0
- package/dist/webfont-unicode-range.test.d.ts +1 -0
- package/dist/webfont-unicode-range.test.js +174 -0
- package/package.json +55 -0
- package/src/animator.test.ts +179 -0
- package/src/animator.ts +660 -0
- package/src/border-radius.test.ts +160 -0
- package/src/capture.ts +810 -0
- package/src/cli.ts +582 -0
- package/src/conic-raster.test.ts +213 -0
- package/src/conic-raster.ts +309 -0
- package/src/coretext-extractor.test.ts +130 -0
- package/src/coretext-helper.ts +256 -0
- package/src/cross-origin-font-face.test.ts +119 -0
- package/src/cursor-overlay.test.ts +95 -0
- package/src/cursor-overlay.ts +297 -0
- package/src/dark-mode-capture.test.ts +177 -0
- package/src/dark-mode-form-controls.test.ts +228 -0
- package/src/dom-to-svg.ts +8376 -0
- package/src/embed-remote-images.test.ts +461 -0
- package/src/form-controls.ts +1174 -0
- package/src/frame-merge.test.ts +157 -0
- package/src/frame-merge.ts +447 -0
- package/src/globals.d.ts +2 -0
- package/src/gradients.test.ts +175 -0
- package/src/gradients.ts +955 -0
- package/src/index.ts +12 -0
- package/src/kerf-jsx-augmentation.d.ts +36 -0
- package/src/kerfjs-imports.test.tsx +45 -0
- package/src/mask.test.ts +274 -0
- package/src/optimize.ts +34 -0
- package/src/preserve-aspect-ratio.test.ts +49 -0
- package/src/resize-embedded-images.test.ts +292 -0
- package/src/resize-embedded-images.ts +180 -0
- package/src/stacking-context.test.ts +967 -0
- package/src/text-renderer.test.ts +162 -0
- package/src/text-renderer.ts +623 -0
- package/src/text-to-path.test.ts +639 -0
- package/src/text-to-path.ts +1810 -0
- package/src/utils/escapeHtml.ts +16 -0
- package/src/webfont-unicode-range.test.ts +207 -0
|
@@ -0,0 +1,1016 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM-to-SVG Converter
|
|
3
|
+
*
|
|
4
|
+
* Uses Playwright to inspect DOM elements and recreate them as native SVG.
|
|
5
|
+
*/
|
|
6
|
+
import type { Page } from "@playwright/test";
|
|
7
|
+
/**
|
|
8
|
+
* Convert a `file://` (or absolute filesystem) URL to a base64 data URI so the
|
|
9
|
+
* generated SVG is self-contained and renders in tools that block local-file
|
|
10
|
+
* references for security (most online SVG viewers, embeds, etc.). Pass-through
|
|
11
|
+
* for http(s):// and existing data: URLs. Returns the original string on any
|
|
12
|
+
* error so failures degrade gracefully.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @internal — exposed for `resize-embedded-images.ts` (DM-539). The resize
|
|
16
|
+
* pre-pass reads source bytes from this cache (populated by `embedRemoteImages`)
|
|
17
|
+
* and writes per-(URL, size) resized variants into `_resizedDataUriCache`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const _dataUriCache: Map<string, string>;
|
|
20
|
+
/**
|
|
21
|
+
* @internal — DM-539. Per-source-URL map of sizeKey → resized data URI. The
|
|
22
|
+
* sizeKey is `${ceil(targetW * hiDPI)}x${ceil(targetH * hiDPI)}`. Populated by
|
|
23
|
+
* `resizeEmbeddedImages` (only when `embedRemoteImagesResize: true`); read by
|
|
24
|
+
* `embedResizedDataUri` (DM-540) when the renderer emits an `<image href>`.
|
|
25
|
+
* Empty at module load — first capture with the resize flag fills it.
|
|
26
|
+
*/
|
|
27
|
+
export declare const _resizedDataUriCache: Map<string, Map<string, string>>;
|
|
28
|
+
/**
|
|
29
|
+
* @internal — DM-549. Per-conic-gradient-layer-text map of `${tileW}x${tileH}` →
|
|
30
|
+
* data URI containing rasterized PNG bytes. Populated by `rasterizeConicGradients`
|
|
31
|
+
* (the conic raster pre-pass) and read by `buildConicGradientDef` (DM-550) when
|
|
32
|
+
* the renderer emits a `<pattern><image>` for a conic background layer. Empty
|
|
33
|
+
* at module load — first capture with conic content fills it.
|
|
34
|
+
*/
|
|
35
|
+
export declare const _conicTileCache: Map<string, Map<string, string>>;
|
|
36
|
+
/**
|
|
37
|
+
* DM-540 — renderer-side lookup for the image-resize-on-embed pipeline.
|
|
38
|
+
* Returns the resized PNG data URI for `(url, ceil(w * hiDPI), ceil(h * hiDPI))`
|
|
39
|
+
* when the resize pre-pass populated `_resizedDataUriCache` for that key;
|
|
40
|
+
* otherwise falls back to `embedAsDataUri(url)` so the renderer behaves
|
|
41
|
+
* identically to today when resize is disabled (no entries in the resized
|
|
42
|
+
* cache → source-resolution data URI returned).
|
|
43
|
+
*/
|
|
44
|
+
export declare function embedResizedDataUri(url: string, consumerW: number, consumerH: number, hiDPIFactor?: number): string;
|
|
45
|
+
export interface EmbedRemoteImagesOptions {
|
|
46
|
+
/**
|
|
47
|
+
* DM-527: append per-URL fetch failures here as `CaptureWarning` entries.
|
|
48
|
+
* If omitted, warnings push to the module-global `lastCaptureWarnings`
|
|
49
|
+
* (visible via `getLastCaptureWarnings` / `logCaptureWarnings`). Concurrent
|
|
50
|
+
* captures should pass an explicit array to avoid racing on the global.
|
|
51
|
+
*/
|
|
52
|
+
warnings?: CaptureWarning[];
|
|
53
|
+
/**
|
|
54
|
+
* DM-528: per-URL fetch timeout in ms. A stalled CDN host (slow DNS, slow
|
|
55
|
+
* first-byte, unresponsive origin) would otherwise hang the capture
|
|
56
|
+
* indefinitely — the parallel `Promise.all` won't resolve until every
|
|
57
|
+
* fetch settles. With this timeout the slowest fetch caps total pre-pass
|
|
58
|
+
* time at ~`timeoutMs * (retries + 1) + retryBackoffMs * retries` (since
|
|
59
|
+
* fetches run in parallel). Timed-out fetches produce a `remote-image`
|
|
60
|
+
* warning and the URL stays as-is in the SVG. Default 10000.
|
|
61
|
+
*/
|
|
62
|
+
timeoutMs?: number;
|
|
63
|
+
/**
|
|
64
|
+
* DM-529: number of retry attempts for transient failures (5xx response,
|
|
65
|
+
* network error, or timeout). 4xx responses are not retried — those are
|
|
66
|
+
* deterministic and a retry would just consume time. The originating
|
|
67
|
+
* fetch + retries together can take up to
|
|
68
|
+
* `(retries + 1) * timeoutMs + retries * retryBackoffMs` per URL, so keep
|
|
69
|
+
* this small. Default 1.
|
|
70
|
+
*/
|
|
71
|
+
retries?: number;
|
|
72
|
+
/**
|
|
73
|
+
* DM-529: delay (ms) between attempts when retrying a transient failure.
|
|
74
|
+
* Default 500.
|
|
75
|
+
*/
|
|
76
|
+
retryBackoffMs?: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* DM-512: fetch every http(s) image URL referenced by the captured tree and
|
|
80
|
+
* stash the resolved bytes as a data: URI in the renderer's data-URI cache.
|
|
81
|
+
* Subsequent calls to `embedAsDataUri` for those URLs return the cached data
|
|
82
|
+
* URI instead of passing the URL through verbatim — yielding a self-contained
|
|
83
|
+
* SVG that loads correctly in image viewers (Preview, Finder QuickLook, etc.)
|
|
84
|
+
* that don't fetch remote resources from local files.
|
|
85
|
+
*
|
|
86
|
+
* Walks the captured tree once collecting URLs from: `imageSrc` (for `<img>`),
|
|
87
|
+
* `pseudoImages[].url` (for `::before`/`::after` content: url(...)), and CSS
|
|
88
|
+
* `url(...)` tokens inside `styles.backgroundImage` / `.maskImage` /
|
|
89
|
+
* `.borderImageSource` / `.listStyleImage`. Dedupes per call.
|
|
90
|
+
*
|
|
91
|
+
* Per-URL fetch failures (network error, non-2xx, missing Content-Type) leave
|
|
92
|
+
* the URL in the tree as-is, so the SVG still references it. DM-527: each
|
|
93
|
+
* failure is surfaced as a `CaptureWarning` (feature: `remote-image`) carrying
|
|
94
|
+
* the URL and the HTTP status / error class, so callers can trace which images
|
|
95
|
+
* didn't inline. The warning is appended to `options.warnings` if supplied,
|
|
96
|
+
* otherwise to `getLastCaptureWarnings()`.
|
|
97
|
+
*/
|
|
98
|
+
export declare function embedRemoteImages(tree: CapturedElement[], options?: EmbedRemoteImagesOptions): Promise<void>;
|
|
99
|
+
export interface TextSegment {
|
|
100
|
+
text: string;
|
|
101
|
+
x: number;
|
|
102
|
+
y: number;
|
|
103
|
+
width: number;
|
|
104
|
+
height: number;
|
|
105
|
+
/**
|
|
106
|
+
* Per-character viewport-absolute x offsets (one entry per visible char in
|
|
107
|
+
* `text`). When provided, renderers anchor each glyph at xOffsets[i] instead
|
|
108
|
+
* of summing fontkit advances — closing the per-char drift that accumulates
|
|
109
|
+
* over long paragraphs. May be undefined when capture couldn't produce it
|
|
110
|
+
* (e.g. input/textarea values).
|
|
111
|
+
*/
|
|
112
|
+
xOffsets?: number[];
|
|
113
|
+
/** Override color for this segment (e.g. ::before / ::after pseudos whose
|
|
114
|
+
* CSS `color` differs from the element's). Renderer uses parent fill when
|
|
115
|
+
* undefined. */
|
|
116
|
+
color?: string;
|
|
117
|
+
/** Override font-size in CSS pixels (e.g. abbr[title]::after { font-size: 0.9em }).
|
|
118
|
+
* Undefined means inherit from the element. */
|
|
119
|
+
fontSize?: number;
|
|
120
|
+
/** Override font-weight (e.g. li[data-badge]::before { font-weight: bold }).
|
|
121
|
+
* Undefined means inherit from the element. */
|
|
122
|
+
fontWeight?: string;
|
|
123
|
+
/** Override font-style (e.g. ::first-line { font-style: italic }). */
|
|
124
|
+
fontStyle?: string;
|
|
125
|
+
/** Override font-family (e.g. `.icon-angle-right { font-family: 'sdicon' }`
|
|
126
|
+
* with `::before { content: '\\e87a' }` — the icon glyph routes through
|
|
127
|
+
* the icon webfont, not the parent element's body font). DM-513. */
|
|
128
|
+
fontFamily?: string;
|
|
129
|
+
/** Override font-variant (e.g. ::first-line { font-variant: small-caps }).
|
|
130
|
+
* When 'small-caps', renderer applies the OpenType `smcp` feature so
|
|
131
|
+
* lowercase letters shape as small uppercase forms — Chrome paints them
|
|
132
|
+
* the same way and the captured xOffsets already encode the small-caps
|
|
133
|
+
* advance widths, so the only thing the renderer needs to change is the
|
|
134
|
+
* glyph variant per character. (DM-294) */
|
|
135
|
+
fontVariant?: string;
|
|
136
|
+
/**
|
|
137
|
+
* Override fontBoundingBoxAscent (px) when the segment uses a font/size
|
|
138
|
+
* different from the element (::before / ::after with custom font-size).
|
|
139
|
+
* Renderer falls back to the element's fontAscent when this is undefined.
|
|
140
|
+
*/
|
|
141
|
+
fontAscent?: number;
|
|
142
|
+
/**
|
|
143
|
+
* Viewport-relative rectangle (CSS pixels) to screenshot when the WHOLE
|
|
144
|
+
* segment is raster-worthy — used for ::before / ::after pseudos whose
|
|
145
|
+
* entire text is a color-bitmap run. Populated by CAPTURE_SCRIPT;
|
|
146
|
+
* captureElementTree fills in rasterDataUri. Renderer emits one <image>
|
|
147
|
+
* covering rasterRect and skips the text pipeline entirely. See SK-1058.
|
|
148
|
+
*/
|
|
149
|
+
rasterRect?: {
|
|
150
|
+
x: number;
|
|
151
|
+
y: number;
|
|
152
|
+
width: number;
|
|
153
|
+
height: number;
|
|
154
|
+
};
|
|
155
|
+
/** data:image/png;base64,… populated by Node-side raster. Renderer checks this. */
|
|
156
|
+
rasterDataUri?: string;
|
|
157
|
+
/**
|
|
158
|
+
* Per-character raster overlays for emoji / color-bitmap codepoints mixed
|
|
159
|
+
* into an otherwise path-rendered text run (SK-1090). Each entry pins the
|
|
160
|
+
* char's exact viewport-relative rect; rasterizeBitmapGlyphs fills in
|
|
161
|
+
* dataUri, and the renderer stamps an <image> on top of the path text at
|
|
162
|
+
* that rect. Path emission for the underlying glyph is left intact — the
|
|
163
|
+
* <image> overlays wherever needed, and for pure-emoji codepoints the path
|
|
164
|
+
* pipeline emits nothing anyway (zero-contour glyph from fontkit).
|
|
165
|
+
*/
|
|
166
|
+
rasterGlyphs?: Array<{
|
|
167
|
+
charIndex: number;
|
|
168
|
+
rect: {
|
|
169
|
+
x: number;
|
|
170
|
+
y: number;
|
|
171
|
+
width: number;
|
|
172
|
+
height: number;
|
|
173
|
+
};
|
|
174
|
+
dataUri?: string;
|
|
175
|
+
/** When true, the underlying text-path emit for this charIndex must be
|
|
176
|
+
* suppressed: the raster image is the ONLY paint for this codepoint
|
|
177
|
+
* (e.g. ::first-letter drop caps where the styled big-letter raster
|
|
178
|
+
* would otherwise sit on top of the body-size path glyph). DM-439. */
|
|
179
|
+
suppressGlyph?: boolean;
|
|
180
|
+
}>;
|
|
181
|
+
/**
|
|
182
|
+
* Pseudo-element box paint (DM-497): when this segment came from a
|
|
183
|
+
* `::before` / `::after` whose computed style sets a non-trivial
|
|
184
|
+
* `background-color` or `border-radius`, the renderer emits a `<rect>` of
|
|
185
|
+
* these dimensions BEHIND the segment's text glyphs to honor the pseudo
|
|
186
|
+
* box paint (badge / pill / chip pattern). Coordinates are viewport-relative
|
|
187
|
+
* and already include padding + border insets so the rect surrounds the
|
|
188
|
+
* captured text segment with the author-specified inflation.
|
|
189
|
+
*/
|
|
190
|
+
pseudoBox?: {
|
|
191
|
+
x: number;
|
|
192
|
+
y: number;
|
|
193
|
+
width: number;
|
|
194
|
+
height: number;
|
|
195
|
+
/** Pre-resolved srgb-form CSS color (or "transparent"). Renderer parses
|
|
196
|
+
* via parseColor and emits as the rect fill. */
|
|
197
|
+
backgroundColor?: string;
|
|
198
|
+
/** Resolved px border-radius (CSS shorthand — single value, four-corner
|
|
199
|
+
* symmetric). */
|
|
200
|
+
borderRadius?: number;
|
|
201
|
+
/** Uniform border (single side-width + color). Per-side variation isn't
|
|
202
|
+
* supported in this pass; mixed-style borders fall through. */
|
|
203
|
+
borderWidth?: number;
|
|
204
|
+
borderColor?: string;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
export interface CapturedElement {
|
|
208
|
+
tag: string;
|
|
209
|
+
text: string;
|
|
210
|
+
x: number;
|
|
211
|
+
y: number;
|
|
212
|
+
width: number;
|
|
213
|
+
height: number;
|
|
214
|
+
/**
|
|
215
|
+
* If the source DOM had `data-domotion-anim="<id>"` on this element, the id
|
|
216
|
+
* is captured here. The renderer surfaces it as `class="anim-<id>"` on the
|
|
217
|
+
* rendered group so an intra-frame animation (DM-209) can target it via CSS
|
|
218
|
+
* keyframes. The animator (or CLI wrapper) is responsible for setting the
|
|
219
|
+
* data attribute on the live DOM before capture.
|
|
220
|
+
*/
|
|
221
|
+
animId?: string;
|
|
222
|
+
styles: {
|
|
223
|
+
backgroundColor: string;
|
|
224
|
+
borderColor: string;
|
|
225
|
+
borderWidth: string;
|
|
226
|
+
borderRadius: string;
|
|
227
|
+
/**
|
|
228
|
+
* Resolved per-corner border-radius (top-left, top-right, bottom-right,
|
|
229
|
+
* bottom-left). Chrome returns longhand corner values in pixels even when
|
|
230
|
+
* the author used percentages, so capturing these lets the renderer pick
|
|
231
|
+
* a circle radius for `border-radius: 50%` instead of treating the "50"
|
|
232
|
+
* from the shorthand as a 50-px corner. See SK-1093.
|
|
233
|
+
*/
|
|
234
|
+
borderTopLeftRadius?: string;
|
|
235
|
+
borderTopRightRadius?: string;
|
|
236
|
+
borderBottomRightRadius?: string;
|
|
237
|
+
borderBottomLeftRadius?: string;
|
|
238
|
+
/** Per-side border widths as strings (e.g. "6px"). All set together so we can decide uniform-vs-split in the renderer. */
|
|
239
|
+
borderTopWidth: string;
|
|
240
|
+
borderRightWidth: string;
|
|
241
|
+
borderBottomWidth: string;
|
|
242
|
+
borderLeftWidth: string;
|
|
243
|
+
borderTopStyle: string;
|
|
244
|
+
borderRightStyle: string;
|
|
245
|
+
borderBottomStyle: string;
|
|
246
|
+
borderLeftStyle: string;
|
|
247
|
+
borderTopColor: string;
|
|
248
|
+
borderRightColor: string;
|
|
249
|
+
borderBottomColor: string;
|
|
250
|
+
borderLeftColor: string;
|
|
251
|
+
/**
|
|
252
|
+
* For table cells: `"collapse"` means the parent table sets
|
|
253
|
+
* `border-collapse: collapse` so adjacent cells share a single painted
|
|
254
|
+
* border instead of stacking two adjacent ones. The renderer paints
|
|
255
|
+
* cell borders centered on the cell edge (no half-inset) in this mode
|
|
256
|
+
* so that two cells'\'' shared edges overlap exactly into one line
|
|
257
|
+
* instead of doubling.
|
|
258
|
+
*/
|
|
259
|
+
borderCollapse: string;
|
|
260
|
+
overflowX: string;
|
|
261
|
+
overflowY: string;
|
|
262
|
+
scrollbarGutter: string;
|
|
263
|
+
/** el.scrollHeight / scrollWidth vs client* — used to decide whether to paint a scrollbar. */
|
|
264
|
+
scrollWidth: number;
|
|
265
|
+
scrollHeight: number;
|
|
266
|
+
clientWidth: number;
|
|
267
|
+
clientHeight: number;
|
|
268
|
+
scrollTop: number;
|
|
269
|
+
scrollLeft: number;
|
|
270
|
+
objectFit: string;
|
|
271
|
+
objectPosition: string;
|
|
272
|
+
filter: string;
|
|
273
|
+
backdropFilter: string;
|
|
274
|
+
/**
|
|
275
|
+
* DM-476 frosted-glass fallback: when the element has a non-trivial
|
|
276
|
+
* `backdrop-filter` AND a near-transparent `background-color` (alpha
|
|
277
|
+
* ≤ 0.1), CAPTURE_SCRIPT reads `document.body`'s computed background
|
|
278
|
+
* colour and stores it here as a normalised `rgb(...)` / `rgba(...)`
|
|
279
|
+
* string so the renderer can paint a synthesised opaque fill where
|
|
280
|
+
* Chromium would have painted blurred underlying pixels. Undefined
|
|
281
|
+
* when the element doesn't trigger the frosted condition. See
|
|
282
|
+
* `docs/19-frosted-backdrop-fallback.md`.
|
|
283
|
+
*/
|
|
284
|
+
frostedBgFallback?: string;
|
|
285
|
+
mixBlendMode: string;
|
|
286
|
+
clipPath: string;
|
|
287
|
+
mask: string;
|
|
288
|
+
maskImage: string;
|
|
289
|
+
maskMode: string;
|
|
290
|
+
maskSize: string;
|
|
291
|
+
maskPosition: string;
|
|
292
|
+
maskRepeat: string;
|
|
293
|
+
maskComposite: string;
|
|
294
|
+
listStyleType: string;
|
|
295
|
+
listStyleImage: string;
|
|
296
|
+
listStylePosition: string;
|
|
297
|
+
/** CSS `display` (e.g. `block`, `list-item`, `flex`). Used by the
|
|
298
|
+
* renderer to detect display:list-item on non-li tags. DM-451. */
|
|
299
|
+
display?: string;
|
|
300
|
+
backgroundImage: string;
|
|
301
|
+
backgroundSize: string;
|
|
302
|
+
backgroundPosition: string;
|
|
303
|
+
backgroundRepeat: string;
|
|
304
|
+
backgroundClip: string;
|
|
305
|
+
backgroundOrigin: string;
|
|
306
|
+
backgroundAttachment: string;
|
|
307
|
+
/**
|
|
308
|
+
* CSS `-webkit-text-fill-color`. When `backgroundClip` is `text` the
|
|
309
|
+
* common pattern is `webkit-text-fill-color: transparent` so the
|
|
310
|
+
* background-image (gradient / url) shows through the glyph shapes —
|
|
311
|
+
* a "gradient headline" effect (Stripe / Resend / Linear hero copy).
|
|
312
|
+
* Captured separately because `color` may still report a normal value
|
|
313
|
+
* when the rendered text is actually transparent. DM-462.
|
|
314
|
+
*/
|
|
315
|
+
webkitTextFillColor?: string;
|
|
316
|
+
paddingTop: string;
|
|
317
|
+
paddingRight: string;
|
|
318
|
+
paddingBottom: string;
|
|
319
|
+
paddingLeft: string;
|
|
320
|
+
/** Intrinsic dimensions per background-image layer (same order as splitTopLevelCommas). */
|
|
321
|
+
backgroundIntrinsic?: Array<{
|
|
322
|
+
w: number;
|
|
323
|
+
h: number;
|
|
324
|
+
} | null>;
|
|
325
|
+
borderImageSource: string;
|
|
326
|
+
borderImageSlice: string;
|
|
327
|
+
borderImageWidth: string;
|
|
328
|
+
borderImageOutset: string;
|
|
329
|
+
borderImageRepeat: string;
|
|
330
|
+
/** Intrinsic pixel dimensions of a border-image url() source, resolved at capture time. */
|
|
331
|
+
borderImageIntrinsicWidth?: number;
|
|
332
|
+
borderImageIntrinsicHeight?: number;
|
|
333
|
+
zIndex: string;
|
|
334
|
+
position: string;
|
|
335
|
+
float: string;
|
|
336
|
+
/** CSS `order` (flex/grid items). Per CSS Flexbox 1 §5.4.1 and CSS Grid 1
|
|
337
|
+
* §17, paint order is order-modified document order — items are painted
|
|
338
|
+
* in ascending `order` value, ties broken by source (DOM) order. The
|
|
339
|
+
* property has no effect on non-flex/non-grid items but Chrome still
|
|
340
|
+
* reports it on every computed style, so we capture unconditionally. */
|
|
341
|
+
order: string;
|
|
342
|
+
/** CSS `flex-direction` on a flex container (`row` / `row-reverse` /
|
|
343
|
+
* `column` / `column-reverse`). Empirically Chrome paints children of a
|
|
344
|
+
* `*-reverse` flex container in REVERSE of their order-modified document
|
|
345
|
+
* order, so the rightmost (or bottommost) item paints LAST in every
|
|
346
|
+
* flex-direction — matching what users expect from a visually-reordered
|
|
347
|
+
* layout. Captured on the parent so the child sorter can read it. */
|
|
348
|
+
flexDirection: string;
|
|
349
|
+
/** For <td>/<th> with empty-cells: hide — suppress bg + border. */
|
|
350
|
+
emptyCellsHidden?: boolean;
|
|
351
|
+
/** Form-control state captured so we can synthesize native chrome. */
|
|
352
|
+
inputType?: string;
|
|
353
|
+
/** CSS `appearance` / `-webkit-appearance` longhand. 'none' means the
|
|
354
|
+
* author has opted out of UA chrome — the renderer should let the host
|
|
355
|
+
* rect (background / border / border-radius) show through and only
|
|
356
|
+
* overlay the :checked indicator. DM-285. */
|
|
357
|
+
inputAppearance?: string;
|
|
358
|
+
checked?: boolean;
|
|
359
|
+
indeterminate?: boolean;
|
|
360
|
+
disabled?: boolean;
|
|
361
|
+
progressValue?: number;
|
|
362
|
+
progressMax?: number;
|
|
363
|
+
/** Custom CSS on ::-webkit-progress-bar (the track) — when set, overrides the default track. */
|
|
364
|
+
progressBarBg?: string;
|
|
365
|
+
progressBarBgImage?: string;
|
|
366
|
+
progressBarRadius?: string;
|
|
367
|
+
/** Custom CSS on ::-webkit-progress-value (the fill) — when set, overrides the synthesized fill. */
|
|
368
|
+
progressValueBg?: string;
|
|
369
|
+
progressValueBgImage?: string;
|
|
370
|
+
progressValueRadius?: string;
|
|
371
|
+
meterValue?: number;
|
|
372
|
+
meterMin?: number;
|
|
373
|
+
meterMax?: number;
|
|
374
|
+
meterLow?: number;
|
|
375
|
+
meterHigh?: number;
|
|
376
|
+
meterOptimum?: number;
|
|
377
|
+
/** Custom CSS on ::-webkit-meter-bar / ::-webkit-meter-*-value pseudo-elements. */
|
|
378
|
+
meterBarBg?: string;
|
|
379
|
+
meterBarBgImage?: string;
|
|
380
|
+
meterBarRadius?: string;
|
|
381
|
+
meterOptimumBg?: string;
|
|
382
|
+
meterOptimumBgImage?: string;
|
|
383
|
+
meterSuboptimumBg?: string;
|
|
384
|
+
meterSuboptimumBgImage?: string;
|
|
385
|
+
meterEvenLessGoodBg?: string;
|
|
386
|
+
meterEvenLessGoodBgImage?: string;
|
|
387
|
+
detailsOpen?: boolean;
|
|
388
|
+
/** True when the `<summary>`'s `::marker` was hidden by author CSS
|
|
389
|
+
* (e.g. `::marker { color: transparent }` or
|
|
390
|
+
* `::-webkit-details-marker { color: transparent }`), so the renderer
|
|
391
|
+
* should NOT paint its own UA disclosure triangle on top of the
|
|
392
|
+
* author's custom marker. DM-448. */
|
|
393
|
+
summaryMarkerSuppressed?: boolean;
|
|
394
|
+
selectChevron?: boolean;
|
|
395
|
+
/** Text of the currently-selected option, rendered inside the `<select>`
|
|
396
|
+
* content rect for closed dropdowns (DM-246). For listbox-mode selects
|
|
397
|
+
* (`size > 1` or `multiple`) this is undefined and per-option rendering
|
|
398
|
+
* flows through the listbox path instead. */
|
|
399
|
+
selectDisplayText?: string;
|
|
400
|
+
/** Captured option list for listbox-mode `<select>` (size > 1 or
|
|
401
|
+
* multiple). Each entry is one row the renderer paints inside the
|
|
402
|
+
* select's content rect. DM-282. */
|
|
403
|
+
selectListboxOptions?: Array<{
|
|
404
|
+
text: string;
|
|
405
|
+
selected: boolean;
|
|
406
|
+
disabled: boolean;
|
|
407
|
+
/** Optgroup label row (italic + bold; not user-selectable). */
|
|
408
|
+
isOptgroupLabel?: boolean;
|
|
409
|
+
/** Indented child of an optgroup. */
|
|
410
|
+
isOptgroupChild?: boolean;
|
|
411
|
+
}>;
|
|
412
|
+
accentColor?: string;
|
|
413
|
+
caretColor?: string;
|
|
414
|
+
/** For <input type=range/color/date/time/...> — the current value. */
|
|
415
|
+
inputValue?: string;
|
|
416
|
+
inputMin?: string;
|
|
417
|
+
inputMax?: string;
|
|
418
|
+
inputStep?: string;
|
|
419
|
+
/** True for inputs with the `multiple` attribute (file / email / select). DM-271. */
|
|
420
|
+
inputMultiple?: boolean;
|
|
421
|
+
/** For <input type=file> — name of the first selected file, or empty. */
|
|
422
|
+
inputFileName?: string;
|
|
423
|
+
/** Custom-styled <input type=range> ::-webkit-slider-runnable-track / ::-webkit-slider-thumb (SK-1131). */
|
|
424
|
+
rangeTrackBg?: string;
|
|
425
|
+
rangeTrackHeight?: string;
|
|
426
|
+
rangeTrackRadius?: string;
|
|
427
|
+
/** Resolved gradient text for the slider track (SK-1224). Captured when the rule sets background or background-image to a *-gradient(). */
|
|
428
|
+
rangeTrackBgImage?: string;
|
|
429
|
+
rangeThumbBg?: string;
|
|
430
|
+
rangeThumbWidth?: string;
|
|
431
|
+
rangeThumbHeight?: string;
|
|
432
|
+
rangeThumbRadius?: string;
|
|
433
|
+
/** Resolved gradient text for the slider thumb (SK-1224). */
|
|
434
|
+
rangeThumbBgImage?: string;
|
|
435
|
+
/** ::-webkit-slider-runnable-track border shorthand (DM-273). */
|
|
436
|
+
rangeTrackBorder?: string;
|
|
437
|
+
/** ::-webkit-slider-thumb border shorthand (DM-273). */
|
|
438
|
+
rangeThumbBorder?: string;
|
|
439
|
+
/** ::-webkit-slider-thumb box-shadow (DM-319). Used for the donut-ring
|
|
440
|
+
* effect: `box-shadow: 0 0 0 Npx <color>` paints an outer ring of width
|
|
441
|
+
* N around the thumb. We only render the spread-only form. */
|
|
442
|
+
rangeThumbBoxShadow?: string;
|
|
443
|
+
/** ::-webkit-color-swatch pseudo styles (SK-1223). */
|
|
444
|
+
colorSwatchBg?: string;
|
|
445
|
+
colorSwatchBgImage?: string;
|
|
446
|
+
colorSwatchBorder?: string;
|
|
447
|
+
colorSwatchRadius?: string;
|
|
448
|
+
colorSwatchWrapperPadding?: string;
|
|
449
|
+
/** ::-webkit-inner-spin-button pseudo styles (SK-1223; capture only — renderer pickup is a follow-up). */
|
|
450
|
+
numberSpinButtonBg?: string;
|
|
451
|
+
numberSpinButtonBorder?: string;
|
|
452
|
+
numberSpinButtonRadius?: string;
|
|
453
|
+
/** ::-webkit-search-cancel-button pseudo styles (SK-1223; capture only — renderer pickup is a follow-up). */
|
|
454
|
+
searchCancelButtonBg?: string;
|
|
455
|
+
searchCancelButtonBorder?: string;
|
|
456
|
+
searchCancelButtonRadius?: string;
|
|
457
|
+
/** For <input type=file> — captured ::file-selector-button pseudo styles. */
|
|
458
|
+
fileButtonBg?: string;
|
|
459
|
+
fileButtonColor?: string;
|
|
460
|
+
fileButtonBorder?: string;
|
|
461
|
+
fileButtonBorderRadius?: string;
|
|
462
|
+
fileButtonPadding?: string;
|
|
463
|
+
fileButtonFontWeight?: string;
|
|
464
|
+
fileButtonFontSize?: string;
|
|
465
|
+
fileButtonFontFamily?: string;
|
|
466
|
+
fileButtonMarginRight?: string;
|
|
467
|
+
/** Canvas-measureText width of the button label at the captured font (DM-288).
|
|
468
|
+
* Lets the renderer position the trailing 'No file chosen' placeholder at
|
|
469
|
+
* exactly Chrome's painted x rather than overestimating via a per-char ratio. */
|
|
470
|
+
fileButtonLabelWidth?: number;
|
|
471
|
+
/** CSS outline (drawn outside the border-box, doesn't take layout space). */
|
|
472
|
+
outlineStyle?: string;
|
|
473
|
+
outlineWidth?: string;
|
|
474
|
+
outlineColor?: string;
|
|
475
|
+
outlineOffset?: string;
|
|
476
|
+
/** CSS box-shadow (raw value: outset/inset, x y blur spread color, comma-separated). */
|
|
477
|
+
boxShadow?: string;
|
|
478
|
+
/** CSS text-shadow (raw value: x y blur color, comma-separated; no inset/spread). */
|
|
479
|
+
textShadow?: string;
|
|
480
|
+
/** CSS transform (e.g. `rotate(30deg)`, `scale(1.5)`, `matrix(1,0,0,1,0,0)`). 'none' → no transform. */
|
|
481
|
+
transform?: string;
|
|
482
|
+
/** CSS will-change (DM-498): a comma-separated hint listing properties the
|
|
483
|
+
* author intends to animate. When the list contains a property whose
|
|
484
|
+
* non-initial value WOULD create a stacking context (transform, opacity,
|
|
485
|
+
* filter, mask, clip-path, perspective, top/right/bottom/left, position,
|
|
486
|
+
* z-index, isolation, mix-blend-mode), the element itself becomes a
|
|
487
|
+
* stacking-context root regardless of whether that property has a
|
|
488
|
+
* non-initial value applied. Used by `establishesStackingContext`. */
|
|
489
|
+
willChange?: string;
|
|
490
|
+
/** CSS contain (DM-498): `layout`, `paint`, `strict`, `content`, `size`,
|
|
491
|
+
* or combinations. `paint` / `strict` / `content` (which includes paint)
|
|
492
|
+
* create a stacking context per spec. */
|
|
493
|
+
contain?: string;
|
|
494
|
+
/** CSS isolation (DM-498): `isolate` creates a stacking context. */
|
|
495
|
+
isolation?: string;
|
|
496
|
+
/**
|
|
497
|
+
* DM-552: page-level color-scheme inferred from the capture context.
|
|
498
|
+
* Sourced from `matchMedia('(prefers-color-scheme: dark)').matches` at
|
|
499
|
+
* capture time and ONLY populated on the captured tree's root element
|
|
500
|
+
* (other elements omit it). Renderer reads this to decide whether to
|
|
501
|
+
* emit `color-scheme="dark"` on the root `<svg>`.
|
|
502
|
+
*/
|
|
503
|
+
rootColorScheme?: "light" | "dark";
|
|
504
|
+
/**
|
|
505
|
+
* DM-552: `getComputedStyle(document.documentElement).backgroundColor`
|
|
506
|
+
* resolved by Chromium at capture time. Covers the transparent-root
|
|
507
|
+
* case where the page declares no background and Chromium fills its
|
|
508
|
+
* UA default per scheme (`#ffffff` for light, `rgb(28, 28, 28)`-ish
|
|
509
|
+
* for dark). ONLY populated on the captured tree's root element.
|
|
510
|
+
*/
|
|
511
|
+
rootBgComputed?: string;
|
|
512
|
+
/** CSS transform-origin resolved to pixel pair (e.g. `60px 30px`). Defaults to '50% 50%' = bbox center. */
|
|
513
|
+
transformOrigin?: string;
|
|
514
|
+
/** CSS writing-mode (`horizontal-tb` | `vertical-rl` | `vertical-lr` | `sideways-rl` | `sideways-lr`). */
|
|
515
|
+
writingMode?: string;
|
|
516
|
+
/** CSS text-orientation (`mixed` | `upright` | `sideways`). Used in vertical writing-modes. */
|
|
517
|
+
textOrientation?: string;
|
|
518
|
+
/** CSS resize. Non-none on textareas paints the bottom-right resize handle. */
|
|
519
|
+
resize?: string;
|
|
520
|
+
/** CSS text-overflow ('clip' | 'ellipsis' | "<string>" | …). Renderer paints
|
|
521
|
+
* the truncation marker at the visible right edge when overflow is hidden
|
|
522
|
+
* and white-space prevents wrapping. (DM-373) */
|
|
523
|
+
textOverflow?: string;
|
|
524
|
+
/** Whitespace handling — needed alongside text-overflow to determine if the
|
|
525
|
+
* truncation marker should paint. */
|
|
526
|
+
whiteSpace?: string;
|
|
527
|
+
color: string;
|
|
528
|
+
fontSize: string;
|
|
529
|
+
fontFamily: string;
|
|
530
|
+
fontWeight: string;
|
|
531
|
+
/** 'italic' | 'oblique' | 'normal' — drives the SF Pro slnt axis in
|
|
532
|
+
* text-to-path so <em>, <i>, [style=font-style:italic] etc. render
|
|
533
|
+
* slanted instead of upright. */
|
|
534
|
+
fontStyle?: string;
|
|
535
|
+
opacity: string;
|
|
536
|
+
lineHeight: string;
|
|
537
|
+
letterSpacing: string;
|
|
538
|
+
fontKerning: string;
|
|
539
|
+
fontStretch: string;
|
|
540
|
+
fontVariationSettings: string;
|
|
541
|
+
fontFeatureSettings: string;
|
|
542
|
+
/** CSS font-variant-caps — 'normal' | 'small-caps' | 'all-small-caps' |
|
|
543
|
+
* 'petite-caps' | 'all-petite-caps' | 'unicase' | 'titling-caps'.
|
|
544
|
+
* Renderer applies the matching OpenType feature (smcp / c2sc / etc.).
|
|
545
|
+
* DM-361. */
|
|
546
|
+
fontVariantCaps?: string;
|
|
547
|
+
/** CSS direction ('ltr' / 'rtl'). Drives BiDi reordering on RTL paragraphs. */
|
|
548
|
+
direction?: string;
|
|
549
|
+
/** BCP-47 language tag inherited from `el.lang` / nearest ancestor `[lang]` /
|
|
550
|
+
* `<html lang>`. Routes Han fallback to the matching PingFang regional
|
|
551
|
+
* variant (TC / HK / MO) or Hiragino Kaku for `ja`. (DM-394) */
|
|
552
|
+
lang?: string;
|
|
553
|
+
/** `text-decoration-line` — 'underline', 'line-through', 'overline', or
|
|
554
|
+
* combinations. 'none' means no decoration; renderer draws an SVG line
|
|
555
|
+
* below / through / above the text when present. */
|
|
556
|
+
textDecorationLine?: string;
|
|
557
|
+
/** `text-decoration-color` — color for the decoration line. Falls back to
|
|
558
|
+
* the element's text color when undefined. */
|
|
559
|
+
textDecorationColor?: string;
|
|
560
|
+
/** `text-decoration-style` — 'solid' / 'dashed' / 'dotted' / 'double' /
|
|
561
|
+
* 'wavy'. Undefined or 'solid' = plain line. */
|
|
562
|
+
textDecorationStyle?: string;
|
|
563
|
+
/** `text-decoration-thickness` — explicit length (e.g. `5px`) or `auto`.
|
|
564
|
+
* When set to a length, overrides the auto thickness in
|
|
565
|
+
* `getDecorationMetrics`. DM-431. */
|
|
566
|
+
textDecorationThickness?: string;
|
|
567
|
+
/** `text-underline-offset` — extra distance below the baseline for the
|
|
568
|
+
* underline stroke. Adds to the auto offset. DM-431. */
|
|
569
|
+
textUnderlineOffset?: string;
|
|
570
|
+
/** `text-decoration-skip-ink` — 'auto' (default; break around descenders),
|
|
571
|
+
* 'none' (always solid), or 'all'. Per Chromium's
|
|
572
|
+
* `decoration_line_painter.cc`, only solid + double underlines honor
|
|
573
|
+
* skip-ink; dashed / dotted / wavy ignore it. DM-446. */
|
|
574
|
+
textDecorationSkipInk?: string;
|
|
575
|
+
};
|
|
576
|
+
children: CapturedElement[];
|
|
577
|
+
imageSrc?: string;
|
|
578
|
+
/** Intrinsic pixel dimensions of <img>, used for object-fit: none. */
|
|
579
|
+
imageIntrinsic?: {
|
|
580
|
+
w: number;
|
|
581
|
+
h: number;
|
|
582
|
+
};
|
|
583
|
+
/** True when the <img> failed to load (`complete && naturalWidth === 0`).
|
|
584
|
+
* Renderer paints the broken-image fallback (icon + alt text). DM-372. */
|
|
585
|
+
imageBroken?: boolean;
|
|
586
|
+
/** <img alt> attribute, painted next to the broken-image icon. DM-372. */
|
|
587
|
+
imageAlt?: string;
|
|
588
|
+
/** Intrinsic pixel dimensions of list-style-image on <li>. */
|
|
589
|
+
listMarkerIntrinsic?: {
|
|
590
|
+
w: number;
|
|
591
|
+
h: number;
|
|
592
|
+
};
|
|
593
|
+
/** 1-based list-item counter value used to format numeric/alpha markers. */
|
|
594
|
+
listItemIndex?: number;
|
|
595
|
+
/** Computed ::marker pseudo styles when set on an <li>. CSS lets authors
|
|
596
|
+
* recolor / re-weight / resize the marker independent of the list item
|
|
597
|
+
* text (e.g. li::marker { color: #ea580c; font-weight: bold }). See
|
|
598
|
+
* SK-1115. */
|
|
599
|
+
markerColor?: string;
|
|
600
|
+
markerFontWeight?: string;
|
|
601
|
+
markerFontSize?: string;
|
|
602
|
+
/** Computed `::marker { content: ... }`. When non-default ("normal" or
|
|
603
|
+
* empty), Chrome paints this string in place of the list-style-type
|
|
604
|
+
* bullet/number. Captured as the raw computed value (may include
|
|
605
|
+
* surrounding quotes). DM-447. */
|
|
606
|
+
markerContent?: string;
|
|
607
|
+
/** Computed `::marker { font-family }`. Defaults to inherit, but authors
|
|
608
|
+
* can override (e.g. `font-family: monospace` on numeric markers). */
|
|
609
|
+
markerFontFamily?: string;
|
|
610
|
+
/** ::before / ::after pseudo-element image content (content: url(...)). */
|
|
611
|
+
pseudoImages?: Array<{
|
|
612
|
+
url: string;
|
|
613
|
+
x: number;
|
|
614
|
+
y: number;
|
|
615
|
+
width: number;
|
|
616
|
+
height: number;
|
|
617
|
+
}>;
|
|
618
|
+
svgContent?: string;
|
|
619
|
+
/** Individual text node segments (for mixed content with interleaved child elements) */
|
|
620
|
+
textSegments?: TextSegment[];
|
|
621
|
+
/** Bounding box of all text (union of segments) */
|
|
622
|
+
textTop?: number;
|
|
623
|
+
textLeft?: number;
|
|
624
|
+
textHeight?: number;
|
|
625
|
+
textWidth?: number;
|
|
626
|
+
/**
|
|
627
|
+
* Chrome's `canvas.measureText().fontBoundingBoxAscent` for the element's
|
|
628
|
+
* computed font (px, integer-rounded). This is the exact distance Chrome
|
|
629
|
+
* paints from line-box top to baseline — reading it from the browser
|
|
630
|
+
* sidesteps the fontkit-vs-Chrome metric divergence (Helvetica/Arial/Times
|
|
631
|
+
* etc on macOS use winAscent, not hhea, while SF Pro has equal metrics; the
|
|
632
|
+
* "right metric per font" is fragile to derive but trivial to measure).
|
|
633
|
+
*/
|
|
634
|
+
fontAscent?: number;
|
|
635
|
+
fontDescent?: number;
|
|
636
|
+
/**
|
|
637
|
+
* Per-char x positions for input/textarea value text (SK-1234), measured
|
|
638
|
+
* via a hidden DOM probe with the same font/value. Lets the renderer
|
|
639
|
+
* anchor each glyph at the position Chromium would paint instead of
|
|
640
|
+
* trusting fontkit's native advances (which can drift up to ~0.5px per
|
|
641
|
+
* char vs HarfBuzz). One entry per UTF-16 code unit; viewport-relative.
|
|
642
|
+
*/
|
|
643
|
+
inputXOffsets?: number[];
|
|
644
|
+
/** Rasterized text as PNG data URI (rendered via canvas for cross-browser consistency) */
|
|
645
|
+
textImageUri?: string;
|
|
646
|
+
/** Scale factor used for text rasterization (e.g. 2 for retina) */
|
|
647
|
+
textImageScale?: number;
|
|
648
|
+
/**
|
|
649
|
+
* True when `text` came from an input/textarea `placeholder=…` attribute
|
|
650
|
+
* (value was empty). Renderer paints the text in placeholderColor instead
|
|
651
|
+
* of the normal text color. See SK-1097 / SK-1100.
|
|
652
|
+
*/
|
|
653
|
+
isPlaceholderText?: boolean;
|
|
654
|
+
/** Computed ::placeholder color (normalized). Set when isPlaceholderText. */
|
|
655
|
+
placeholderColor?: string;
|
|
656
|
+
/** Computed ::placeholder font-style (e.g. italic). Set when isPlaceholderText. */
|
|
657
|
+
placeholderFontStyle?: string;
|
|
658
|
+
/** Computed ::placeholder font-weight. Set when isPlaceholderText. */
|
|
659
|
+
placeholderFontWeight?: string;
|
|
660
|
+
/**
|
|
661
|
+
* Viewport-relative rect of the element's internal content area (minus
|
|
662
|
+
* borders + padding) that rasterizeBitmapGlyphs should screenshot and
|
|
663
|
+
* stash on dataUri for the renderer to stamp in place of path text. Used
|
|
664
|
+
* for <textarea> whose soft-wrap text layout is too involved to replicate
|
|
665
|
+
* in the path pipeline (see SK-1108) — rely on Chrome's own render of the
|
|
666
|
+
* content region. Detection happens in CAPTURE_SCRIPT.
|
|
667
|
+
*/
|
|
668
|
+
elementRaster?: {
|
|
669
|
+
x: number;
|
|
670
|
+
y: number;
|
|
671
|
+
width: number;
|
|
672
|
+
height: number;
|
|
673
|
+
dataUri?: string;
|
|
674
|
+
};
|
|
675
|
+
/**
|
|
676
|
+
* For <canvas> / <video> / <iframe> / <object> / <embed>: a viewport-relative
|
|
677
|
+
* content-box rect (border-box minus border + padding) that
|
|
678
|
+
* rasterizeReplacedElements should screenshot via Playwright and stash on
|
|
679
|
+
* dataUri. The renderer then emits an <image> at the same rect to cover what
|
|
680
|
+
* Chrome actually painted in that element's content area, so these element
|
|
681
|
+
* types stop leaving blank holes in real-world captures. The capture warning
|
|
682
|
+
* is still emitted because these types are out of the spirit of the path-
|
|
683
|
+
* based rendering contract — the snapshot is a frozen raster, not a faithful
|
|
684
|
+
* re-render. See docs/17-replaced-element-snapshots.md (DM-457).
|
|
685
|
+
*/
|
|
686
|
+
replacedSnapshot?: {
|
|
687
|
+
x: number;
|
|
688
|
+
y: number;
|
|
689
|
+
width: number;
|
|
690
|
+
height: number;
|
|
691
|
+
rid: string;
|
|
692
|
+
dataUri?: string;
|
|
693
|
+
};
|
|
694
|
+
/**
|
|
695
|
+
* Image-replacement icon (DM-506): a CSS-sprite icon whose accessible label
|
|
696
|
+
* is hidden via `text-indent: -9999px; overflow: hidden` (or the modern
|
|
697
|
+
* `text-indent: <neg>; overflow: hidden; white-space: nowrap` variant). The
|
|
698
|
+
* element's painted box is rasterised through the `replacedSnapshot` path so
|
|
699
|
+
* the sprite slice is captured as Chrome painted it; capture also clears
|
|
700
|
+
* `text` / `textSegments` / `styles.backgroundImage` so the renderer doesn't
|
|
701
|
+
* double-paint the sliced sprite or leak the off-screen text into the SVG.
|
|
702
|
+
* `titleText` is the suppressed author text — emitted as an SVG `<title>`
|
|
703
|
+
* child of the rasterised `<image>` so screen readers and tooltips still
|
|
704
|
+
* surface the label. See `docs/23-css-sprite-icons.md`.
|
|
705
|
+
*/
|
|
706
|
+
imageReplacement?: {
|
|
707
|
+
titleText: string;
|
|
708
|
+
};
|
|
709
|
+
/**
|
|
710
|
+
* <fieldset> with a top-aligned <legend>: Chrome's UA paints the fieldset's
|
|
711
|
+
* top border at the legend's vertical center (not at fs.y) and notches the
|
|
712
|
+
* border across the legend's horizontal extent. The captured x/y/width/
|
|
713
|
+
* height already encode the inset (y shifted down by legend.height/2,
|
|
714
|
+
* height reduced to match), and this field carries the legend's full
|
|
715
|
+
* absolute bbox so the renderer can clip the top border behind it via an
|
|
716
|
+
* even-odd clipPath. DM-342 / DM-343.
|
|
717
|
+
*/
|
|
718
|
+
fieldsetLegendNotch?: {
|
|
719
|
+
x: number;
|
|
720
|
+
y: number;
|
|
721
|
+
w: number;
|
|
722
|
+
h: number;
|
|
723
|
+
};
|
|
724
|
+
/**
|
|
725
|
+
* Top-level (root only) collection of `<mask>` definitions referenced by
|
|
726
|
+
* fragment URLs (`mask-image: url("#id")`) anywhere in the captured tree.
|
|
727
|
+
* CAPTURE_SCRIPT resolves each fragment id to the corresponding inline
|
|
728
|
+
* `<mask>` element via `document.getElementById` and serialises its
|
|
729
|
+
* `outerHTML` here. The renderer copies these into the output `<defs>`
|
|
730
|
+
* with id rewriting so a captured `<mask id="m1">` becomes a
|
|
731
|
+
* domotion-prefixed mask def referenced by elements that point at `#m1`.
|
|
732
|
+
* Same-document only — external `.svg#fragment` refs are deferred (DM-496).
|
|
733
|
+
* See `docs/21-mask-fragment-references.md`.
|
|
734
|
+
*/
|
|
735
|
+
maskDefs?: MaskFragmentDef[];
|
|
736
|
+
/**
|
|
737
|
+
* DM-494: Raster snapshots of elements referenced by `mask-image:
|
|
738
|
+
* element(#id)`. Top-level (root only) — same-document only (cross-document
|
|
739
|
+
* `element()` is not in scope; CSS spec doesn't define it). Each raster is
|
|
740
|
+
* the actual painted output of the referenced element captured via
|
|
741
|
+
* `page.screenshot({ clip: rect, omitBackground: true })` after a hide-
|
|
742
|
+
* everything-else stylesheet, encoded as `data:image/png;base64,…`.
|
|
743
|
+
* Renderer's `buildMaskDef` looks up the entry by `id` and emits an
|
|
744
|
+
* `<image>` inside the `<mask>` with `mask-type="luminance"` per Chrome's
|
|
745
|
+
* `mask-mode: match-source` default for element() references. See
|
|
746
|
+
* `docs/22-mask-element-paint-references.md`.
|
|
747
|
+
*/
|
|
748
|
+
maskRasters?: MaskRasterRef[];
|
|
749
|
+
}
|
|
750
|
+
export interface MaskFragmentDef {
|
|
751
|
+
/** Original DOM id of the captured `<mask>` element. */
|
|
752
|
+
id: string;
|
|
753
|
+
/** Verbatim `outerHTML` of the captured `<mask>` element. */
|
|
754
|
+
outerHTML: string;
|
|
755
|
+
}
|
|
756
|
+
export interface MaskRasterRef {
|
|
757
|
+
/** DOM id referenced by `mask-image: element(#id)` — used by the renderer
|
|
758
|
+
* to look up the raster from the layer reference. */
|
|
759
|
+
id: string;
|
|
760
|
+
/** `data:image/png;base64,…` of the referenced element's painted box.
|
|
761
|
+
* Populated by `rasterizeMaskSources`; may be undefined if the screenshot
|
|
762
|
+
* failed (e.g. clip went off-page) — renderer falls back to no mask
|
|
763
|
+
* emission and warns. */
|
|
764
|
+
dataUri?: string;
|
|
765
|
+
/** Captured element rect (viewport-relative px). Used by the post-capture
|
|
766
|
+
* pass to drive page.screenshot's clip. Renderer doesn't consume this
|
|
767
|
+
* directly; the `<image>` placement comes from the consuming element's
|
|
768
|
+
* mask-position / mask-size. */
|
|
769
|
+
width: number;
|
|
770
|
+
height: number;
|
|
771
|
+
/** `data-domotion-rid` value attached to the live DOM target so the
|
|
772
|
+
* hide-everything-else stylesheet has a unique selector. */
|
|
773
|
+
rid: string;
|
|
774
|
+
/** Viewport-relative rect of the referenced element, used by the post-
|
|
775
|
+
* capture pass. */
|
|
776
|
+
rect: {
|
|
777
|
+
x: number;
|
|
778
|
+
y: number;
|
|
779
|
+
width: number;
|
|
780
|
+
height: number;
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
export interface CaptureWarning {
|
|
784
|
+
/** Short selector path identifying the element that tripped the warning. */
|
|
785
|
+
selector: string;
|
|
786
|
+
/** Feature name (e.g. 'transform', 'backdrop-filter', '<iframe>'). */
|
|
787
|
+
feature: string;
|
|
788
|
+
/** Short detail about what's not supported and/or a tracking ticket. */
|
|
789
|
+
detail: string;
|
|
790
|
+
}
|
|
791
|
+
export declare function getLastCaptureWarnings(): CaptureWarning[];
|
|
792
|
+
/**
|
|
793
|
+
* Print the last capture's warnings to stderr in a compact format. Useful in
|
|
794
|
+
* CLI / test scripts that want a one-line-per-warning summary.
|
|
795
|
+
*/
|
|
796
|
+
export declare function logCaptureWarnings(label?: string): void;
|
|
797
|
+
/**
|
|
798
|
+
* Capture the visual tree of elements within a viewport region. Warnings about
|
|
799
|
+
* unsupported features encountered during capture are stored and accessible
|
|
800
|
+
* via getLastCaptureWarnings() / logCaptureWarnings().
|
|
801
|
+
*/
|
|
802
|
+
export declare function captureElementTree(page: Page, selector: string | undefined, viewport: {
|
|
803
|
+
x: number;
|
|
804
|
+
y: number;
|
|
805
|
+
width: number;
|
|
806
|
+
height: number;
|
|
807
|
+
}): Promise<CapturedElement[]>;
|
|
808
|
+
/**
|
|
809
|
+
* Same capture as `captureElementTree` but returns the warnings inline so
|
|
810
|
+
* callers running multiple captures concurrently don't race on the
|
|
811
|
+
* `lastCaptureWarnings` module global. The global is still updated so
|
|
812
|
+
* single-capture callers using `getLastCaptureWarnings()` keep working.
|
|
813
|
+
*/
|
|
814
|
+
export declare function captureElementTreeWithWarnings(page: Page, selector: string | undefined, viewport: {
|
|
815
|
+
x: number;
|
|
816
|
+
y: number;
|
|
817
|
+
width: number;
|
|
818
|
+
height: number;
|
|
819
|
+
}, opts?: {
|
|
820
|
+
/** DM-562: when provided, `rasterizeReplacedElements` crops replaced-
|
|
821
|
+
* element rects from this PNG instead of taking fresh page.screenshot
|
|
822
|
+
* calls. Eliminates timing drift between the expected screenshot and
|
|
823
|
+
* rotating cross-origin-iframe content. Caller is responsible for
|
|
824
|
+
* ensuring the source covers the same coordinate space as `viewport`. */
|
|
825
|
+
rasterizeFromImagePath?: string;
|
|
826
|
+
}): Promise<{
|
|
827
|
+
tree: CapturedElement[];
|
|
828
|
+
warnings: CaptureWarning[];
|
|
829
|
+
}>;
|
|
830
|
+
/**
|
|
831
|
+
* Calibrate `fontAscent` on text-bearing elements by scanning a reference
|
|
832
|
+
* PNG (Chrome's actual paint) for each element's painted ink top, then
|
|
833
|
+
* back-solving the sub-pixel baseline as
|
|
834
|
+
* `inkTop - textTop + actualBoundingBoxAscent(text)` where the cap-height
|
|
835
|
+
* comes from `canvas.measureText(text).actualBoundingBoxAscent` (sub-pixel
|
|
836
|
+
* accurate, unlike `fontBoundingBoxAscent` which Chrome integer-rounds).
|
|
837
|
+
*
|
|
838
|
+
* Closes the residual ±0.6 px text-baseline drift documented in DM-397 /
|
|
839
|
+
* DM-418. Empirical extraction at capture time — uses Chrome's actual
|
|
840
|
+
* painted output as ground truth instead of trying to mirror Chromium's
|
|
841
|
+
* per-platform LayoutNG strut math.
|
|
842
|
+
*
|
|
843
|
+
* Caller must provide PNG bytes from a Chrome screenshot of the same
|
|
844
|
+
* viewport that was captured. For the test pipeline this is the same
|
|
845
|
+
* `expected.png` we already write to disk for diffing.
|
|
846
|
+
*/
|
|
847
|
+
export declare function calibrateBaselines(page: Page, elements: CapturedElement[], pngBytes: Buffer | Uint8Array): Promise<void>;
|
|
848
|
+
/**
|
|
849
|
+
* Wrap inner SVG markup (as returned by `elementTreeToSvg`) in a complete
|
|
850
|
+
* `<svg>` document with the standard namespace, viewBox, and intrinsic size.
|
|
851
|
+
* This is the boilerplate every standalone-capture user would otherwise write
|
|
852
|
+
* themselves — call this when you want a self-contained SVG file.
|
|
853
|
+
*/
|
|
854
|
+
export declare function wrapSvg(inner: string, width: number, height: number, opts?: {
|
|
855
|
+
tree?: CapturedElement[];
|
|
856
|
+
}): string;
|
|
857
|
+
/**
|
|
858
|
+
* DM-552: returns ` color-scheme="dark"` (with leading space, suitable for
|
|
859
|
+
* direct concatenation into an `<svg ...>` opening tag) when the captured
|
|
860
|
+
* tree's root reports `rootColorScheme === "dark"`. Returns an empty string
|
|
861
|
+
* for the light / no-scheme case so today's SVG output is byte-identical at
|
|
862
|
+
* the default. Use from any code path that emits a root `<svg>` outside of
|
|
863
|
+
* `wrapSvg` (e.g., `tests/runner.tsx` and `tests/real-world.tsx` build their
|
|
864
|
+
* own opening tags so they can inject a body-bg `<rect>` underneath the
|
|
865
|
+
* captured content).
|
|
866
|
+
*/
|
|
867
|
+
export declare function rootSvgColorSchemeAttr(elements: CapturedElement[]): string;
|
|
868
|
+
/**
|
|
869
|
+
* DM-554: returns a body-bg `<rect>` markup string for the canvas when the
|
|
870
|
+
* captured tree's root provides a `rootBgComputed` (set by CAPTURE_SCRIPT
|
|
871
|
+
* from `getComputedStyle(document.documentElement).backgroundColor`).
|
|
872
|
+
* Returns an empty string when the field is missing (pre-DM-552 captures)
|
|
873
|
+
* or the resolved bg is transparent (pages that intend a transparent SVG).
|
|
874
|
+
*
|
|
875
|
+
* Used by `wrapSvg` and exported so external consumers that build their
|
|
876
|
+
* own `<svg>` opening tag (because they need to inject a body-bg rect at a
|
|
877
|
+
* specific position relative to other root-level rects, e.g. a frame
|
|
878
|
+
* overlay) can produce the same markup without re-implementing the
|
|
879
|
+
* fallback chain.
|
|
880
|
+
*/
|
|
881
|
+
export declare function transparentRootBgRect(elements: CapturedElement[], width: number, height: number): string;
|
|
882
|
+
/**
|
|
883
|
+
* Convert a CapturedElement tree into SVG markup.
|
|
884
|
+
*/
|
|
885
|
+
export declare function elementTreeToSvg(elements: CapturedElement[], width: number, height: number,
|
|
886
|
+
/** Prefix for clipPath IDs — required when combining multiple frames in one SVG to avoid ID collisions */
|
|
887
|
+
idPrefix?: string,
|
|
888
|
+
/**
|
|
889
|
+
* When true (default), include the shared glyph definitions in this frame's
|
|
890
|
+
* <defs>. Multi-frame animated SVGs should pass false so glyph defs can be
|
|
891
|
+
* hoisted to the top-level SVG <defs> and shared across frames.
|
|
892
|
+
*/
|
|
893
|
+
includeGlyphDefs?: boolean,
|
|
894
|
+
/**
|
|
895
|
+
* DM-540: hiDPI multiplier the renderer uses when looking up resized
|
|
896
|
+
* variants in `_resizedDataUriCache`. Must match the value passed to
|
|
897
|
+
* `resizeEmbeddedImages` for the same tree, or the lookup misses and
|
|
898
|
+
* the renderer falls back to the source-resolution data URI. Default 2.
|
|
899
|
+
*/
|
|
900
|
+
hiDPIFactor?: number): string;
|
|
901
|
+
export interface RGBA {
|
|
902
|
+
r: number;
|
|
903
|
+
g: number;
|
|
904
|
+
b: number;
|
|
905
|
+
a: number;
|
|
906
|
+
}
|
|
907
|
+
export declare function parseColor(css: string): RGBA | null;
|
|
908
|
+
/** Per-corner border-radius axis-pair (h = horizontal, v = vertical).
|
|
909
|
+
* An elliptical corner has h ≠ v; a circular corner has h = v. */
|
|
910
|
+
export type CornerRadiusPair = {
|
|
911
|
+
h: number;
|
|
912
|
+
v: number;
|
|
913
|
+
};
|
|
914
|
+
/** Resolved per-corner border-radius for the four corners of a rect, with
|
|
915
|
+
* CSS-spec corner-overlap scaling already applied. `uniform` is true when
|
|
916
|
+
* all four corners are circular AND share the same radius, which lets the
|
|
917
|
+
* renderer emit a single `<rect rx>` instead of a per-corner `<path>`. */
|
|
918
|
+
export type CornerRadii = {
|
|
919
|
+
tl: CornerRadiusPair;
|
|
920
|
+
tr: CornerRadiusPair;
|
|
921
|
+
br: CornerRadiusPair;
|
|
922
|
+
bl: CornerRadiusPair;
|
|
923
|
+
uniform: boolean;
|
|
924
|
+
};
|
|
925
|
+
/** Resolve the four per-corner radii for a captured element, applying CSS's
|
|
926
|
+
* corner-overlap scale-down (https://www.w3.org/TR/css-backgrounds-3/#corner-overlap):
|
|
927
|
+
* if any edge's two corner radii would together exceed the edge length, all
|
|
928
|
+
* four corners are scaled down uniformly. This is what produces the pill
|
|
929
|
+
* shape for `border-radius:999px` on a short element — without the spec
|
|
930
|
+
* clamp, two adjacent 999-px corners would overlap visibly. Falls back to
|
|
931
|
+
* the legacy single `borderRadius` shorthand when the per-corner longhands
|
|
932
|
+
* weren't captured (older snapshots). */
|
|
933
|
+
export declare function parseCornerRadii(styles: {
|
|
934
|
+
borderTopLeftRadius?: string;
|
|
935
|
+
borderTopRightRadius?: string;
|
|
936
|
+
borderBottomRightRadius?: string;
|
|
937
|
+
borderBottomLeftRadius?: string;
|
|
938
|
+
borderRadius?: string;
|
|
939
|
+
}, width: number, height: number): CornerRadii;
|
|
940
|
+
/** Inset each corner radius by the matching border-side widths, clamping to 0.
|
|
941
|
+
* Use this to derive the inner radii used by background clips (where the
|
|
942
|
+
* border has eaten into the corner) and inner border strokes. CSS specifies
|
|
943
|
+
* that the inner corner is the outer corner pulled in by the adjacent border
|
|
944
|
+
* widths (top + left for TL, top + right for TR, etc.). */
|
|
945
|
+
export declare function insetCornerRadii(c: CornerRadii, top: number, right: number, bottom: number, left: number): CornerRadii;
|
|
946
|
+
/** Emit an SVG path `d` attribute for a rounded rectangle with per-corner radii.
|
|
947
|
+
* Path goes clockwise from the top-left, using elliptical arc commands at each
|
|
948
|
+
* corner. Zero-radius corners collapse to a sharp 90° join. */
|
|
949
|
+
export declare function roundedRectPath(x: number, y: number, w: number, h: number, c: CornerRadii): string;
|
|
950
|
+
/** Emit a rounded-rect SVG element. Uses `<rect rx>` when the corners are
|
|
951
|
+
* uniform (cheaper, less markup); falls back to `<path>` for asymmetric or
|
|
952
|
+
* elliptical corners. The `attrs` string is injected verbatim — pass in
|
|
953
|
+
* fill/stroke/etc. */
|
|
954
|
+
export declare function roundedRectSvg(x: number, y: number, w: number, h: number, c: CornerRadii, attrs: string): string;
|
|
955
|
+
/**
|
|
956
|
+
* Rewrite a captured `<mask>` element's `outerHTML` so it can be safely
|
|
957
|
+
* inlined in the output SVG's `<defs>`. The mask's own `id` becomes
|
|
958
|
+
* `outputId`, and every other DOM id referenced inside the subtree gets
|
|
959
|
+
* prefixed with `idPrefix` so it can't collide with ids elsewhere in the
|
|
960
|
+
* output (multi-frame animated SVGs reuse the same prefix model). Every
|
|
961
|
+
* `url(#X)` reference inside the subtree is updated to point at the
|
|
962
|
+
* rewritten id. DM-493.
|
|
963
|
+
*/
|
|
964
|
+
export declare function rewriteFragmentMaskDef(outerHTML: string, outputId: string, idPrefix: string): string;
|
|
965
|
+
/**
|
|
966
|
+
* Reposition a (previously rewritten) `<mask>` outerHTML so its content lives
|
|
967
|
+
* in the masked element's absolute user-space. CSS `mask-image: url("#id")`
|
|
968
|
+
* positions the mask source at the masked element's content-box origin, but
|
|
969
|
+
* SVG `<mask>` with `maskUnits="userSpaceOnUse"` interprets its content
|
|
970
|
+
* absolutely against the root SVG — so the captured mask coords (which are
|
|
971
|
+
* relative to the original `<mask>` element) need shifting by `(elX, elY)`.
|
|
972
|
+
* We do this by:
|
|
973
|
+
* 1. Forcing `maskUnits="userSpaceOnUse"` on the outer `<mask>`.
|
|
974
|
+
* 2. Replacing the mask's `x/y/width/height` with the masked element's
|
|
975
|
+
* absolute box (so the mask region matches the element).
|
|
976
|
+
* 3. Wrapping the mask's children in `<g transform="translate(elX, elY)">`.
|
|
977
|
+
* DM-493.
|
|
978
|
+
*/
|
|
979
|
+
export declare function positionFragmentMaskDef(rewrittenOuterHTML: string, elX: number, elY: number, elW: number, elH: number): string;
|
|
980
|
+
/**
|
|
981
|
+
* Translate a CSS mask-image value + mask-* siblings into an SVG <mask>.
|
|
982
|
+
* Handles single-layer gradients and url() sources. Position/size/repeat are
|
|
983
|
+
* applied via an internal <pattern> for url sources; gradients use direct
|
|
984
|
+
* gradient fills sized to the element box.
|
|
985
|
+
*
|
|
986
|
+
* SVG <mask> uses luminance by default (bright pixels visible). CSS mask-mode
|
|
987
|
+
* 'alpha' makes the alpha channel control visibility. We set mask-type on the
|
|
988
|
+
* <mask> element accordingly. Note: Chromium may render mask-mode:'match-source'
|
|
989
|
+
* differently depending on the source; we pick alpha for gradients and url()
|
|
990
|
+
* (common case) and respect explicit mask-mode when given.
|
|
991
|
+
*/
|
|
992
|
+
export declare function buildMaskDef(id: string, maskImage: string, elX: number, elY: number, w: number, h: number, maskMode: string, sizeCss: string, posCss: string, repeatCss: string, compositeCss: string,
|
|
993
|
+
/** DM-494: lookup table for `mask-image: element(#id)` references. Optional —
|
|
994
|
+
* callers without element() refs can omit it. The renderer's main caller
|
|
995
|
+
* threads through `elementMaskRasters` (collected from tree[0].maskRasters);
|
|
996
|
+
* unit tests can pass undefined to exercise the non-element() branches. */
|
|
997
|
+
elementRasters?: ReadonlyMap<string, MaskRasterRef>): {
|
|
998
|
+
id: string;
|
|
999
|
+
def: string;
|
|
1000
|
+
};
|
|
1001
|
+
/**
|
|
1002
|
+
* Translate CSS object-fit + object-position to an SVG preserveAspectRatio
|
|
1003
|
+
* attribute. Best-effort — SVG does not cover every CSS combination exactly.
|
|
1004
|
+
*
|
|
1005
|
+
* Mapping:
|
|
1006
|
+
* fill -> 'none' (stretch both axes, may distort)
|
|
1007
|
+
* contain -> '<align> meet' (fit inside, letterbox)
|
|
1008
|
+
* cover -> '<align> slice' (fill, crop)
|
|
1009
|
+
* none -> not representable without intrinsic size info; 'none' stretch is the least-bad default
|
|
1010
|
+
* scale-down -> treated as 'contain' (common case; exact rule requires intrinsic size)
|
|
1011
|
+
*
|
|
1012
|
+
* object-position keywords (top/right/bottom/left/center) and '0% 0%' / '100% 100%'
|
|
1013
|
+
* map to xMin/xMid/xMax + yMin/yMid/yMax. Percentages are bucketed to thirds
|
|
1014
|
+
* since SVG has no finer-grained alignment.
|
|
1015
|
+
*/
|
|
1016
|
+
export declare function preserveAspectRatioFor(fit: string | undefined, pos: string | undefined): string;
|