= {
[P in keyof T as Exclude]: T[P];
};
-// Transform a string into its kebab case equivalent (camelCase -> kebab-case). Useful for CSS-in-JS to CSS.
-export type Kebab = T extends `${infer F}${infer R}`
- ? Kebab ? '' : '-'}${Lowercase}`>
- : A;
-
-// Transform every key of an object to its kebab case equivalent using the above utility
-export type KebabKeys = { [K in keyof T as K extends string ? Kebab : K]: T[K] };
-
// Similar to `keyof`, gets the type of all the values of an object
export type ValueOf = T[keyof T];
diff --git a/packages/astro/src/types/public/config.ts b/packages/astro/src/types/public/config.ts
index a2f9d3253ea9..4e7acda3bd5f 100644
--- a/packages/astro/src/types/public/config.ts
+++ b/packages/astro/src/types/public/config.ts
@@ -363,9 +363,9 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
* @see output
* @description
*
- * Deploy to your favorite server, serverless, or edge host with build adapters. Import one of our first-party adapters for [Netlify](https://docs.astro.build/en/guides/deploy/netlify/#adapter-for-ssr), [Vercel](https://docs.astro.build/en/guides/deploy/vercel/#adapter-for-ssr), and more to engage Astro SSR.
+ * Deploy to your favorite server, serverless, or edge host with build adapters. Import one of our first-party adapters ([Cloudflare](/en/guides/integrations-guide/cloudflare/), [Netlify](/en/guides/integrations-guide/netlify/), [Node.js](/en/guides/integrations-guide/node/), [Vercel](/en/guides/integrations-guide/vercel/)) or explore [community adapters](https://astro.build/integrations/2/?search=&categories%5B%5D=adapters) to enable on-demand rendering in your Astro project.
*
- * [See our On-demand Rendering guide](https://docs.astro.build/en/guides/on-demand-rendering/) for more on SSR, and [our deployment guides](https://docs.astro.build/en/guides/deploy/) for a complete list of hosts.
+ * See our [on-demand rendering guide](/en/guides/on-demand-rendering/) for more on Astro's server rendering options.
*
* ```js
* import netlify from '@astrojs/netlify';
@@ -906,6 +906,26 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
* ```
*/
+ /**
+ * @docs
+ * @name server.allowedHosts
+ * @type {string[] | true}
+ * @default `[]`
+ * @version 5.4.0
+ * @description
+ *
+ * A list of hostnames that Astro is allowed to respond to. When the value is set to `true`, any
+ * hostname is allowed.
+ *
+ * ```js
+ * {
+ * server: {
+ * allowedHosts: ['staging.example.com', 'qa.example.com']
+ * }
+ * }
+ * ```
+ */
+
/**
* @docs
* @name server.open
@@ -1311,7 +1331,7 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
* @description
* The default layout type for responsive images. Can be overridden by the `layout` prop on the image component.
* Requires the `experimental.responsiveImages` flag to be enabled.
- * - `responsive` - The image will scale to fit the container, maintaining its aspect ratio, but will not exceed the specified dimensions.
+ * - `constrained` - The image will scale to fit the container, maintaining its aspect ratio, but will not exceed the specified dimensions.
* - `fixed` - The image will maintain its original dimensions.
* - `full-width` - The image will scale to fit the container, maintaining its aspect ratio.
*/
@@ -2076,14 +2096,14 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
* }
* ```
*
- * When enabled, you can pass a `layout` props to any `` or `` component to create a responsive image. When a layout is set, images have automatically generated `srcset` and `sizes` attributes based on the image's dimensions and the layout type. Images with `responsive` and `full-width` layouts will have styles applied to ensure they resize according to their container.
+ * When enabled, you can pass a `layout` props to any `` or `` component to create a responsive image. When a layout is set, images have automatically generated `srcset` and `sizes` attributes based on the image's dimensions and the layout type. Images with `constrained` and `full-width` layouts will have styles applied to ensure they resize according to their container.
*
* ```astro title=MyComponent.astro
* ---
* import { Image, Picture } from 'astro:assets';
* import myImage from '../assets/my_image.png';
* ---
- *
+ *
*
* ```
* This `` component will generate the following HTML output:
@@ -2105,31 +2125,28 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
* fetchpriority="auto"
* width="800"
* height="600"
- * style="--w: 800; --h: 600; --fit: cover; --pos: center;"
- * data-astro-image="responsive"
+ * style="--fit: cover; --pos: center;"
+ * data-astro-image="constrained"
* >
* ```
*
* The following styles are applied to ensure the images resize correctly:
*
* ```css title="Responsive Image Styles"
- * [data-astro-image] {
- * width: 100%;
- * height: auto;
- * object-fit: var(--fit);
- * object-position: var(--pos);
- * aspect-ratio: var(--w) / var(--h)
+ *
+ * :where([data-astro-image]) {
+ * object-fit: var(--fit);
+ * object-position: var(--pos);
* }
*
- * [data-astro-image=responsive] {
- * max-width: calc(var(--w) * 1px);
- * max-height: calc(var(--h) * 1px)
+ * :where([data-astro-image='full-width']) {
+ * width: 100%;
* }
*
- * [data-astro-image=fixed] {
- * width: calc(var(--w) * 1px);
- * height: calc(var(--h) * 1px)
+ * :where([data-astro-image='constrained']) {
+ * max-width: 100%;
* }
+ *
* ```
* You can enable responsive images for all `` and `` components by setting `image.experimentalLayout` with a default value. This can be overridden by the `layout` prop on each component.
*
@@ -2138,7 +2155,7 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
* {
* image: {
* // Used for all `` and `` components unless overridden
- * experimentalLayout: 'responsive',
+ * experimentalLayout: 'constrained',
* },
* experimental: {
* responsiveImages: true,
@@ -2163,12 +2180,12 @@ export interface ViteUserConfig extends OriginalViteUserConfig {
*
* These are additional properties available to the `` and `` components when responsive images are enabled:
*
- * - `layout`: The layout type for the image. Can be `responsive`, `fixed`, `full-width` or `none`. Defaults to value of `image.experimentalLayout`.
+ * - `layout`: The layout type for the image. Can be `constrained`, `fixed`, `full-width` or `none`. Defaults to value of `image.experimentalLayout`.
* - `fit`: Defines how the image should be cropped if the aspect ratio is changed. Values match those of CSS `object-fit`. Defaults to `cover`, or the value of `image.experimentalObjectFit` if set.
* - `position`: Defines the position of the image crop if the aspect ratio is changed. Values match those of CSS `object-position`. Defaults to `center`, or the value of `image.experimentalObjectPosition` if set.
* - `priority`: If set, eagerly loads the image. Otherwise images will be lazy-loaded. Use this for your largest above-the-fold image. Defaults to `false`.
*
- * The `widths` and `sizes` attributes are automatically generated based on the image's dimensions and the layout type, and in most cases should not be set manually. The generated `sizes` attribute for `responsive` and `full-width` images
+ * The `widths` and `sizes` attributes are automatically generated based on the image's dimensions and the layout type, and in most cases should not be set manually. The generated `sizes` attribute for `constrained` and `full-width` images
* is based on the assumption that the image is displayed at close to the full width of the screen when the viewport is smaller than the image's width. If it is significantly different (e.g. if it's in a multi-column layout on small screens) you may need to adjust the `sizes` attribute manually for best results.
*
* The `densities` attribute is not compatible with responsive images and will be ignored if set.
diff --git a/packages/astro/src/types/typed-emitter.ts b/packages/astro/src/types/typed-emitter.ts
index 43139bd4e687..771907bf0863 100644
--- a/packages/astro/src/types/typed-emitter.ts
+++ b/packages/astro/src/types/typed-emitter.ts
@@ -4,7 +4,7 @@
* https://github.com/andywer/typed-emitter/blob/9a139b6fa0ec6b0db6141b5b756b784e4f7ef4e4/LICENSE
*/
-export type EventMap = {
+type EventMap = {
[key: string]: (...args: any[]) => void;
};
diff --git a/packages/astro/src/vite-plugin-astro-server/controller.ts b/packages/astro/src/vite-plugin-astro-server/controller.ts
index 9ba345d69a20..06c8796e7e39 100644
--- a/packages/astro/src/vite-plugin-astro-server/controller.ts
+++ b/packages/astro/src/vite-plugin-astro-server/controller.ts
@@ -16,7 +16,7 @@ export interface DevServerController {
onHMRError: LoaderEvents['hmr-error'];
}
-export type CreateControllerParams =
+type CreateControllerParams =
| {
loader: ModuleLoader;
}
@@ -84,7 +84,7 @@ function createLoaderController(loader: ModuleLoader): DevServerController {
return controller;
}
-export interface RunWithErrorHandlingParams {
+interface RunWithErrorHandlingParams {
controller: DevServerController;
pathname: string;
run: () => Promise;
diff --git a/packages/astro/src/vite-plugin-astro-server/plugin.ts b/packages/astro/src/vite-plugin-astro-server/plugin.ts
index 88b8b0a81b1a..3e64b560a87f 100644
--- a/packages/astro/src/vite-plugin-astro-server/plugin.ts
+++ b/packages/astro/src/vite-plugin-astro-server/plugin.ts
@@ -26,7 +26,7 @@ import { handleRequest } from './request.js';
import { setRouteError } from './server-state.js';
import { trailingSlashMiddleware } from './trailing-slash.js';
-export interface AstroPluginOptions {
+interface AstroPluginOptions {
settings: AstroSettings;
logger: Logger;
fs: typeof fs;
diff --git a/packages/astro/src/vite-plugin-astro-server/response.ts b/packages/astro/src/vite-plugin-astro-server/response.ts
index ac7883c6028f..a1747c2dd54c 100644
--- a/packages/astro/src/vite-plugin-astro-server/response.ts
+++ b/packages/astro/src/vite-plugin-astro-server/response.ts
@@ -1,29 +1,11 @@
import type http from 'node:http';
import { Http2ServerResponse } from 'node:http2';
-import type { ErrorWithMetadata } from '../core/errors/index.js';
-import type { ModuleLoader } from '../core/module-loader/index.js';
-
import { Readable } from 'node:stream';
import { getSetCookiesFromResponse } from '../core/cookies/index.js';
import { getViteErrorPayload } from '../core/errors/dev/index.js';
+import type { ErrorWithMetadata } from '../core/errors/index.js';
+import type { ModuleLoader } from '../core/module-loader/index.js';
import { redirectTemplate } from '../core/routing/3xx.js';
-import notFoundTemplate from '../template/4xx.js';
-
-export async function handle404Response(
- origin: string,
- req: http.IncomingMessage,
- res: http.ServerResponse,
-) {
- const pathname = decodeURI(new URL(origin + req.url).pathname);
-
- const html = notFoundTemplate({
- statusCode: 404,
- title: 'Not found',
- tabTitle: '404: Not Found',
- pathname,
- });
- writeHtmlResponse(res, 404, html);
-}
export async function handle500Response(
loader: ModuleLoader,
diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts
index cbaa768c414f..8c52ed4dc218 100644
--- a/packages/astro/src/vite-plugin-astro-server/route.ts
+++ b/packages/astro/src/vite-plugin-astro-server/route.ts
@@ -30,7 +30,7 @@ type AsyncReturnType Promise> = T extends (
? R
: any;
-export interface MatchedRoute {
+interface MatchedRoute {
route: RouteData;
filePath: URL;
resolvedPathname: string;
diff --git a/packages/astro/src/vite-plugin-astro-server/server-state.ts b/packages/astro/src/vite-plugin-astro-server/server-state.ts
index 94f1fe8a5027..5e6c13111dc1 100644
--- a/packages/astro/src/vite-plugin-astro-server/server-state.ts
+++ b/packages/astro/src/vite-plugin-astro-server/server-state.ts
@@ -1,6 +1,6 @@
-export type ErrorState = 'fresh' | 'error';
+type ErrorState = 'fresh' | 'error';
-export interface RouteState {
+interface RouteState {
state: ErrorState;
error?: Error;
}
@@ -18,10 +18,6 @@ export function createServerState(): ServerState {
};
}
-export function hasAnyFailureState(serverState: ServerState) {
- return serverState.state !== 'fresh';
-}
-
export function setRouteError(serverState: ServerState, pathname: string, error: Error) {
if (serverState.routes.has(pathname)) {
const routeState = serverState.routes.get(pathname)!;
diff --git a/packages/astro/src/vite-plugin-astro/hmr.ts b/packages/astro/src/vite-plugin-astro/hmr.ts
index 93fecc7aa1f0..1dd09d143cca 100644
--- a/packages/astro/src/vite-plugin-astro/hmr.ts
+++ b/packages/astro/src/vite-plugin-astro/hmr.ts
@@ -3,7 +3,7 @@ import type { Logger } from '../core/logger/core.js';
import type { CompileMetadata } from './types.js';
import { frontmatterRE } from './utils.js';
-export interface HandleHotUpdateOptions {
+interface HandleHotUpdateOptions {
logger: Logger;
astroFileToCompileMetadata: Map;
}
diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts
index 21d9dcfb1486..8edbc98ae31c 100644
--- a/packages/astro/src/vite-plugin-astro/index.ts
+++ b/packages/astro/src/vite-plugin-astro/index.ts
@@ -2,11 +2,7 @@ import type { SourceDescription } from 'rollup';
import type * as vite from 'vite';
import type { Logger } from '../core/logger/core.js';
import type { AstroSettings } from '../types/astro.js';
-import type {
- PluginCssMetadata as AstroPluginCssMetadata,
- PluginMetadata as AstroPluginMetadata,
- CompileMetadata,
-} from './types.js';
+import type { PluginMetadata as AstroPluginMetadata, CompileMetadata } from './types.js';
import { defaultClientConditions, defaultServerConditions, normalizePath } from 'vite';
import type { AstroConfig } from '../types/public/config.js';
@@ -16,7 +12,7 @@ import { handleHotUpdate } from './hmr.js';
import { parseAstroRequest } from './query.js';
import { loadId } from './utils.js';
export { getAstroMetadata } from './metadata.js';
-export type { AstroPluginMetadata, AstroPluginCssMetadata };
+export type { AstroPluginMetadata };
interface AstroPluginOptions {
settings: AstroSettings;
@@ -138,17 +134,15 @@ export default function astro({ settings, logger }: AstroPluginOptions): vite.Pl
return {
code: result.code,
- // This metadata is used by `cssScopeToPlugin` to remove this module from the bundle
- // if the `filename` default export (the Astro component) is unused.
+ // `vite.cssScopeTo` is a Vite feature that allows this CSS to be treeshaken
+ // if the Astro component's default export is not used
meta: result.isGlobal
? undefined
- : ({
- astroCss: {
- cssScopeTo: {
- [filename]: ['default'],
- },
+ : {
+ vite: {
+ cssScopeTo: [filename, 'default'],
},
- } satisfies AstroPluginCssMetadata),
+ },
};
}
case 'script': {
diff --git a/packages/astro/src/vite-plugin-astro/query.ts b/packages/astro/src/vite-plugin-astro/query.ts
index c9829de3f6a8..266657d69790 100644
--- a/packages/astro/src/vite-plugin-astro/query.ts
+++ b/packages/astro/src/vite-plugin-astro/query.ts
@@ -1,4 +1,4 @@
-export interface AstroQuery {
+interface AstroQuery {
astro?: boolean;
src?: boolean;
type?: 'script' | 'template' | 'style' | 'custom';
@@ -7,7 +7,7 @@ export interface AstroQuery {
raw?: boolean;
}
-export interface ParsedRequestResult {
+interface ParsedRequestResult {
filename: string;
query: AstroQuery;
}
diff --git a/packages/astro/src/vite-plugin-astro/types.ts b/packages/astro/src/vite-plugin-astro/types.ts
index d85fd6483064..0cb0c70c0799 100644
--- a/packages/astro/src/vite-plugin-astro/types.ts
+++ b/packages/astro/src/vite-plugin-astro/types.ts
@@ -2,7 +2,7 @@ import type { HoistedScript, TransformResult } from '@astrojs/compiler';
import type { CompileCssResult } from '../core/compile/types.js';
import type { PropagationHint } from '../types/public/internal.js';
-export interface PageOptions {
+interface PageOptions {
prerender?: boolean;
}
@@ -18,27 +18,6 @@ export interface PluginMetadata {
};
}
-export interface PluginCssMetadata {
- astroCss: {
- /**
- * For Astro CSS virtual modules, it can scope to the main Astro module's default export
- * so that if those exports are treeshaken away, the CSS module will also be treeshaken.
- *
- * Example config if the CSS id is `/src/Foo.astro?astro&type=style&lang.css`:
- * ```js
- * cssScopeTo: {
- * '/src/Foo.astro': ['default']
- * }
- * ```
- *
- * The above is the only config we use today, but we're exposing as a `Record` to follow the
- * upstream Vite implementation: https://github.com/vitejs/vite/pull/16058. When/If that lands,
- * we can also remove our custom implementation.
- */
- cssScopeTo: Record;
- };
-}
-
export interface CompileMetadata {
/** Used for HMR to compare code changes */
originalCode: string;
diff --git a/packages/astro/src/vite-plugin-load-fallback/index.ts b/packages/astro/src/vite-plugin-load-fallback/index.ts
index f7cc9cd1c907..02385207da59 100644
--- a/packages/astro/src/vite-plugin-load-fallback/index.ts
+++ b/packages/astro/src/vite-plugin-load-fallback/index.ts
@@ -6,7 +6,7 @@ import { cleanUrl } from '../vite-plugin-utils/index.js';
type NodeFileSystemModule = typeof nodeFs;
-export interface LoadFallbackPluginParams {
+interface LoadFallbackPluginParams {
fs?: NodeFileSystemModule;
root: URL;
}
diff --git a/packages/astro/src/vite-plugin-markdown/images.ts b/packages/astro/src/vite-plugin-markdown/images.ts
index b99d1af233b2..c98d3c2ca04f 100644
--- a/packages/astro/src/vite-plugin-markdown/images.ts
+++ b/packages/astro/src/vite-plugin-markdown/images.ts
@@ -15,7 +15,7 @@ export function getMarkdownCodeForImages(
const imageSources = {};
${localImagePaths
.map((entry) => {
- const rawUrl = JSON.stringify(entry.raw);
+ const rawUrl = JSON.stringify(entry.raw).replace(/'/g, ''');
return `{
const regex = new RegExp('__ASTRO_IMAGE_="([^"]*' + ${rawUrl.replace(
/[.*+?^${}()|[\]\\]/g,
@@ -25,7 +25,7 @@ export function getMarkdownCodeForImages(
let occurrenceCounter = 0;
while ((match = regex.exec(html)) !== null) {
const matchKey = ${rawUrl} + '_' + occurrenceCounter;
- const imageProps = JSON.parse(match[1].replace(/"/g, '"'));
+ const imageProps = JSON.parse(match[1].replace(/"/g, '"').replace(/'/g, "'"));
const { src, ...props } = imageProps;
imageSources[matchKey] = await getImage({src: Astro__${entry.safeName}, ...props});
occurrenceCounter++;
@@ -35,7 +35,7 @@ export function getMarkdownCodeForImages(
.join('\n')}
${remoteImagePaths
.map((raw) => {
- const rawUrl = JSON.stringify(raw);
+ const rawUrl = JSON.stringify(raw).replace(/'/g, ''');
return `{
const regex = new RegExp('__ASTRO_IMAGE_="([^"]*' + ${rawUrl.replace(
/[.*+?^${}()|[\]\\]/g,
@@ -45,7 +45,7 @@ export function getMarkdownCodeForImages(
let occurrenceCounter = 0;
while ((match = regex.exec(html)) !== null) {
const matchKey = ${rawUrl} + '_' + occurrenceCounter;
- const props = JSON.parse(match[1].replace(/"/g, '"'));
+ const props = JSON.parse(match[1].replace(/"/g, '"').replace(/'/g, "'"));
imageSources[matchKey] = await getImage(props);
occurrenceCounter++;
}
diff --git a/packages/astro/src/vite-plugin-scanner/index.ts b/packages/astro/src/vite-plugin-scanner/index.ts
index a86205484960..4f1700dfe79f 100644
--- a/packages/astro/src/vite-plugin-scanner/index.ts
+++ b/packages/astro/src/vite-plugin-scanner/index.ts
@@ -9,7 +9,7 @@ import { isEndpoint, isPage } from '../core/util.js';
import { normalizePath, rootRelativePath } from '../core/viteUtils.js';
import type { AstroSettings, RoutesList } from '../types/astro.js';
-export interface AstroPluginScannerOptions {
+interface AstroPluginScannerOptions {
settings: AstroSettings;
logger: Logger;
routesList: RoutesList;
diff --git a/packages/astro/templates/env.mjs b/packages/astro/templates/env.mjs
index 6526033514de..c314b4392aca 100644
--- a/packages/astro/templates/env.mjs
+++ b/packages/astro/templates/env.mjs
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
// @ts-check
import { schema } from 'virtual:astro:env/internal';
import {
diff --git a/packages/astro/test/astro-cookies.test.js b/packages/astro/test/astro-cookies.test.js
index 482474b54be2..e375cf1e8a74 100644
--- a/packages/astro/test/astro-cookies.test.js
+++ b/packages/astro/test/astro-cookies.test.js
@@ -194,5 +194,12 @@ describe('Astro.cookies', () => {
assert.equal(response.status, 200);
assert.match(response.headers.get('Set-Cookie'), /test=value/);
});
+
+ it('can set cookies in a rewritten endpoint request from middleware', async () => {
+ const request = new Request('http://example.com/rewrite-me');
+ const response = await app.render(request, { addCookieHeader: true });
+ assert.equal(response.status, 200);
+ assert.match(response.headers.get('Set-Cookie'), /my_cookie=value/);
+ });
});
});
diff --git a/packages/astro/test/build-concurrency.test.js b/packages/astro/test/build-concurrency.test.js
new file mode 100644
index 000000000000..87a0b4912856
--- /dev/null
+++ b/packages/astro/test/build-concurrency.test.js
@@ -0,0 +1,29 @@
+import * as assert from 'node:assert/strict';
+import { before, describe, it } from 'node:test';
+import { loadFixture } from './test-utils.js';
+
+describe('Building with concurrency > 1', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/build-concurrency/',
+ build: {
+ concurrency: 2,
+ },
+ });
+ });
+
+ it('Errors and exits', async () => {
+ let built = false;
+ try {
+ await fixture.build();
+ built = true;
+ } catch (err) {
+ assert.match(err.message, /This is a test/);
+ }
+
+ assert.equal(built, false, 'Build should not complete');
+ });
+});
diff --git a/packages/astro/test/core-image-layout.test.js b/packages/astro/test/core-image-layout.test.js
index bb0e03c481a6..16b62b95f9c3 100644
--- a/packages/astro/test/core-image-layout.test.js
+++ b/packages/astro/test/core-image-layout.test.js
@@ -86,22 +86,16 @@ describe('astro:image:layout', () => {
it('sets the style', () => {
let $img = $('#local-both img');
- assert.match($img.attr('style'), /--w: 300/);
- assert.match($img.attr('style'), /--h: 400/);
- assert.equal($img.data('astro-image'), 'responsive');
+ assert.equal($img.data('astro-image'), 'constrained');
});
it('sets the style when no dimensions set', () => {
let $img = $('#local img');
- assert.match($img.attr('style'), /--w: 2316/);
- assert.match($img.attr('style'), /--h: 1544/);
- assert.equal($img.data('astro-image'), 'responsive');
+ assert.equal($img.data('astro-image'), 'constrained');
});
it('sets style for fixed image', () => {
let $img = $('#local-fixed img');
- assert.match($img.attr('style'), /--w: 800/);
- assert.match($img.attr('style'), /--h: 600/);
assert.equal($img.data('astro-image'), 'fixed');
});
@@ -396,8 +390,8 @@ describe('astro:image:layout', () => {
it('adds inline style attributes', () => {
let $img = $('#picture-attributes img');
const style = $img.attr('style');
- assert.match(style, /--w:/);
- assert.match(style, /--h:/);
+ assert.match(style, /--fit:/);
+ assert.match(style, /--pos:/);
});
it('passing in style as an object', () => {
@@ -645,22 +639,16 @@ describe('astro:image:layout', () => {
it('sets the style', () => {
let $img = $('#local-both img');
- assert.match($img.attr('style'), /--w: 300/);
- assert.match($img.attr('style'), /--h: 400/);
- assert.equal($img.data('astro-image'), 'responsive');
+ assert.equal($img.data('astro-image'), 'constrained');
});
it('sets the style when no dimensions set', () => {
let $img = $('#local img');
- assert.match($img.attr('style'), /--w: 2316/);
- assert.match($img.attr('style'), /--h: 1544/);
- assert.equal($img.data('astro-image'), 'responsive');
+ assert.equal($img.data('astro-image'), 'constrained');
});
it('sets style for fixed image', () => {
let $img = $('#local-fixed img');
- assert.match($img.attr('style'), /--w: 800/);
- assert.match($img.attr('style'), /--h: 600/);
assert.equal($img.data('astro-image'), 'fixed');
});
diff --git a/packages/astro/test/core-image.test.js b/packages/astro/test/core-image.test.js
index 10ca9b686412..353f544a75cb 100644
--- a/packages/astro/test/core-image.test.js
+++ b/packages/astro/test/core-image.test.js
@@ -493,7 +493,7 @@ describe('astro:image', () => {
$ = cheerio.load(html);
let $img = $('img');
- assert.equal($img.length, 3);
+ assert.equal($img.length, 4);
$img.each((_, el) => {
assert.equal(el.attribs.src?.startsWith('/_image'), true);
});
diff --git a/packages/astro/test/fixtures/astro-cookies/src/middleware.ts b/packages/astro/test/fixtures/astro-cookies/src/middleware.ts
new file mode 100644
index 000000000000..c5df6f851f7c
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-cookies/src/middleware.ts
@@ -0,0 +1,9 @@
+import { defineMiddleware } from "astro:middleware";
+
+export const onRequest = defineMiddleware((ctx, next) => {
+ if (ctx.url.pathname === "/rewrite-me") {
+ return next("/rewrite-target");
+ } else {
+ return next();
+ }
+})
diff --git a/packages/astro/test/fixtures/build-concurrency/package.json b/packages/astro/test/fixtures/build-concurrency/package.json
new file mode 100644
index 000000000000..d5dfaf4598e9
--- /dev/null
+++ b/packages/astro/test/fixtures/build-concurrency/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "@test/concurrency",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/astro/test/fixtures/build-concurrency/src/pages/index.astro b/packages/astro/test/fixtures/build-concurrency/src/pages/index.astro
new file mode 100644
index 000000000000..3ce79d51ca0d
--- /dev/null
+++ b/packages/astro/test/fixtures/build-concurrency/src/pages/index.astro
@@ -0,0 +1,5 @@
+---
+throw Error('This is a test')
+---
+
+Hello world!
diff --git a/packages/astro/test/fixtures/build-concurrency/src/pages/page2.astro b/packages/astro/test/fixtures/build-concurrency/src/pages/page2.astro
new file mode 100644
index 000000000000..ecfc83400ea5
--- /dev/null
+++ b/packages/astro/test/fixtures/build-concurrency/src/pages/page2.astro
@@ -0,0 +1,4 @@
+---
+---
+
+Page 2
diff --git a/packages/astro/test/fixtures/core-image-layout/astro.config.mjs b/packages/astro/test/fixtures/core-image-layout/astro.config.mjs
index b32208e5f67a..b819fd8778a4 100644
--- a/packages/astro/test/fixtures/core-image-layout/astro.config.mjs
+++ b/packages/astro/test/fixtures/core-image-layout/astro.config.mjs
@@ -3,7 +3,7 @@ import { defineConfig } from 'astro/config';
export default defineConfig({
image: {
- experimentalLayout: 'responsive',
+ experimentalLayout: 'constrained',
},
experimental: {
diff --git a/packages/astro/test/fixtures/core-image/src/assets/penguin with apostrophe'.jpg b/packages/astro/test/fixtures/core-image/src/assets/penguin with apostrophe'.jpg
new file mode 100644
index 000000000000..1a8986ac5092
Binary files /dev/null and b/packages/astro/test/fixtures/core-image/src/assets/penguin with apostrophe'.jpg differ
diff --git a/packages/astro/test/fixtures/core-image/src/pages/specialChars.md b/packages/astro/test/fixtures/core-image/src/pages/specialChars.md
index a5f22cb59e45..ab52da3c5d06 100644
--- a/packages/astro/test/fixtures/core-image/src/pages/specialChars.md
+++ b/packages/astro/test/fixtures/core-image/src/pages/specialChars.md
@@ -1,5 +1,6 @@



+
Image with special characters in file name worked.
diff --git a/packages/astro/test/fixtures/reroute/src/pages/index.astro b/packages/astro/test/fixtures/reroute/src/pages/index.astro
index 91a6fd0fb0fc..64932710db3c 100644
--- a/packages/astro/test/fixtures/reroute/src/pages/index.astro
+++ b/packages/astro/test/fixtures/reroute/src/pages/index.astro
@@ -1,5 +1,6 @@
---
const auth = Astro.locals.auth;
+const origin = Astro.originPathname;
---
@@ -8,5 +9,6 @@ const auth = Astro.locals.auth;
Index
{auth ? Called auth
: ""}
+ Origin: {origin}
diff --git a/packages/astro/test/fixtures/rewrite-issue-13633/astro.config.mjs b/packages/astro/test/fixtures/rewrite-issue-13633/astro.config.mjs
new file mode 100644
index 000000000000..cb4250b192d4
--- /dev/null
+++ b/packages/astro/test/fixtures/rewrite-issue-13633/astro.config.mjs
@@ -0,0 +1,8 @@
+import { defineConfig } from 'astro/config';
+
+// https://astro.build/config
+export default defineConfig({
+ base: '',
+ trailingSlash: 'never',
+ output: 'server'
+});
diff --git a/packages/astro/test/fixtures/rewrite-issue-13633/package.json b/packages/astro/test/fixtures/rewrite-issue-13633/package.json
new file mode 100644
index 000000000000..58b8a21e221f
--- /dev/null
+++ b/packages/astro/test/fixtures/rewrite-issue-13633/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "@test/rewrite-issue13633",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/astro/test/fixtures/rewrite-issue-13633/src/middleware.js b/packages/astro/test/fixtures/rewrite-issue-13633/src/middleware.js
new file mode 100644
index 000000000000..4b3de7f2847b
--- /dev/null
+++ b/packages/astro/test/fixtures/rewrite-issue-13633/src/middleware.js
@@ -0,0 +1,4 @@
+export const onRequest = async (ctx, next) => {
+ const response = await next('/');
+ return response;
+};
diff --git a/packages/astro/test/fixtures/rewrite-issue-13633/src/pages/about.astro b/packages/astro/test/fixtures/rewrite-issue-13633/src/pages/about.astro
new file mode 100644
index 000000000000..17712c0f72fc
--- /dev/null
+++ b/packages/astro/test/fixtures/rewrite-issue-13633/src/pages/about.astro
@@ -0,0 +1,12 @@
+---
+
+---
+
+
+
+ About page
+
+
+About page
+
+
diff --git a/packages/astro/test/fixtures/rewrite-issue-13633/src/pages/index.astro b/packages/astro/test/fixtures/rewrite-issue-13633/src/pages/index.astro
new file mode 100644
index 000000000000..336e7fcfaeda
--- /dev/null
+++ b/packages/astro/test/fixtures/rewrite-issue-13633/src/pages/index.astro
@@ -0,0 +1,12 @@
+---
+
+---
+
+
+
+ Index page
+
+
+Index page
+
+
diff --git a/packages/astro/test/fonts.test.js b/packages/astro/test/fonts.test.js
index a4364aa62a78..4f8aabdb146c 100644
--- a/packages/astro/test/fonts.test.js
+++ b/packages/astro/test/fonts.test.js
@@ -1,76 +1,101 @@
-import assert from 'node:assert/strict';
// @ts-check
-import { after, before, describe, it } from 'node:test';
+import assert from 'node:assert/strict';
+import { readdir } from 'node:fs/promises';
+import { describe, it } from 'node:test';
import { fontProviders } from 'astro/config';
import * as cheerio from 'cheerio';
import { loadFixture } from './test-utils.js';
-describe('astro:fonts', () => {
- /** @type {import('./test-utils.js').Fixture} */
- let fixture;
- /** @type {import('./test-utils.js').DevServer} */
- let devServer;
+/**
+ * @param {Omit} inlineConfig
+ */
+async function createDevFixture(inlineConfig) {
+ const fixture = await loadFixture({ root: './fixtures/fonts/', ...inlineConfig });
+ const devServer = await fixture.startDevServer();
- describe(' component', () => {
- // TODO: remove once fonts are stabilized
- describe('Fonts are not enabled', () => {
- before(async () => {
- fixture = await loadFixture({
- root: './fixtures/fonts/',
- });
- devServer = await fixture.startDevServer();
- });
-
- after(async () => {
+ return {
+ fixture,
+ devServer,
+ run: async (/** @type {() => any} */ cb) => {
+ try {
+ return await cb();
+ } finally {
await devServer.stop();
- });
+ }
+ },
+ };
+}
+/**
+ * @param {Omit} inlineConfig
+ */
+async function createBuildFixture(inlineConfig) {
+ const fixture = await loadFixture({ root: './fixtures/fonts/', ...inlineConfig });
+ await fixture.build({});
- it('Throws an error if fonts are not enabled', async () => {
- const res = await fixture.fetch('/');
- const body = await res.text();
- assert.equal(
- body.includes('