svg-vectordrawable 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -24
- package/dist/browser-lite.d.ts +162 -0
- package/dist/browser-lite.global.js +3400 -0
- package/dist/browser-lite.js +3375 -0
- package/dist/browser.d.ts +155 -0
- package/dist/browser.global.js +5307 -3022
- package/dist/browser.js +2541 -627
- package/dist/cli.js +3007 -32
- package/dist/index.cjs +2647 -649
- package/dist/index.d.cts +134 -7
- package/dist/index.d.ts +134 -7
- package/dist/index.js +3130 -14
- package/package.json +27 -17
- package/dist/chunk-QG2B6V6V.js +0 -1130
- package/dist/cli.cjs +0 -1221
- package/dist/cli.d.cts +0 -1
- package/dist/cli.d.ts +0 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ npm i svg-vectordrawable
|
|
|
12
12
|
|
|
13
13
|
## Why another one?
|
|
14
14
|
|
|
15
|
-
`svg2vectordrawable` is unmaintained (last release 2022),
|
|
15
|
+
`svg2vectordrawable` is unmaintained (last release 2022), depends on `svgo@^2.8`, and ignores
|
|
16
16
|
`gradientTransform` (Figma radial gradients render at the wrong place). This library is on
|
|
17
17
|
`svgo@4`, bakes `gradientTransform` into the Android coordinates, and **fails loud** instead of
|
|
18
18
|
emitting plausible‑but‑wrong output.
|
|
@@ -22,19 +22,74 @@ emitting plausible‑but‑wrong output.
|
|
|
22
22
|
```ts
|
|
23
23
|
import { convert } from 'svg-vectordrawable';
|
|
24
24
|
|
|
25
|
-
const { xml, warnings } = convert(svgString, {
|
|
25
|
+
const { xml, warnings, minSdk } = convert(svgString, {
|
|
26
26
|
optimize: true, // run svgo normalization first (recommended)
|
|
27
27
|
currentColor: '#000', // value substituted for `currentColor`
|
|
28
28
|
floatPrecision: 3,
|
|
29
29
|
fillBlackForUnfilled: true, // unfilled paths get black (SVG default)
|
|
30
30
|
xmlTag: false, // prepend <?xml ...?>
|
|
31
31
|
tint: '#FFFFFFFF', // android:tint on <vector> (Android color literal)
|
|
32
|
-
strict: false, // throw on
|
|
32
|
+
strict: false, // true: throw on lossy and approximated output; 'lossy': only on lossy output
|
|
33
|
+
minSdk: 21, // warn (`min-sdk-exceeded`) when the output needs a higher API level
|
|
34
|
+
rules: {}, // per-code severity, overrides `strict` (see below)
|
|
33
35
|
onWarn: (w) => console.warn(w.code, w.message),
|
|
34
36
|
});
|
|
35
37
|
```
|
|
36
38
|
|
|
37
|
-
`convert` is synchronous and returns `{ xml, warnings }`.
|
|
39
|
+
`convert` is synchronous and returns `{ xml, warnings, minSdk }`. `minSdk` is the Android API level the
|
|
40
|
+
output needs: 24 when it uses gradients or `fillType="evenOdd"`, otherwise 21.
|
|
41
|
+
|
|
42
|
+
### Preview
|
|
43
|
+
|
|
44
|
+
`vectorDrawableToSvg` turns a VectorDrawable back into SVG, to preview the result in a browser or a PR:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { convert, vectorDrawableToSvg } from 'svg-vectordrawable';
|
|
48
|
+
const preview = vectorDrawableToSvg(convert(svg).xml, { density: 2, applyTint: true });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Warnings, errors and `rules`
|
|
52
|
+
|
|
53
|
+
Every construct that cannot be converted faithfully emits a warning with a stable `code` (listed in
|
|
54
|
+
the exported `WARNING_CODES`). Each code has a category (exported `WARNING_CATEGORIES`): **lossy**
|
|
55
|
+
(content lost or wrong), **approximation** (rendering slightly differs) or **info** (Android lint
|
|
56
|
+
style, API level). `strict: true` turns lossy and approximation warnings into errors, `strict: 'lossy'`
|
|
57
|
+
only lossy ones; info warnings are never raised by `strict`. `rules` sets the severity per code
|
|
58
|
+
(`'off' | 'warn' | 'error'`) and wins over `strict`. Errors are thrown as a
|
|
59
|
+
`ConversionError` carrying the offending `warning`, so you can fall back (e.g. to a PNG):
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { convert, ConversionError } from 'svg-vectordrawable';
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// Reject anything lossy, but accept approximated group opacity.
|
|
66
|
+
const { xml } = convert(svg, { strict: true, rules: { 'opacity-approximated': 'warn' } });
|
|
67
|
+
} catch (err) {
|
|
68
|
+
if (err instanceof ConversionError) console.log('cannot convert:', err.warning.code);
|
|
69
|
+
else throw err;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
| Code | Meaning |
|
|
74
|
+
| ------------------------------ | -------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `unsupported-element` | `<text>`, `<image>`, `<foreignObject>`, `<switch>` — skipped |
|
|
76
|
+
| `unsupported-attribute` | non-clip `mask`, `filter`, `marker*`, `vector-effect`, `paint-order`, `arcs` joins — ignored |
|
|
77
|
+
| `unsupported-stroke-dasharray` | dash pattern that cannot be resolved (`em`/`ex` units) — drawn solid |
|
|
78
|
+
| `unsupported-stroke-gradient` | no longer emitted (gradient strokes are supported); kept for compatibility |
|
|
79
|
+
| `unsupported-paint` | `<pattern>` paint — fallback color or black |
|
|
80
|
+
| `unsupported-style` | CSS left in a `<style>` that could not be applied to elements — ignored |
|
|
81
|
+
| `unsupported-clip-path` | `objectBoundingBox` clip, evenodd clip with crossing contours, unconvertible content |
|
|
82
|
+
| `gradient-approximated` | radial focal point; elliptical radial on a path that also has a solid stroke |
|
|
83
|
+
| `opacity-approximated` | opacity folded onto overlapping children / fill+stroke — overlaps look darker |
|
|
84
|
+
| `missing-gradient` | `url(#id)` paint pointing at nothing, no fallback — black |
|
|
85
|
+
| `missing-clip-path` | `clip-path` pointing at nothing — ignored |
|
|
86
|
+
| `group-skew` | skewed `<g>` baked into path geometry |
|
|
87
|
+
| `gradient-under-skew` | gradient placement under a baked skew is approximate |
|
|
88
|
+
| `gradient-bbox-unavailable` | `objectBoundingBox` gradient without a measurable path box |
|
|
89
|
+
| `empty-path` | shape without geometry — skipped |
|
|
90
|
+
| `min-sdk-exceeded` (info) | the output needs a higher API level than the `minSdk` option |
|
|
91
|
+
| `large-vector` (info) | `android:width`/`height` above 200 dp (Android lint `VectorRaster`) |
|
|
92
|
+
| `long-path-data` (info, off) | a `pathData` longer than 800 characters (lint `VectorPath`); enable it with `rules` |
|
|
38
93
|
|
|
39
94
|
Node file helpers:
|
|
40
95
|
|
|
@@ -42,6 +97,7 @@ Node file helpers:
|
|
|
42
97
|
import { convertFile, convertDir } from 'svg-vectordrawable';
|
|
43
98
|
convertFile('icon.svg', 'res/drawable/icon.xml');
|
|
44
99
|
convertDir('svg/', 'res/drawable/');
|
|
100
|
+
convertDir('svg/', 'res/drawable/', {}, { androidNames: true }); // valid Android resource names
|
|
45
101
|
```
|
|
46
102
|
|
|
47
103
|
### CLI
|
|
@@ -53,6 +109,10 @@ svgvd icon.svg --stdout # print to stdout
|
|
|
53
109
|
svgvd -s '<svg>…</svg>' # convert an inline SVG string
|
|
54
110
|
svgvd icon.svg --xml-tag --tint '#FFFFFFFF'
|
|
55
111
|
svgvd icon.svg --strict # fail on anything not representable
|
|
112
|
+
svgvd icon.svg --strict --rule opacity-approximated=warn # per-code severity
|
|
113
|
+
svgvd icon.svg --strict=lossy # fail only when content would be lost
|
|
114
|
+
svgvd icon.svg --min-sdk 21 # warn when the output needs a higher API level
|
|
115
|
+
svgvd icons/ -o res/drawable/ --android-names # Arrow-Left.svg → arrow_left.xml (valid resource names)
|
|
56
116
|
```
|
|
57
117
|
|
|
58
118
|
### Browser
|
|
@@ -65,39 +125,67 @@ import { convert } from 'svg-vectordrawable/browser';
|
|
|
65
125
|
const { xml } = convert(svgString);
|
|
66
126
|
```
|
|
67
127
|
|
|
128
|
+
`svg-vectordrawable/browser-lite` is the same API without svgo (116 KB instead of 1.1 MB for the
|
|
129
|
+
IIFE build): conversion always runs with `optimize: false`, so `<style>` CSS is not inlined and
|
|
130
|
+
shapes are converted as authored.
|
|
131
|
+
|
|
68
132
|
## What it handles
|
|
69
133
|
|
|
70
|
-
| Feature
|
|
71
|
-
|
|
|
72
|
-
| Paths, `fill`, `stroke` (width/cap/join/miter), `fill-rule` → `fillType`
|
|
73
|
-
| Shapes (`rect`/`circle`/`ellipse`/`line`/`poly*`) → path
|
|
74
|
-
| Colors: `#rgb[a]`, `#rrggbb[aa]`, `rgb()/rgba()`, `hsl()/hsla()`, named, `currentColor`
|
|
75
|
-
| Attribute inheritance (incl. presentation attrs on the `<svg>` root and `<g>`)
|
|
76
|
-
| Inline `style="…"` and `<style>` (via svgo)
|
|
77
|
-
| Linear & radial **gradients**, `gradientTransform`, **`objectBoundingBox`** (via path bbox), `href` sharing, `spreadMethod` → `tileMode`
|
|
78
|
-
| `<g transform>` → `<group>` (translate/rotate/scale); **skew/shear baked into geometry**
|
|
79
|
-
| **`<use>` / `<symbol>`** references — inlined before conversion
|
|
80
|
-
| `clip-path` → `<clip-path>`
|
|
81
|
-
| `opacity` folded into `fillAlpha`/`strokeAlpha`
|
|
134
|
+
| Feature | Status |
|
|
135
|
+
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
|
|
136
|
+
| Paths, `fill`, `stroke` (width/cap/join/miter), `fill-rule` → `fillType` | ✅ |
|
|
137
|
+
| Shapes (`rect`/`circle`/`ellipse`/`line`/`poly*`) → path | ✅ |
|
|
138
|
+
| Colors: `#rgb[a]`, `#rrggbb[aa]`, `rgb()/rgba()`, `hsl()/hsla()`, named, `currentColor` | ✅ |
|
|
139
|
+
| Attribute inheritance (incl. presentation attrs on the `<svg>` root and `<g>`) | ✅ |
|
|
140
|
+
| Inline `style="…"` and `<style>` (via svgo) | ✅ |
|
|
141
|
+
| Linear & radial **gradients**, `gradientTransform`, **`objectBoundingBox`** (via path bbox), `href` sharing, `spreadMethod` → `tileMode` | ✅ |
|
|
142
|
+
| `<g transform>` → `<group>` (translate/rotate/scale); **skew/shear baked into geometry** | ✅ |
|
|
143
|
+
| **`<use>` / `<symbol>`** references — inlined before conversion | ✅ |
|
|
144
|
+
| `clip-path` → `<clip-path>` (on shapes and `<g>`, incl. `<use>` / transformed clip content) | ✅ |
|
|
145
|
+
| `opacity` folded into `fillAlpha`/`strokeAlpha` (root `<svg>` opacity → exact `android:alpha`) | ✅ |
|
|
146
|
+
| `viewBox` origin, `preserveAspectRatio` (meet / slice / none), nested `<svg>`, `<a>`, `display` / `visibility`, units (`px`/`in`/`cm`/`mm`/`pt`/`pc`/`%`) | ✅ |
|
|
82
147
|
|
|
83
148
|
## Known limitations
|
|
84
149
|
|
|
85
150
|
A VectorDrawable simply cannot represent some SVG features. These are **warned** (or throw in
|
|
86
151
|
`strict` mode), never silently mis‑rendered:
|
|
87
152
|
|
|
88
|
-
- `<
|
|
89
|
-
-
|
|
153
|
+
- `<filter>`, `<pattern>`, `<image>`, `<text>` — not representable. A `<mask>` is converted to a
|
|
154
|
+
`<clip-path>` when it is clip-equivalent (opaque white content, or opaque content with `mask-type: alpha`);
|
|
155
|
+
any other mask (gray, translucent, stroked, gradient…) is warned with the reason.
|
|
156
|
+
- `stroke-dasharray` in font-relative units (`em`, `ex`) — the stroke is drawn solid. Other dash
|
|
157
|
+
patterns are baked into the path geometry (VectorDrawable has no native dashes).
|
|
158
|
+
- Radial gradients are circles in VectorDrawable. Elliptical radials (non-uniform `gradientTransform`,
|
|
159
|
+
`objectBoundingBox` on a non-square shape) are made exact by drawing the fill inside a `<group>`
|
|
160
|
+
carrying the ellipse's deformation; they stay approximated only when the same path also has a solid
|
|
161
|
+
stroke (it would be distorted). Focal points (`fx`/`fy`) are approximated (`gradient-approximated`).
|
|
162
|
+
- CSS that svgo cannot inline (`@media`, `:hover`, complex selectors) — `unsupported-style`.
|
|
90
163
|
- `gradientUnits="objectBoundingBox"` is resolved from the path's bounding box; only when that box
|
|
91
164
|
is unavailable does it fall back to the viewport (with a warning).
|
|
92
|
-
- `
|
|
165
|
+
- `filter`, `marker-*`, non-clip `mask` references and `clipPathUnits="objectBoundingBox"` — warned, not applied.
|
|
166
|
+
- Group `opacity` has no VectorDrawable equivalent: it is folded onto each child, which is exact only
|
|
167
|
+
when the children do not overlap (`opacity-approximated` otherwise).
|
|
93
168
|
|
|
94
169
|
## Robustness
|
|
95
170
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
171
|
+
- **Icon corpus in CI** (`scripts/corpus.mjs`): 9,251 icons (Feather, Bootstrap Icons, Heroicons,
|
|
172
|
+
Tabler, pinned versions) converted with and without svgo on every push — zero exceptions, zero
|
|
173
|
+
warnings required.
|
|
174
|
+
- **Android toolchain**: the fixtures (gradients, `gradientTransform`, `objectBoundingBox`, `<use>`,
|
|
175
|
+
sheared groups, clip-path, nested transforms) are **compiled and linked with `aapt2`** against
|
|
176
|
+
`android.jar`, so attribute names and values are validated, not just XML well-formedness.
|
|
177
|
+
- **Visual regression**: every fixture is rendered with resvg next to its VectorDrawable and must match
|
|
178
|
+
within 1% of inked pixels (`pnpm test:visual`).
|
|
179
|
+
- **Android's own renderer**: the generated VectorDrawables are drawn by layoutlib (Android's Skia/hwui,
|
|
180
|
+
through Paparazzi on the JVM) and compared with the source SVG (`pnpm run validate:android`; needs a
|
|
181
|
+
full JDK 17+ and the Android SDK).
|
|
182
|
+
- **Golden snapshots** lock the exact XML against regressions.
|
|
183
|
+
|
|
184
|
+
## Documentation
|
|
185
|
+
|
|
186
|
+
- [Migrating from `svg2vectordrawable`](docs/migration-from-svg2vectordrawable.md)
|
|
187
|
+
- [Integrations](docs/integrations.md) (Node scripts, React Native icons, Gradle, Vite/webpack, CI)
|
|
188
|
+
- [Comparison with `svg2vectordrawable` and Android Studio's Svg2Vector](docs/comparison.md)
|
|
101
189
|
|
|
102
190
|
## License
|
|
103
191
|
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { Config } from 'svgo';
|
|
2
|
+
|
|
3
|
+
/** Every warning code the converter can emit (stable, machine-readable). */
|
|
4
|
+
declare const WARNING_CODES: readonly ["unsupported-element", "unsupported-attribute", "unsupported-stroke-dasharray", "unsupported-stroke-gradient", "unsupported-paint", "unsupported-clip-path", "missing-gradient", "missing-clip-path", "gradient-under-skew", "gradient-bbox-unavailable", "group-skew", "opacity-approximated", "gradient-approximated", "unsupported-style", "empty-path", "min-sdk-exceeded", "long-path-data", "large-vector"];
|
|
5
|
+
/** Stable machine-readable warning codes. */
|
|
6
|
+
type WarningCode = (typeof WARNING_CODES)[number];
|
|
7
|
+
/**
|
|
8
|
+
* What a warning means for the output:
|
|
9
|
+
* - `lossy`: content is dropped or drawn wrong (an element, an attribute, a paint, a clip…);
|
|
10
|
+
* - `approximation`: everything is drawn, but the rendering differs slightly from the SVG;
|
|
11
|
+
* - `info`: the output is faithful; Android-side advice (API level, lint-style performance hints).
|
|
12
|
+
*/
|
|
13
|
+
type WarningCategory = 'lossy' | 'approximation' | 'info';
|
|
14
|
+
/** The category of every warning code (see {@link WarningCategory}); drives the `strict` presets. */
|
|
15
|
+
declare const WARNING_CATEGORIES: Readonly<Record<WarningCode, WarningCategory>>;
|
|
16
|
+
/**
|
|
17
|
+
* `strict` presets: `true` turns every `lossy` and `approximation` warning into an error, `'lossy'`
|
|
18
|
+
* only the `lossy` ones. `info` codes are never escalated by `strict` (only by `rules`).
|
|
19
|
+
*/
|
|
20
|
+
type StrictMode = boolean | 'lossy';
|
|
21
|
+
/** What to do with a warning: drop it, report it, or throw a `ConversionError`. */
|
|
22
|
+
type Severity = 'off' | 'warn' | 'error';
|
|
23
|
+
/** A non-fatal issue encountered during conversion. */
|
|
24
|
+
interface Warning {
|
|
25
|
+
/** Stable machine-readable code, e.g. `unsupported-element`. */
|
|
26
|
+
code: WarningCode;
|
|
27
|
+
/** Human-readable explanation. */
|
|
28
|
+
message: string;
|
|
29
|
+
/** SVG element/attribute the warning relates to, when known. */
|
|
30
|
+
node?: string;
|
|
31
|
+
}
|
|
32
|
+
interface ConvertOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Run svgo normalization first (inline styles, shapes→paths, bake transforms…).
|
|
35
|
+
* Strongly recommended; it is what makes conversion robust across SVG sources.
|
|
36
|
+
* @default true
|
|
37
|
+
*/
|
|
38
|
+
optimize?: boolean;
|
|
39
|
+
/** Override the svgo config used for normalization (only when `optimize` is true). */
|
|
40
|
+
svgoConfig?: Config;
|
|
41
|
+
/** Decimal places kept for generated numbers (coordinates, radii). @default 3 */
|
|
42
|
+
floatPrecision?: number;
|
|
43
|
+
/** Concrete color substituted for `currentColor`. @default '#000000' */
|
|
44
|
+
currentColor?: string;
|
|
45
|
+
/**
|
|
46
|
+
* SVG paints unfilled shapes black by default. When true, paths without an
|
|
47
|
+
* explicit fill get `android:fillColor="#FF000000"`. @default true
|
|
48
|
+
*/
|
|
49
|
+
fillBlackForUnfilled?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Throw a `ConversionError` on the first warning of a category instead of reporting it:
|
|
52
|
+
* `true` for `lossy` and `approximation` codes, `'lossy'` for `lossy` codes only (see
|
|
53
|
+
* {@link WARNING_CATEGORIES}). `info` codes keep their default severity under any preset.
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
strict?: StrictMode;
|
|
57
|
+
/**
|
|
58
|
+
* Per-code severity, overriding `strict` and the defaults. E.g.
|
|
59
|
+
* `{ strict: true, rules: { 'opacity-approximated': 'warn' } }` rejects anything lossy but
|
|
60
|
+
* tolerates approximated opacity; `{ rules: { 'long-path-data': 'warn' } }` enables that hint.
|
|
61
|
+
*/
|
|
62
|
+
rules?: Partial<Record<WarningCode, Severity>>;
|
|
63
|
+
/** Indentation width (spaces). @default 4 */
|
|
64
|
+
indent?: number;
|
|
65
|
+
/** Prepend an XML declaration (`<?xml version="1.0" encoding="utf-8"?>`). @default false */
|
|
66
|
+
xmlTag?: boolean;
|
|
67
|
+
/** Add `android:tint` to the `<vector>`. Android color literal (e.g. `#AARRGGBB`), passed verbatim. */
|
|
68
|
+
tint?: string;
|
|
69
|
+
/** Called for every warning as it happens (in addition to the returned list). */
|
|
70
|
+
onWarn?: (warning: Warning) => void;
|
|
71
|
+
/**
|
|
72
|
+
* The app's `minSdk`: when the output needs a higher API level (see `ConvertResult.minSdk`),
|
|
73
|
+
* a `min-sdk-exceeded` warning names the features responsible. Unset: no check.
|
|
74
|
+
*/
|
|
75
|
+
minSdk?: number;
|
|
76
|
+
}
|
|
77
|
+
interface ConvertResult {
|
|
78
|
+
/** The generated Android VectorDrawable XML. */
|
|
79
|
+
xml: string;
|
|
80
|
+
/** All non-fatal issues encountered. */
|
|
81
|
+
warnings: Warning[];
|
|
82
|
+
/**
|
|
83
|
+
* Lowest Android API level that renders the output natively: 24 when it uses gradients
|
|
84
|
+
* (`<aapt:attr>` complex colors) or `android:fillType`, otherwise 21 (VectorDrawable itself).
|
|
85
|
+
*/
|
|
86
|
+
minSdk: number;
|
|
87
|
+
}
|
|
88
|
+
/** An RGBA color expressed as Android `#AARRGGBB`. */
|
|
89
|
+
type AndroidColor = `#${string}`;
|
|
90
|
+
|
|
91
|
+
/** Thrown when a warning's severity resolves to `'error'` (via `strict` or `rules`). */
|
|
92
|
+
declare class ConversionError extends Error {
|
|
93
|
+
/** The warning that stopped the conversion. */
|
|
94
|
+
readonly warning: Warning;
|
|
95
|
+
constructor(warning: Warning);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* VectorDrawable → SVG preview: re-serializes a VectorDrawable XML string into a standalone SVG string
|
|
100
|
+
* that renders the same picture, to preview a drawable in a browser, an image viewer or a PR review.
|
|
101
|
+
*
|
|
102
|
+
* Android semantics reproduced here (AndroidX `VectorDrawableCompat` / framework `VectorDrawable`):
|
|
103
|
+
* - `<vector>`: the viewport is stretched to width × height (no aspect preservation), `android:alpha`
|
|
104
|
+
* applies to the whole drawing. `android:tint` / `android:tintMode` are ignored unless
|
|
105
|
+
* {@link PreviewOptions.applyTint} is set (the default `src_in` mode recolors every pixel).
|
|
106
|
+
* - `<group>`: local matrix = T(translate + pivot) · R(rotation) · S(scale) · T(−pivot), i.e. Android
|
|
107
|
+
* applies scale → rotate → translate around the pivot.
|
|
108
|
+
* - `<clip-path>`: clips every *subsequent* sibling of its group (and their descendants); several
|
|
109
|
+
* clip-paths in a group, or nested groups, intersect. Clip paths use the non-zero rule.
|
|
110
|
+
* - `<path>`: no fill unless `fillColor`; no stroke unless `strokeColor` and `strokeWidth` > 0;
|
|
111
|
+
* `fillAlpha` / `strokeAlpha` multiply the color alpha (or the gradient); defaults butt / miter / 4.
|
|
112
|
+
* - `<aapt:attr name="android:fillColor|strokeColor"><gradient>`: linear / radial gradients in the
|
|
113
|
+
* path's coordinate space (= SVG `userSpaceOnUse`), `tileMode` clamp / repeated / mirror.
|
|
114
|
+
*
|
|
115
|
+
* Unsupported input throws an `Error` naming the construct: sweep gradients (no SVG equivalent),
|
|
116
|
+
* resource / theme references instead of color literals (`@color/…`, `?attr/…`), unknown elements,
|
|
117
|
+
* malformed XML, a missing or non-positive viewport. `trimPathStart` / `trimPathEnd` /
|
|
118
|
+
* `trimPathOffset` (never produced by the converter) are ignored.
|
|
119
|
+
*
|
|
120
|
+
* Deliberately self-contained (its own tiny XML parser, no import from the converter): the test
|
|
121
|
+
* harness uses it to validate the converter's output, so a converter bug cannot be masked by shared
|
|
122
|
+
* code. It has no Node-only dependency and is exported from the browser entry too.
|
|
123
|
+
*/
|
|
124
|
+
/** Options of {@link vectorDrawableToSvg}. */
|
|
125
|
+
interface PreviewOptions {
|
|
126
|
+
/**
|
|
127
|
+
* Pixels per dp for the SVG `width` / `height` (default `1`, i.e. mdpi: `24dp` → `24`). Use e.g.
|
|
128
|
+
* `4` for an xxxhdpi-sized preview. The viewBox is the vector's viewport whatever the density.
|
|
129
|
+
*/
|
|
130
|
+
density?: number;
|
|
131
|
+
/**
|
|
132
|
+
* Apply the vector's `android:tint` (color literal only) with its `android:tintMode` (default
|
|
133
|
+
* `src_in`; `src_over`, `src_atop`, `multiply`, `screen`, `add` supported) as an SVG filter.
|
|
134
|
+
* Default `false`: the tint is ignored and the drawing keeps its own colors.
|
|
135
|
+
*/
|
|
136
|
+
applyTint?: boolean;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Converts a VectorDrawable XML string into an equivalent standalone SVG string (preview).
|
|
140
|
+
*
|
|
141
|
+
* The SVG `width` / `height` are the vector's `android:width` / `android:height` in dp times
|
|
142
|
+
* `options.density` (default 1), its `viewBox` the viewport, stretched with `preserveAspectRatio="none"`
|
|
143
|
+
* like Android. See the module documentation for the reproduced semantics and the unsupported input,
|
|
144
|
+
* which throws an `Error` (e.g. a sweep gradient or a `@color/…` reference).
|
|
145
|
+
*
|
|
146
|
+
* ```ts
|
|
147
|
+
* import { convert, vectorDrawableToSvg } from 'svg-vectordrawable';
|
|
148
|
+
* const preview = vectorDrawableToSvg(convert(svg).xml, { density: 4 });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function vectorDrawableToSvg(xml: string, options?: PreviewOptions): string;
|
|
152
|
+
|
|
153
|
+
/** Options of the lite build: no svgo normalization, hence no `svgoConfig` and `optimize` false. */
|
|
154
|
+
type LiteConvertOptions = Omit<ConvertOptions, 'optimize' | 'svgoConfig'> & {
|
|
155
|
+
/** Always false in the lite build; `true` throws (use `svg-vectordrawable/browser`). */
|
|
156
|
+
optimize?: false;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/** Same as the main `convert`, with `optimize` forced to `false`. */
|
|
160
|
+
declare function convert(svg: string, options?: LiteConvertOptions): ConvertResult;
|
|
161
|
+
|
|
162
|
+
export { type AndroidColor, ConversionError, type LiteConvertOptions as ConvertOptions, type ConvertResult, type LiteConvertOptions, type PreviewOptions, type Severity, type StrictMode, WARNING_CATEGORIES, WARNING_CODES, type Warning, type WarningCategory, type WarningCode, convert, vectorDrawableToSvg };
|