Include trailingSlash in astro:build:done hook (#4553)

This commit is contained in:
Matthew Phillips 2022-08-30 11:45:16 -04:00 committed by GitHub
parent 69b640b87c
commit 2f05f5d307
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 192 additions and 3 deletions

View file

@ -0,0 +1,7 @@
---
'astro': patch
---
Include trailingSlash in astro:build:done hook
This change ensures that the `pages` provided in the `astro:build:done` hook conform to the `trailingSlash` and `build.format` configs.

View file

@ -240,8 +240,26 @@ interface GeneratePathOptions {
renderers: SSRLoadedRenderer[];
}
function shouldAppendForwardSlash(trailingSlash: AstroConfig['trailingSlash'], buildFormat: AstroConfig['build']['format']): boolean {
switch(trailingSlash) {
case 'always': return true;
case 'never': return false;
case 'ignore': {
switch(buildFormat) {
case 'directory': return true;
case 'file': return false;
}
}
}
}
function addPageName(pathname: string, opts: StaticBuildOptions): void {
opts.pageNames.push(pathname.replace(/^\//, ''));
const trailingSlash = opts.astroConfig.trailingSlash;
const buildFormat = opts.astroConfig.build.format;
const pageName = shouldAppendForwardSlash(trailingSlash, buildFormat) ?
pathname.replace(/\/?$/, '/').replace(/^\//, '') :
pathname.replace(/^\//, '')
opts.pageNames.push(pageName);
}
function getUrlForPath(

View file

@ -38,6 +38,7 @@
},
"devDependencies": {
"astro": "workspace:*",
"astro-scripts": "workspace:*"
"astro-scripts": "workspace:*",
"xml2js": "0.4.23"
}
}

View file

@ -0,0 +1,7 @@
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
integrations: [sitemap()],
site: 'http://example.com'
})

View file

@ -0,0 +1,9 @@
{
"name": "@test/sitemap-trailing-slash",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*",
"@astrojs/sitemap": "workspace:*"
}
}

View file

@ -0,0 +1,8 @@
<html>
<head>
<title>One</title>
</head>
<body>
<h1>One</h1>
</body>
</html>

View file

@ -0,0 +1,8 @@
<html>
<head>
<title>Two</title>
</head>
<body>
<h1>Two</h1>
</body>
</html>

View file

@ -0,0 +1,30 @@
import { loadFixture as baseLoadFixture } from '../../../astro/test/test-utils.js';
import * as xml2js from 'xml2js';
/**
* @typedef {import('../../../astro/test/test-utils').Fixture} Fixture
*/
export function loadFixture(inlineConfig) {
if (!inlineConfig || !inlineConfig.root)
throw new Error("Must provide { root: './fixtures/...' }");
// resolve the relative root (i.e. "./fixtures/tailwindcss") to a full filepath
// without this, the main `loadFixture` helper will resolve relative to `packages/astro/test`
return baseLoadFixture({
...inlineConfig,
root: new URL(inlineConfig.root, import.meta.url).toString(),
});
}
export function readXML(fileOrPromise) {
const parseString = xml2js.parseString;
return Promise.resolve(fileOrPromise).then(xml => {
return new Promise((resolve, reject) => {
parseString(xml, function (err, result) {
if(err) return reject(err);
resolve(result);
});
})
});
}

View file

@ -0,0 +1,79 @@
import { loadFixture, readXML } from './test-utils.js';
import { expect } from 'chai';
describe('Trailing slash', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
describe('trailingSlash: ignore', () => {
describe('build.format: directory', () => {
before(async () => {
fixture = await loadFixture({
root: './fixtures/trailing-slash/',
trailingSlash: 'ignore',
build: {
format: 'directory'
}
});
await fixture.build();
});
it('URLs end with trailing slash', async () => {
const data = await readXML(fixture.readFile('/sitemap-0.xml'));
const urls = data.urlset.url;
expect(urls[0].loc[0]).to.equal('http://example.com/one/');
});
});
describe('build.format: file', () => {
before(async () => {
fixture = await loadFixture({
root: './fixtures/trailing-slash/',
trailingSlash: 'ignore',
build: {
format: 'file'
}
});
await fixture.build();
});
it('URLs do not end with trailing slash', async () => {
const data = await readXML(fixture.readFile('/sitemap-0.xml'));
const urls = data.urlset.url;
expect(urls[0].loc[0]).to.equal('http://example.com/one');
});
});
});
describe('trailingSlash: never', () => {
before(async () => {
fixture = await loadFixture({
root: './fixtures/trailing-slash/',
trailingSlash: 'never',
});
await fixture.build();
});
it('URLs do no end with trailing slash', async () => {
const data = await readXML(fixture.readFile('/sitemap-0.xml'));
const urls = data.urlset.url;
expect(urls[0].loc[0]).to.equal('http://example.com/one');
});
});
describe('trailingSlash: always', () => {
before(async () => {
fixture = await loadFixture({
root: './fixtures/trailing-slash/',
trailingSlash: 'always',
});
await fixture.build();
});
it('URLs end with trailing slash', async () => {
const data = await readXML(fixture.readFile('/sitemap-0.xml'));
const urls = data.urlset.url;
expect(urls[0].loc[0]).to.equal('http://example.com/one/');
});
});
});

View file

@ -2552,6 +2552,7 @@ importers:
astro: workspace:*
astro-scripts: workspace:*
sitemap: ^7.1.1
xml2js: 0.4.23
zod: ^3.17.3
dependencies:
sitemap: 7.1.1
@ -2559,6 +2560,15 @@ importers:
devDependencies:
astro: link:../../astro
astro-scripts: link:../../../scripts
xml2js: 0.4.23
packages/integrations/sitemap/test/fixtures/trailing-slash:
specifiers:
'@astrojs/sitemap': workspace:*
astro: workspace:*
dependencies:
'@astrojs/sitemap': link:../../..
astro: link:../../../../../astro
packages/integrations/solid:
specifiers:
@ -15540,7 +15550,6 @@ packages:
/sax/1.2.4:
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
dev: false
/scheduler/0.23.0:
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
@ -17443,6 +17452,19 @@ packages:
optional: true
dev: true
/xml2js/0.4.23:
resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==}
engines: {node: '>=4.0.0'}
dependencies:
sax: 1.2.4
xmlbuilder: 11.0.1
dev: true
/xmlbuilder/11.0.1:
resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==}
engines: {node: '>=4.0'}
dev: true
/xregexp/2.0.0:
resolution: {integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==}
dev: true