fix(image): allow usage of image from any directory (#5932)

Currently, @astrojs/image allows *importing* images from srcDir
only. Importing images from outside srcDir fails miserably *in dev
mode* and produces incorrect src.

This happens because `path.relative(fileURLToPath(config.srcDir), id)`
resolves to "../something" and when joined with '/@astroimage' cancels
it out (`join('/@astroimage', '../../something')` => `'/something'`).

Rework /@astroimage URL scheme to be similar to "/@fs/" scheme—always
export absolute path to the target file.
This commit is contained in:
Alexey Shmalko 2023-01-30 22:29:41 +02:00 committed by Matthew Phillips
parent dc37849f1d
commit c54a115e29
14 changed files with 173 additions and 45 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/image': minor
---
Allow images from outside srcDir

View file

@ -47,8 +47,7 @@
"image-size": "^1.0.2", "image-size": "^1.0.2",
"kleur": "^4.1.5", "kleur": "^4.1.5",
"magic-string": "^0.27.0", "magic-string": "^0.27.0",
"mime": "^3.0.0", "mime": "^3.0.0"
"slash": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/http-cache-semantics": "^4.0.1", "@types/http-cache-semantics": "^4.0.1",

View file

@ -1,10 +1,9 @@
import type { AstroConfig } from 'astro'; import type { AstroConfig } from 'astro';
import MagicString from 'magic-string'; import MagicString from 'magic-string';
import fs from 'node:fs/promises'; import fs from 'node:fs/promises';
import path, { basename, extname, join } from 'node:path'; import { basename, extname, join } from 'node:path';
import { Readable } from 'node:stream'; import { Readable } from 'node:stream';
import { fileURLToPath, pathToFileURL } from 'node:url'; import { fileURLToPath, pathToFileURL } from 'node:url';
import slash from 'slash';
import type { Plugin, ResolvedConfig } from 'vite'; import type { Plugin, ResolvedConfig } from 'vite';
import type { IntegrationOptions } from './index.js'; import type { IntegrationOptions } from './index.js';
import type { InputFormat } from './loaders/index.js'; import type { InputFormat } from './loaders/index.js';
@ -65,12 +64,7 @@ export function createPlugin(config: AstroConfig, options: Required<IntegrationO
meta.src = `__ASTRO_IMAGE_ASSET__${handle}__`; meta.src = `__ASTRO_IMAGE_ASSET__${handle}__`;
} else { } else {
const relId = path.relative(fileURLToPath(config.srcDir), id); meta.src = '/@astroimage' + url.pathname;
meta.src = join('/@astroimage', relId);
// Windows compat
meta.src = slash(meta.src);
} }
return `export default ${JSON.stringify(meta)}`; return `export default ${JSON.stringify(meta)}`;
@ -78,9 +72,9 @@ export function createPlugin(config: AstroConfig, options: Required<IntegrationO
configureServer(server) { configureServer(server) {
server.middlewares.use(async (req, res, next) => { server.middlewares.use(async (req, res, next) => {
if (req.url?.startsWith('/@astroimage/')) { if (req.url?.startsWith('/@astroimage/')) {
const [, id] = req.url.split('/@astroimage/'); // Reconstructing URL to get rid of query parameters in path
const url = new URL(req.url.slice('/@astroimage'.length), 'file:');
const url = new URL(id, config.srcDir);
const file = await fs.readFile(url); const file = await fs.readFile(url);
const meta = await metadata(url); const meta = await metadata(url);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View file

@ -1,6 +1,7 @@
--- ---
import socialJpg from '../assets/social.jpg'; import socialJpg from '../assets/social.jpg';
import introJpg from '../assets/blog/introducing astro.jpg'; import introJpg from '../assets/blog/introducing astro.jpg';
import outsideSrc from '../../social.png';
import { Image } from '@astrojs/image/components'; import { Image } from '@astrojs/image/components';
const publicImage = new URL('./hero.jpg', Astro.url); const publicImage = new URL('./hero.jpg', Astro.url);
--- ---
@ -18,6 +19,8 @@ const publicImage = new URL('./hero.jpg', Astro.url);
<br /> <br />
<Image id="no-transforms" src={socialJpg} alt="no-transforms" /> <Image id="no-transforms" src={socialJpg} alt="no-transforms" />
<br /> <br />
<Image id="outside-src" src={outsideSrc} alt="outside-src" />
<br />
<Image id="google" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" width={544} height={184} format="webp" alt="Google" /> <Image id="google" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" width={544} height={184} format="webp" alt="Google" />
<br /> <br />
<Image id="inline" src={import('../assets/social.jpg')} width={506} alt="inline" /> <Image id="inline" src={import('../assets/social.jpg')} width={506} alt="inline" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View file

@ -1,6 +1,7 @@
--- ---
import socialJpg from '../assets/social.jpg'; import socialJpg from '../assets/social.jpg';
import introJpg from '../assets/blog/introducing astro.jpg'; import introJpg from '../assets/blog/introducing astro.jpg';
import outsideSrc from '../../social.png';
import { Picture } from '@astrojs/image/components'; import { Picture } from '@astrojs/image/components';
const publicImage = new URL('./hero.jpg', Astro.url); const publicImage = new URL('./hero.jpg', Astro.url);
--- ---
@ -14,6 +15,8 @@ const publicImage = new URL('./hero.jpg', Astro.url);
<br /> <br />
<Picture id="spaces" src={introJpg} sizes="100vw" widths={[384, 768]} aspectRatio={768/414} alt="spaces" /> <Picture id="spaces" src={introJpg} sizes="100vw" widths={[384, 768]} aspectRatio={768/414} alt="spaces" />
<br /> <br />
<Picture id="outside-src" src={outsideSrc} sizes="100vw" widths={[384, 768]} aspectRatio={768/414} alt="outside-src" />
<br />
<Picture id="social-jpg" src={socialJpg} sizes="(min-width: 640px) 50vw, 100vw" widths={[253, 506]} alt="Social image" /> <Picture id="social-jpg" src={socialJpg} sizes="(min-width: 640px) 50vw, 100vw" widths={[253, 506]} alt="Social image" />
<br /> <br />
<Picture id="google" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" sizes="(min-width: 640px) 50vw, 100vw" widths={[272, 544]} aspectRatio={544/184} alt="Google logo" formats={["avif", "webp", "png"]} /> <Picture id="google" src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" sizes="(min-width: 640px) 50vw, 100vw" widths={[272, 544]} aspectRatio={544/184} alt="Google logo" formats={["avif", "webp", "png"]} />

View file

@ -2,9 +2,13 @@ import { expect } from 'chai';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import sizeOf from 'image-size'; import sizeOf from 'image-size';
import fs from 'fs/promises'; import fs from 'fs/promises';
import { fileURLToPath } from 'url'; import { fileURLToPath, pathToFileURL } from 'node:url';
import { join } from 'node:path';
import { loadFixture } from './test-utils.js'; import { loadFixture } from './test-utils.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const toAstroImage = (relpath) => '/@astroimage' + pathToFileURL(join(__dirname, 'fixtures/basic-image', relpath)).pathname;
describe('SSG images - dev', function () { describe('SSG images - dev', function () {
let fixture; let fixture;
let devServer; let devServer;
@ -25,25 +29,32 @@ describe('SSG images - dev', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
}, },
{ {
title: 'Local image no transforms', title: 'Local image no transforms',
id: '#no-transforms', id: '#no-transforms',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: {}, query: {},
}, },
{ {
title: 'Filename with spaces', title: 'Filename with spaces',
id: '#spaces', id: '#spaces',
url: '/@astroimage/assets/blog/introducing astro.jpg', url: toAstroImage('src/assets/blog/introducing astro.jpg'),
query: { f: 'webp', w: '768', h: '414' }, query: { f: 'webp', w: '768', h: '414' },
}, },
{
title: 'File outside src',
id: '#outside-src',
url: toAstroImage('social.png'),
query: { f: 'png', w: '2024', h: '1012' },
contentType: 'image/png',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
}, },
{ {
@ -123,19 +134,32 @@ describe('SSG images with subpath - dev', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
}, },
{
title: 'Local image no transforms',
id: '#no-transforms',
url: toAstroImage('src/assets/social.jpg'),
query: {},
},
{ {
title: 'Filename with spaces', title: 'Filename with spaces',
id: '#spaces', id: '#spaces',
url: '/@astroimage/assets/blog/introducing astro.jpg', url: toAstroImage('src/assets/blog/introducing astro.jpg'),
query: { f: 'webp', w: '768', h: '414' }, query: { f: 'webp', w: '768', h: '414' },
}, },
{
title: 'File outside src',
id: '#outside-src',
url: toAstroImage('social.png'),
query: { f: 'png', w: '2024', h: '1012' },
contentType: 'image/png',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
}, },
{ {
@ -210,8 +234,7 @@ describe('SSG images - build', function () {
}); });
function verifyImage(pathname, expected) { function verifyImage(pathname, expected) {
const url = new URL('./fixtures/basic-image/dist/' + pathname, import.meta.url); const dist = join(fileURLToPath(new URL('.', import.meta.url)), 'fixtures/basic-image/dist', pathname);
const dist = fileURLToPath(url);
const result = sizeOf(dist); const result = sizeOf(dist);
expect(result).to.deep.equal(expected); expect(result).to.deep.equal(expected);
} }
@ -229,6 +252,12 @@ describe('SSG images - build', function () {
regex: /^\/_astro\/introducing astro.\w{8}_\w{4,10}.webp/, regex: /^\/_astro\/introducing astro.\w{8}_\w{4,10}.webp/,
size: { width: 768, height: 414, type: 'webp' }, size: { width: 768, height: 414, type: 'webp' },
}, },
{
title: 'File outside src',
id: '#outside-src',
regex: /^\/_astro\/social.\w{8}_\w{4,10}.png/,
size: { type: 'png', width: 2024, height: 1012 },
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
@ -311,6 +340,12 @@ describe('SSG images with subpath - build', function () {
regex: /^\/docs\/_astro\/introducing astro.\w{8}_\w{4,10}.webp/, regex: /^\/docs\/_astro\/introducing astro.\w{8}_\w{4,10}.webp/,
size: { width: 768, height: 414, type: 'webp' }, size: { width: 768, height: 414, type: 'webp' },
}, },
{
title: 'File outside src',
id: '#outside-src',
regex: /^\/docs\/_astro\/social.\w{8}_\w{4,10}.png/,
size: { type: 'png', width: 2024, height: 1012 },
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',

View file

@ -1,8 +1,13 @@
import { expect } from 'chai'; import { expect } from 'chai';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { join } from 'node:path';
import { loadFixture } from './test-utils.js'; import { loadFixture } from './test-utils.js';
import testAdapter from '../../../astro/test/test-adapter.js'; import testAdapter from '../../../astro/test/test-adapter.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const toAstroImage = (relpath) => '/@astroimage' + pathToFileURL(join(__dirname, 'fixtures/basic-image', relpath)).pathname;
describe('SSR images - dev', function () { describe('SSR images - dev', function () {
let fixture; let fixture;
let devServer; let devServer;
@ -28,28 +33,35 @@ describe('SSR images - dev', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
}, },
{ {
title: 'Local image no transforms', title: 'Local image no transforms',
id: '#no-transforms', id: '#no-transforms',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: {}, query: {},
contentType: 'image/jpeg', contentType: 'image/jpeg',
}, },
{ {
title: 'Filename with spaces', title: 'Filename with spaces',
id: '#spaces', id: '#spaces',
url: '/@astroimage/assets/blog/introducing astro.jpg', url: toAstroImage('src/assets/blog/introducing astro.jpg'),
query: { f: 'webp', w: '768', h: '414' }, query: { f: 'webp', w: '768', h: '414' },
contentType: 'image/webp', contentType: 'image/webp',
}, },
{
title: 'File outside src',
id: '#outside-src',
url: toAstroImage('social.png'),
query: { f: 'png', w: '2024', h: '1012' },
contentType: 'image/png',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
}, },
@ -150,21 +162,28 @@ describe('SSR images with subpath - dev', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
}, },
{ {
title: 'Filename with spaces', title: 'Filename with spaces',
id: '#spaces', id: '#spaces',
url: '/@astroimage/assets/blog/introducing astro.jpg', url: toAstroImage('src/assets/blog/introducing astro.jpg'),
query: { f: 'webp', w: '768', h: '414' }, query: { f: 'webp', w: '768', h: '414' },
contentType: 'image/webp', contentType: 'image/webp',
}, },
{
title: 'File outside src',
id: '#outside-src',
url: toAstroImage('social.png'),
query: { f: 'png', w: '2024', h: '1012' },
contentType: 'image/png',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
}, },

View file

@ -3,9 +3,13 @@ import * as cheerio from 'cheerio';
import fs from 'fs'; import fs from 'fs';
import sizeOf from 'image-size'; import sizeOf from 'image-size';
import path from 'path'; import path from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath, pathToFileURL } from 'node:url';
import { join } from 'node:path';
import { loadFixture } from './test-utils.js'; import { loadFixture } from './test-utils.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const toAstroImage = (relpath) => '/@astroimage' + pathToFileURL(join(__dirname, 'fixtures/basic-picture', relpath)).pathname;
describe('SSG pictures - dev', function () { describe('SSG pictures - dev', function () {
let fixture; let fixture;
let devServer; let devServer;
@ -26,21 +30,28 @@ describe('SSG pictures - dev', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
alt: 'Social image', alt: 'Social image',
}, },
{ {
title: 'Filename with spaces', title: 'Filename with spaces',
id: '#spaces', id: '#spaces',
url: '/@astroimage/assets/blog/introducing astro.jpg', url: toAstroImage('src/assets/blog/introducing astro.jpg'),
query: { f: 'jpg', w: '768', h: '414' }, query: { f: 'jpg', w: '768', h: '414' },
alt: 'spaces', alt: 'spaces',
}, },
{
title: 'File outside src',
id: '#outside-src',
url: toAstroImage('social.png'),
query: { f: 'png', w: '768', h: '414' },
alt: 'outside-src',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
alt: 'Inline social image', alt: 'Inline social image',
}, },
@ -120,21 +131,28 @@ describe('SSG pictures with subpath - dev', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
alt: 'Social image', alt: 'Social image',
}, },
{ {
title: 'Filename with spaces', title: 'Filename with spaces',
id: '#spaces', id: '#spaces',
url: '/@astroimage/assets/blog/introducing astro.jpg', url: toAstroImage('src/assets/blog/introducing astro.jpg'),
query: { f: 'jpg', w: '768', h: '414' }, query: { f: 'jpg', w: '768', h: '414' },
alt: 'spaces', alt: 'spaces',
}, },
{
title: 'File outside src',
id: '#outside-src',
url: toAstroImage('social.png'),
query: { f: 'png', w: '768', h: '414' },
alt: 'outside-src',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
alt: 'Inline social image', alt: 'Inline social image',
}, },
@ -222,6 +240,13 @@ describe('SSG pictures - build', function () {
size: { width: 768, height: 414, type: 'jpg' }, size: { width: 768, height: 414, type: 'jpg' },
alt: 'spaces', alt: 'spaces',
}, },
{
title: 'File outside src',
id: '#outside-src',
regex: /^\/_astro\/social.\w{8}_\w{4,10}.png/,
size: { type: 'png', width: 768, height: 414 },
alt: 'outside-src',
},
{ {
title: 'Inline images', title: 'Inline images',
id: '#inline', id: '#inline',
@ -322,6 +347,13 @@ describe('SSG pictures with subpath - build', function () {
size: { width: 506, height: 253, type: 'jpg' }, size: { width: 506, height: 253, type: 'jpg' },
alt: 'Social image', alt: 'Social image',
}, },
{
title: 'File outside src',
id: '#outside-src',
regex: /^\/docs\/_astro\/social.\w{8}_\w{4,10}.png/,
size: { type: 'png', width: 768, height: 414 },
alt: 'outside-src',
},
{ {
title: 'Inline images', title: 'Inline images',
id: '#inline', id: '#inline',

View file

@ -30,6 +30,13 @@ describe('SSR pictures - build', function () {
query: { w: '768', h: '414', f: 'jpg', href: /^\/_astro\/introducing astro.\w{8}.jpg/ }, query: { w: '768', h: '414', f: 'jpg', href: /^\/_astro\/introducing astro.\w{8}.jpg/ },
alt: 'spaces', alt: 'spaces',
}, },
{
title: 'File outside src',
id: '#outside-src',
url: '/_image',
query: { w: '768', h: '414', f: 'png', href: /^\/_astro\/social.\w{8}.png/ },
alt: 'outside-src',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
@ -141,6 +148,13 @@ describe('SSR pictures with subpath - build', function () {
query: { w: '768', h: '414', f: 'jpg', href: /^\/docs\/_astro\/introducing astro.\w{8}.jpg/ }, query: { w: '768', h: '414', f: 'jpg', href: /^\/docs\/_astro\/introducing astro.\w{8}.jpg/ },
alt: 'spaces', alt: 'spaces',
}, },
{
title: 'File outside src',
id: '#outside-src',
url: '/_image',
query: { w: '768', h: '414', f: 'png', href: /^\/docs\/_astro\/social.\w{8}.png/ },
alt: 'outside-src',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',

View file

@ -1,8 +1,13 @@
import { expect } from 'chai'; import { expect } from 'chai';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { join } from 'node:path';
import { loadFixture } from './test-utils.js'; import { loadFixture } from './test-utils.js';
import testAdapter from '../../../astro/test/test-adapter.js'; import testAdapter from '../../../astro/test/test-adapter.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const toAstroImage = (relpath) => '/@astroimage' + pathToFileURL(join(__dirname, 'fixtures/basic-picture', relpath)).pathname;
describe('SSR pictures - dev', function () { describe('SSR pictures - dev', function () {
let fixture; let fixture;
let devServer; let devServer;
@ -28,7 +33,7 @@ describe('SSR pictures - dev', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
alt: 'Social image', alt: 'Social image',
@ -36,15 +41,23 @@ describe('SSR pictures - dev', function () {
{ {
title: 'Filename with spaces', title: 'Filename with spaces',
id: '#spaces', id: '#spaces',
url: '/@astroimage/assets/blog/introducing astro.jpg', url: toAstroImage('src/assets/blog/introducing astro.jpg'),
query: { w: '768', h: '414', f: 'jpg' }, query: { w: '768', h: '414', f: 'jpg' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
alt: 'spaces', alt: 'spaces',
}, },
{
title: 'File outside src',
id: '#outside-src',
url: toAstroImage('social.png'),
query: { f: 'png', w: '768', h: '414' },
contentType: 'image/png',
alt: 'outside-src',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
alt: 'Inline social image', alt: 'Inline social image',
@ -157,7 +170,7 @@ describe('SSR pictures with subpath - dev', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
alt: 'Social image', alt: 'Social image',
@ -165,15 +178,23 @@ describe('SSR pictures with subpath - dev', function () {
{ {
title: 'Filename with spaces', title: 'Filename with spaces',
id: '#spaces', id: '#spaces',
url: '/@astroimage/assets/blog/introducing astro.jpg', url: toAstroImage('src/assets/blog/introducing astro.jpg'),
query: { w: '768', h: '414', f: 'jpg' }, query: { w: '768', h: '414', f: 'jpg' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
alt: 'spaces', alt: 'spaces',
}, },
{
title: 'File outside src',
id: '#outside-src',
url: toAstroImage('social.png'),
query: { f: 'png', w: '768', h: '414' },
contentType: 'image/png',
alt: 'outside-src',
},
{ {
title: 'Inline imports', title: 'Inline imports',
id: '#inline', id: '#inline',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
contentType: 'image/jpeg', contentType: 'image/jpeg',
alt: 'Inline social image', alt: 'Inline social image',

View file

@ -1,7 +1,12 @@
import { expect } from 'chai'; import { expect } from 'chai';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { join } from 'node:path';
import { loadFixture } from './test-utils.js'; import { loadFixture } from './test-utils.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const toAstroImage = (relpath) => '/@astroimage' + pathToFileURL(join(__dirname, 'fixtures/squoosh-service', relpath)).pathname;
describe('Squoosh service', function () { describe('Squoosh service', function () {
let fixture; let fixture;
let devServer; let devServer;
@ -22,7 +27,7 @@ describe('Squoosh service', function () {
{ {
title: 'Local images', title: 'Local images',
id: '#social-jpg', id: '#social-jpg',
url: '/@astroimage/assets/social.jpg', url: toAstroImage('src/assets/social.jpg'),
query: { f: 'jpg', w: '506', h: '253' }, query: { f: 'jpg', w: '506', h: '253' },
}, },
{ {

View file

@ -2706,7 +2706,6 @@ importers:
mocha: ^9.2.2 mocha: ^9.2.2
rollup-plugin-copy: ^3.4.0 rollup-plugin-copy: ^3.4.0
sharp: ^0.31.0 sharp: ^0.31.0
slash: ^4.0.0
vite: ^4.0.3 vite: ^4.0.3
dependencies: dependencies:
'@altano/tiny-async-pool': 1.0.2 '@altano/tiny-async-pool': 1.0.2
@ -2715,7 +2714,6 @@ importers:
kleur: 4.1.5 kleur: 4.1.5
magic-string: 0.27.0 magic-string: 0.27.0
mime: 3.0.0 mime: 3.0.0
slash: 4.0.0
devDependencies: devDependencies:
'@types/http-cache-semantics': 4.0.1 '@types/http-cache-semantics': 4.0.1
'@types/mime': 2.0.3 '@types/mime': 2.0.3