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
|
* @name trailingSlash
|
||||||
* @type {('always' | 'never' | 'ignore')}
|
* @type {('always' | 'never' | 'ignore')}
|
||||||
* @default `'ignore'`
|
* @default `'ignore'`
|
||||||
* @see buildOptions.pageUrlFormat
|
* @see build.format
|
||||||
* @description
|
* @description
|
||||||
*
|
*
|
||||||
* Set the route matching behavior of the dev server. Choose from the following options:
|
* 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';
|
format?: 'file' | 'directory';
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@ import type {
|
||||||
AstroConfig,
|
AstroConfig,
|
||||||
ComponentInstance,
|
ComponentInstance,
|
||||||
EndpointHandler,
|
EndpointHandler,
|
||||||
|
RouteType,
|
||||||
SSRLoadedRenderer,
|
SSRLoadedRenderer,
|
||||||
} from '../../@types/astro';
|
} from '../../@types/astro';
|
||||||
import type { BuildInternals } from '../../core/build/internal.js';
|
import type { BuildInternals } from '../../core/build/internal.js';
|
||||||
|
@ -243,6 +244,27 @@ function addPageName(pathname: string, opts: StaticBuildOptions): void {
|
||||||
opts.pageNames.push(pathname.replace(/^\//, ''));
|
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(
|
async function generatePath(
|
||||||
pathname: string,
|
pathname: string,
|
||||||
opts: StaticBuildOptions,
|
opts: StaticBuildOptions,
|
||||||
|
@ -290,7 +312,8 @@ async function generatePath(
|
||||||
}
|
}
|
||||||
|
|
||||||
const ssr = opts.astroConfig.output === 'server';
|
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 = {
|
const options: RenderOptions = {
|
||||||
adapterName: undefined,
|
adapterName: undefined,
|
||||||
links,
|
links,
|
||||||
|
|
|
@ -169,6 +169,6 @@ describe('getStaticPaths - Astro.url', () => {
|
||||||
const html = await fixture.readFile('/food/tacos/index.html');
|
const html = await fixture.readFile('/food/tacos/index.html');
|
||||||
const $ = cheerio.load(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/');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
|
@ -1697,6 +1697,12 @@ importers:
|
||||||
packages/astro/test/fixtures/multiple-renderers/renderers/two:
|
packages/astro/test/fixtures/multiple-renderers/renderers/two:
|
||||||
specifiers: {}
|
specifiers: {}
|
||||||
|
|
||||||
|
packages/astro/test/fixtures/page-format:
|
||||||
|
specifiers:
|
||||||
|
astro: workspace:*
|
||||||
|
dependencies:
|
||||||
|
astro: link:../../..
|
||||||
|
|
||||||
packages/astro/test/fixtures/page-level-styles:
|
packages/astro/test/fixtures/page-level-styles:
|
||||||
specifiers:
|
specifiers:
|
||||||
astro: workspace:*
|
astro: workspace:*
|
||||||
|
|
Loading…
Add table
Reference in a new issue