Add trailingSlash & pageDirectoryUrl config options (#1197)
This commit is contained in:
parent
1185d8ffcb
commit
c06da5dd78
17 changed files with 284 additions and 92 deletions
5
.changeset/soft-goats-wash.md
Normal file
5
.changeset/soft-goats-wash.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Add configuration options for url format behavior: buildOptions.pageDirectoryUrl & trailingSlash
|
5
.changeset/tough-dancers-hear.md
Normal file
5
.changeset/tough-dancers-hear.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Move 404.html output from /404/index.html to /404.html
|
|
@ -1 +0,0 @@
|
|||
<h1>hello</h1>
|
|
@ -3,30 +3,18 @@ layout: ~/layouts/MainLayout.astro
|
|||
title: Configuration Reference
|
||||
---
|
||||
|
||||
To configure Astro, add an `astro.config.mjs` file in the root of your project. All settings are optional. Here are the defaults:
|
||||
To configure Astro, add an `astro.config.mjs` file in the root of your project. All settings are optional.
|
||||
|
||||
You can view the full configuration API (including information about default configuration) on GitHub: https://github.com/snowpackjs/astro/blob/latest/packages/astro/src/@types/config.ts
|
||||
|
||||
```js
|
||||
// Example: astro.config.mjs
|
||||
|
||||
/** @type {import('astro').AstroUserConfig} */
|
||||
export default {
|
||||
projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project.
|
||||
src: './src', // Path to Astro components, pages, and data
|
||||
pages: './src/pages', // Path to Astro/Markdown pages
|
||||
dist: './dist', // When running `astro build`, path to final static output
|
||||
public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don't need processing.
|
||||
buildOptions: {
|
||||
// site: '', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs.
|
||||
sitemap: true, // Generate sitemap (set to "false" to disable)
|
||||
site: 'https://example.com',
|
||||
},
|
||||
devOptions: {
|
||||
port: 3000, // The port to run the dev server on.
|
||||
// tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js'
|
||||
},
|
||||
// component renderers which are enabled by default
|
||||
renderers: [
|
||||
'@astrojs/renderer-svelte',
|
||||
'@astrojs/renderer-vue',
|
||||
'@astrojs/renderer-react',
|
||||
'@astrojs/renderer-preact',
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { ImportSpecifier, ImportDefaultSpecifier, ImportNamespaceSpecifier } from '@babel/types';
|
||||
import type { AstroMarkdownOptions } from '@astrojs/markdown-support';
|
||||
import type { AstroConfig } from './config';
|
||||
|
||||
export interface RouteData {
|
||||
type: 'page';
|
||||
|
@ -22,33 +23,7 @@ export interface AstroConfigRaw {
|
|||
jsx?: string;
|
||||
}
|
||||
|
||||
export { AstroMarkdownOptions };
|
||||
export interface AstroConfig {
|
||||
dist: string;
|
||||
projectRoot: URL;
|
||||
pages: URL;
|
||||
public: URL;
|
||||
src: URL;
|
||||
renderers?: string[];
|
||||
/** Options for rendering markdown content */
|
||||
markdownOptions?: Partial<AstroMarkdownOptions>;
|
||||
/** Options specific to `astro build` */
|
||||
buildOptions: {
|
||||
/** Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. */
|
||||
site?: string;
|
||||
/** Generate sitemap (set to "false" to disable) */
|
||||
sitemap: boolean;
|
||||
};
|
||||
/** Options for the development server run with `astro dev`. */
|
||||
devOptions: {
|
||||
hostname?: string;
|
||||
/** The port to run the dev server on. */
|
||||
port: number;
|
||||
projectRoot?: string;
|
||||
/** Path to tailwind.config.js, if used */
|
||||
tailwindConfig?: string;
|
||||
};
|
||||
}
|
||||
export { AstroMarkdownOptions, AstroConfig };
|
||||
|
||||
export type AstroUserConfig = Omit<AstroConfig, 'buildOptions' | 'devOptions'> & {
|
||||
buildOptions: {
|
||||
|
|
75
packages/astro/src/@types/config.ts
Normal file
75
packages/astro/src/@types/config.ts
Normal file
|
@ -0,0 +1,75 @@
|
|||
import type { AstroMarkdownOptions } from '@astrojs/markdown-support';
|
||||
export interface AstroConfig {
|
||||
/**
|
||||
* Where to resolve all URLs relative to. Useful if you have a monorepo project.
|
||||
* Default: '.' (current working directory)
|
||||
*/
|
||||
projectRoot: URL;
|
||||
/**
|
||||
* Path to the `astro build` output.
|
||||
* Default: './dist'
|
||||
*/
|
||||
dist: string;
|
||||
/**
|
||||
* Path to all of your Astro components, pages, and data.
|
||||
* Default: './src'
|
||||
*/
|
||||
src: URL;
|
||||
/**
|
||||
* Path to your Astro/Markdown pages. Each file in this directory
|
||||
* becomes a page in your final build.
|
||||
* Default: './src/pages'
|
||||
*/
|
||||
pages: URL;
|
||||
/**
|
||||
* Path to your public files. These are copied over into your build directory, untouched.
|
||||
* Useful for favicons, images, and other files that don't need processing.
|
||||
* Default: './public'
|
||||
*/
|
||||
public: URL;
|
||||
/**
|
||||
* Framework component renderers enable UI framework rendering (static and dynamic).
|
||||
* When you define this in your configuration, all other defaults are disabled.
|
||||
* Default: [
|
||||
* '@astrojs/renderer-svelte',
|
||||
* '@astrojs/renderer-vue',
|
||||
* '@astrojs/renderer-react',
|
||||
* '@astrojs/renderer-preact',
|
||||
* ],
|
||||
*/
|
||||
renderers?: string[];
|
||||
/** Options for rendering markdown content */
|
||||
markdownOptions?: Partial<AstroMarkdownOptions>;
|
||||
/** Options specific to `astro build` */
|
||||
buildOptions: {
|
||||
/** Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. */
|
||||
site?: string;
|
||||
/** Generate an automatically-generated sitemap for your build.
|
||||
* Default: true
|
||||
*/
|
||||
sitemap: boolean;
|
||||
/**
|
||||
* Control the output file/URL format of each page.
|
||||
* If true, Astro will generate a directory with a nested index.html (ex: "/foo/index.html") for each page.
|
||||
* If false, Astro will generate a matching HTML file (ex: "/foo.html") instead of a directory.
|
||||
* Default: true
|
||||
*/
|
||||
pageDirectoryUrl: boolean;
|
||||
};
|
||||
/** Options for the development server run with `astro dev`. */
|
||||
devOptions: {
|
||||
hostname?: string;
|
||||
/** The port to run the dev server on. */
|
||||
port: number;
|
||||
/** Path to tailwind.config.js, if used */
|
||||
tailwindConfig?: string;
|
||||
/**
|
||||
* Configure The trailing slash behavior of URL route matching:
|
||||
* 'always' - Only match URLs that include a trailing slash (ex: "/foo/")
|
||||
* 'never' - Never match URLs that include a trailing slash (ex: "/foo")
|
||||
* 'ignore' - Match URLs regardless of whether a trailing "/" exists
|
||||
* Default: 'always'
|
||||
*/
|
||||
trailingSlash: 'always' | 'never' | 'ignore';
|
||||
};
|
||||
}
|
|
@ -45,18 +45,30 @@ export async function getStaticPathsForPage({
|
|||
};
|
||||
}
|
||||
|
||||
function formatOutFile(path: string, pageDirectoryUrl: boolean) {
|
||||
if (path === '/404') {
|
||||
return '/404.html';
|
||||
}
|
||||
if (path === '/') {
|
||||
return '/index.html';
|
||||
}
|
||||
if (pageDirectoryUrl) {
|
||||
return _path.posix.join(path, '/index.html');
|
||||
}
|
||||
return `${path}.html`;
|
||||
}
|
||||
/** Build static page */
|
||||
export async function buildStaticPage({ astroConfig, buildState, path, route, astroRuntime }: PageBuildOptions): Promise<void> {
|
||||
const location = convertMatchToLocation(route, astroConfig);
|
||||
const result = await astroRuntime.load(path);
|
||||
const normalizedPath = astroConfig.devOptions.trailingSlash === 'never' ? path : path.endsWith('/') ? path : `${path}/`;
|
||||
const result = await astroRuntime.load(normalizedPath);
|
||||
if (result.statusCode !== 200) {
|
||||
let err = (result as any).error;
|
||||
if (!(err instanceof Error)) err = new Error(err);
|
||||
err.filename = fileURLToPath(location.fileURL);
|
||||
throw err;
|
||||
}
|
||||
const outFile = _path.posix.join(path, '/index.html');
|
||||
buildState[outFile] = {
|
||||
buildState[formatOutFile(path, astroConfig.buildOptions.pageDirectoryUrl)] = {
|
||||
srcPath: location.fileURL,
|
||||
contents: result.contents,
|
||||
contentType: 'text/html',
|
||||
|
|
|
@ -72,20 +72,21 @@ export async function collectBundleStats(buildState: BuildOutput, depTree: Bundl
|
|||
}
|
||||
|
||||
export function logURLStats(logging: LogOptions, urlStats: URLStatsMap) {
|
||||
const builtURLs = [...urlStats.keys()].map((url) => url.replace(/index\.html$/, ''));
|
||||
builtURLs.sort((a, b) => a.localeCompare(b, 'en', { numeric: true }));
|
||||
const builtURLs = [...urlStats.keys()].sort((a, b) => a.localeCompare(b, 'en', { numeric: true }));
|
||||
info(logging, null, '');
|
||||
const log = table(logging, [60, 20]);
|
||||
log(info, ' ' + bold(underline('Pages')), bold(underline('Page Weight (GZip)')));
|
||||
|
||||
const lastIndex = builtURLs.length - 1;
|
||||
builtURLs.forEach((url, index) => {
|
||||
const sep = index === 0 ? '┌' : index === lastIndex ? '└' : '├';
|
||||
const urlPart = ' ' + sep + ' ' + url;
|
||||
|
||||
const bytes = (urlStats.get(url) || urlStats.get(url + 'index.html'))?.stats.map((s) => s.gzipSize).reduce((a, b) => a + b, 0) || 0;
|
||||
const bytes =
|
||||
urlStats
|
||||
.get(url)
|
||||
?.stats.map((s) => s.gzipSize)
|
||||
.reduce((a, b) => a + b, 0) || 0;
|
||||
const kb = (bytes * 0.001).toFixed(2);
|
||||
const sizePart = kb + ' kB';
|
||||
log(info, urlPart + 'index.html', sizePart);
|
||||
log(info, urlPart, sizePart);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -55,17 +55,19 @@ function validateConfig(config: any): void {
|
|||
async function configDefaults(userConfig?: any): Promise<any> {
|
||||
const config: any = { ...(userConfig || {}) };
|
||||
|
||||
if (!config.projectRoot) config.projectRoot = '.';
|
||||
if (!config.src) config.src = './src';
|
||||
if (!config.pages) config.pages = './src/pages';
|
||||
if (!config.dist) config.dist = './dist';
|
||||
if (!config.public) config.public = './public';
|
||||
if (!config.devOptions) config.devOptions = {};
|
||||
if (!config.devOptions.port) config.devOptions.port = await getPort({ port: getPort.makeRange(3000, 3050) });
|
||||
if (!config.devOptions.hostname) config.devOptions.hostname = 'localhost';
|
||||
if (!config.buildOptions) config.buildOptions = {};
|
||||
if (!config.markdownOptions) config.markdownOptions = {};
|
||||
if (typeof config.buildOptions.sitemap === 'undefined') config.buildOptions.sitemap = true;
|
||||
if (config.projectRoot === undefined) config.projectRoot = '.';
|
||||
if (config.src === undefined) config.src = './src';
|
||||
if (config.pages === undefined) config.pages = './src/pages';
|
||||
if (config.dist === undefined) config.dist = './dist';
|
||||
if (config.public === undefined) config.public = './public';
|
||||
if (config.devOptions === undefined) config.devOptions = {};
|
||||
if (config.devOptions.port === undefined) config.devOptions.port = await getPort({ port: getPort.makeRange(3000, 3050) });
|
||||
if (config.devOptions.hostname === undefined) config.devOptions.hostname = 'localhost';
|
||||
if (config.devOptions.trailingSlash === undefined) config.devOptions.trailingSlash = 'ignore';
|
||||
if (config.buildOptions === undefined) config.buildOptions = {};
|
||||
if (config.buildOptions.pageDirectoryUrl === undefined) config.buildOptions.pageDirectoryUrl = true;
|
||||
if (config.markdownOptions === undefined) config.markdownOptions = {};
|
||||
if (config.buildOptions.sitemap === undefined) config.buildOptions.sitemap = true;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -119,8 +119,8 @@ export function createManifest({ config, cwd }: { config: AstroConfig; cwd?: str
|
|||
} else {
|
||||
components.push(item.file);
|
||||
const component = item.file;
|
||||
const pattern = getPattern(segments, true);
|
||||
const generate = getGenerator(segments, false);
|
||||
const pattern = getPattern(segments, config.devOptions.trailingSlash);
|
||||
const generate = getGenerator(segments, config.devOptions.trailingSlash);
|
||||
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join('/')}` : null;
|
||||
|
||||
routes.push({
|
||||
|
@ -218,7 +218,17 @@ function getParts(part: string, file: string) {
|
|||
return result;
|
||||
}
|
||||
|
||||
function getPattern(segments: Part[][], addTrailingSlash: boolean) {
|
||||
function getTrailingSlashPattern(addTrailingSlash: AstroConfig['devOptions']['trailingSlash']): string {
|
||||
if (addTrailingSlash === 'always') {
|
||||
return '\\/$';
|
||||
}
|
||||
if (addTrailingSlash === 'never') {
|
||||
return '$';
|
||||
}
|
||||
return '\\/?$';
|
||||
}
|
||||
|
||||
function getPattern(segments: Part[][], addTrailingSlash: AstroConfig['devOptions']['trailingSlash']) {
|
||||
const pathname = segments
|
||||
.map((segment) => {
|
||||
return segment[0].spread
|
||||
|
@ -241,11 +251,11 @@ function getPattern(segments: Part[][], addTrailingSlash: boolean) {
|
|||
})
|
||||
.join('');
|
||||
|
||||
const trailing = addTrailingSlash && segments.length ? '\\/?$' : '$';
|
||||
const trailing = addTrailingSlash && segments.length ? getTrailingSlashPattern(addTrailingSlash) : '$';
|
||||
return new RegExp(`^${pathname || '\\/'}${trailing}`);
|
||||
}
|
||||
|
||||
function getGenerator(segments: Part[][], addTrailingSlash: boolean) {
|
||||
function getGenerator(segments: Part[][], addTrailingSlash: AstroConfig['devOptions']['trailingSlash']) {
|
||||
const template = segments
|
||||
.map((segment) => {
|
||||
return segment[0].spread
|
||||
|
@ -268,7 +278,7 @@ function getGenerator(segments: Part[][], addTrailingSlash: boolean) {
|
|||
})
|
||||
.join('');
|
||||
|
||||
const trailing = addTrailingSlash && segments.length ? '/' : '';
|
||||
const trailing = addTrailingSlash !== 'never' && segments.length ? '/' : '';
|
||||
const toPath = compile(template + trailing);
|
||||
return toPath;
|
||||
}
|
||||
|
|
16
packages/astro/test/astro-pageDirectoryUrl.test.js
Normal file
16
packages/astro/test/astro-pageDirectoryUrl.test.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { suite } from 'uvu';
|
||||
import * as assert from 'uvu/assert';
|
||||
import { setupBuild } from './helpers.js';
|
||||
|
||||
const PageDirectoryUrl = suite('pageDirectoryUrl');
|
||||
|
||||
setupBuild(PageDirectoryUrl, './fixtures/astro-page-directory-url');
|
||||
|
||||
PageDirectoryUrl('outputs', async ({ build, readFile }) => {
|
||||
await build();
|
||||
assert.ok(await readFile('/client.html'));
|
||||
assert.ok(await readFile('/nested-md.html'));
|
||||
assert.ok(await readFile('/nested-astro.html'));
|
||||
});
|
||||
|
||||
PageDirectoryUrl.run();
|
5
packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs
vendored
Normal file
5
packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
buildOptions: {
|
||||
pageDirectoryUrl: false
|
||||
}
|
||||
};
|
3
packages/astro/test/fixtures/astro-page-directory-url/snowpack.config.json
vendored
Normal file
3
packages/astro/test/fixtures/astro-page-directory-url/snowpack.config.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"workspaceRoot": "../../../../../"
|
||||
}
|
7
packages/astro/test/fixtures/astro-page-directory-url/src/pages/client.astro
vendored
Normal file
7
packages/astro/test/fixtures/astro-page-directory-url/src/pages/client.astro
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Stuff</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
12
packages/astro/test/fixtures/astro-page-directory-url/src/pages/nested-astro/index.astro
vendored
Normal file
12
packages/astro/test/fixtures/astro-page-directory-url/src/pages/nested-astro/index.astro
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
let title = 'Nested page'
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!-- Head Stuff -->
|
||||
</head>
|
||||
<body>
|
||||
<h1>{title}</h1>
|
||||
</body>
|
||||
</html>
|
5
packages/astro/test/fixtures/astro-page-directory-url/src/pages/nested-md/index.md
vendored
Normal file
5
packages/astro/test/fixtures/astro-page-directory-url/src/pages/nested-md/index.md
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: My Page
|
||||
---
|
||||
|
||||
Hello world
|
|
@ -5,16 +5,14 @@ import { createManifest } from '../dist/manifest/create.js';
|
|||
|
||||
const cwd = new URL('./fixtures/route-manifest/', import.meta.url);
|
||||
|
||||
/**
|
||||
* @param {string} dir
|
||||
* @param {string[]} [extensions]
|
||||
* @returns
|
||||
*/
|
||||
const create = (dir) => {
|
||||
const create = (dir, trailingSlash) => {
|
||||
return createManifest({
|
||||
config: {
|
||||
projectRoot: cwd,
|
||||
pages: new URL(dir, cwd),
|
||||
devOptions: {
|
||||
trailingSlash,
|
||||
},
|
||||
},
|
||||
cwd: fileURLToPath(cwd),
|
||||
});
|
||||
|
@ -26,8 +24,82 @@ function cleanRoutes(routes) {
|
|||
});
|
||||
}
|
||||
|
||||
test('creates routes', () => {
|
||||
const { routes } = create('basic');
|
||||
test('creates routes with trailingSlashes = always', () => {
|
||||
const { routes } = create('basic', 'always');
|
||||
assert.equal(cleanRoutes(routes), [
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/$/,
|
||||
params: [],
|
||||
component: 'basic/index.astro',
|
||||
path: '/',
|
||||
},
|
||||
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/about\/$/,
|
||||
params: [],
|
||||
component: 'basic/about.astro',
|
||||
path: '/about',
|
||||
},
|
||||
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/blog\/$/,
|
||||
params: [],
|
||||
component: 'basic/blog/index.astro',
|
||||
path: '/blog',
|
||||
},
|
||||
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/blog\/([^/]+?)\/$/,
|
||||
params: ['slug'],
|
||||
component: 'basic/blog/[slug].astro',
|
||||
path: null,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('creates routes with trailingSlashes = never', () => {
|
||||
const { routes } = create('basic', 'never');
|
||||
assert.equal(cleanRoutes(routes), [
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/$/,
|
||||
params: [],
|
||||
component: 'basic/index.astro',
|
||||
path: '/',
|
||||
},
|
||||
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/about$/,
|
||||
params: [],
|
||||
component: 'basic/about.astro',
|
||||
path: '/about',
|
||||
},
|
||||
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/blog$/,
|
||||
params: [],
|
||||
component: 'basic/blog/index.astro',
|
||||
path: '/blog',
|
||||
},
|
||||
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/blog\/([^/]+?)$/,
|
||||
params: ['slug'],
|
||||
component: 'basic/blog/[slug].astro',
|
||||
path: null,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('creates routes with trailingSlashes = ignore', () => {
|
||||
const { routes } = create('basic', 'ignore');
|
||||
assert.equal(cleanRoutes(routes), [
|
||||
{
|
||||
type: 'page',
|
||||
|
@ -64,7 +136,7 @@ test('creates routes', () => {
|
|||
});
|
||||
|
||||
test('encodes invalid characters', () => {
|
||||
const { routes } = create('encoding');
|
||||
const { routes } = create('encoding', 'always');
|
||||
|
||||
// had to remove ? and " because windows
|
||||
|
||||
|
@ -76,34 +148,34 @@ test('encodes invalid characters', () => {
|
|||
routes.map((p) => p.pattern),
|
||||
[
|
||||
// /^\/%22$/,
|
||||
/^\/%23\/?$/,
|
||||
/^\/%23\/$/,
|
||||
// /^\/%3F$/
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('ignores files and directories with leading underscores', () => {
|
||||
const { routes } = create('hidden-underscore');
|
||||
const { routes } = create('hidden-underscore', 'always');
|
||||
|
||||
assert.equal(routes.map((r) => r.component).filter(Boolean), ['hidden-underscore/index.astro', 'hidden-underscore/e/f/g/h.astro']);
|
||||
});
|
||||
|
||||
test('ignores files and directories with leading dots except .well-known', () => {
|
||||
const { routes } = create('hidden-dot');
|
||||
const { routes } = create('hidden-dot', 'always');
|
||||
|
||||
assert.equal(routes.map((r) => r.component).filter(Boolean), ['hidden-dot/.well-known/dnt-policy.astro']);
|
||||
});
|
||||
|
||||
test('fails if dynamic params are not separated', () => {
|
||||
assert.throws(() => {
|
||||
create('invalid-params');
|
||||
create('invalid-params', 'always');
|
||||
}, /Invalid route invalid-params\/\[foo\]\[bar\]\.astro — parameters must be separated/);
|
||||
});
|
||||
|
||||
test('disallows rest parameters inside segments', () => {
|
||||
assert.throws(
|
||||
() => {
|
||||
create('invalid-rest');
|
||||
create('invalid-rest', 'always');
|
||||
},
|
||||
/** @param {Error} e */
|
||||
(e) => {
|
||||
|
@ -113,11 +185,11 @@ test('disallows rest parameters inside segments', () => {
|
|||
});
|
||||
|
||||
test('ignores things that look like lockfiles', () => {
|
||||
const { routes } = create('lockfiles');
|
||||
const { routes } = create('lockfiles', 'always');
|
||||
assert.equal(cleanRoutes(routes), [
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/foo\/?$/,
|
||||
pattern: /^\/foo\/$/,
|
||||
params: [],
|
||||
component: 'lockfiles/foo.astro',
|
||||
path: '/foo',
|
||||
|
@ -126,12 +198,12 @@ test('ignores things that look like lockfiles', () => {
|
|||
});
|
||||
|
||||
test('allows multiple slugs', () => {
|
||||
const { routes } = create('multiple-slugs');
|
||||
const { routes } = create('multiple-slugs', 'always');
|
||||
|
||||
assert.equal(cleanRoutes(routes), [
|
||||
{
|
||||
type: 'page',
|
||||
pattern: /^\/([^/]+?)\.([^/]+?)\/?$/,
|
||||
pattern: /^\/([^/]+?)\.([^/]+?)\/$/,
|
||||
component: 'multiple-slugs/[file].[ext].astro',
|
||||
params: ['file', 'ext'],
|
||||
path: null,
|
||||
|
@ -140,7 +212,7 @@ test('allows multiple slugs', () => {
|
|||
});
|
||||
|
||||
test('sorts routes correctly', () => {
|
||||
const { routes } = create('sorting');
|
||||
const { routes } = create('sorting', 'always');
|
||||
|
||||
assert.equal(
|
||||
routes.map((p) => p.component),
|
||||
|
|
Loading…
Reference in a new issue