diff --git a/.changeset/rotten-worms-walk.md b/.changeset/rotten-worms-walk.md new file mode 100644 index 000000000000..a7a014056ea3 --- /dev/null +++ b/.changeset/rotten-worms-walk.md @@ -0,0 +1,6 @@ +--- +'@astrojs/image': patch +'astro': patch +--- + +Avoid removing leading slash for `build.assetsPrefix` value in the build output diff --git a/packages/astro/src/core/path.ts b/packages/astro/src/core/path.ts index 8a0ac4a8676b..cbf959f69f57 100644 --- a/packages/astro/src/core/path.ts +++ b/packages/astro/src/core/path.ts @@ -52,7 +52,18 @@ function isString(path: unknown): path is string { } export function joinPaths(...paths: (string | undefined)[]) { - return paths.filter(isString).map(trimSlashes).join('/'); + return paths + .filter(isString) + .map((path, i) => { + if (i === 0) { + return removeTrailingForwardSlash(path); + } else if (i === paths.length - 1) { + return removeLeadingForwardSlash(path); + } else { + return trimSlashes(path); + } + }) + .join('/'); } export function removeFileExtension(path: string) { diff --git a/packages/astro/test/astro-assets-prefix.test.js b/packages/astro/test/astro-assets-prefix.test.js index be80d460114d..58eb11e39b6a 100644 --- a/packages/astro/test/astro-assets-prefix.test.js +++ b/packages/astro/test/astro-assets-prefix.test.js @@ -63,6 +63,29 @@ describe('Assets Prefix - Static', () => { }); }); +describe('Assets Prefix - Static with path prefix', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/astro-assets-prefix/', + build: { + assetsPrefix: '/starting-slash', + }, + }); + await fixture.build(); + }); + + it('all stylesheets should start with assetPrefix', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + const stylesheets = $('link[rel="stylesheet"]'); + stylesheets.each((i, el) => { + expect(el.attribs.href).to.match(/^\/starting-slash\/.*/); + }); + }); +}); + describe('Assets Prefix - Server', () => { let app; @@ -119,3 +142,32 @@ describe('Assets Prefix - Server', () => { expect(imgAsset.attr('src')).to.match(assetsPrefixRegex); }); }); + +describe('Assets Prefix - Server with path prefix', () => { + let app; + + before(async () => { + const fixture = await loadFixture({ + root: './fixtures/astro-assets-prefix/', + output: 'server', + adapter: testAdapter(), + build: { + assetsPrefix: '/starting-slash', + }, + }); + await fixture.build(); + app = await fixture.loadTestAdapterApp(); + }); + + it('all stylesheets should start with assetPrefix', async () => { + const request = new Request('http://example.com/custom-base/'); + const response = await app.render(request); + expect(response.status).to.equal(200); + const html = await response.text(); + const $ = cheerio.load(html); + const stylesheets = $('link[rel="stylesheet"]'); + stylesheets.each((i, el) => { + expect(el.attribs.href).to.match(/^\/starting-slash\/.*/); + }); + }); +}); diff --git a/packages/integrations/image/src/utils/paths.ts b/packages/integrations/image/src/utils/paths.ts index 023fdc143d51..a6618ff1e9d5 100644 --- a/packages/integrations/image/src/utils/paths.ts +++ b/packages/integrations/image/src/utils/paths.ts @@ -75,5 +75,16 @@ function isString(path: unknown): path is string { } export function joinPaths(...paths: (string | undefined)[]) { - return paths.filter(isString).map(trimSlashes).join('/'); + return paths + .filter(isString) + .map((path, i) => { + if (i === 0) { + return removeTrailingForwardSlash(path); + } else if (i === paths.length - 1) { + return removeLeadingForwardSlash(path); + } else { + return trimSlashes(path); + } + }) + .join('/'); }