From e2746ef39f5f2ca2d45ab3a081edf4f7200a5b98 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:14:58 -0800 Subject: [PATCH] feat: set intrinsic width and height for SVGs (#13126) --- .changeset/tricky-squids-provide.md | 5 + packages/enhanced-img/package.json | 1 + packages/enhanced-img/src/preprocessor.js | 74 +++--- packages/enhanced-img/test/Input.svelte | 2 - packages/enhanced-img/test/Output.svelte | 6 +- .../enhanced-img/test/preprocessor.spec.js | 2 +- playgrounds/basic/package.json | 1 + playgrounds/basic/src/routes/+page.svelte | 6 + .../basic/src/routes/about/+page.svelte | 1 - .../basic/src/routes/images/+page.svelte | 11 + .../src/routes/images/state-of-js-chart.png | Bin 0 -> 190480 bytes .../basic/src/routes/images/svelte-logo.svg | 1 + playgrounds/basic/vite.config.js | 3 +- pnpm-lock.yaml | 216 +++++++++--------- 14 files changed, 169 insertions(+), 160 deletions(-) create mode 100644 .changeset/tricky-squids-provide.md delete mode 100644 playgrounds/basic/src/routes/about/+page.svelte create mode 100644 playgrounds/basic/src/routes/images/+page.svelte create mode 100644 playgrounds/basic/src/routes/images/state-of-js-chart.png create mode 100644 playgrounds/basic/src/routes/images/svelte-logo.svg diff --git a/.changeset/tricky-squids-provide.md b/.changeset/tricky-squids-provide.md new file mode 100644 index 000000000000..d15da40874d9 --- /dev/null +++ b/.changeset/tricky-squids-provide.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/enhanced-img': patch +--- + +feat: set intrinsic width and height for SVGs diff --git a/packages/enhanced-img/package.json b/packages/enhanced-img/package.json index 4fc2bbc76dcb..41157706762f 100644 --- a/packages/enhanced-img/package.json +++ b/packages/enhanced-img/package.json @@ -37,6 +37,7 @@ "types": "types/index.d.ts", "dependencies": { "magic-string": "^0.30.5", + "sharp": "^0.33.5", "svelte-parse-markup": "^0.1.5", "vite-imagetools": "^7.0.1", "zimmerframe": "^1.1.2" diff --git a/packages/enhanced-img/src/preprocessor.js b/packages/enhanced-img/src/preprocessor.js index 7331cff18e11..de800b653734 100644 --- a/packages/enhanced-img/src/preprocessor.js +++ b/packages/enhanced-img/src/preprocessor.js @@ -4,8 +4,9 @@ import { existsSync } from 'node:fs'; import * as path from 'node:path'; import MagicString from 'magic-string'; -import { walk } from 'zimmerframe'; +import sharp from 'sharp'; import { parse } from 'svelte-parse-markup'; +import { walk } from 'zimmerframe'; // TODO: expose this in vite-imagetools rather than duplicating it const OPTIMIZABLE = /^[^?]+\.(avif|heif|gif|jpeg|jpg|png|tiff|webp)(\?.*)?$/; @@ -70,33 +71,36 @@ export function image(opts) { const original_url = src_attribute.raw.trim(); let url = original_url; - const sizes = get_attr_value(node, 'sizes'); - const width = get_attr_value(node, 'width'); - url += url.includes('?') ? '&' : '?'; - if (sizes && 'raw' in sizes) { - url += 'imgSizes=' + encodeURIComponent(sizes.raw) + '&'; - } - if (width && 'raw' in width) { - url += 'imgWidth=' + encodeURIComponent(width.raw) + '&'; + if (OPTIMIZABLE.test(url)) { + const sizes = get_attr_value(node, 'sizes'); + const width = get_attr_value(node, 'width'); + url += url.includes('?') ? '&' : '?'; + if (sizes && 'raw' in sizes) { + url += 'imgSizes=' + encodeURIComponent(sizes.raw) + '&'; + } + if (width && 'raw' in width) { + url += 'imgWidth=' + encodeURIComponent(width.raw) + '&'; + } + url += 'enhanced'; } - url += 'enhanced'; - if (OPTIMIZABLE.test(url)) { - // resolves the import so that we can build the entire picture template string and don't - // need any logic blocks - const resolved_id = (await opts.plugin_context.resolve(url, filename))?.id; - if (!resolved_id) { - const file_path = url.substring(0, url.indexOf('?')); - if (existsSync(path.resolve(opts.vite_config.publicDir, file_path))) { - throw new Error( - `Could not locate ${file_path}. Please move it to be located relative to the page in the routes directory or reference it beginning with /static/. See https://vitejs.dev/guide/assets for more details on referencing assets.` - ); - } + // resolves the import so that we can build the entire picture template string and don't + // need any logic blocks + const resolved_id = (await opts.plugin_context.resolve(url, filename))?.id; + if (!resolved_id) { + const query_index = url.indexOf('?'); + const file_path = query_index >= 0 ? url.substring(0, query_index) : url; + if (existsSync(path.resolve(opts.vite_config.publicDir, file_path))) { throw new Error( - `Could not locate ${file_path}. See https://vitejs.dev/guide/assets for more details on referencing assets.` + `Could not locate ${file_path}. Please move it to be located relative to the page in the routes directory or reference it beginning with /static/. See https://vitejs.dev/guide/assets for more details on referencing assets.` ); } + throw new Error( + `Could not locate ${file_path}. See https://vitejs.dev/guide/assets for more details on referencing assets.` + ); + } + if (OPTIMIZABLE.test(url)) { let image = images.get(resolved_id); if (!image) { image = await process(resolved_id, opts); @@ -104,17 +108,14 @@ export function image(opts) { } s.update(node.start, node.end, img_to_picture(content, node, image)); } else { - // e.g. => const name = '__IMPORTED_ASSET_' + imports.size + '__'; - const { start, end } = src_attribute; - // update src with reference to imported asset - s.update( - is_quote(content, start - 1) ? start - 1 : start, - is_quote(content, end) ? end + 1 : end, - `{${name}}` - ); - // update `enhanced:img` to `img` - s.update(node.start + 1, node.start + 1 + 'enhanced:img'.length, 'img'); + const metadata = await sharp(resolved_id).metadata(); + const new_markup = ``; + s.update(node.start, node.end, new_markup); imports.set(original_url, name); } } @@ -175,15 +176,6 @@ export function image(opts) { }; } -/** - * @param {string} content - * @param {number} index - * @returns {boolean} - */ -function is_quote(content, index) { - return content.charAt(index) === '"' || content.charAt(index) === "'"; -} - /** * @param {string} resolved_id * @param {{ diff --git a/packages/enhanced-img/test/Input.svelte b/packages/enhanced-img/test/Input.svelte index 3a29902d0930..35fd9c59901d 100644 --- a/packages/enhanced-img/test/Input.svelte +++ b/packages/enhanced-img/test/Input.svelte @@ -45,8 +45,6 @@ - - {#each images as image} {/each} diff --git a/packages/enhanced-img/test/Output.svelte b/packages/enhanced-img/test/Output.svelte index 4d8bcc402272..d8c18c1ad88f 100644 --- a/packages/enhanced-img/test/Output.svelte +++ b/packages/enhanced-img/test/Output.svelte @@ -1,6 +1,4 @@ -