0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-03-17 23:11:29 -05:00

Merge branch 'next' into responsive-images

This commit is contained in:
Matt Kane 2024-11-08 13:58:35 +00:00
commit ffe063c544
102 changed files with 1425 additions and 783 deletions

View file

@ -0,0 +1,5 @@
---
'astro': minor
---
Updates to Vite 6.0.0-beta.6

View file

@ -53,6 +53,7 @@
"eighty-boxes-applaud",
"eighty-donkeys-fly",
"eighty-ligers-punch",
"empty-houses-melt",
"five-jars-hear",
"fluffy-jars-live",
"forty-trains-notice",
@ -84,6 +85,7 @@
"nasty-crabs-worry",
"neat-dots-hear",
"neat-queens-learn",
"old-actors-learn",
"old-zebras-teach",
"perfect-fans-fly",
"pink-yaks-exercise",
@ -91,6 +93,7 @@
"poor-dots-add",
"poor-frogs-dream",
"poor-seals-clap",
"pretty-walls-camp",
"quick-ads-exercise",
"quick-onions-leave",
"rotten-phones-scream",
@ -113,6 +116,7 @@
"ten-walls-tap",
"three-days-cough",
"three-olives-reflect",
"tough-planets-dress",
"twelve-comics-march",
"twenty-cobras-push",
"unlucky-bobcats-sit",

View file

@ -0,0 +1,5 @@
---
'@astrojs/svelte': patch
---
New release to include changes from 5.7.3

View file

@ -0,0 +1,5 @@
---
'astro': minor
---
Adds a new components exported from `astro/components`: Welcome, to be used by the new Basics template

View file

@ -0,0 +1,50 @@
name: Continuous benchmark
on:
workflow_dispatch:
pull_request:
branches:
- main
push:
branches:
- main
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
FORCE_COLOR: true
CODSPEED_TOKEN: ${{ secrets.CODSPEED_TOKEN }}
CODSPEED: true
jobs:
codspeed:
if: ${{ github.repository_owner == 'withastro' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Setup PNPM
uses: pnpm/action-setup@v3
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm run build
- name: Run the benchmarks
uses: CodSpeedHQ/action@fa1dcde8d58f2ab0b407a6a24d6cc5a8c1444a8c # v3.1.0
timeout-minutes: 30
with:
run: pnpm benchmark codspeed

View file

@ -14,7 +14,7 @@ export const astroBin = path.resolve(astroPkgPath, '../astro.js');
export function calculateStat(numbers) {
const avg = numbers.reduce((a, b) => a + b, 0) / numbers.length;
const stdev = Math.sqrt(
numbers.map((x) => Math.pow(x - avg, 2)).reduce((a, b) => a + b, 0) / numbers.length
numbers.map((x) => Math.pow(x - avg, 2)).reduce((a, b) => a + b, 0) / numbers.length,
);
const max = Math.max(...numbers);
return { avg, stdev, max };

View file

@ -1,6 +1,6 @@
import { fileURLToPath } from 'node:url';
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import { exec } from 'tinyexec';
import { astroBin, calculateStat } from './_util.js';
/** Default project to run for this benchmark if not specified */
@ -8,9 +8,8 @@ export const defaultProject = 'render-default';
/**
* @param {URL} projectDir
* @param {URL} outputFile
*/
export async function run(projectDir, outputFile) {
export async function run(projectDir) {
const root = fileURLToPath(projectDir);
console.log('Benchmarking `astro --help`...');
@ -28,7 +27,7 @@ export async function run(projectDir, outputFile) {
printResult({
'astro --help': helpStat,
'astro info': infoStat,
})
}),
);
console.log('='.repeat(10));
}
@ -45,7 +44,7 @@ async function benchmarkCommand(command, args, root) {
for (let i = 0; i < 10; i++) {
const start = performance.now();
await exec(command, args, { nodeOptions: { cwd: root } });
await exec(command, args, { nodeOptions: { cwd: root }, throwOnError: true });
durations.push(performance.now() - start);
}
@ -69,6 +68,6 @@ function printResult(result) {
],
{
align: ['l', 'r', 'r', 'r'],
}
},
);
}

View file

@ -0,0 +1,50 @@
import path from 'node:path';
import { withCodSpeed } from '@codspeed/tinybench-plugin';
import { Bench } from 'tinybench';
import { exec } from 'tinyexec';
import { renderPages } from '../make-project/render-default.js';
import { astroBin } from './_util.js';
export async function run({ memory: _memory, render, stress: _stress }) {
const options = {
iterations: 10,
};
const bench = process.env.CODSPEED ? withCodSpeed(new Bench(options)) : new Bench(options);
let app;
bench.add(
'Rendering',
async () => {
console.info('Start task.');
const result = {};
for (const fileName of renderPages) {
const pathname = '/' + fileName.slice(0, -path.extname(fileName).length);
const request = new Request(new URL(pathname, 'http://exmpale.com'));
const response = await app.render(request);
const html = await response.text();
if (!result[pathname]) result[pathname] = [];
result[pathname].push(html);
}
console.info('Finish task.');
return result;
},
{
async beforeAll() {
// build for rendering
await exec(astroBin, ['build'], {
nodeOptions: {
cwd: render.root,
stdio: 'inherit',
},
});
const entry = new URL('./dist/server/entry.mjs', `file://${render.root}`);
const { manifest, createApp } = await import(entry);
app = createApp(manifest);
app.manifest = manifest;
},
},
);
await bench.run();
console.table(bench.table());
}

View file

@ -1,7 +1,7 @@
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { markdownTable } from 'markdown-table';
import { exec } from 'tinyexec';
import { astroBin } from './_util.js';
/** @typedef {Record<string, import('../../packages/astro/src/core/config/timer').Stat>} AstroTimerStat */
@ -26,6 +26,7 @@ export async function run(projectDir, outputFile) {
ASTRO_TIMER_PATH: outputFilePath,
},
},
throwOnError: true,
});
console.log('Raw results written to', outputFilePath);
@ -55,6 +56,6 @@ function printResult(output) {
],
{
align: ['l', 'r', 'r', 'r'],
}
},
);
}

View file

@ -1,12 +1,12 @@
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import http from 'node:http';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { markdownTable } from 'markdown-table';
import { waitUntilBusy } from 'port-authority';
import { calculateStat, astroBin } from './_util.js';
import { exec } from 'tinyexec';
import { renderPages } from '../make-project/render-default.js';
import { astroBin, calculateStat } from './_util.js';
const port = 4322;
@ -25,6 +25,7 @@ export async function run(projectDir, outputFile) {
cwd: root,
stdio: 'inherit',
},
throwOnError: true,
});
console.log('Previewing...');
@ -33,6 +34,7 @@ export async function run(projectDir, outputFile) {
cwd: root,
stdio: 'inherit',
},
throwOnError: true,
});
console.log('Waiting for server ready...');
@ -58,14 +60,14 @@ export async function run(projectDir, outputFile) {
console.log('Done!');
}
async function benchmarkRenderTime() {
export async function benchmarkRenderTime(portToListen = port) {
/** @type {Record<string, number[]>} */
const result = {};
for (const fileName of renderPages) {
// Render each file 100 times and push to an array
for (let i = 0; i < 100; i++) {
const pathname = '/' + fileName.slice(0, -path.extname(fileName).length);
const renderTime = await fetchRenderTime(`http://localhost:${port}${pathname}`);
const renderTime = await fetchRenderTime(`http://localhost:${portToListen}${pathname}`);
if (!result[pathname]) result[pathname] = [];
result[pathname].push(renderTime);
}
@ -95,7 +97,7 @@ function printResult(result) {
],
{
align: ['l', 'r', 'r', 'r'],
}
},
);
}

View file

