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

Merge branch 'main' into fix/add-html-extension-to-sitemap-uls-with-buildformat-file

This commit is contained in:
Javier de la Rubia 2024-09-30 16:39:51 +02:00 committed by GitHub
commit a587415ddf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
865 changed files with 14317 additions and 16898 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
View transitions: Fixes Astro's fade animation to prevent flashing during morph transitions.

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fixes injected endpoint `prerender` option detection

View file

@ -41,7 +41,7 @@ jobs:
- name: Get changed files in the .changeset folder
id: changed-files
uses: tj-actions/changed-files@v44
uses: tj-actions/changed-files@v45
if: steps.blocked.outputs.result != 'true'
with:
files: |

61
.github/workflows/dispatch-event.yml vendored Normal file
View file

@ -0,0 +1,61 @@
name: Dispatch event
on:
workflow_dispatch:
push:
branches:
- main
tags:
- '!**'
permissions:
contents: read
actions: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
ASTRO_ADAPTERS_REPO: withastro/adapters
ASTRO_STARLIGHT_REPO: withastro/starlight
ASTRO_PUSH_MAIN_EVENT: astro-push-main-event
jobs:
repository-dispatch:
name: Repository dispatch
runs-on: ubuntu-latest
steps:
- name: Dispatch event on push - adapters
if: ${{ github.event_name == 'push' }}
uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3
with:
token: ${{ secrets.ASTRO_REPOSITORY_DISPATCH }}
repository: ${{ env.ASTRO_ADAPTERS_REPO }}
event-type: ${{ env.ASTRO_PUSH_MAIN_EVENT }}
client-payload: '{"event": ${{ toJson(github.event) }}}'
- name: Dispatch event on push - starlight
if: ${{ github.event_name == 'push' }}
uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3
with:
token: ${{ secrets.ASTRO_REPOSITORY_DISPATCH }}
repository: ${{ env.ASTRO_STARLIGHT_REPO }}
event-type: ${{ env.ASTRO_PUSH_MAIN_EVENT }}
client-payload: '{"event": ${{ toJson(github.event) }}}'
# For testing only, the payload is mocked
- name: Dispatch event on workflow dispatch - adapters
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3
with:
token: ${{ secrets.ASTRO_REPOSITORY_DISPATCH }}
repository: ${{ env.ASTRO_ADAPTERS_REPO }}
event-type: ${{ env.ASTRO_PUSH_MAIN_EVENT }}
client-payload: '{"event": {"head_commit": {"id": "${{ env.GITHUB_SHA }}"}}}'
- name: Dispatch event on workflow dispatch - starlight
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3
with:
token: ${{ secrets.ASTRO_REPOSITORY_DISPATCH }}
repository: ${{ env.ASTRO_STARLIGHT_REPO }}
event-type: ${{ env.ASTRO_PUSH_MAIN_EVENT }}
client-payload: '{"event": {"head_commit": {"id": "${{ env.GITHUB_SHA }}"}}}'

19
.github/workflows/preview-comment.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: Add continuous release label
on:
issue_comment:
types: [created]
permissions:
pull-requests: write
jobs:
label:
if: ${{ github.repository_owner == 'withastro' && startsWith(github.event.comment.body, '!preview') }}
runs-on: ubuntu-latest
steps:
- run: |
gh issue edit ${{ github.event.issue.number }} --add-label "pr: preview" --repo ${{ github.repository }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

60
.github/workflows/preview-release.yml vendored Normal file
View file

@ -0,0 +1,60 @@
name: Preview release
on:
pull_request:
branches: [main]
types: [opened, synchronize, labeled, ready_for_review]
concurrency:
group: ${{ github.workflow }}-${{ github.event.number }}
cancel-in-progress: true
permissions:
contents: read
actions: write
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
FORCE_COLOR: true
ASTRO_TELEMETRY_DISABLED: true
# 7 GiB by default on GitHub, setting to 6 GiB
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
NODE_OPTIONS: --max-old-space-size=6144
jobs:
preview:
if: |
${{ github.repository_owner == 'withastro' && github.event.issue.pull_request && contains(github.event.pull_request.labels.*.name, 'pr: preview') }}
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
issues: write
pull-requests: write
name: Publish preview release
timeout-minutes: 5
steps:
- name: Disable git crlf
run: git config --global core.autocrlf false
- name: Checkout
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 Packages
run: pnpm run build
- name: Publish packages
run: pnpx pkg-pr-new publish --pnpm './packages/*' './packages/integrations/*'

8
.gitignore vendored
View file

@ -16,9 +16,6 @@ package-lock.json
.eslintcache
.pnpm-store
# ignore top-level vscode settings
/.vscode/settings.json
# do not commit .env files or any files that end with `.env`
*.env
@ -37,3 +34,8 @@ packages/**/e2e/**/fixtures/**/.astro/
packages/**/e2e/**/fixtures/**/env.d.ts
examples/**/.astro/
examples/**/env.d.ts
# make it easy for people to add project-specific Astro settings that they don't
# want to share with others (see
# https://github.com/withastro/astro/pull/11759#discussion_r1721444711)
*.code-workspace

View file

@ -3,7 +3,8 @@
"astro-build.astro-vscode",
"esbenp.prettier-vscode",
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint"
"dbaeumer.vscode-eslint",
"biomejs.biome"
],
"unwantedRecommendations": []
}

