@dicebear/converter 10.0.0-rc.1 → 10.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/core.js +24 -3
- package/lib/node/core.js +25 -2
- package/lib/utils/mime-type.d.ts +3 -0
- package/lib/utils/mime-type.js +3 -0
- package/lib/utils/svg.d.ts +8 -0
- package/lib/utils/svg.js +16 -0
- package/package.json +2 -2
package/lib/core.js
CHANGED
|
@@ -12,6 +12,12 @@ export const toWebp = (avatar, options = {}) => {
|
|
|
12
12
|
export const toAvif = (avatar, options = {}) => {
|
|
13
13
|
return toFormat(avatar, 'avif', options);
|
|
14
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Browser conversion entry point. Returns a {@link Result} with `toDataUri()`
|
|
17
|
+
* and `toArrayBuffer()` methods that lazily render the avatar to the chosen
|
|
18
|
+
* raster format. Warns when `includeExif` is set, since Exif metadata is
|
|
19
|
+
* only supported by the Node build.
|
|
20
|
+
*/
|
|
15
21
|
function toFormat(avatar, format, options = {}) {
|
|
16
22
|
if (options.includeExif) {
|
|
17
23
|
console.warn('The `exif` option is not supported in the browser version of `@dicebear/converter`. \n' +
|
|
@@ -23,6 +29,10 @@ function toFormat(avatar, format, options = {}) {
|
|
|
23
29
|
toArrayBuffer: () => toArrayBuffer(svg, format, options),
|
|
24
30
|
};
|
|
25
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Returns a `data:` URI for the rendered avatar. The `svg` format is
|
|
34
|
+
* fast-pathed; other formats go through a `<canvas>` rasterization step.
|
|
35
|
+
*/
|
|
26
36
|
async function toDataUri(svg, format, options) {
|
|
27
37
|
if ('svg' === format) {
|
|
28
38
|
return `data:${getMimeType(format)};utf8,${encodeURIComponent(svg)}`;
|
|
@@ -30,16 +40,27 @@ async function toDataUri(svg, format, options) {
|
|
|
30
40
|
const canvas = await toCanvas(svg, format, options);
|
|
31
41
|
return canvas.toDataURL(getMimeType(format));
|
|
32
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Returns the rasterized avatar as a raw `ArrayBuffer` by routing the canvas
|
|
45
|
+
* through `canvas.toBlob`.
|
|
46
|
+
*/
|
|
33
47
|
async function toArrayBuffer(rawSvg, format, options) {
|
|
34
48
|
const canvas = await toCanvas(rawSvg, format, options);
|
|
35
49
|
return await new Promise((resolve, reject) => {
|
|
36
50
|
canvas.toBlob((blob) => {
|
|
37
|
-
blob
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
if (blob) {
|
|
52
|
+
resolve(blob.arrayBuffer());
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
reject(new Error('Could not create blob'));
|
|
56
|
+
}
|
|
40
57
|
}, getMimeType(format));
|
|
41
58
|
});
|
|
42
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Renders the SVG into a fresh `<canvas>` of the requested size. JPEG output
|
|
62
|
+
* gets a white background fill so transparent regions don't render black.
|
|
63
|
+
*/
|
|
43
64
|
async function toCanvas(rawSvg, format, options) {
|
|
44
65
|
const { svg, size } = ensureSize(rawSvg, options.size);
|
|
45
66
|
const canvas = document.createElement('canvas');
|
package/lib/node/core.js
CHANGED
|
@@ -17,6 +17,12 @@ export const toWebp = (avatar, options = {}) => {
|
|
|
17
17
|
export const toAvif = (avatar, options = {}) => {
|
|
18
18
|
return toFormat(avatar, 'avif', options);
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Node conversion entry point. Returns a {@link Result} with `toDataUri()`
|
|
22
|
+
* and `toArrayBuffer()` methods that lazily render the avatar via resvg +
|
|
23
|
+
* sharp, optionally embedding Exif metadata derived from the SVG's
|
|
24
|
+
* `<metadata>` block.
|
|
25
|
+
*/
|
|
20
26
|
function toFormat(avatar, format, options) {
|
|
21
27
|
var _a;
|
|
22
28
|
const svg = typeof avatar === 'string' ? avatar : avatar.toString();
|
|
@@ -27,6 +33,10 @@ function toFormat(avatar, format, options) {
|
|
|
27
33
|
toArrayBuffer: () => toArrayBuffer(svg, format, exif, options),
|
|
28
34
|
};
|
|
29
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Returns a `data:` URI for the rendered avatar. The `svg` format is
|
|
38
|
+
* fast-pathed; raster formats are base64-encoded.
|
|
39
|
+
*/
|
|
30
40
|
async function toDataUri(svg, format, exif, options) {
|
|
31
41
|
if (format === 'svg') {
|
|
32
42
|
return `data:${getMimeType(format)};utf8,${encodeURIComponent(svg)}`;
|
|
@@ -34,9 +44,17 @@ async function toDataUri(svg, format, exif, options) {
|
|
|
34
44
|
const buffer = await toBuffer(svg, format, exif, options);
|
|
35
45
|
return `data:${getMimeType(format)};base64,${buffer.toString('base64')}`;
|
|
36
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns the rasterized avatar as a raw `ArrayBuffer` by unwrapping the
|
|
49
|
+
* underlying Node `Buffer`.
|
|
50
|
+
*/
|
|
37
51
|
async function toArrayBuffer(rawSvg, format, exif, options) {
|
|
38
52
|
return (await toBuffer(rawSvg, format, exif, options)).buffer;
|
|
39
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Renders the SVG via resvg-js, optionally re-encodes through sharp for
|
|
56
|
+
* non-PNG formats, and writes Exif metadata using exiftool when present.
|
|
57
|
+
*/
|
|
40
58
|
async function toBuffer(rawSvg, format, exif, options) {
|
|
41
59
|
const hasFonts = Array.isArray(options.fonts);
|
|
42
60
|
const { svg, size } = ensureSize(rawSvg, options.size);
|
|
@@ -63,8 +81,13 @@ async function toBuffer(rawSvg, format, exif, options) {
|
|
|
63
81
|
}
|
|
64
82
|
return buffer;
|
|
65
83
|
}
|
|
66
|
-
|
|
67
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Maps the SVG's embedded `<metadata>` block to an Exif tag set covering
|
|
86
|
+
* IPTC-PhotoMetadata and Google's image license metadata schemas.
|
|
87
|
+
*
|
|
88
|
+
* @see https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata
|
|
89
|
+
* @see https://developers.google.com/search/docs/appearance/structured-data/image-license-metadata
|
|
90
|
+
*/
|
|
68
91
|
function getExif(svg) {
|
|
69
92
|
const metadata = getMetadata(svg);
|
|
70
93
|
const exif = {};
|
package/lib/utils/mime-type.d.ts
CHANGED
package/lib/utils/mime-type.js
CHANGED
package/lib/utils/svg.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { Metadata } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Re-emits the SVG with explicit `width`/`height` attributes set to the
|
|
4
|
+
* sanitized size, so downstream rasterizers know how large to render.
|
|
5
|
+
*/
|
|
2
6
|
export declare function ensureSize(svg: string, size?: number): {
|
|
3
7
|
svg: string;
|
|
4
8
|
size: number;
|
|
5
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Extracts the embedded RDF/Dublin Core metadata block from an avatar SVG
|
|
12
|
+
* into a flat {@link Metadata} object. Missing fields become `undefined`.
|
|
13
|
+
*/
|
|
6
14
|
export declare function getMetadata(svg: string): Metadata;
|
package/lib/utils/svg.js
CHANGED
|
@@ -12,12 +12,20 @@ const xmlRoundTripOptions = {
|
|
|
12
12
|
};
|
|
13
13
|
const xmlRoundTripParser = new XMLParser(xmlRoundTripOptions);
|
|
14
14
|
const xmlRoundTripBuilder = new XMLBuilder(xmlRoundTripOptions);
|
|
15
|
+
/**
|
|
16
|
+
* Clamps a requested size into a sane integer range, falling back to
|
|
17
|
+
* `DEFAULT_SIZE` for non-finite or non-positive inputs.
|
|
18
|
+
*/
|
|
15
19
|
function sanitizeSize(size) {
|
|
16
20
|
if (!Number.isFinite(size) || size <= 0) {
|
|
17
21
|
return DEFAULT_SIZE;
|
|
18
22
|
}
|
|
19
23
|
return Math.floor(Math.min(size, MAX_SIZE));
|
|
20
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Re-emits the SVG with explicit `width`/`height` attributes set to the
|
|
27
|
+
* sanitized size, so downstream rasterizers know how large to render.
|
|
28
|
+
*/
|
|
21
29
|
export function ensureSize(svg, size = DEFAULT_SIZE) {
|
|
22
30
|
var _a;
|
|
23
31
|
size = sanitizeSize(size);
|
|
@@ -31,12 +39,20 @@ export function ensureSize(svg, size = DEFAULT_SIZE) {
|
|
|
31
39
|
svg = xmlRoundTripBuilder.build(parsed);
|
|
32
40
|
return { svg, size };
|
|
33
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Returns a non-empty string truncated to {@link MAX_METADATA_LENGTH}, or
|
|
44
|
+
* `undefined` for non-string or empty input.
|
|
45
|
+
*/
|
|
34
46
|
function sanitizeMetadataValue(value) {
|
|
35
47
|
if (typeof value !== 'string' || value.length === 0) {
|
|
36
48
|
return undefined;
|
|
37
49
|
}
|
|
38
50
|
return value.slice(0, MAX_METADATA_LENGTH);
|
|
39
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Extracts the embedded RDF/Dublin Core metadata block from an avatar SVG
|
|
54
|
+
* into a flat {@link Metadata} object. Missing fields become `undefined`.
|
|
55
|
+
*/
|
|
40
56
|
export function getMetadata(svg) {
|
|
41
57
|
var _a, _b;
|
|
42
58
|
const parser = new XMLParser();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dicebear/converter",
|
|
3
|
-
"version": "10.0.0-rc.
|
|
3
|
+
"version": "10.0.0-rc.3",
|
|
4
4
|
"description": "SVG Converter for DiceBear",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dicebear"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@resvg/resvg-js": "^2.6.2",
|
|
40
40
|
"exiftool-vendored": "^35.5.0",
|
|
41
|
-
"fast-xml-parser": "^5.
|
|
41
|
+
"fast-xml-parser": "^5.7.1",
|
|
42
42
|
"sharp": "^0.34.5",
|
|
43
43
|
"tmp-promise": "^3.0.3"
|
|
44
44
|
},
|