@ -1,10 +1,10 @@
import autocannon from 'autocannon';
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import autocannon from 'autocannon';
import { markdownTable } from 'markdown-table';
import { waitUntilBusy } from 'port-authority';
import pb from 'pretty-bytes';
import { exec } from 'tinyexec';
import { astroBin } from './_util.js';
const port = 4321;
@ -24,12 +24,15 @@ export async function run(projectDir, outputFile) {
cwd: root,
stdio: 'inherit',
},
throwOnError: true,
});
console.log('Previewing...');
const previewProcess = execaCommand(`${astroBin} preview --port ${port}`, {
cwd: root,
stdio: 'inherit',
const previewProcess = await exec(astroBin, ['preview', '--port', port], {
nodeOptions: {
cwd: root,
stdio: 'inherit',
},
});
console.log('Waiting for server ready...');
@ -58,7 +61,7 @@ export async function run(projectDir, outputFile) {
/**
* @returns {Promise<import('autocannon').Result>}
*/
async function benchmarkCannon() {
export async function benchmarkCannon() {
return new Promise((resolve, reject) => {
const instance = autocannon(
{
@ -75,7 +78,7 @@ async function benchmarkCannon() {
instance.stop();
resolve(result);
}
}
},
);
autocannon.track(instance, { renderResultsTable: false });
});
@ -94,7 +97,7 @@ function printResult(output) {
],
{
align: ['l', 'r', 'r', 'r'],
}
},
);
const reqAndBytesTable = markdownTable(
@ -105,7 +108,7 @@ function printResult(output) {
],
{
align: ['l', 'r', 'r', 'r', 'r'],
}
},
);
return `${latencyTable}\n\n${reqAndBytesTable}`;

View file

@ -1,7 +1,7 @@
import mri from 'mri';
import fs from 'node:fs/promises';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import {fileURLToPath, pathToFileURL} from 'node:url';
const args = mri(process.argv.slice(2));
@ -14,6 +14,7 @@ Command
memory Run build memory and speed test
render Run rendering speed test
server-stress Run server stress test
codspeed Run codspeed test
cli-startup Run CLI startup speed test
Options
@ -29,6 +30,7 @@ const benchmarks = {
render: () => import('./bench/render.js'),
'server-stress': () => import('./bench/server-stress.js'),
'cli-startup': () => import('./bench/cli-startup.js'),
codspeed: () => import('./bench/codspeed.js')
};
if (commandName && !(commandName in benchmarks)) {
@ -37,12 +39,26 @@ if (commandName && !(commandName in benchmarks)) {
}
if (commandName) {
// Run single benchmark
const bench = benchmarks[commandName];
const benchMod = await bench();
const projectDir = await makeProject(args.project || benchMod.defaultProject);
const outputFile = await getOutputFile(commandName);
await benchMod.run(projectDir, outputFile);
if (commandName === 'codspeed') {
const render = await makeProject('render-bench');
const rootRender = fileURLToPath(render);
const bench = benchmarks[commandName];
const benchMod = await bench();
const payload = {
render: {
root: rootRender,
output: await getOutputFile('render')
},
};
await benchMod.run(payload);
} else {
// Run single benchmark
const bench = benchmarks[commandName];
const benchMod = await bench();
const projectDir = await makeProject(args.project || benchMod.defaultProject);
const outputFile = await getOutputFile(commandName);
await benchMod.run(projectDir, outputFile);
}
} else {
// Run all benchmarks
for (const name in benchmarks) {
@ -54,7 +70,7 @@ if (commandName) {
}
}
async function makeProject(name) {
export async function makeProject(name) {
console.log('Making project:', name);
const projectDir = new URL(`./projects/${name}/`, import.meta.url);
@ -78,6 +94,5 @@ async function getOutputFile(benchmarkName) {
// Prepare output file directory
await fs.mkdir(new URL('./', file), { recursive: true });
return file;
}

View file

@ -0,0 +1,132 @@
import fs from 'node:fs/promises';
import { loremIpsumHtml, loremIpsumMd } from './_util.js';
// Map of files to be generated and tested for rendering.
// Ideally each content should be similar for comparison.
const renderFiles = {
'components/ListItem.astro': `\
---
const { className, item, attrs } = Astro.props;
const nested = item !== 0;
---
<li class={className}>
<a
href={item}
aria-current={item === 0}
class:list={[{ large: !nested }, className]}
{...attrs}
>
<span>{item}</span>
</a>
</li>
`,
'components/Sublist.astro': `\
---
import ListItem from '../components/ListItem.astro';
const { items } = Astro.props;
const className = "text-red-500";
const style = { color: "red" };
---
<ul style={style}>
{items.map((item) => (
<ListItem className={className} item={item} attrs={{}} />
))}
</ul>
`,
'pages/astro.astro': `\
---
const className = "text-red-500";
const style = { color: "red" };
const items = Array.from({ length: 10000 }, (_, i) => ({i}));
---
<html>
<head>
<title>My Site</title>
</head>
<body>
<h1 class={className + ' text-lg'}>List</h1>
<ul style={style}>
{items.map((item) => (
<li class={className}>
<a
href={item.i}
aria-current={item.i === 0}
class:list={[{ large: item.i === 0 }, className]}
{...({})}
>
<span>{item.i}</span>
</a>
</li>
))}
</ul>
${Array.from({ length: 1000 })
.map(() => `<p>${loremIpsumHtml}</p>`)
.join('\n')}
</body>
</html>`,
'pages/md.md': `\
# List
${Array.from({ length: 1000 }, (_, i) => i)
.map((v) => `- ${v}`)
.join('\n')}
${Array.from({ length: 1000 })
.map(() => loremIpsumMd)
.join('\n\n')}
`,
'pages/mdx.mdx': `\
export const className = "text-red-500";
export const style = { color: "red" };
export const items = Array.from({ length: 1000 }, (_, i) => i);
# List
<ul style={style}>
{items.map((item) => (
<li class={className}>{item}</li>
))}
</ul>
${Array.from({ length: 1000 })
.map(() => loremIpsumMd)
.join('\n\n')}
`,
};
export const renderPages = [];
for (const file of Object.keys(renderFiles)) {
if (file.startsWith('pages/')) {
renderPages.push(file.replace('pages/', ''));
}
}
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/components', projectDir), { recursive: true });
await Promise.all(
Object.entries(renderFiles).map(([name, content]) => {
return fs.writeFile(new URL(`./src/${name}`, projectDir), content, 'utf-8');
})
);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
import adapter from '@benchmark/adapter';
import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
output: 'server',
adapter: adapter(),
});`,
'utf-8'
);
}

View file

@ -10,6 +10,7 @@
"@astrojs/mdx": "workspace:*",
"@astrojs/node": "^8.3.4",
"@benchmark/timer": "workspace:*",
"@benchmark/adapter": "workspace:*",
"astro": "workspace:*",
"autocannon": "^7.15.0",
"markdown-table": "^3.0.4",
@ -18,5 +19,9 @@
"pretty-bytes": "^6.1.1",
"sharp": "^0.33.3",
"tinyexec": "^0.3.1"
},
"devDependencies": {
"@codspeed/tinybench-plugin": "^3.1.1",
"tinybench": "^2.9.0"
}
}

View file

@ -0,0 +1,3 @@
# @benchmark/timer
Like `@astrojs/node`, but returns the rendered time in milliseconds for the page instead of the page content itself. This is used for internal benchmarks only.

View file

@ -0,0 +1,35 @@
{
"name": "@benchmark/adapter",
"description": "Bench adapter",
"private": true,
"version": "0.0.0",
"type": "module",
"types": "./dist/index.d.ts",
"author": "withastro",
"license": "MIT",
"keywords": [
"withastro",
"astro-adapter"
],
"exports": {
".": "./dist/index.js",
"./server.js": "./dist/server.js",
"./package.json": "./package.json"
},
"scripts": {
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
"build:ci": "astro-scripts build \"src/**/*.ts\"",
"dev": "astro-scripts dev \"src/**/*.ts\""
},
"dependencies": {
"server-destroy": "^1.0.1"
},
"peerDependencies": {
"astro": "workspace:*"
},
"devDependencies": {
"@types/server-destroy": "^1.0.4",
"astro": "workspace:*",
"astro-scripts": "workspace:*"
}
}

View file

@ -0,0 +1,32 @@
import type { AstroAdapter, AstroIntegration } from 'astro';
export default function createIntegration(): AstroIntegration {
return {
name: '@benchmark/timer',
hooks: {
'astro:config:setup': ({ updateConfig }) => {
updateConfig({
vite: {
ssr: {
noExternal: ['@benchmark/timer'],
},
},
});
},
'astro:config:done': ({ setAdapter }) => {
setAdapter({
name: '@benchmark/adapter',
serverEntrypoint: '@benchmark/adapter/server.js',
exports: ['manifest', 'createApp'],
supportedAstroFeatures: {
serverOutput: 'stable',
envGetSecret: 'experimental',
staticOutput: 'stable',
hybridOutput: 'stable',
i18nDomains: 'stable',
},
});
},
},
};
}

View file

@ -0,0 +1,34 @@
import * as fs from 'node:fs';
import type { SSRManifest } from 'astro';
import { App } from 'astro/app';
import { applyPolyfills } from 'astro/app/node';
applyPolyfills();
class MyApp extends App {
#manifest: SSRManifest | undefined;
#streaming: boolean;
constructor(manifest: SSRManifest, streaming = false) {
super(manifest, streaming);
this.#manifest = manifest;
this.#streaming = streaming;
}
async render(request: Request) {
const url = new URL(request.url);
if (this.#manifest?.assets.has(url.pathname)) {
const filePath = new URL('../../client/' + this.removeBase(url.pathname), import.meta.url);
const data = await fs.promises.readFile(filePath);
return new Response(data);
}
return super.render(request);
}
}
export function createExports(manifest: SSRManifest) {
return {
manifest,
createApp: (streaming: boolean) => new MyApp(manifest, streaming),
};
}

View file

@ -0,0 +1,7 @@
{
"extends": "../../../tsconfig.base.json",
"include": ["src"],
"compilerOptions": {
"outDir": "./dist"
}
}

View file

@ -6,7 +6,9 @@ export function getAdapter(): AstroAdapter {
serverEntrypoint: '@benchmark/timer/server.js',
previewEntrypoint: '@benchmark/timer/preview.js',
exports: ['handler'],
supportedAstroFeatures: {},
supportedAstroFeatures: {
serverOutput: 'stable',
},
};
}

View file

@ -9,20 +9,17 @@
"**/_temp-fixtures/**",
"**/vendor/**",
"**/.vercel/**",
"benchmark/projects/",
"benchmark/results/",
"benchmark/bench/_template.js",
],
"include": ["test/**", "e2e/**", "packages/**", "/scripts/**"],
"include": ["test/**", "e2e/**", "packages/**", "/scripts/**", "benchmark/bench"],
},
"formatter": {
"indentStyle": "tab",
"indentWidth": 2,
"lineWidth": 100,
"ignore": [
"benchmark/projects/",
"benchmark/results/",
".changeset",
"pnpm-lock.yaml",
"*.astro",
],
"ignore": [".changeset", "pnpm-lock.yaml", "*.astro"],
},
"organizeImports": {
"enabled": true,

View file

@ -10,6 +10,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
}
}

View file

@ -13,6 +13,6 @@
"@astrojs/mdx": "^4.0.0-beta.3",
"@astrojs/rss": "^4.0.9",
"@astrojs/sitemap": "^3.2.1",
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
}
}

View file

@ -15,7 +15,7 @@
],
"scripts": {},
"devDependencies": {
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
},
"peerDependencies": {
"astro": "^4.0.0 || ^5.0.0"

View file

@ -11,7 +11,7 @@
"test": "vitest run"
},
"dependencies": {
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"@astrojs/react": "^3.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",

View file

@ -13,6 +13,6 @@
"@astrojs/alpinejs": "^0.4.0",
"@types/alpinejs": "^3.13.10",
"alpinejs": "^3.14.3",
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
}
}

View file

@ -13,11 +13,11 @@
"@astrojs/preact": "^3.5.3",
"@astrojs/react": "^3.6.2",
"@astrojs/solid-js": "^4.4.2",
"@astrojs/svelte": "^6.0.0-beta.1",
"@astrojs/svelte": "^6.0.0-beta.2",
"@astrojs/vue": "^5.0.0-beta.1",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"preact": "^10.24.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",

View file

@ -12,7 +12,7 @@
"dependencies": {
"@astrojs/preact": "^3.5.3",
"@preact/signals": "^1.3.0",
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"preact": "^10.24.3"
}
}

View file

@ -13,7 +13,7 @@
"@astrojs/react": "^3.6.2",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"react": "^18.3.1",
"react-dom": "^18.3.1"
}

View file

@ -11,7 +11,7 @@
},
"dependencies": {
"@astrojs/solid-js": "^4.4.2",
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"solid-js": "^1.9.2"
}
}

View file

@ -10,8 +10,8 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/svelte": "^6.0.0-beta.1",
"astro": "^5.0.0-beta.6",
"@astrojs/svelte": "^6.0.0-beta.2",
"astro": "^5.0.0-beta.7",
"svelte": "^4.2.19"
}
}

View file

@ -11,7 +11,7 @@
},
"dependencies": {
"@astrojs/vue": "^5.0.0-beta.1",
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"vue": "^3.5.12"
}
}

View file

@ -11,6 +11,6 @@
},
"dependencies": {
"@astrojs/node": "^9.0.0-alpha.1",
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
}
}

View file

@ -15,7 +15,7 @@
],
"scripts": {},
"devDependencies": {
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
},
"peerDependencies": {
"astro": "^4.0.0"

View file

@ -10,6 +10,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
}
}

View file

@ -10,6 +10,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
}
}

View file

@ -12,8 +12,8 @@
},
"dependencies": {
"@astrojs/node": "^9.0.0-alpha.1",
"@astrojs/svelte": "^6.0.0-beta.1",
"astro": "^5.0.0-beta.6",
"@astrojs/svelte": "^6.0.0-beta.2",
"astro": "^5.0.0-beta.7",
"svelte": "^4.2.19"
}
}

View file

@ -9,8 +9,8 @@
"astro": "astro"
},
"dependencies": {
"astro": "^5.0.0-beta.6",
"sass": "^1.80.3",
"astro": "^5.0.0-beta.7",
"sass": "^1.80.6",
"sharp": "^0.33.3"
}
}

View file

@ -15,6 +15,6 @@
"./app": "./dist/app.js"
},
"devDependencies": {
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
}
}

View file

@ -11,6 +11,6 @@
},
"dependencies": {
"@astrojs/markdoc": "^0.12.0-beta.0",
"astro": "^5.0.0-beta.6"
"astro": "^5.0.0-beta.7"
}
}

View file

@ -12,7 +12,7 @@
"dependencies": {
"@astrojs/mdx": "^4.0.0-beta.3",
"@astrojs/preact": "^3.5.3",
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"preact": "^10.24.3"
}
}

View file

@ -12,7 +12,7 @@
"dependencies": {
"@astrojs/preact": "^3.5.3",
"@nanostores/preact": "^0.5.2",
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"nanostores": "^0.11.3",
"preact": "^10.24.3"
}

View file

@ -13,7 +13,7 @@
"@astrojs/mdx": "^4.0.0-beta.3",
"@astrojs/tailwind": "^5.1.2",
"@types/canvas-confetti": "^1.6.4",
"astro": "^5.0.0-beta.6",
"astro": "^5.0.0-beta.7",
"autoprefixer": "^10.4.20",
"canvas-confetti": "^1.9.3",
"postcss": "^8.4.47",

View file

@ -11,7 +11,7 @@
"test": "vitest"
},
"dependencies": {
"astro": "^5.0.0-beta.6",
"vitest": "^2.1.3"
"astro": "^5.0.0-beta.7",
"vitest": "^2.1.4"
}
}

View file

@ -59,7 +59,7 @@
"@changesets/cli": "^2.27.9",
"@types/node": "^18.17.8",
"esbuild": "^0.21.5",
"eslint": "^9.13.0",
"eslint": "^9.14.0",
"eslint-plugin-regexp": "^2.6.0",
"globby": "^14.0.2",
"only-allow": "^1.2.1",
@ -67,12 +67,12 @@
"prettier-plugin-astro": "^0.14.1",
"turbo": "^2.2.3",
"typescript": "~5.6.3",
"typescript-eslint": "^8.11.0"
"typescript-eslint": "^8.13.0"
},
"pnpm": {
"overrides": {
"vitest>vite": "6.0.0-beta.2",
"vite-node>vite": "6.0.0-beta.2"
"vitest>vite": "6.0.0-beta.6",
"vite-node>vite": "6.0.0-beta.6"
},
"peerDependencyRules": {
"allowAny": [

View file

@ -1,5 +1,13 @@
# astro
## 5.0.0-beta.7
### Minor Changes
- [#12323](https://github.com/withastro/astro/pull/12323) [`c280655`](https://github.com/withastro/astro/commit/c280655655cc6c22121f32c5f7c76836adf17230) Thanks [@bluwy](https://github.com/bluwy)! - Updates to Vite 6.0.0-beta.6
- [#12379](https://github.com/withastro/astro/pull/12379) [`94f4fe8`](https://github.com/withastro/astro/commit/94f4fe8180f02cf19fb617dde7d67d4f7bee8dac) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Adds a new components exported from `astro/components`: Welcome, to be used by the new Basics template
## 5.0.0-beta.6
### Major Changes
@ -1118,6 +1126,34 @@
- Updated dependencies [[`83a2a64`](https://github.com/withastro/astro/commit/83a2a648418ad30f4eb781d1c1b5f2d8a8ac846e)]:
- @astrojs/markdown-remark@6.0.0-alpha.0
## 4.16.10
### Patch Changes
- [#12311](https://github.com/withastro/astro/pull/12311) [`bf2723e`](https://github.com/withastro/astro/commit/bf2723e83140099914b29c6d51eb147a065be460) Thanks [@dinesh-58](https://github.com/dinesh-58)! - Adds `checked` to the list of boolean attributes.
- [#12363](https://github.com/withastro/astro/pull/12363) [`222f718`](https://github.com/withastro/astro/commit/222f71894cc7118319ce83b3b29fa61a9dbebb75) Thanks [@Fryuni](https://github.com/Fryuni)! - Fixes code generated by `astro add` command when adding a version of an integration other than the default `latest`.
- [#12368](https://github.com/withastro/astro/pull/12368) [`493fe43`](https://github.com/withastro/astro/commit/493fe43cd3ef94b087b8958031ecc964ae73463b) Thanks [@bluwy](https://github.com/bluwy)! - Improves error logs when executing commands
- [#12355](https://github.com/withastro/astro/pull/12355) [`c4726d7`](https://github.com/withastro/astro/commit/c4726d7ba8cc93157390ce64d5c8b718ed5cac29) Thanks [@apatel369](https://github.com/apatel369)! - Improves error reporting for invalid frontmatter in MDX files during the `astro build` command. The error message now includes the file path where the frontmatter parsing failed.
## 4.16.9
### Patch Changes
- [#12333](https://github.com/withastro/astro/pull/12333) [`836cd91`](https://github.com/withastro/astro/commit/836cd91c37cea8ae58dd04a326435fcb2c88f358) Thanks [@imattacus](https://github.com/imattacus)! - Destroy the server response stream if async error is thrown
- [#12358](https://github.com/withastro/astro/pull/12358) [`7680349`](https://github.com/withastro/astro/commit/76803498738f9e86e7948ce81e01e63607e03549) Thanks [@spacedawwwg](https://github.com/spacedawwwg)! - Honors `inlineAstroConfig` parameter in `getViteConfig` when creating a logger
- [#12353](https://github.com/withastro/astro/pull/12353) [`35795a1`](https://github.com/withastro/astro/commit/35795a1a54b2bfaf331c58ca91b47e5672e08c4e) Thanks [@hippotastic](https://github.com/hippotastic)! - Fixes an issue in dev server watch file handling that could cause multiple restarts for a single file change.
- [#12351](https://github.com/withastro/astro/pull/12351) [`5751488`](https://github.com/withastro/astro/commit/57514881655b62a0bc39ace1e1ed4b89b96f74ca) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Reverts a change made in `4.16.6` that prevented usage of `astro:env` secrets inside middleware in SSR
- [#12346](https://github.com/withastro/astro/pull/12346) [`20e5a84`](https://github.com/withastro/astro/commit/20e5a843c86e9328814615edf3e8a6fb5e4696cc) Thanks [@bluwy](https://github.com/bluwy)! - Fixes sourcemap generation when prefetch is enabled
- [#12349](https://github.com/withastro/astro/pull/12349) [`1fc83d3`](https://github.com/withastro/astro/commit/1fc83d3ba8315c31b2a3aadc77b20b1615d261a0) Thanks [@norskeld](https://github.com/norskeld)! - Fixes the `getImage` options type so it properly extends `ImageTransform`
## 4.16.8
### Patch Changes

View file

@ -1,8 +1,8 @@
// The `ts-ignore` comments here are necessary because we're importing this file inside the `astro:components`
// virtual module's types, which means that `tsc` will try to resolve these imports.
// @ts-ignore
export { default as Code } from "./Code.astro";
export { default as Code } from './Code.astro';
// @ts-ignore
export { default as Debug } from "./Debug.astro";
export { default as Debug } from './Debug.astro';
// @ts-ignore
export { default as Welcome } from "./Welcome.astro";
export { default as Welcome } from './Welcome.astro';

View file

@ -81,7 +81,8 @@ test.describe('Error display', () => {
expect(fileLocation).toMatch(/^vue\/VueRuntimeError.vue/);
});
test('shows correct line when a style preprocess has an error', async ({ page, astro }) => {
// TODO: unskip when upgrading to Vite 6.0.0-beta.7 or above
test.skip('shows correct line when a style preprocess has an error', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/astro-sass-error'), { waitUntil: 'networkidle' });
const { fileLocation, absoluteFileLocation } = await getErrorOverlayContent(page);

View file

@ -4,6 +4,6 @@
"private": true,
"dependencies": {
"astro": "workspace:*",
"sass": "^1.80.4"
"sass": "^1.80.6"
}
}

View file

@ -12,7 +12,7 @@
"preact": "^10.24.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sass": "^1.80.4",
"sass": "^1.80.6",
"solid-js": "^1.9.3",
"svelte": "^4.2.19",
"vue": "^3.5.12"

View file

@ -4,6 +4,6 @@
"private": true,
"devDependencies": {
"astro": "workspace:*",
"sass": "^1.80.4"
"sass": "^1.80.6"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "astro",
"version": "5.0.0-beta.6",
"version": "5.0.0-beta.7",
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
"type": "module",
"author": "withastro",
@ -165,7 +165,7 @@
"tsconfck": "^3.1.4",
"unist-util-visit": "^5.0.0",
"vfile": "^6.0.3",
"vite": "6.0.0-beta.2",
"vite": "6.0.0-beta.6",
"vitefu": "^1.0.3",
"which-pm": "^3.0.0",
"xxhash-wasm": "^1.0.2",
@ -200,7 +200,7 @@
"eol": "^0.10.0",
"execa": "^8.0.1",
"expect-type": "^1.1.0",
"fs-fixture": "^2.5.0",
"fs-fixture": "^2.6.0",
"mdast-util-mdx": "^3.0.0",
"mdast-util-mdx-jsx": "^3.1.3",
"node-mocks-http": "^1.16.1",
@ -209,8 +209,8 @@
"rehype-slug": "^6.0.0",
"rehype-toc": "^3.0.2",
"remark-code-titles": "^0.1.2",
"rollup": "^4.24.2",
"sass": "^1.80.4",
"rollup": "^4.24.4",
"sass": "^1.80.6",
"undici": "^6.20.1",
"unified": "^11.0.5",
"vitest": "^2.1.1"

View file

@ -1,5 +1,5 @@
import type { WithRequired } from '../type-utils.js';
import type { ImageLayout } from '../types/public/index.js';
import type { OmitPreservingIndexSignature, Simplify, WithRequired } from '../type-utils.js';
import type { VALID_INPUT_FORMATS, VALID_OUTPUT_FORMATS } from './consts.js';
import type { ImageService } from './services/service.js';
@ -67,10 +67,12 @@ export type SrcSetValue = UnresolvedSrcSetValue & {
/**
* A yet to be resolved image transform. Used by `getImage`
*/
export type UnresolvedImageTransform = Omit<ImageTransform, 'src'> & {
src: ImageMetadata | string | Promise<{ default: ImageMetadata }>;
inferSize?: boolean;
} & {
export type UnresolvedImageTransform = Simplify<
OmitPreservingIndexSignature<ImageTransform, 'src'> & {
src: ImageMetadata | string | Promise<{ default: ImageMetadata }>;
inferSize?: boolean;
}
> & {
[isESMImport]?: never;
};

View file

@ -9,7 +9,6 @@ import { getDefaultExportOptions } from 'magicast/helpers';
import preferredPM from 'preferred-pm';
import prompts from 'prompts';
import maxSatisfying from 'semver/ranges/max-satisfying.js';
import { exec } from 'tinyexec';
import yoctoSpinner from 'yocto-spinner';
import {
loadTSConfig,
@ -30,6 +29,7 @@ import { appendForwardSlash } from '../../core/path.js';
import { apply as applyPolyfill } from '../../core/polyfill.js';
import { ensureProcessNodeEnv, parseNpmName } from '../../core/util.js';
import { eventCliSession, telemetry } from '../../events/index.js';
import { exec } from '../exec.js';
import { type Flags, createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
import { fetchPackageJson, fetchPackageVersions } from '../install-package.js';
@ -344,7 +344,11 @@ export async function add(names: string[], { flags }: AddOptions) {
logger.info('SKIP_FORMAT', msg.success(`Configuration up-to-date.`));
break;
}
default: {
// NOTE: failure shouldn't happen in practice because `updateAstroConfig` doesn't return that.
// Pipe this to the same handling as `UpdateResult.updated` for now.
case UpdateResult.failure:
case UpdateResult.updated:
case undefined: {
const list = integrations.map((integration) => ` - ${integration.packageName}`).join('\n');
logger.info(
'SKIP_FORMAT',
@ -375,7 +379,7 @@ export async function add(names: string[], { flags }: AddOptions) {
`Unknown error parsing tsconfig.json or jsconfig.json. Could not update TypeScript settings.`,
);
}
default:
case UpdateResult.updated:
logger.info('SKIP_FORMAT', msg.success(`Successfully updated TypeScript settings`));
}
}
@ -390,13 +394,16 @@ function isAdapter(
// Some examples:
// - @astrojs/image => image
// - @astrojs/markdown-component => markdownComponent
// - @astrojs/image@beta => image
// - astro-cast => cast
// - astro-cast@next => cast
// - markdown-astro => markdown
// - some-package => somePackage
// - example.com => exampleCom
// - under_score => underScore
// - 123numeric => numeric
// - @npm/thingy => npmThingy
// - @npm/thingy@1.2.3 => npmThingy
// - @jane/foo.js => janeFoo
// - @tokencss/astro => tokencss
const toIdent = (name: string) => {
@ -409,7 +416,9 @@ const toIdent = (name: string) => {
// convert to camel case
.replace(/[.\-_/]+([a-zA-Z])/g, (_, w) => w.toUpperCase())
// drop invalid first characters
.replace(/^[^a-zA-Z$_]+/, '');
.replace(/^[^a-zA-Z$_]+/, '')
// drop version or tag
.replace(/@.*$/, '');
return `${ident[0].toLowerCase()}${ident.slice(1)}`;
};

View file

@ -1,4 +1,5 @@
import { type Result, exec } from 'tinyexec';
import type { Result } from 'tinyexec';
import { exec } from '../exec.js';
/**
* Credit: Azhar22
@ -8,6 +9,7 @@ const getPlatformSpecificCommand = (): [string] | [string, string[]] => {
const isGitPod = Boolean(process.env.GITPOD_REPO_ROOT);
const platform = isGitPod ? 'gitpod' : process.platform;
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (platform) {
case 'android':
case 'linux':

View file

@ -0,0 +1,26 @@
import { NonZeroExitError, type Options, x } from 'tinyexec';
/**
* Improve tinyexec error logging and set `throwOnError` to `true` by default
*/
export function exec(command: string, args?: string[], options?: Partial<Options>) {
return x(command, args, {
throwOnError: true,
...options,
}).then(
(o) => o,
(e) => {
if (e instanceof NonZeroExitError) {
const fullCommand = args?.length
? `${command} ${args.map((a) => (a.includes(' ') ? `"${a}"` : a)).join(' ')}`
: command;
const message = `The command \`${fullCommand}\` exited with code ${e.exitCode}`;
const newError = new Error(message, e.cause ? { cause: e.cause } : undefined);
(newError as any).stderr = e.output?.stderr;
(newError as any).stdout = e.output?.stdout;
throw newError;
}
throw e;
},
);
}

