Make Astro.url conform to build.format during the build (#4352)
* Make Astro.url conform to build.format during the build * Adding a changeset * Better implementation * fix some stuff that tests failed on * Add docs * Change to minor * account for empty path
This commit is contained in:
parent
11ce2b6ce9
commit
cd154e447b
8 changed files with 108 additions and 3 deletions
5
.changeset/beige-deers-travel.md
Normal file
5
.changeset/beige-deers-travel.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': minor
|
||||
---
|
||||
|
||||
Make Astro.url match the build.format configuration during the build
|
|
@ -428,7 +428,7 @@ export interface AstroUserConfig {
|
|||
* @name trailingSlash
|
||||
* @type {('always' | 'never' | 'ignore')}
|
||||
* @default `'ignore'`
|
||||
* @see buildOptions.pageUrlFormat
|
||||
* @see build.format
|
||||
* @description
|
||||
*
|
||||
* Set the route matching behavior of the dev server. Choose from the following options:
|
||||
|
@ -517,6 +517,13 @@ export interface AstroUserConfig {
|
|||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* #### Effect on Astro.url
|
||||
* Setting `build.format` controls what `Astro.url` is set to during the build. When it is:
|
||||
* - `directory` - The `Astro.url.pathname` will include a trailing slash to mimic folder behavior; ie `/foo/`.
|
||||
* - `file` - The `Astro.url.pathname` will include `.html`; ie `/foo.html`.
|
||||
*
|
||||
* This means that when you create relative URLs using `new URL('./relative', Astro.url)`, you will get consistent behavior between dev and build.
|
||||
*/
|
||||
format?: 'file' | 'directory';
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ import type {
|
|||
AstroConfig,
|
||||
ComponentInstance,
|
||||
EndpointHandler,
|
||||
RouteType,
|
||||
SSRLoadedRenderer,
|
||||
} from '../../@types/astro';
|
||||
import type { BuildInternals } from '../../core/build/internal.js';
|
||||
|
@ -243,6 +244,27 @@ function addPageName(pathname: string, opts: StaticBuildOptions): void {
|
|||
opts.pageNames.push(pathname.replace(/^\//, ''));
|
||||
}
|
||||
|
||||
function getUrlForPath(pathname: string, base: string, origin: string, format: 'directory' | 'file', routeType: RouteType): URL {
|
||||
/**
|
||||
* Examples:
|
||||
* pathname: /, /foo
|
||||
* base: /
|
||||
*/
|
||||
const ending = format === 'directory' ? '/' : '.html';
|
||||
let buildPathname: string;
|
||||
if(pathname === '/' || pathname === '') {
|
||||
buildPathname = base;
|
||||
} else if(routeType === 'endpoint') {
|
||||
const buildPathRelative = removeLeadingForwardSlash(pathname);
|
||||
buildPathname = base + buildPathRelative;
|
||||
} else {
|
||||
const buildPathRelative = removeTrailingForwardSlash(removeLeadingForwardSlash(pathname)) + ending;
|
||||
buildPathname = base + buildPathRelative;
|
||||
}
|
||||
const url = new URL(buildPathname, origin);
|
||||
return url;
|
||||
}
|
||||
|
||||
async function generatePath(
|
||||
pathname: string,
|
||||
opts: StaticBuildOptions,
|
||||
|
@ -290,7 +312,8 @@ async function generatePath(
|
|||
}
|
||||
|
||||
const ssr = opts.astroConfig.output === 'server';
|
||||
const url = new URL(opts.astroConfig.base + removeLeadingForwardSlash(pathname), origin);
|
||||
const url = getUrlForPath(pathname, opts.astroConfig.base, origin,
|
||||
opts.astroConfig.build.format, pageData.route.type);
|
||||
const options: RenderOptions = {
|
||||
adapterName: undefined,
|
||||
links,
|
||||
|
|
|
@ -169,6 +169,6 @@ describe('getStaticPaths - Astro.url', () => {
|
|||
const html = await fixture.readFile('/food/tacos/index.html');
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
expect($('#url').text()).to.equal('/food/tacos');
|
||||
expect($('#url').text()).to.equal('/food/tacos/');
|
||||
});
|
||||
});
|
||||
|
|
8
packages/astro/test/fixtures/page-format/package.json
vendored
Normal file
8
packages/astro/test/fixtures/page-format/package.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "@test/page-format",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"astro": "workspace:*"
|
||||
}
|
||||
}
|
4
packages/astro/test/fixtures/page-format/src/pages/nested/page.astro
vendored
Normal file
4
packages/astro/test/fixtures/page-format/src/pages/nested/page.astro
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
const another = new URL('./another/', Astro.url);
|
||||
---
|
||||
<a id="another" href={another.pathname}></a>
|
52
packages/astro/test/page-format.test.js
Normal file
52
packages/astro/test/page-format.test.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { expect } from 'chai';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
||||
describe('build.format', () => {
|
||||
describe('directory', () => {
|
||||
/** @type {import('./test-utils').Fixture} */
|
||||
let fixture;
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/page-format/',
|
||||
});
|
||||
});
|
||||
|
||||
describe('Build', () => {
|
||||
before(async () => {
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('relative urls created point to sibling folders', async () => {
|
||||
let html = await fixture.readFile('/nested/page/index.html');
|
||||
let $ = cheerio.load(html);
|
||||
expect($('#another').attr('href')).to.equal('/nested/page/another/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('file', () => {
|
||||
/** @type {import('./test-utils').Fixture} */
|
||||
let fixture;
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/page-format/',
|
||||
build: {
|
||||
format: 'file',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('Build', () => {
|
||||
before(async () => {
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('relative urls created point to sibling folders', async () => {
|
||||
let html = await fixture.readFile('/nested/page.html');
|
||||
let $ = cheerio.load(html);
|
||||
expect($('#another').attr('href')).to.equal('/nested/another/');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1697,6 +1697,12 @@ importers:
|
|||
packages/astro/test/fixtures/multiple-renderers/renderers/two:
|
||||
specifiers: {}
|
||||
|
||||
packages/astro/test/fixtures/page-format:
|
||||
specifiers:
|
||||
astro: workspace:*
|
||||
dependencies:
|
||||
astro: link:../../..
|
||||
|
||||
packages/astro/test/fixtures/page-level-styles:
|
||||
specifiers:
|
||||
astro: workspace:*
|
||||
|
|
Loading…
Reference in a new issue