21
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,21 @@
{
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"editor.codeActionsOnSave": {
"quickFix.biome": "explicit",
"source.fixAll.biome": "explicit"
}
}

View file

@ -70,6 +70,7 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll
| [@astrojs/mdx](packages/integrations/mdx) | [![@astrojs/mdx version](https://img.shields.io/npm/v/@astrojs/mdx.svg?label=%20)](packages/integrations/mdx/CHANGELOG.md) |
| [@astrojs/db](packages/db) | [![@astrojs/db version](https://img.shields.io/npm/v/@astrojs/db.svg?label=%20)](packages/db/CHANGELOG.md) |
| [@astrojs/rss](packages/astro-rss) | [![@astrojs/rss version](https://img.shields.io/npm/v/@astrojs/rss.svg?label=%20)](packages/astro-rss/CHANGELOG.md) |
| [@astrojs/netlify](https://github.com/withastro/adapters/blob/main/packages/netlify) | [![@astrojs/netlify version](https://img.shields.io/npm/v/@astrojs/netlify.svg?label=%20)](https://github.com/withastro/adapters/blob/main/packages/netlify/CHANGELOG.md) |
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6178/badge)](https://bestpractices.coreinfrastructure.org/projects/6178)

View file

@ -1,5 +1,5 @@
import { fileURLToPath } from 'node:url';
import { execaCommand } from 'execa';
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import { astroBin, calculateStat } from './_util.js';
@ -14,11 +14,11 @@ export async function run(projectDir, outputFile) {
const root = fileURLToPath(projectDir);
console.log('Benchmarking `astro --help`...');
const helpStat = await benchmarkCommand(`node ${astroBin} --help`, root);
const helpStat = await benchmarkCommand('node', [astroBin, '--help'], root);
console.log('Done');
console.log('Benchmarking `astro info`...');
const infoStat = await benchmarkCommand(`node ${astroBin} info`, root);
console.log('Benchmarking `astro preferences list`...');
const infoStat = await benchmarkCommand('node', [astroBin, 'preferences', 'list'], root);
console.log('Done');
console.log('Result preview:');
@ -35,16 +35,17 @@ export async function run(projectDir, outputFile) {
/**
* @param {string} command
* @param {string[]} args
* @param {string} root
* @returns {Promise<import('./_util.js').Stat>}
*/
async function benchmarkCommand(command, root) {
async function benchmarkCommand(command, args, root) {
/** @type {number[]} */
const durations = [];
for (let i = 0; i < 10; i++) {
const start = performance.now();
await execaCommand(command, { cwd: root });
await exec(command, args, { nodeOptions: { cwd: root } });
durations.push(performance.now() - start);
}

View file

@ -1,4 +1,4 @@
import { execaCommand } from 'execa';
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
@ -18,11 +18,13 @@ export async function run(projectDir, outputFile) {
const outputFilePath = fileURLToPath(outputFile);
console.log('Building and benchmarking...');
await execaCommand(`node --expose-gc --max_old_space_size=256 ${astroBin} build`, {
cwd: root,
stdio: 'inherit',
env: {
ASTRO_TIMER_PATH: outputFilePath,
await exec('node', ['--expose-gc', '--max_old_space_size=10000', astroBin, 'build'], {
nodeOptions: {
cwd: root,
stdio: 'inherit',
env: {
ASTRO_TIMER_PATH: outputFilePath,
},
},
});

View file

@ -1,4 +1,4 @@
import { execaCommand } from 'execa';
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import http from 'node:http';
@ -20,15 +20,19 @@ export async function run(projectDir, outputFile) {
const root = fileURLToPath(projectDir);
console.log('Building...');
await execaCommand(`${astroBin} build`, {
cwd: root,
stdio: 'inherit',
await exec(astroBin, ['build'], {
nodeOptions: {
cwd: root,
stdio: 'inherit',
},
});
console.log('Previewing...');
const previewProcess = execaCommand(`${astroBin} preview --port ${port}`, {
cwd: root,
stdio: 'inherit',
const previewProcess = exec(astroBin, ['preview', '--port', port], {
nodeOptions: {
cwd: root,
stdio: 'inherit',
},
});
console.log('Waiting for server ready...');

View file

@ -1,5 +1,5 @@
import autocannon from 'autocannon';
import { execaCommand } from 'execa';
import { exec } from 'tinyexec';
import { markdownTable } from 'markdown-table';
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
@ -19,9 +19,11 @@ export async function run(projectDir, outputFile) {
const root = fileURLToPath(projectDir);
console.log('Building...');
await execaCommand(`${astroBin} build`, {
cwd: root,
stdio: 'inherit',
await exec(astroBin, ['build'], {
nodeOptions: {
cwd: root,
stdio: 'inherit',
},
});
console.log('Previewing...');

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

View file

@ -0,0 +1,63 @@
import fs from 'node:fs/promises';
import { loremIpsumMd } from './_util.js';
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content/blog', projectDir), { recursive: true });
await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./src/image.jpg', projectDir));
const promises = [];
for (let i = 0; i < 10000; i++) {
const content = `\
# Article ${i}
${loremIpsumMd}
![image ${i}](../../image.jpg)
`;
promises.push(
fs.writeFile(new URL(`./src/content/blog/article-${i}.md`, projectDir), content, 'utf-8')
);
}
await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.slug }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<h1>{entry.data.title}</h1>
<Content />
`,
'utf-8'
);
await Promise.all(promises);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
export default defineConfig({
});`,
'utf-8'
);
}

View file

@ -0,0 +1,80 @@
import fs from 'node:fs/promises';
import { loremIpsumMd } from './_util.js';
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./data/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content', projectDir), { recursive: true });
await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./image.jpg', projectDir));
const promises = [];
for (let i = 0; i < 10000; i++) {
const content = `\
# Article ${i}
${loremIpsumMd}
![image ${i}](../../image.jpg)
`;
promises.push(
fs.writeFile(new URL(`./data/blog/article-${i}.md`, projectDir), content, 'utf-8')
);
}
await fs.writeFile(
new URL(`./src/content/config.ts`, projectDir),
/*ts */ `
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '*', base: './data/blog' }),
});
export const collections = { blog }
`
);
await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\
---
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.id }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await render(entry);
---
<h1>{entry.data.title}</h1>
<Content />
`,
'utf-8'
);
await Promise.all(promises);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
export default defineConfig({
experimental: {
contentLayer: true
}
});`,
'utf-8'
);
}

View file

@ -0,0 +1,66 @@
import fs from 'node:fs/promises';
import { loremIpsumMd } from './_util.js';
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content/blog', projectDir), { recursive: true });
await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./src/image.jpg', projectDir));
const promises = [];
for (let i = 0; i < 10000; i++) {
const content = `\
# Article ${i}
${loremIpsumMd}
![image ${i}](../../image.jpg)
`;
promises.push(
fs.writeFile(new URL(`./src/content/blog/article-${i}.mdx`, projectDir), content, 'utf-8')
);
}
await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.slug }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<h1>{entry.data.title}</h1>
<Content />
`,
'utf-8'
);
await Promise.all(promises);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
});`,
'utf-8'
);
}

View file

@ -0,0 +1,83 @@
import fs from 'node:fs/promises';
import { loremIpsumMd } from './_util.js';
/**
* @param {URL} projectDir
*/
export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true });
await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./data/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content', projectDir), { recursive: true });
await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./image.jpg', projectDir));
const promises = [];
for (let i = 0; i < 10000; i++) {
const content = `\
# Article ${i}
${loremIpsumMd}
![image ${i}](../../image.jpg)
`;
promises.push(
fs.writeFile(new URL(`./data/blog/article-${i}.mdx`, projectDir), content, 'utf-8')
);
}
await fs.writeFile(
new URL(`./src/content/config.ts`, projectDir),
/*ts */ `
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '*', base: './data/blog' }),
});
export const collections = { blog }
`
);
await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\
---
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.id }, props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await render(entry);
---
<h1>{entry.data.title}</h1>
<Content />
`,
'utf-8'
);
await Promise.all(promises);
await fs.writeFile(
new URL('./astro.config.js', projectDir),
`\
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
experimental: {
contentLayer: true
}
});`,
'utf-8'
);
}

View file

@ -8,14 +8,15 @@
},
"dependencies": {
"@astrojs/mdx": "workspace:*",
"@astrojs/node": "workspace:*",
"@astrojs/node": "^8.3.4",
"@benchmark/timer": "workspace:*",
"astro": "workspace:*",
"autocannon": "^7.15.0",
"execa": "^8.0.1",
"markdown-table": "^3.0.3",
"mri": "^1.2.0",
"port-authority": "^2.0.1",
"pretty-bytes": "^6.1.1"
"pretty-bytes": "^6.1.1",
"sharp": "^0.33.3",
"tinyexec": "^0.3.0"
}
}

View file

@ -29,7 +29,7 @@
"astro": "workspace:*"
},
"devDependencies": {
"@types/server-destroy": "^1.0.3",
"@types/server-destroy": "^1.0.4",
"astro": "workspace:*",
"astro-scripts": "workspace:*"
}

View file

@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.1/schema.json",
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"files": {
"ignore": [
"vendor",
@ -9,7 +9,7 @@
"**/vendor/**",
"**/.vercel/**"
],
"include": ["test/**", "e2e/**", "packages/**"]
"include": ["test/**", "e2e/**", "packages/**", "/scripts/**"]
},
"formatter": {
"indentStyle": "tab",
@ -26,7 +26,16 @@
"organizeImports": {
"enabled": true
},
"linter": { "enabled": false },
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"style": {
"useNodejsImportProtocol": "error",
"useImportType": "error"
}
}
},
"javascript": {
"formatter": {
"trailingCommas": "all",
@ -52,6 +61,16 @@
"lineWidth": 1
}
}
},
{
"include": ["*.test.js"],
"linter": {
"rules": {
"suspicious": {
"noFocusedTests": "error"
}
}
}
}
]
}

View file

@ -5,7 +5,6 @@ import { builtinModules } from 'node:module';
import tseslint from 'typescript-eslint';
// plugins
import noOnlyTestsEslint from 'eslint-plugin-no-only-tests';
import regexpEslint from 'eslint-plugin-regexp';
const typescriptEslint = tseslint.plugin;
@ -47,7 +46,6 @@ export default [
},
plugins: {
'@typescript-eslint': typescriptEslint,
'no-only-tests': noOnlyTestsEslint,
regexp: regexpEslint,
},
rules: {
@ -62,7 +60,6 @@ export default [
ignoreRestSiblings: true,
},
],
'no-only-tests/no-only-tests': 'error',
'@typescript-eslint/no-shadow': 'error',
'no-console': 'warn',

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.15.9"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,9 +11,9 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/mdx": "^3.1.3",
"@astrojs/mdx": "^3.1.7",
"@astrojs/rss": "^4.0.7",
"@astrojs/sitemap": "^3.1.6",
"astro": "^4.13.3"
"astro": "^4.15.9"
}
}

View file

@ -1,2 +1 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View file

@ -15,7 +15,7 @@
],
"scripts": {},
"devDependencies": {
"astro": "^4.13.3"
"astro": "^4.15.9"
},
"peerDependencies": {
"astro": "^4.0.0"

View file

@ -12,14 +12,14 @@
"test": "vitest run"
},
"dependencies": {
"astro": "^4.13.3",
"astro": "^4.15.9",
"@astrojs/react": "^3.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"vitest": "^2.0.5"
"vitest": "^2.1.1"
},
"devDependencies": {
"@types/react-dom": "^18.3.0",
"@types/react": "^18.3.3"
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0"
}
}

View file

@ -14,6 +14,6 @@
"@astrojs/alpinejs": "^0.4.0",
"@types/alpinejs": "^3.13.10",
"alpinejs": "^3.14.1",
"astro": "^4.13.3"
"astro": "^4.15.9"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -13,7 +13,7 @@
"dependencies": {
"@astrojs/lit": "^4.3.0",
"@webcomponents/template-shadowroot": "^0.2.1",
"astro": "^4.13.3",
"lit": "^3.1.4"
"astro": "^4.15.9",
"lit": "^3.2.0"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,19 +11,19 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/preact": "^3.5.1",
"@astrojs/preact": "^3.5.3",
"@astrojs/react": "^3.6.2",
"@astrojs/solid-js": "^4.4.1",
"@astrojs/svelte": "^5.7.0",
"@astrojs/vue": "^4.5.0",
"@types/react": "^18.3.3",
"@astrojs/solid-js": "^4.4.2",
"@astrojs/svelte": "^5.7.1",
"@astrojs/vue": "^4.5.1",
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"astro": "^4.13.3",
"preact": "^10.23.1",
"astro": "^4.15.9",
"preact": "^10.24.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"solid-js": "^1.8.19",
"svelte": "^4.2.18",
"vue": "^3.4.35"
"solid-js": "^1.9.1",
"svelte": "^4.2.19",
"vue": "^3.5.10"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,9 +11,9 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/preact": "^3.5.1",
"@astrojs/preact": "^3.5.3",
"@preact/signals": "^1.3.0",
"astro": "^4.13.3",
"preact": "^10.23.1"
"astro": "^4.15.9",
"preact": "^10.24.1"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -12,9 +12,9 @@
},
"dependencies": {
"@astrojs/react": "^3.6.2",
"@types/react": "^18.3.3",
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"astro": "^4.13.3",
"astro": "^4.15.9",
"react": "^18.3.1",
"react-dom": "^18.3.1"
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,8 +11,8 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/solid-js": "^4.4.1",
"astro": "^4.13.3",
"solid-js": "^1.8.19"
"@astrojs/solid-js": "^4.4.2",
"astro": "^4.15.9",
"solid-js": "^1.9.1"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,8 +11,8 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/svelte": "^5.7.0",
"astro": "^4.13.3",
"svelte": "^4.2.18"
"@astrojs/svelte": "^5.7.1",
"astro": "^4.15.9",
"svelte": "^4.2.19"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,8 +11,8 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/vue": "^4.5.0",
"astro": "^4.13.3",
"vue": "^3.4.35"
"@astrojs/vue": "^4.5.1",
"astro": "^4.15.9",
"vue": "^3.5.10"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,7 +11,7 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/node": "^8.3.2",
"astro": "^4.13.3"
"@astrojs/node": "^8.3.4",
"astro": "^4.15.9"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -15,7 +15,7 @@
],
"scripts": {},
"devDependencies": {
"astro": "^4.13.3"
"astro": "^4.15.9"
},
"peerDependencies": {
"astro": "^4.0.0"

View file

@ -12,8 +12,8 @@
"server": "node dist/server/entry.mjs"
},
"dependencies": {
"@astrojs/node": "^8.3.2",
"astro": "^4.13.3",
"@astrojs/node": "^8.3.4",
"astro": "^4.15.9",
"html-minifier": "^4.0.0"
},
"devDependencies": {

View file

@ -1,4 +1,4 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />
declare namespace App {
interface Locals {
user: {

View file

@ -56,16 +56,27 @@ const validation = defineMiddleware(async (context, next) => {
} else if (context.request.url.endsWith('/api/login')) {
const response = await next();
// the login endpoint will return to us a JSON with username and password
const data = await response.json();
// we naively check if username and password are equals to some string
if (data.username === 'astro' && data.password === 'astro') {
// we store the token somewhere outside of locals because the `locals` object is attached to the request
// and when doing a redirect, we lose that information
loginInfo.token = 'loggedIn';
loginInfo.currentTime = new Date().getTime();
return context.redirect('/admin');
}
}
if (response.headers.get('content-type') === 'application/json') {
const data = await response.json();
// we naively check if username and password are equals to some string
if (data.username === 'astro' && data.password === 'astro') {
// we store the token somewhere outside of locals because the `locals` object is attached to the request
// and when doing a redirect, we lose that information
loginInfo.token = 'loggedIn';
loginInfo.currentTime = new Date().getTime();
return context.redirect('/admin');
}
}
return response;
} else if (context.request.url.endsWith('/api/logout')) {
const response = await next();
if (response.ok) {
loginInfo.token = undefined;
loginInfo.currentTime = undefined;
return context.redirect('/login');
}
return response;
}
return next();
});

View file

@ -1,11 +1,16 @@
---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
const user = Astro.locals.user;
---
<Layout title="Welcome back!!">
<main>
<h1>Welcome back <span class="text-gradient">{user.name} {user.surname}</span></h1>
{}
<ul role="list" class="link-card-grid">
<Card href="/api/logout" title="Logout" body="Logout now" />
</ul>
</main>
</Layout>

View file

@ -0,0 +1,21 @@
import type { APIRoute, APIContext } from "astro";
export const POST: APIRoute = async (context: APIContext) => {
try {
const data = await context.request.formData();
return new Response(
JSON.stringify({
username: data.get("username"),
password: data.get("password"),
}),
{
headers: { "Content-Type": "application/json" },
}
);
} catch (e) {
if (e instanceof Error) {
console.error(e.message);
}
}
return new Response(null, { status: 400 });
};

View file

@ -0,0 +1,5 @@
import type { APIRoute, APIContext } from "astro";
export const GET: APIRoute = async (_: APIContext) => {
return new Response(null, { status: 200 });
};

View file

@ -12,7 +12,7 @@ import Card from '../components/Card.astro';
</p>
{}
<ul role="list" class="link-card-grid">
<Card href="/login" title="Login" body="Try the login" />
<Card href="/login" title="Login" body="Try the login with astro/astro" />
</ul>
</main>
</Layout>

View file

@ -14,6 +14,7 @@ if (status === 301) {
<p class="instructions">
To get started, open the directory <code>src/pages</code> in your project.<br />
<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
<strong>Login with:</strong> Username: <code>astro</code> Password: <code>astro</code>
</p>
{redirectMessage}
<form action="/api/login" method="POST">

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.15.9"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.15.9"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.15.9"
}
}

View file

@ -1,2 +1 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View file

@ -10,17 +10,17 @@
"astro": "astro"
},
"devDependencies": {
"@astrojs/node": "^8.3.2",
"@astrojs/node": "^8.3.4",
"@astrojs/react": "^3.6.2",
"@astrojs/tailwind": "^5.1.0",
"@astrojs/tailwind": "^5.1.1",
"@fortawesome/fontawesome-free": "^6.6.0",
"@tailwindcss/forms": "^0.5.7",
"@types/react": "^18.3.3",
"@tailwindcss/forms": "^0.5.9",
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"astro": "^4.13.3",
"postcss": "^8.4.40",
"astro": "^4.15.9",
"postcss": "^8.4.47",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tailwindcss": "^3.4.7"
"tailwindcss": "^3.4.13"
}
}

View file

@ -12,9 +12,9 @@
"server": "node dist/server/entry.mjs"
},
"dependencies": {
"@astrojs/node": "^8.3.2",
"@astrojs/svelte": "^5.7.0",
"astro": "^4.13.3",
"svelte": "^4.2.18"
"@astrojs/node": "^8.3.4",
"@astrojs/svelte": "^5.7.1",
"astro": "^4.15.9",
"svelte": "^4.2.19"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -10,8 +10,8 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3",
"sass": "^1.77.8",
"astro": "^4.15.9",
"sass": "^1.79.4",
"sharp": "^0.33.3"
}
}

View file

@ -15,6 +15,6 @@
"./app": "./dist/app.js"
},
"devDependencies": {
"astro": "^4.13.3"
"astro": "^4.15.9"
}
}

View file

@ -10,8 +10,8 @@
"astro": "astro"
},
"devDependencies": {
"@astrojs/tailwind": "^5.1.0",
"@astrojs/node": "^8.3.2",
"astro": "^4.13.3"
"@astrojs/tailwind": "^5.1.1",
"@astrojs/node": "^8.3.4",
"astro": "^4.15.9"
}
}

View file

@ -11,7 +11,7 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/markdoc": "^0.11.3",
"astro": "^4.13.3"
"@astrojs/markdoc": "^0.11.4",
"astro": "^4.15.9"
}
}

View file

@ -1,2 +1 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View file

@ -12,7 +12,7 @@
},
"dependencies": {
"@astrojs/markdown-remark": "^5.2.0",
"astro": "^4.13.3",
"astro": "^4.15.9",
"hast-util-select": "^6.0.2",
"rehype-autolink-headings": "^7.1.0",
"rehype-slug": "^6.0.0",

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,6 +11,6 @@
"astro": "astro"
},
"dependencies": {
"astro": "^4.13.3"
"astro": "^4.15.9"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,9 +11,9 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/mdx": "^3.1.3",
"@astrojs/preact": "^3.5.1",
"astro": "^4.13.3",
"preact": "^10.23.1"
"@astrojs/mdx": "^3.1.7",
"@astrojs/preact": "^3.5.3",
"astro": "^4.15.9",
"preact": "^10.24.1"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,10 +11,10 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/preact": "^3.5.1",
"@astrojs/preact": "^3.5.3",
"@nanostores/preact": "^0.5.2",
"astro": "^4.13.3",
"nanostores": "^0.11.0",
"preact": "^10.23.1"
"astro": "^4.15.9",
"nanostores": "^0.11.3",
"preact": "^10.24.1"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -11,13 +11,13 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/mdx": "^3.1.3",
"@astrojs/tailwind": "^5.1.0",
"@astrojs/mdx": "^3.1.7",
"@astrojs/tailwind": "^5.1.1",
"@types/canvas-confetti": "^1.6.4",
"astro": "^4.13.3",
"astro": "^4.15.9",
"autoprefixer": "^10.4.20",
"canvas-confetti": "^1.9.3",
"postcss": "^8.4.40",
"tailwindcss": "^3.4.7"
"postcss": "^8.4.47",
"tailwindcss": "^3.4.13"
}
}

View file

@ -1 +1 @@
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />

View file

@ -12,7 +12,7 @@
"test": "vitest"
},
"dependencies": {
"astro": "^4.13.3",
"vitest": "^2.0.5"
"astro": "^4.15.9",
"vitest": "^2.1.1"
}
}

View file

@ -30,12 +30,12 @@
"test:smoke:example": "turbo run build --concurrency=100% --filter=\"@example/*\"",
"test:smoke:docs": "turbo run build --filter=docs",
"test:check-examples": "node ./scripts/smoke/check.js",
"test:vite-ci": "turbo run test --filter=astro",
"test:vite-ci": "cd packages/astro && pnpm run test:node",
"test:e2e": "cd packages/astro && pnpm playwright install chromium firefox && pnpm run test:e2e",
"test:e2e:match": "cd packages/astro && pnpm playwright install chromium firefox && pnpm run test:e2e:match",
"test:e2e:hosts": "turbo run test:hosted",
"benchmark": "astro-benchmark",
"lint": "eslint . --report-unused-disable-directives",
"lint": "biome lint && eslint . --report-unused-disable-directives",
"version": "changeset version && node ./scripts/deps/update-example-versions.js && pnpm install --no-frozen-lockfile && pnpm run format",
"preinstall": "npx only-allow pnpm"
},
@ -52,22 +52,21 @@
"astro-benchmark": "workspace:*"
},
"devDependencies": {
"@astrojs/check": "^0.9.1",
"@biomejs/biome": "1.8.1",
"@astrojs/check": "^0.9.3",
"@biomejs/biome": "1.8.3",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.7",
"@changesets/cli": "^2.27.8",
"@types/node": "^18.17.8",
"esbuild": "^0.21.5",
"eslint": "^9.8.0",
"eslint-plugin-no-only-tests": "^3.1.0",
"eslint": "^9.11.1",
"eslint-plugin-regexp": "^2.6.0",
"globby": "^14.0.2",
"only-allow": "^1.2.1",
"prettier": "^3.3.3",
"prettier-plugin-astro": "^0.14.1",
"turbo": "^1.13.4",
"typescript": "~5.5.4",
"typescript-eslint": "^8.0.1"
"turbo": "^2.1.2",
"typescript": "~5.6.2",
"typescript-eslint": "^8.7.0"
},
"pnpm": {
"peerDependencyRules": {

View file

@ -33,7 +33,7 @@
"xml2js": "0.6.2"
},
"dependencies": {
"fast-xml-parser": "^4.4.1",
"fast-xml-parser": "^4.5.0",
"kleur": "^4.1.5"
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -150,6 +150,9 @@ declare module 'astro:transitions/client' {
import('./dist/virtual-modules/transitions-events.js').TransitionBeforeSwapEvent;
export const isTransitionBeforePreparationEvent: EventModule['isTransitionBeforePreparationEvent'];
export const isTransitionBeforeSwapEvent: EventModule['isTransitionBeforeSwapEvent'];
type TransitionSwapFunctionModule =
typeof import('./dist/virtual-modules/transitions-swap-functions.js');
export const swapFunctions: TransitionSwapFunctionModule['swapFunctions'];
}
declare module 'astro:prefetch' {
@ -172,6 +175,10 @@ declare module 'astro:components' {
export * from 'astro/components';
}
declare module 'astro:schema' {
export * from 'astro/zod';
}
type MD = import('./dist/@types/astro.js').MarkdownInstance<Record<string, any>>;
interface ExportedMarkdownModuleEntities {
frontmatter: MD['frontmatter'];

View file

@ -23,6 +23,13 @@ interface Props extends Omit<HTMLAttributes<'pre'>, 'lang'> {
* @default "plaintext"
*/
lang?: BuiltinLanguage | SpecialLanguage | LanguageRegistration;
/**
* A metastring to pass to the highlighter.
* Allows passing information to transformers: https://shiki.style/guide/transformers#meta
*
* @default undefined
*/
meta?: string;
/**
* The styling theme.
* Supports all themes listed here: https://shiki.style/themes
@ -72,6 +79,7 @@ interface Props extends Omit<HTMLAttributes<'pre'>, 'lang'> {
const {
code,
lang = 'plaintext',
meta,
theme = 'github-dark',
themes = {},
defaultColor = 'light',
@ -110,6 +118,7 @@ const highlighter = await getCachedHighlighter({
const html = await highlighter.highlight(code, typeof lang === 'string' ? lang : lang.name, {
inline,
meta,
attributes: rest as any,
});
---

View file

@ -10,12 +10,22 @@
@keyframes astroFadeIn {
from {
opacity: 0;
mix-blend-mode: plus-lighter;
}
to {
opacity: 1;
mix-blend-mode: plus-lighter;
}
}
@keyframes astroFadeOut {
from {
opacity: 1;
mix-blend-mode: plus-lighter;
}
to {
opacity: 0;
mix-blend-mode: plus-lighter;
}
}

View file

@ -26,6 +26,9 @@ export function getViteConfig(
export function sharpImageService(config?: SharpImageServiceConfig): ImageServiceConfig;
/**
* @deprecated The Squoosh image service is deprecated and will be removed in Astro 5.x.
* We suggest migrating to the default Sharp image service instead, as it is faster, more powerful and better maintained.
*
* Return the configuration needed to use the Squoosh-based image service
* See: https://docs.astro.build/en/guides/images/#configure-squoosh
*/

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
import { testFactory, waitForHydrate } from './test-utils.js';
const test = testFactory({ root: './fixtures/actions-blog/' });
const test = testFactory(import.meta.url, { root: './fixtures/actions-blog/' });
let devServer;
@ -23,6 +23,7 @@ test.describe('Astro Actions - Blog', () => {
await page.goto(astro.resolveUrl('/blog/first-post/'));
const likeButton = page.getByLabel('Like');
await waitForHydrate(page, likeButton);
await expect(likeButton, 'like button starts with 10 likes').toContainText('10');
await likeButton.click();
await expect(likeButton, 'like button should increment likes').toContainText('11');
@ -125,4 +126,13 @@ test.describe('Astro Actions - Blog', () => {
await expect(comments).toBeVisible();
await expect(comments).toContainText(body);
});
test('Logout action redirects', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/blog/first-post/'));
const logoutButton = page.getByTestId('logout-button');
await waitForHydrate(page, logoutButton);
await logoutButton.click();
await expect(page).toHaveURL(astro.resolveUrl('/blog/'));
});
});

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
import { testFactory, waitForHydrate } from './test-utils.js';
const test = testFactory({ root: './fixtures/actions-react-19/' });
const test = testFactory(import.meta.url, { root: './fixtures/actions-react-19/' });
let devServer;
@ -23,10 +23,12 @@ test.describe('Astro Actions - React 19', () => {
await page.goto(astro.resolveUrl('/blog/first-post/'));
const likeButton = page.getByLabel('likes-client');
await waitForHydrate(page, likeButton);
await expect(likeButton).toBeVisible();
await likeButton.click();
await expect(likeButton, 'like button should be disabled when pending').toBeDisabled();
await expect(likeButton).not.toBeDisabled({ timeout: 5000 });
await expect(likeButton).not.toBeDisabled();
});
test('Like action - server progressive enhancement', async ({ page, astro }) => {
@ -43,6 +45,8 @@ test.describe('Astro Actions - React 19', () => {
await page.goto(astro.resolveUrl('/blog/first-post/'));
const likeButton = page.getByLabel('likes-action-client');
await waitForHydrate(page, likeButton);
await expect(likeButton).toBeVisible();
await likeButton.click();

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({ root: './fixtures/astro-component/' });
const test = testFactory(import.meta.url, { root: './fixtures/astro-component/' });
let devServer;

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({
const test = testFactory(import.meta.url, {
root: './fixtures/astro-envs/',
devToolbar: {
enabled: false,

View file

@ -0,0 +1,33 @@
import { expect } from '@playwright/test';
import { testFactory, waitForHydrate } from './test-utils.js';
const test = testFactory(import.meta.url, { root: './fixtures/client-idle-timeout/' });
let devServer;
test.beforeAll(async ({ astro }) => {
devServer = await astro.startDevServer();
});
test.afterAll(async () => {
await devServer.stop();
});
test.describe('Client idle timeout', () => {
test('React counter', async ({ astro, page }) => {
await page.goto(astro.resolveUrl('/'));
const counter = page.locator('#react-counter');
await expect(counter, 'component is visible').toBeVisible();
const count = counter.locator('pre');
await expect(count, 'initial count is 0').toHaveText('0');
await waitForHydrate(page, counter);
const inc = counter.locator('.increment');
await inc.click();
await expect(count, 'count incremented by 1').toHaveText('1');
});
});

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({ root: './fixtures/client-only/' });
const test = testFactory(import.meta.url, { root: './fixtures/client-only/' });
let devServer;

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({ root: './fixtures/content-collections/' });
const test = testFactory(import.meta.url, { root: './fixtures/content-collections/' });
let devServer;

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({
const test = testFactory(import.meta.url, {
root: './fixtures/css/',
devToolbar: {
enabled: false,

View file

@ -2,7 +2,7 @@ import { expect } from '@playwright/test';
import testAdapter from '../test/test-adapter.js';
import { testFactory, waitForHydrate } from './test-utils.js';
const test = testFactory({
const test = testFactory(import.meta.url, {
root: './fixtures/custom-client-directives/',
});

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({
const test = testFactory(import.meta.url, {
root: './fixtures/dev-toolbar/',
});

View file

@ -1,7 +1,7 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({
const test = testFactory(import.meta.url, {
root: './fixtures/dev-toolbar/',
});

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