View file

@ -133,8 +133,8 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
}
case 'sync': {
const { sync } = await import('./sync/index.js');
const exitCode = await sync({ flags });
return process.exit(exitCode);
await sync({ flags });
return;
}
case 'preferences': {
const { preferences } = await import('./preferences/index.js');

View file

@ -4,10 +4,10 @@ import ci from 'ci-info';
import { bold, cyan, dim, magenta } from 'kleur/colors';
import preferredPM from 'preferred-pm';
import prompts from 'prompts';
import { exec } from 'tinyexec';
import whichPm from 'which-pm';
import yoctoSpinner from 'yocto-spinner';
import type { Logger } from '../core/logger/core.js';
import { exec } from './exec.js';
const require = createRequire(import.meta.url);

View file

@ -22,10 +22,5 @@ export async function sync({ flags }: SyncOptions) {
return 0;
}
try {
await _sync(flagsToAstroInlineConfig(flags), { telemetry: true });
return 0;
} catch (_) {
return 1;
}
await _sync(flagsToAstroInlineConfig(flags), { telemetry: true });
}

View file

@ -1,5 +1,4 @@
import type { UserConfig as ViteUserConfig, UserConfigFn as ViteUserConfigFn } from 'vite';
import { Logger } from '../core/logger/core.js';
import { createRouteManifest } from '../core/routing/index.js';
import type { AstroInlineConfig, AstroUserConfig, Locales } from '../types/public/config.js';
import { createDevelopmentManifest } from '../vite-plugin-astro-server/plugin.js';
@ -30,7 +29,7 @@ export function getViteConfig(
const [
fs,
{ mergeConfig },
{ nodeLogDestination },
{ createNodeLogger },
{ resolveConfig, createSettings },
{ createVite },
{ runHookConfigSetup, runHookConfigDone },
@ -38,16 +37,13 @@ export function getViteConfig(
] = await Promise.all([
import('node:fs'),
import('vite'),
import('../core/logger/node.js'),
import('../core/config/logging.js'),
import('../core/config/index.js'),
import('../core/create-vite.js'),
import('../integrations/hooks.js'),
import('./vite-plugin-content-listen.js'),
]);
const logger = new Logger({
dest: nodeLogDestination,
level: 'info',
});
const logger = createNodeLogger(inlineAstroConfig);
const { astroConfig: config } = await resolveConfig(inlineAstroConfig, cmd);
let settings = await createSettings(config, userViteConfig.root);
settings = await runHookConfigSetup({ settings, command: cmd, logger });

View file

@ -122,14 +122,10 @@ export class App {
throw new Error(`Unable to resolve [${specifier}]`);
}
const bundlePath = this.#manifest.entryModules[specifier];
switch (true) {
case bundlePath.startsWith('data:'):
case bundlePath.length === 0: {
return bundlePath;
}
default: {
return createAssetLink(bundlePath, this.#manifest.base, this.#manifest.assetsPrefix);
}
if (bundlePath.startsWith('data:') || bundlePath.length === 0) {
return bundlePath;
} else {
return createAssetLink(bundlePath, this.#manifest.base, this.#manifest.assetsPrefix);
}
},
serverLike: true,

View file

@ -153,8 +153,10 @@ export class NodeApp extends App {
}
destination.end();
// the error will be logged by the "on end" callback above
} catch {
destination.end('Internal server error');
} catch (err) {
destination.write('Internal server error', () => {
err instanceof Error ? destination.destroy(err) : destination.destroy();
});
}
}
}

View file

@ -370,6 +370,7 @@ function getUrlForPath(
ending = trailingSlash === 'never' ? '' : '/';
break;
}
case 'file':
default: {
ending = '.html';
break;

View file

@ -122,24 +122,17 @@ export async function staticBuild(
contentFileNames?: string[],
) {
const { settings } = opts;
switch (settings.buildOutput) {
case 'static': {
settings.timer.start('Static generate');
await generatePages(opts, internals);
await cleanServerOutput(opts, ssrOutputChunkNames, contentFileNames, internals);
settings.timer.end('Static generate');
return;
}
case 'server': {
settings.timer.start('Server generate');
await generatePages(opts, internals);
await cleanStaticOutput(opts, internals);
await ssrMoveAssets(opts);
settings.timer.end('Server generate');
return;
}
default: // `settings.buildOutput` will always be one of the above at this point, but TS doesn't know that
return;
if (settings.buildOutput === 'static') {
settings.timer.start('Static generate');
await generatePages(opts, internals);
await cleanServerOutput(opts, ssrOutputChunkNames, contentFileNames, internals);
settings.timer.end('Static generate');
} else if (settings.buildOutput === 'server') {
settings.timer.start('Server generate');
await generatePages(opts, internals);
await cleanStaticOutput(opts, internals);
await ssrMoveAssets(opts);
settings.timer.end('Server generate');
}
}

View file

@ -176,8 +176,11 @@ export async function createContainerWithAutomaticRestart({
// Restart the Astro dev server instead of Vite's when the API is called by plugins.
// Ignore the `forceOptimize` parameter for now.
restart.container.viteServer.restart = () =>
handleServerRestart('', restart.container.viteServer);
restart.container.viteServer.restart = async () => {
if (!restart.container.restartInFlight) {
await handleServerRestart('', restart.container.viteServer);
}
};
// Set up shortcuts

View file

@ -1429,7 +1429,7 @@ export const GenerateContentTypesError = {
title: 'Failed to generate content types.',
message: (errorMessage: string) =>
`\`astro sync\` command failed to generate content collection types: ${errorMessage}`,
hint: 'Check your `src/content/config.*` file for typos.',
hint: 'This error is often caused by a syntax error inside your content, or your content configuration file. Check your `src/content/config.*` file for typos.',
} satisfies ErrorData;
/**
* @docs

View file

@ -298,6 +298,11 @@ export function formatErrorMessage(err: ErrorWithMetadata, showFullStacktrace: b
output.push(` ${cyan(underline(docsLink))}`);
}
if (showFullStacktrace && err.loc) {
output.push(` ${bold('Location:')}`);
output.push(` ${underline(`${err.loc.file}:${err.loc.line ?? 0}:${err.loc.column ?? 0}`)}`);
}
if (err.stack) {
output.push(` ${bold('Stack trace:')}`);
output.push(dim(formatErrorStackTrace(err, showFullStacktrace)));

View file

@ -26,6 +26,7 @@ import {
AstroError,
AstroErrorData,
AstroUserError,
type ErrorWithMetadata,
createSafeError,
isAstroError,
} from '../errors/index.js';
@ -68,17 +69,7 @@ export default async function sync(
});
const manifest = await createRouteManifest({ settings, fsMod: fs }, logger);
// Run `astro:config:done`
// Actions will throw if there is misconfiguration, so catch here.
try {
await runHookConfigDone({ settings, logger });
} catch (err) {
if (err instanceof Error) {
const errorMessage = err.toString();
logger.error('sync', errorMessage);
}
throw err;
}
await runHookConfigDone({ settings, logger });
return await syncInternal({
settings,
@ -127,51 +118,41 @@ export async function syncInternal({
const timerStart = performance.now();
try {
if (!skip?.content) {
await syncContentCollections(settings, { mode, fs, logger, manifest });
settings.timer.start('Sync content layer');
let store: MutableDataStore | undefined;
try {
const dataStoreFile = getDataStoreFile(settings);
if (existsSync(dataStoreFile)) {
store = await MutableDataStore.fromFile(dataStoreFile);
}
} catch (err: any) {
logger.error('content', err.message);
if (!skip?.content) {
await syncContentCollections(settings, { mode, fs, logger, manifest });
settings.timer.start('Sync content layer');
let store: MutableDataStore | undefined;
try {
const dataStoreFile = getDataStoreFile(settings);
if (existsSync(dataStoreFile)) {
store = await MutableDataStore.fromFile(dataStoreFile);
}
if (!store) {
store = new MutableDataStore();
}
const contentLayer = globalContentLayer.init({
settings,
logger,
store,
});
await contentLayer.sync();
settings.timer.end('Sync content layer');
} else if (fs.existsSync(fileURLToPath(getContentPaths(settings.config, fs).contentDir))) {
// Content is synced after writeFiles. That means references are not created
// To work around it, we create a stub so the reference is created and content
// sync will override the empty file
settings.injectedTypes.push({
filename: CONTENT_TYPES_FILE,
content: '',
});
} catch (err: any) {
logger.error('content', err.message);
}
syncAstroEnv(settings);
writeInjectedTypes(settings, fs);
logger.info('types', `Generated ${dim(getTimeStat(timerStart, performance.now()))}`);
} catch (err) {
const error = createSafeError(err);
logger.error(
'types',
formatErrorMessage(collectErrorMetadata(error), logger.level() === 'debug') + '\n',
);
// Will return exit code 1 in CLI
throw error;
if (!store) {
store = new MutableDataStore();
}
const contentLayer = globalContentLayer.init({
settings,
logger,
store,
});
await contentLayer.sync();
settings.timer.end('Sync content layer');
} else if (fs.existsSync(fileURLToPath(getContentPaths(settings.config, fs).contentDir))) {
// Content is synced after writeFiles. That means references are not created
// To work around it, we create a stub so the reference is created and content
// sync will override the empty file
settings.injectedTypes.push({
filename: CONTENT_TYPES_FILE,
content: '',
});
}
syncAstroEnv(settings);
writeInjectedTypes(settings, fs);
logger.info('types', `Generated ${dim(getTimeStat(timerStart, performance.now()))}`);
}
function getTsReference(type: 'path' | 'types', value: string) {
@ -270,7 +251,7 @@ async function syncContentCollections(
}
}
} catch (e) {
const safeError = createSafeError(e);
const safeError = createSafeError(e) as ErrorWithMetadata;
if (isAstroError(e)) {
throw e;
}
@ -280,6 +261,7 @@ async function syncContentCollections(
...AstroErrorData.GenerateContentTypesError,
hint,
message: AstroErrorData.GenerateContentTypesError.message(safeError.message),
location: safeError.loc,
},
{ cause: e },
);

View file

@ -1 +0,0 @@
export const ENV_SYMBOL = Symbol.for('astro:env/dev');

View file

@ -1,16 +1,12 @@
import { AstroError, AstroErrorData } from '../core/errors/index.js';
import { invalidVariablesToError } from './errors.js';
import { ENV_SYMBOL } from './runtime-constants.js';
import type { ValidationResultInvalid } from './validators.js';
export { validateEnvVariable, getEnvFieldType } from './validators.js';
export type GetEnv = (key: string) => string | undefined;
type OnSetGetEnv = (reset: boolean) => void;
let _getEnv: GetEnv = (key) => {
const env = (globalThis as any)[ENV_SYMBOL] ?? {};
return env[key];
};
let _getEnv: GetEnv = (key) => process.env[key];
export function setGetEnv(fn: GetEnv, reset = false) {
_getEnv = fn;

View file

@ -9,7 +9,6 @@ import {
VIRTUAL_MODULES_IDS_VALUES,
} from './constants.js';
import { type InvalidVariable, invalidVariablesToError } from './errors.js';
import { ENV_SYMBOL } from './runtime-constants.js';
import type { EnvSchema } from './schema.js';
import { getEnvFieldType, validateEnvVariable } from './validators.js';
@ -29,7 +28,11 @@ export function astroEnv({ settings, mode, sync }: AstroEnvPluginParams): Plugin
enforce: 'pre',
buildStart() {
const loadedEnv = loadEnv(mode, fileURLToPath(settings.config.root), '');
(globalThis as any)[ENV_SYMBOL] = loadedEnv;
for (const [key, value] of Object.entries(loadedEnv)) {
if (value !== undefined) {
process.env[key] = value;
}
}
const validatedVariables = validatePublicVariables({
schema,

View file

@ -65,6 +65,7 @@ export function isValidKey(key: string): key is PreferenceKey {
}
export function coerce(key: string, value: unknown) {
const type = typeof dget(DEFAULT_PREFERENCES, key);
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (type) {
case 'string':
return value;
@ -142,6 +143,7 @@ function getGlobalPreferenceDir() {
const { XDG_CONFIG_HOME = path.join(homedir, '.config') } = process.env;
return path.join(XDG_CONFIG_HOME, name);
};
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (process.platform) {
case 'darwin':
return macos();

View file

@ -45,15 +45,25 @@ export default function astroPrefetch({ settings }: { settings: AstroSettings })
},
transform(code, id) {
// NOTE: Handle replacing the specifiers even if prefetch is disabled so View Transitions
// can import the internal module as not hit runtime issues.
// can import the internal module and not hit runtime issues.
if (id.includes(prefetchInternalModuleFsSubpath)) {
return code
.replace('__PREFETCH_PREFETCH_ALL__', JSON.stringify(prefetch?.prefetchAll))
.replace('__PREFETCH_DEFAULT_STRATEGY__', JSON.stringify(prefetch?.defaultStrategy))
// We perform a simple replacement with padding so that the code offset is not changed and
// we don't have to generate a sourcemap. This has the assumption that the replaced string
// will always be shorter than the search string to work.
code = code
.replace(
'__EXPERIMENTAL_CLIENT_PRERENDER__',
JSON.stringify(settings.config.experimental.clientPrerender),
'__PREFETCH_PREFETCH_ALL__', // length: 25
`${JSON.stringify(prefetch?.prefetchAll)}`.padEnd(25),
)
.replace(
'__PREFETCH_DEFAULT_STRATEGY__', // length: 29
`${JSON.stringify(prefetch?.defaultStrategy)}`.padEnd(29),
)
.replace(
'__EXPERIMENTAL_CLIENT_PRERENDER__', // length: 33
`${JSON.stringify(settings.config.experimental.clientPrerender)}`.padEnd(33),
);
return { code, map: null };
}
},
};

View file

@ -204,6 +204,8 @@ export default {
label.append(astroSelect);
break;
}
case 'number':
case 'text':
default:
break;
}

View file

@ -44,6 +44,7 @@ function guessRenderers(componentUrl?: string): string[] {
case 'jsx':
case 'tsx':
return ['@astrojs/react', '@astrojs/preact', '@astrojs/solid-js', '@astrojs/vue (jsx)'];
case undefined:
default:
return [
'@astrojs/react',

View file

@ -7,7 +7,7 @@ import { HTMLString, markHTMLString } from '../escape.js';
export const voidElementNames =
/^(area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/i;
const htmlBooleanAttributes =
/^(?:allowfullscreen|async|autofocus|autoplay|controls|default|defer|disabled|disablepictureinpicture|disableremoteplayback|formnovalidate|hidden|loop|nomodule|novalidate|open|playsinline|readonly|required|reversed|scoped|seamless|selected|itemscope)$/i;
/^(?:allowfullscreen|async|autofocus|autoplay|checked|controls|default|defer|disabled|disablepictureinpicture|disableremoteplayback|formnovalidate|hidden|loop|nomodule|novalidate|open|playsinline|readonly|required|reversed|scoped|seamless|selected|itemscope)$/i;
const AMPERSAND_REGEX = /&/g;
const DOUBLE_QUOTE_REGEX = /"/g;

View file

@ -16,6 +16,11 @@ export type OmitIndexSignature<ObjectType> = {
: KeyType]: ObjectType[KeyType];
};
// This is an alternative `Omit<T, K>` implementation that _doesn't_ remove the index signature of an object.
export type OmitPreservingIndexSignature<T, K extends PropertyKey> = {
[P in keyof T as Exclude<P, K>]: 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 string, A extends string = ''> = T extends `${infer F}${infer R}`
? Kebab<R, `${A}${F extends Lowercase<F> ? '' : '-'}${Lowercase<F>}`>

View file

@ -189,6 +189,9 @@ export default function astro({ settings, logger }: AstroPluginOptions): vite.Pl
return result;
}
case 'custom':
case 'template':
case undefined:
default:
return null;
}

View file

@ -14,6 +14,6 @@
"vue": "^3.5.12"
},
"devDependencies": {
"postcss-preset-env": "^10.0.8"
"postcss-preset-env": "^10.0.9"
}
}

View file

@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@astrojs/solid-js": "workspace:*",
"@solidjs/router": "^0.14.10",
"@solidjs/router": "^0.15.1",
"@test/solid-jsx-component": "file:./deps/solid-jsx-component",
"astro": "workspace:*",
"solid-js": "^1.9.3"

View file

@ -1,5 +1,16 @@
# create-astro
## 4.11.0-beta.0
### Minor Changes
- [#12083](https://github.com/withastro/astro/pull/12083) [`9263e96`](https://github.com/withastro/astro/commit/9263e965932b9a6a116801c063c6b7105c39643e) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Reworks the experience of creating a new Astro project using the `create astro` CLI command.
- Updates the list of templates to include Starlight and combines the "minimal" and "basics" templates into a new, refreshed "Basics" template to serve as the single, minimal Astro project starter.
- Removes the TypeScript question. Astro is TypeScript-only, so this question was often misleading. The "Strict" preset is now the default, but it can still be changed manually in `tsconfig.json`.
- `astro check` is no longer automatically added to the build script.
- Added a new `--add` flag to install additional integrations after creating a project. For example, `pnpm create astro --add react` will create a new Astro project and install the React integration.
## 4.10.0
### Minor Changes

View file

@ -1,6 +1,6 @@
{
"name": "create-astro",
"version": "4.10.0",
"version": "4.11.0-beta.0",
"type": "module",
"author": "withastro",
"license": "MIT",

View file

@ -27,7 +27,10 @@ export async function dependencies(
ctx.add = ctx.add?.reduce<string[]>((acc, item) => acc.concat(item.split(',')), []);
if (ctx.dryRun) {
await info('--dry-run', `Skipping dependency installation${ ctx.add ? ` and adding ${ctx.add.join(', ')}` : '' }`);
await info(
'--dry-run',
`Skipping dependency installation${ctx.add ? ` and adding ${ctx.add.join(', ')}` : ''}`,
);
} else if (deps) {
ctx.tasks.push({
pending: 'Dependencies',

View file

@ -57,6 +57,7 @@ export default function getSeasonalHouston({ fancy }: { fancy?: boolean }): Seas
`Your creativity is the gift that keeps on giving!`,
],
};
case undefined:
default:
return {
hats: fancy ? ['🎩', '🎩', '🎩', '🎩', '🎓', '👑', '🧢', '🍦'] : undefined,

View file

@ -30,7 +30,9 @@ describe('integrations', () => {
await dependencies(context);
assert.ok(fixture.hasMessage('--dry-run Skipping dependency installation and adding node, react'));
assert.ok(
fixture.hasMessage('--dry-run Skipping dependency installation and adding node, react'),
);
});
it('--add node,react', async () => {
@ -39,12 +41,14 @@ describe('integrations', () => {
yes: true,
packageManager: 'npm',
dryRun: true,
add: ['node,react']
add: ['node,react'],
};
await dependencies(context);
assert.ok(fixture.hasMessage('--dry-run Skipping dependency installation and adding node, react'));
assert.ok(
fixture.hasMessage('--dry-run Skipping dependency installation and adding node, react'),
);
});
it('-y', async () => {

View file

@ -91,6 +91,6 @@
"astro-scripts": "workspace:*",
"cheerio": "1.0.0",
"typescript": "^5.6.3",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
}
}

View file

@ -41,7 +41,7 @@
"@playwright/test": "1.48.2",
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
},
"publishConfig": {
"provenance": true

View file

@ -79,7 +79,7 @@
"astro-scripts": "workspace:*",
"devalue": "^5.1.1",
"linkedom": "^0.18.5",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
},
"engines": {
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"

View file

@ -70,7 +70,7 @@
"remark-toc": "^9.0.0",
"shiki": "^1.22.2",
"unified": "^11.0.5",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
},
"engines": {
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"

View file

@ -66,7 +66,7 @@
"cheerio": "1.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
},
"peerDependencies": {
"@types/react": "^17.0.50 || ^18.0.21",

View file

@ -41,7 +41,7 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"solid-js": "^1.9.3",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
},
"peerDependencies": {
"solid-devtools": "^0.30.1",

View file

@ -1,5 +1,11 @@
# @astrojs/svelte
## 6.0.0-beta.2
### Patch Changes
- [`b21a075`](https://github.com/withastro/astro/commit/b21a07500284a3621be4d509f5aa67c0a8fcbf07) Thanks [@bluwy](https://github.com/bluwy)! - New release to include changes from 5.7.3
## 6.0.0-beta.1
### Patch Changes
@ -19,6 +25,12 @@
- Updated dependencies [[`b6fbdaa`](https://github.com/withastro/astro/commit/b6fbdaa94a9ecec706a99e1938fbf5cd028c72e0), [`89bab1e`](https://github.com/withastro/astro/commit/89bab1e70786123fbe933a9d7a1b80c9334dcc5f), [`d74617c`](https://github.com/withastro/astro/commit/d74617cbd3278feba05909ec83db2d73d57a153e), [`e90f559`](https://github.com/withastro/astro/commit/e90f5593d23043579611452a84b9e18ad2407ef9), [`2df49a6`](https://github.com/withastro/astro/commit/2df49a6fb4f6d92fe45f7429430abe63defeacd6), [`8a53517`](https://github.com/withastro/astro/commit/8a5351737d6a14fc55f1dafad8f3b04079e81af6)]:
- astro@5.0.0-alpha.0
## 5.7.3
### Patch Changes
- [#12390](https://github.com/withastro/astro/pull/12390) [`6fd3d59`](https://github.com/withastro/astro/commit/6fd3d5960f5ab16591bfdb94d1f9b9a9b72006cf) Thanks [@bluwy](https://github.com/bluwy)! - Adds support for Svelte 5's new `@render` syntax while maintaining backward compatibility with traditional slots.
## 5.7.2
### Patch Changes

View file

@ -8,7 +8,10 @@ export default (element) => {
let children = undefined;
let $$slots = undefined;
let renderFns = {};
for (const [key, value] of Object.entries(slotted)) {
// Legacy slot support
$$slots ??= {};
if (key === 'default') {
$$slots.default = true;
@ -20,6 +23,16 @@ export default (element) => {
render: () => `<astro-slot name="${key}">${value}</astro-slot>`,
}));
}
// @render support for Svelte ^5.0
if (key === 'default') {
renderFns.children = createRawSnippet(() => ({
render: () => `<astro-slot>${value}</astro-slot>`,
}));
} else {
renderFns[key] = createRawSnippet(() => ({
render: () => `<astro-slot name="${key}">${value}</astro-slot>`,
}));
}
}
const bootstrap = client !== 'only' ? hydrate : mount;
@ -28,6 +41,7 @@ export default (element) => {
...props,
children,
$$slots,
...renderFns,
});
} else {
const component = bootstrap(Component, {
@ -36,6 +50,7 @@ export default (element) => {
...props,
children,
$$slots,
...renderFns,
},
});
existingApplications.set(element, component);

View file

@ -1,6 +1,6 @@
{
"name": "@astrojs/svelte",
"version": "6.0.0-beta.1",
"version": "6.0.0-beta.2",
"description": "Use Svelte components within Astro",
"type": "module",
"types": "./dist/index.d.ts",
@ -57,7 +57,7 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"svelte": "^4.2.19",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
},
"peerDependencies": {
"astro": "^5.0.0-alpha.0",

View file

@ -17,7 +17,10 @@ async function renderToStaticMarkup(Component, props, slotted, metadata) {
let children = undefined;
let $$slots = undefined;
const renderProps = {};
for (const [key, value] of Object.entries(slotted)) {
// Legacy slot support
$$slots ??= {};
if (key === 'default') {
$$slots.default = true;
@ -29,6 +32,11 @@ async function renderToStaticMarkup(Component, props, slotted, metadata) {
render: () => `<${tagName} name="${key}">${value}</${tagName}>`,
}));
}
// @render support for Svelte ^5.0
const slotName = key === 'default' ? 'children' : key;
renderProps[slotName] = createRawSnippet(() => ({
render: () => `<${tagName}${key !== 'default' ? ` name="${key}"` : ''}>${value}</${tagName}>`,
}));
}
const result = render(Component, {
@ -36,6 +44,7 @@ async function renderToStaticMarkup(Component, props, slotted, metadata) {
...props,
children,
$$slots,
...renderProps,
},
});
return { html: result.body };

View file

@ -43,7 +43,7 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"tailwindcss": "^3.4.14",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
},
"peerDependencies": {
"astro": "^3.0.0 || ^4.0.0 || ^5.0.0-beta.0",

View file

@ -48,14 +48,14 @@
"@vitejs/plugin-vue": "^5.1.4",
"@vitejs/plugin-vue-jsx": "^4.0.1",
"@vue/compiler-sfc": "^3.5.12",
"vite-plugin-vue-devtools": "^7.5.4"
"vite-plugin-vue-devtools": "^7.6.3"
},
"devDependencies": {
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"cheerio": "1.0.0",
"linkedom": "^0.18.5",
"vite": "6.0.0-beta.2",
"vite": "6.0.0-beta.6",
"vue": "^3.5.12"
},
"peerDependencies": {

View file

@ -42,6 +42,6 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"typescript": "^5.6.3",
"vite": "6.0.0-beta.2"
"vite": "6.0.0-beta.6"
}
}

View file

@ -21,6 +21,7 @@ function getConfigDir(name: string) {
const { XDG_CONFIG_HOME = path.join(homedir, '.config') } = process.env;
return path.join(XDG_CONFIG_HOME, name);
};
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (process.platform) {
case 'darwin':
return macos();

1224
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more