diff --git a/src/helpers.ts b/src/helpers.ts index 2ed96b10..736b5fa3 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -235,6 +235,26 @@ function toPng(pipeline: sharp.Sharp): Promise { return pipeline.png().toBuffer(); } +async function createSvg( + sourceset: SourceImage[], + options: IconPlaneOptions +): Promise { + const { width, height } = options; + const source = bestSource(sourceset, width, height); + if (source.metadata.format === "svg") { + return source.data; + } else { + const pipeline = await createPlane(sourceset, options); + const png = await toPng(pipeline); + const encodedPng = png.toString("base64"); + return Buffer.from( + ` + +` + ); + } +} + export async function createFavicon( sourceset: SourceImage[], name: string, @@ -248,6 +268,9 @@ export async function createFavicon( ); const contents = toIco(images); return { name, contents }; + } else if (path.extname(name) === ".svg") { + const contents = await createSvg(sourceset, properties[0]); + return { name, contents }; } else { const contents = await createPlane(sourceset, properties[0]).then(toPng); return { name, contents }; diff --git a/src/platforms/favicons.ts b/src/platforms/favicons.ts index 08a3c47f..d355fe6c 100644 --- a/src/platforms/favicons.ts +++ b/src/platforms/favicons.ts @@ -8,6 +8,7 @@ const ICONS_OPTIONS: Record = { "favicon-16x16.png": transparentIcon(16), "favicon-32x32.png": transparentIcon(32), "favicon-48x48.png": transparentIcon(48), + "favicon.svg": transparentIcon(1024), // arbitrary size. if more than one svg source is given, the closest to this size will be picked. }; export class FaviconsPlatform extends Platform { @@ -24,6 +25,10 @@ export class FaviconsPlatform extends Platform { return ``; + } else if (name.endsWith(".svg")) { + return ``; } const { width, height } = options.sizes[0]; diff --git a/test/__snapshots__/array.test.js.snap b/test/__snapshots__/array.test.js.snap index 24206e13..5d7534ef 100644 --- a/test/__snapshots__/array.test.js.snap +++ b/test/__snapshots__/array.test.js.snap @@ -107,6 +107,7 @@ Object { "", "", "", + "", "", "", "", @@ -173,6 +174,13 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", @@ -500,6 +508,7 @@ Object { "", "", "", + "", "", "", "", @@ -566,6 +575,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/__snapshots__/background.test.js.snap b/test/__snapshots__/background.test.js.snap index 50d4ae1d..368bd39e 100644 --- a/test/__snapshots__/background.test.js.snap +++ b/test/__snapshots__/background.test.js.snap @@ -107,6 +107,7 @@ Object { "", "", "", + "", "", "", "", @@ -173,6 +174,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/__snapshots__/default.test.js.snap b/test/__snapshots__/default.test.js.snap index a4cdec21..54af57b9 100644 --- a/test/__snapshots__/default.test.js.snap +++ b/test/__snapshots__/default.test.js.snap @@ -107,6 +107,7 @@ Object { "", "", "", + "", "", "", "", @@ -173,6 +174,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/__snapshots__/manifestMaskable.test.js.snap b/test/__snapshots__/manifestMaskable.test.js.snap index 8195761b..61b9eb3a 100644 --- a/test/__snapshots__/manifestMaskable.test.js.snap +++ b/test/__snapshots__/manifestMaskable.test.js.snap @@ -161,6 +161,7 @@ Object { "", "", "", + "", "", "", "", @@ -227,6 +228,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", @@ -590,6 +597,7 @@ Object { "", "", "", + "", "", "", "", @@ -656,6 +664,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/__snapshots__/meta.test.js.snap b/test/__snapshots__/meta.test.js.snap index d5f93ecc..195c093d 100644 --- a/test/__snapshots__/meta.test.js.snap +++ b/test/__snapshots__/meta.test.js.snap @@ -108,6 +108,7 @@ Object { "", "", "", + "", "", "", "", @@ -174,6 +175,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/__snapshots__/offset.test.js.snap b/test/__snapshots__/offset.test.js.snap index b2867ace..1af67d37 100644 --- a/test/__snapshots__/offset.test.js.snap +++ b/test/__snapshots__/offset.test.js.snap @@ -107,6 +107,7 @@ Object { "", "", "", + "", "", "", "", @@ -173,6 +174,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/__snapshots__/pixelart.test.js.snap b/test/__snapshots__/pixelart.test.js.snap index 90828a02..39b8c1e5 100644 --- a/test/__snapshots__/pixelart.test.js.snap +++ b/test/__snapshots__/pixelart.test.js.snap @@ -107,6 +107,7 @@ Object { "", "", "", + "", "", "", "", @@ -173,6 +174,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/__snapshots__/prefixed.test.js.snap b/test/__snapshots__/prefixed.test.js.snap index 09bc98c9..60f33508 100644 --- a/test/__snapshots__/prefixed.test.js.snap +++ b/test/__snapshots__/prefixed.test.js.snap @@ -107,6 +107,7 @@ Object { "", "", "", + "", "", "", "", @@ -173,6 +174,12 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/__snapshots__/svg.test.js.snap b/test/__snapshots__/svg.test.js.snap index a794a889..1ffa7e7a 100644 --- a/test/__snapshots__/svg.test.js.snap +++ b/test/__snapshots__/svg.test.js.snap @@ -107,6 +107,7 @@ Object { "", "", "", + "", "", "", "", @@ -173,6 +174,13 @@ Object { "contents": null, "name": "favicon-48x48.png", }, + Object { + "contents": " + + +", + "name": "favicon.svg", + }, Object { "contents": null, "name": "android-chrome-36x36.png", diff --git a/test/setup.js b/test/setup.js index 641008bc..c0d798a6 100644 --- a/test/setup.js +++ b/test/setup.js @@ -24,9 +24,17 @@ async function imagePlanes(image) { return result; } +function isSvg(image) { + return path.extname(image.name) === ".svg"; +} + expect.extend({ async toMatchFaviconsSnapshot(received) { for (const image of received.images) { + if (isSvg(image)) { + continue; + } + const planes = await imagePlanes(image); for (const plane of planes) { @@ -46,7 +54,7 @@ expect.extend({ ...received, images: received.images.map((image) => ({ ...image, - contents: null, + contents: isSvg(image) ? image.contents.toString("utf-8") : null, })), };