Compare commits
4 commits
main
...
feat/dev-o
Author | SHA1 | Date | |
---|---|---|---|
|
85d1d60cb5 | ||
|
4ba8b5c73f | ||
|
5bb1398b2a | ||
|
66f7b5aa3f |
109 changed files with 1081 additions and 532 deletions
8
.Dockerfile
Normal file
8
.Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
|||
FROM gitpod/workspace-node
|
||||
|
||||
# Install latest pnpm
|
||||
RUN curl -fsSL https://get.pnpm.io/install.sh | SHELL=`which bash` bash -
|
||||
|
||||
# Install deno in gitpod
|
||||
RUN curl -fsSL https://deno.land/x/install/install.sh | sh
|
||||
RUN /home/gitpod/.deno/bin/deno completions bash > /home/gitpod/.bashrc.d/90-deno && echo 'export DENO_INSTALL="/home/gitpod/.deno"' >> /home/gitpod/.bashrc.d/90-deno && echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /home/gitpod/.bashrc.d/90-deno
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fixed an issue where the transitions router did not work within framework components.
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
'@astrojs/cloudflare': patch
|
||||
---
|
||||
|
||||
fixes `AdvancedRuntime` & `DirectoryRuntime` types to work woth Cloudflare caches
|
|
@ -6,6 +6,10 @@ RUN npm install -g @playwright/test
|
|||
# Install latest pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Install deno
|
||||
ENV DENO_INSTALL=/usr/local
|
||||
RUN curl -fsSL https://deno.land/x/install/install.sh | sh
|
||||
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& curl -sSL https://dl.google.com/linux/direct/google-chrome-stable_current_$(dpkg --print-architecture).deb -o /tmp/chrome.deb \
|
||||
&& apt-get -y install /tmp/chrome.deb
|
||||
|
|
34
.devcontainer/deno/devcontainer.json
Normal file
34
.devcontainer/deno/devcontainer.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "Deno",
|
||||
"build": {
|
||||
"dockerfile": "../examples.deno.Dockerfile"
|
||||
},
|
||||
|
||||
"workspaceFolder": "/workspaces/astro/examples/deno",
|
||||
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"label": "Application",
|
||||
"onAutoForward": "openPreview"
|
||||
}
|
||||
},
|
||||
|
||||
"forwardPorts": [4321],
|
||||
|
||||
"postCreateCommand": "pnpm install && cd /workspaces/astro && pnpm run build",
|
||||
|
||||
"waitFor": "postCreateCommand",
|
||||
|
||||
"postAttachCommand": {
|
||||
"Server": "pnpm start --host"
|
||||
},
|
||||
|
||||
"customizations": {
|
||||
"codespaces": {
|
||||
"openFiles": ["src/pages/index.astro"]
|
||||
},
|
||||
"vscode": {
|
||||
"extensions": ["astro-build.astro-vscode", "esbenp.prettier-vscode"]
|
||||
}
|
||||
}
|
||||
}
|
10
.devcontainer/examples.deno.Dockerfile
Normal file
10
.devcontainer/examples.deno.Dockerfile
Normal file
|
@ -0,0 +1,10 @@
|
|||
FROM mcr.microsoft.com/devcontainers/javascript-node:0-18
|
||||
|
||||
# Install latest pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Install deno
|
||||
ENV DENO_INSTALL=/usr/local
|
||||
RUN curl -fsSL https://deno.land/x/install/install.sh | sh
|
||||
|
||||
COPY example-welcome-message.txt /usr/local/etc/vscode-dev-containers/first-run-notice.txt
|
|
@ -1,5 +1,7 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { builtinModules } = require('module');
|
||||
|
||||
/** @type {import("@types/eslint").Linter.Config} */
|
||||
module.exports = {
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended-type-checked',
|
||||
|
@ -69,6 +71,12 @@ module.exports = {
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['packages/astro/src/runtime/client/**/*.ts'],
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['packages/**/test/*.js', 'packages/**/*.js'],
|
||||
env: {
|
||||
|
|
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
@ -133,6 +133,11 @@ jobs:
|
|||
node-version: ${{ matrix.NODE_VERSION }}
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Use Deno
|
||||
uses: denoland/setup-deno@v1
|
||||
with:
|
||||
deno-version: v1.35.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
|
|
5
.github/workflows/snapshot-release.yml
vendored
5
.github/workflows/snapshot-release.yml
vendored
|
@ -19,11 +19,6 @@ jobs:
|
|||
name: Create a snapshot release of a pull request
|
||||
if: ${{ github.repository_owner == 'withastro' && github.event.issue.pull_request && startsWith(github.event.comment.body, '!preview') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Check if user has admin access (only admins can publish snapshot releases)."
|
||||
uses: "lannonbr/repo-permission-check-action@2.0.0"
|
||||
|
|
24
.github/workflows/test-hosts.yml
vendored
24
.github/workflows/test-hosts.yml
vendored
|
@ -11,6 +11,8 @@ env:
|
|||
VERCEL_ORG_ID: ${{ secrets.VERCEL_TEST_ORG_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_TEST_PROJECT_ID }}
|
||||
VERCEL_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_TEST_SITE_ID }}
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TEST_AUTH_TOKEN }}
|
||||
FORCE_COLOR: true
|
||||
|
||||
jobs:
|
||||
|
@ -32,20 +34,22 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build Astro
|
||||
run: pnpm turbo build --filter astro --filter @astrojs/vercel
|
||||
|
||||
- name: Build test project
|
||||
- name: Install Hosts CLIs
|
||||
run: pnpm install --global netlify-cli vercel
|
||||
|
||||
- name: Deploy Vercel
|
||||
working-directory: ./packages/integrations/vercel/test/hosted/hosted-astro-project
|
||||
run:
|
||||
pnpm run build
|
||||
|
||||
- name: Deploy to Vercel
|
||||
working-directory: ./packages/integrations/vercel/test/hosted/hosted-astro-project
|
||||
run:
|
||||
pnpm dlx vercel --prod --prebuilt
|
||||
vercel --prod --prebuilt
|
||||
|
||||
- name: Test
|
||||
- name: Deploy Netlify
|
||||
working-directory: ./packages/integrations/netlify/test/hosted/hosted-astro-project
|
||||
run:
|
||||
pnpm run build
|
||||
netlify deploy --prod
|
||||
|
||||
- name: Test both hosts
|
||||
run:
|
||||
pnpm run test:e2e:hosts
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
---
|
||||
image:
|
||||
file: .Dockerfile
|
||||
# Commands to start on workspace startup
|
||||
tasks:
|
||||
- before: |
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
# Convert context URL to an array
|
||||
mapfile -t CONTEXT_URL_ITEMS < <(echo "$GITPOD_WORKSPACE_CONTEXT_URL" | tr '/' '\n')
|
||||
|
||||
# Install latest pnpm
|
||||
curl -fsSL https://get.pnpm.io/install.sh | SHELL=`which bash` bash -
|
||||
|
||||
# Check if Gitpod started from a specific example directory in the repository
|
||||
if [ "${CONTEXT_URL_ITEMS[7]}" = "examples" ]; then
|
||||
EXAMPLE_PROJECT=${CONTEXT_URL_ITEMS[8]}
|
||||
|
|
|
@ -52,6 +52,8 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll
|
|||
| [@astrojs/svelte](packages/integrations/svelte) | [![astro version](https://img.shields.io/npm/v/@astrojs/svelte.svg?label=%20)](packages/integrations/svelte/CHANGELOG.md) |
|
||||
| [@astrojs/vue](packages/integrations/vue) | [![astro version](https://img.shields.io/npm/v/@astrojs/vue.svg?label=%20)](packages/integrations/vue/CHANGELOG.md) |
|
||||
| [@astrojs/lit](packages/integrations/lit) | [![astro version](https://img.shields.io/npm/v/@astrojs/lit.svg?label=%20)](packages/integrations/lit/CHANGELOG.md) |
|
||||
| [@astrojs/deno](packages/integrations/deno) | [![astro version](https://img.shields.io/npm/v/@astrojs/deno.svg?label=%20)](packages/integrations/deno/CHANGELOG.md) |
|
||||
| [@astrojs/netlify](packages/integrations/netlify) | [![astro version](https://img.shields.io/npm/v/@astrojs/netlify.svg?label=%20)](packages/integrations/netlify/CHANGELOG.md) |
|
||||
| [@astrojs/node](packages/integrations/node) | [![astro version](https://img.shields.io/npm/v/@astrojs/node.svg?label=%20)](packages/integrations/node/CHANGELOG.md) |
|
||||
| [@astrojs/vercel](packages/integrations/vercel) | [![astro version](https://img.shields.io/npm/v/@astrojs/vercel.svg?label=%20)](packages/integrations/vercel/CHANGELOG.md) |
|
||||
| [@astrojs/cloudflare](packages/integrations/cloudflare) | [![astro version](https://img.shields.io/npm/v/@astrojs/cloudflare.svg?label=%20)](packages/integrations/cloudflare/CHANGELOG.md) |
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,6 @@
|
|||
"@astrojs/mdx": "^1.1.1",
|
||||
"@astrojs/rss": "^3.0.0",
|
||||
"@astrojs/sitemap": "^3.0.1",
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
"scripts": {},
|
||||
"devDependencies": {
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^2.0.0-beta.0"
|
||||
|
|
1
examples/dev-overlay/.codesandbox/Dockerfile
Normal file
1
examples/dev-overlay/.codesandbox/Dockerfile
Normal file
|
@ -0,0 +1 @@
|
|||
FROM node:18-bullseye
|
21
examples/dev-overlay/.gitignore
vendored
Normal file
21
examples/dev-overlay/.gitignore
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
4
examples/dev-overlay/.vscode/extensions.json
vendored
Normal file
4
examples/dev-overlay/.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
examples/dev-overlay/.vscode/launch.json
vendored
Normal file
11
examples/dev-overlay/.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
47
examples/dev-overlay/README.md
Normal file
47
examples/dev-overlay/README.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Astro Starter Kit: Dev Overlay Showcase
|
||||
|
||||
```sh
|
||||
npm create astro@latest -- --template dev-overlay
|
||||
```
|
||||
|
||||
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal)
|
||||
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal)
|
||||
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```text
|
||||
/
|
||||
├── public/
|
||||
├── src/
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
5
examples/dev-overlay/astro-devtools-plugin.js
Normal file
5
examples/dev-overlay/astro-devtools-plugin.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
id: 'custom',
|
||||
title: "I'm a plugin!",
|
||||
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="#fff" d="M7.563 19.28a9.693 9.693 0 0 0 2.496-.217a8.798 8.798 0 0 1 2.98-.131a7.78 7.78 0 0 1 1.289.257c1.077.275 2.61.223 3.005-.41c.29-.468.253-.787-.026-1.199c-.06-.09-.126-.17-.188-.235l-.024-.025a25.109 25.109 0 0 1-.743-.618a25.578 25.578 0 0 1-1.753-1.66a16.153 16.153 0 0 1-1.577-1.893l-.036-.053c-.742-1.139-1.558-1.067-2.002-.318a9.593 9.593 0 0 1-.955 1.332c-.41.482-.83.89-1.306 1.297c-.122.105-.502.42-.411.344c-.004.003-.017.015.05-.071c-.098.12-.95.877-1.2 1.162c-.515.583-.722 1.08-.645 1.48c.073.376.22.587.45.745a1.433 1.433 0 0 0 .48.206c.033.003.072.005.116.007Zm7.099-7.276c1.375 1.97 3.731 3.793 3.731 3.793s2.064 1.748.638 4.038c-1.426 2.29-5.253 1.278-5.253 1.278s-1.52-.49-3.286-.098c-1.765.395-3.286.245-3.286.245S5 21.015 4.553 18.701c-.446-2.314 2.06-4.04 2.258-4.284c.196-.247 1.512-1.073 2.452-2.658c.94-1.586 3.584-2.54 5.399.245Zm5.538-1.42c0 .457.191 2.393-1.552 2.432c-1.743.038-1.816-1.178-1.816-2.05c0-.913.187-2.205 1.59-2.205c1.4 0 1.778 1.369 1.778 1.824Zm-5.429-2.777c-1.18-.152-1.447-1.222-1.333-2.293c.095-.875 1.142-2.219 1.981-2.026c.837.19 1.6 1.3 1.446 2.254c-.152.957-.912 2.218-2.094 2.065ZM9.755 7.44c-.861 0-1.56-.993-1.56-2.22c0-1.227.698-2.22 1.56-2.22c.863 0 1.56.993 1.56 2.22c0 1.227-.697 2.22-1.56 2.22Zm-3.793 4.566c-1.695.365-2.327-1.597-2.14-2.515c0 0 .2-1.987 1.576-2.11c1.093-.095 1.898 1.101 1.98 1.785c.052.444.283 2.475-1.416 2.84Z"/></svg>',
|
||||
};
|
11
examples/dev-overlay/astro.config.mjs
Normal file
11
examples/dev-overlay/astro.config.mjs
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
|
||||
import solidJs from "@astrojs/solid-js";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
devTools: {
|
||||
plugins: ['./astro-devtools-plugin.js']
|
||||
},
|
||||
integrations: [solidJs()]
|
||||
});
|
3
examples/dev-overlay/components/Component.tsx
Normal file
3
examples/dev-overlay/components/Component.tsx
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function HelloWorld(props: { text: string }) {
|
||||
return <><div>{props.text}</div><br/></>;
|
||||
}
|
18
examples/dev-overlay/package.json
Normal file
18
examples/dev-overlay/package.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "@example/dev-overlay",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.2.3",
|
||||
"@astrojs/solid-js": "^3.0.1",
|
||||
"solid-js": "^1.7.11"
|
||||
}
|
||||
}
|
BIN
examples/dev-overlay/public/astro-logo.png
Normal file
BIN
examples/dev-overlay/public/astro-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
9
examples/dev-overlay/public/favicon.svg
Normal file
9
examples/dev-overlay/public/favicon.svg
Normal file
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
After Width: | Height: | Size: 749 B |
23
examples/dev-overlay/src/pages/index.astro
Normal file
23
examples/dev-overlay/src/pages/index.astro
Normal file
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
import { HelloWorld } from '../../components/Component';
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>Astro</title>
|
||||
</head>
|
||||
<body style="background-color: sandybrown;">
|
||||
<h1>Astro</h1>
|
||||
|
||||
<h2>Audit</h2>
|
||||
<img src="/astro-logo.png" />
|
||||
|
||||
<h2>Components</h2>
|
||||
<HelloWorld text="No hydration" />
|
||||
<HelloWorld text="client:load Hydrated" client:load name="hello" />
|
||||
</body>
|
||||
</html>
|
7
examples/dev-overlay/tsconfig.json
Normal file
7
examples/dev-overlay/tsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"jsx": "preserve",
|
||||
"jsxImportSource": "solid-js"
|
||||
}
|
||||
}
|
|
@ -14,6 +14,6 @@
|
|||
"@astrojs/alpinejs": "^0.3.1",
|
||||
"@types/alpinejs": "^3.7.2",
|
||||
"alpinejs": "^3.12.3",
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"dependencies": {
|
||||
"@astrojs/lit": "^3.0.1",
|
||||
"@webcomponents/template-shadowroot": "^0.2.1",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"lit": "^2.8.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"@astrojs/solid-js": "^3.0.2",
|
||||
"@astrojs/svelte": "^4.0.3",
|
||||
"@astrojs/vue": "^3.0.1",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"preact": "^10.17.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"dependencies": {
|
||||
"@astrojs/preact": "^3.0.1",
|
||||
"@preact/signals": "^1.2.1",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"preact": "^10.17.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"@astrojs/react": "^3.0.3",
|
||||
"@types/react": "^18.2.21",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/solid-js": "^3.0.2",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"solid-js": "^1.7.11"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/svelte": "^4.0.3",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"svelte": "^4.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/vue": "^3.0.1",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"vue": "^3.3.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^6.0.3",
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ export default function createIntegration(): AstroIntegration {
|
|||
// See the @astrojs/react integration for an example
|
||||
// https://github.com/withastro/astro/blob/main/packages/integrations/react/src/index.ts
|
||||
},
|
||||
'astro:build:setup': ({ pages, updateConfig }) => {
|
||||
// See the @astrojs/lit integration for an example
|
||||
// https://github.com/withastro/astro/blob/main/packages/integrations/lit/src/index.ts
|
||||
'astro:build:setup': ({ config, updateConfig }) => {
|
||||
// See the @astrojs/netlify integration for an example
|
||||
// https://github.com/withastro/astro/blob/main/packages/integrations/netlify/src/integration-functions.ts
|
||||
},
|
||||
'astro:build:done': ({ dir, routes }) => {
|
||||
// See the @astrojs/partytown integration for an example
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
"scripts": {},
|
||||
"devDependencies": {
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^2.0.0-beta.0"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^6.0.3",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"html-minifier": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"dependencies": {
|
||||
"@astrojs/node": "^6.0.3",
|
||||
"@astrojs/svelte": "^4.0.3",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"svelte": "^4.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/tailwind": "^5.0.2",
|
||||
"@astrojs/tailwind": "^5.0.1",
|
||||
"@astrojs/node": "^6.0.3",
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/markdoc": "^0.5.2",
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/markdown-remark": "^3.2.1",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"hast-util-select": "^5.0.5",
|
||||
"rehype-autolink-headings": "^6.1.1",
|
||||
"rehype-slug": "^5.1.0",
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.2.4"
|
||||
"astro": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"dependencies": {
|
||||
"@astrojs/mdx": "^1.1.1",
|
||||
"@astrojs/preact": "^3.0.1",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"preact": "^10.17.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"dependencies": {
|
||||
"@astrojs/preact": "^3.0.1",
|
||||
"@nanostores/preact": "^0.5.0",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"nanostores": "^0.9.3",
|
||||
"preact": "^10.17.1"
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^1.1.1",
|
||||
"@astrojs/tailwind": "^5.0.2",
|
||||
"@astrojs/tailwind": "^5.0.1",
|
||||
"@types/canvas-confetti": "^1.6.0",
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"canvas-confetti": "^1.6.0",
|
||||
"postcss": "^8.4.28",
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"vite-plugin-pwa": "0.16.4",
|
||||
"workbox-window": "^7.0.0"
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"test": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.2.4",
|
||||
"astro": "^3.2.3",
|
||||
"vitest": "^0.34.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,5 @@
|
|||
# astro
|
||||
|
||||
## 3.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#8638](https://github.com/withastro/astro/pull/8638) [`160d1cd75`](https://github.com/withastro/astro/commit/160d1cd755e70af1d8ec294d01dd2cb32d60db50) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - The `@astrojs/tailwind` integration now creates a `tailwind.config.mjs` file by default
|
||||
|
||||
- [#8767](https://github.com/withastro/astro/pull/8767) [`30de32436`](https://github.com/withastro/astro/commit/30de324361bc261956eb9fc08fe60a82ff602a9b) Thanks [@martrapp](https://github.com/martrapp)! - Revert fix #8472
|
||||
|
||||
[#8472](https://github.com/withastro/astro/pull/8472) caused some style files from previous pages to not be cleanly deleted on view transitions. For a discussion of a future fix for the original issue [#8144](https://github.com/withastro/astro/issues/8114) see [#8745](https://github.com/withastro/astro/pull/8745).
|
||||
|
||||
- [#8741](https://github.com/withastro/astro/pull/8741) [`c4a7ec425`](https://github.com/withastro/astro/commit/c4a7ec4255e7acb9555cb8bb74ea13c5fbb2ac17) Thanks [@lilnasy](https://github.com/lilnasy)! - Fixed an issue on Windows where lowercase drive letters in current working directory led to missing scripts and styles.
|
||||
|
||||
- [#8772](https://github.com/withastro/astro/pull/8772) [`c24f70d91`](https://github.com/withastro/astro/commit/c24f70d91601dd3a6b5a84f04d61824e775e9b44) Thanks [@martrapp](https://github.com/martrapp)! - Fix flickering during view transitions
|
||||
|
||||
- [#8754](https://github.com/withastro/astro/pull/8754) [`93b092266`](https://github.com/withastro/astro/commit/93b092266febfad16a48575f8eee12d5910bf071) Thanks [@bluwy](https://github.com/bluwy)! - Make CSS chunk names less confusing
|
||||
|
||||
- [#8776](https://github.com/withastro/astro/pull/8776) [`29cdfa024`](https://github.com/withastro/astro/commit/29cdfa024886dd581cb207586f7dfec6966bdd4e) Thanks [@martrapp](https://github.com/martrapp)! - Fix transition attributes on islands
|
||||
|
||||
- [#8773](https://github.com/withastro/astro/pull/8773) [`eaed844ea`](https://github.com/withastro/astro/commit/eaed844ea8f2f52e0c9caa40bb3ec7377e10595f) Thanks [@sumimakito](https://github.com/sumimakito)! - Fix an issue where HTML attributes do not render if getHTMLAttributes in an image service returns a Promise
|
||||
|
||||
## 3.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
|
|
@ -32,13 +32,6 @@ async function main() {
|
|||
}
|
||||
}
|
||||
|
||||
// windows drive letters can sometimes be lowercase, which vite cannot process
|
||||
if (process.platform === 'win32') {
|
||||
const cwd = process.cwd();
|
||||
const correctedCwd = cwd.slice(0, 1).toUpperCase() + cwd.slice(1);
|
||||
if (correctedCwd !== cwd) process.chdir(correctedCwd);
|
||||
}
|
||||
|
||||
return import('./dist/cli/index.js')
|
||||
.then(({ cli }) => cli(process.argv))
|
||||
.catch((error) => {
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import React from 'react';
|
||||
import { navigate } from "astro:transitions/client";
|
||||
export default function ClickToNavigate({ to, id }) {
|
||||
return <button id={id} onClick={() => navigate(to)}>Navigate to `{to}`</button>;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
import { ViewTransitions } from 'astro:transitions';
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<ViewTransitions/>
|
||||
</head>
|
||||
<body>
|
||||
<p>Local transitions</p>
|
||||
<slot/>
|
||||
<script>
|
||||
document.addEventListener("astro:after-swap", () => {
|
||||
document.querySelector("p").addEventListener("transitionstart", () => {
|
||||
console.info("transitionstart");
|
||||
});
|
||||
document.documentElement.setAttribute("class", "blue");
|
||||
});
|
||||
document.dispatchEvent(new Event("astro:after-swap"));
|
||||
</script>
|
||||
</body>
|
||||
<style>
|
||||
p {
|
||||
transition: background-color 1s;
|
||||
}
|
||||
p {
|
||||
background-color: #0ee;
|
||||
color: red;
|
||||
}
|
||||
.blue p {
|
||||
background-color: #ee0;
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
</html>
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
import ClickToNavigate from "../components/ClickToNavigate.jsx"
|
||||
import { ViewTransitions } from "astro:transitions";
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
<ViewTransitions />
|
||||
</head>
|
||||
<body>
|
||||
<ClickToNavigate id="react-client-load-navigate-button" to="/two" client:load/>
|
||||
</body>
|
||||
</html>
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
import ListenerLayout from '../components/listener-layout.astro';
|
||||
---
|
||||
<ListenerLayout>
|
||||
<a id="totwo" href="/listener-two">Go to listener two</a>
|
||||
</ListenerLayout>
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
import ListenerLayout from '../components/listener-layout.astro';
|
||||
---
|
||||
<ListenerLayout>
|
||||
<a id="toone" href="/listener-one">Go to listener one</a>
|
||||
</ListenerLayout>
|
|
@ -230,28 +230,6 @@ test.describe('View Transitions', () => {
|
|||
await expect(h, 'imported CSS updated').toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
|
||||
});
|
||||
|
||||
test('No page rendering during swap()', async ({ page, astro }) => {
|
||||
let transitions = 0;
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'info' && msg.text() === 'transitionstart') ++transitions;
|
||||
});
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/listener-one'));
|
||||
let p = page.locator('#totwo');
|
||||
await expect(p, 'should have content').toHaveText('Go to listener two');
|
||||
// on load a CSS transition is started triggered by a class on the html element
|
||||
expect(transitions).toEqual(1);
|
||||
|
||||
// go to page 2
|
||||
await page.click('#totwo');
|
||||
p = page.locator('#toone');
|
||||
await expect(p, 'should have content').toHaveText('Go to listener one');
|
||||
// swap() resets that class, the after-swap listener sets it again.
|
||||
// the temporarily missing class must not trigger page rendering
|
||||
expect(transitions).toEqual(1);
|
||||
});
|
||||
|
||||
test('click hash links does not do navigation', async ({ page, astro }) => {
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
|
@ -670,7 +648,7 @@ test.describe('View Transitions', () => {
|
|||
expect(loads.length, 'There should be 2 page loads').toEqual(2);
|
||||
});
|
||||
|
||||
test.skip('client:only styles are retained on transition', async ({ page, astro }) => {
|
||||
test('client:only styles are retained on transition', async ({ page, astro }) => {
|
||||
const totalExpectedStyles = 7;
|
||||
|
||||
// Go to page 1
|
||||
|
@ -753,21 +731,6 @@ test.describe('View Transitions', () => {
|
|||
await expect(p, 'should have content').toHaveText('Page 1');
|
||||
});
|
||||
|
||||
test('Use the client side router in framework components', async ({ page, astro }) => {
|
||||
await page.goto(astro.resolveUrl('/client-load'));
|
||||
|
||||
// the button is set to naviagte() to /two
|
||||
const button = page.locator('#react-client-load-navigate-button');
|
||||
|
||||
await expect(button, 'should have content').toHaveText('Navigate to `/two`');
|
||||
|
||||
await button.click();
|
||||
|
||||
const p = page.locator('#two');
|
||||
|
||||
await expect(p, 'should have content').toHaveText('Page 2');
|
||||
});
|
||||
|
||||
test('body inline scripts do not re-execute on navigation', async ({ page, astro }) => {
|
||||
const errors = [];
|
||||
page.addListener('pageerror', (err) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "astro",
|
||||
"version": "3.2.4",
|
||||
"version": "3.2.3",
|
||||
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
||||
"type": "module",
|
||||
"author": "withastro",
|
||||
|
|
|
@ -1084,6 +1084,10 @@ export interface AstroUserConfig {
|
|||
remotePatterns?: Partial<RemotePattern>[];
|
||||
};
|
||||
|
||||
devTools?: {
|
||||
plugins: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @docs
|
||||
* @kind heading
|
||||
|
@ -2263,3 +2267,10 @@ export interface ClientDirectiveConfig {
|
|||
name: string;
|
||||
entrypoint: string;
|
||||
}
|
||||
|
||||
export interface DevOverlayItem {
|
||||
id: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
init?(canvas: ShadowRoot, eventTarget: EventTarget): void | Promise<void>;
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ export async function getImage(
|
|||
src: imageURL,
|
||||
attributes:
|
||||
service.getHTMLAttributes !== undefined
|
||||
? await service.getHTMLAttributes(validatedOptions, imageConfig)
|
||||
? service.getHTMLAttributes(validatedOptions, imageConfig)
|
||||
: {},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ const ALIASES = new Map([
|
|||
]);
|
||||
const ASTRO_CONFIG_STUB = `import { defineConfig } from 'astro/config';\n\nexport default defineConfig({});`;
|
||||
const TAILWIND_CONFIG_STUB = `/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
|
@ -74,6 +74,7 @@ const OFFICIAL_ADAPTER_TO_IMPORT_MAP: Record<string, string> = {
|
|||
vercel: '@astrojs/vercel/serverless',
|
||||
cloudflare: '@astrojs/cloudflare',
|
||||
node: '@astrojs/node',
|
||||
deno: '@astrojs/deno',
|
||||
};
|
||||
|
||||
// Users might lack access to the global npm registry, this function
|
||||
|
@ -159,7 +160,7 @@ export async function add(names: string[], { flags }: AddOptions) {
|
|||
'./tailwind.config.mjs',
|
||||
'./tailwind.config.js',
|
||||
],
|
||||
defaultConfigFile: './tailwind.config.mjs',
|
||||
defaultConfigFile: './tailwind.config.cjs',
|
||||
defaultConfigContent: TAILWIND_CONFIG_STUB,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ type RawContentEvent = { name: ChokidarEvent; entry: string };
|
|||
type ContentEvent = { name: ChokidarEvent; entry: URL };
|
||||
|
||||
type DataEntryMetadata = Record<string, never>;
|
||||
type ContentEntryMetadata = { slug: string, path: string };
|
||||
type ContentEntryMetadata = { slug: string };
|
||||
type CollectionEntryMap = {
|
||||
[collection: string]:
|
||||
| {
|
||||
|
@ -276,7 +276,7 @@ export async function createContentTypesGenerator({
|
|||
if (!(entryKey in collectionEntryMap[collectionKey].entries)) {
|
||||
collectionEntryMap[collectionKey] = {
|
||||
type: 'content',
|
||||
entries: { ...collectionInfo.entries, [entryKey]: { slug: addedSlug, path: event.entry.toString() } },
|
||||
entries: { ...collectionInfo.entries, [entryKey]: { slug: addedSlug } },
|
||||
};
|
||||
}
|
||||
return { shouldGenerateTypes: true };
|
||||
|
@ -453,15 +453,7 @@ async function writeContentFiles({
|
|||
)}] }`;
|
||||
|
||||
const slugType = JSON.stringify(entryMetadata.slug);
|
||||
contentTypesStr += [
|
||||
`${entryKey}: {`,
|
||||
` id: ${entryKey};`,
|
||||
` slug: ${slugType};`,
|
||||
` path: ${JSON.stringify(entryMetadata.path)};`,
|
||||
` body: string;`,
|
||||
` collection: ${collectionKey};`,
|
||||
` data: ${dataType}`,
|
||||
`} & ${renderType};`].join("\n");
|
||||
contentTypesStr += `${entryKey}: {\n id: ${entryKey};\n slug: ${slugType};\n body: string;\n collection: ${collectionKey};\n data: ${dataType}\n} & ${renderType};\n`;
|
||||
}
|
||||
contentTypesStr += `};\n`;
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { GetModuleInfo, ModuleInfo } from 'rollup';
|
||||
import type { GetModuleInfo } from 'rollup';
|
||||
|
||||
import crypto from 'node:crypto';
|
||||
import npath from 'node:path';
|
||||
|
@ -6,29 +6,20 @@ import type { AstroSettings } from '../../@types/astro.js';
|
|||
import { viteID } from '../util.js';
|
||||
import { getTopLevelPages } from './graph.js';
|
||||
|
||||
// These pages could be used as base names for the chunk hashed name, but they are confusing
|
||||
// and should be avoided it possible
|
||||
const confusingBaseNames = ['404', '500'];
|
||||
|
||||
// The short name for when the hash can be included
|
||||
// We could get rid of this and only use the createSlugger implementation, but this creates
|
||||
// slightly prettier names.
|
||||
export function shortHashedName(id: string, ctx: { getModuleInfo: GetModuleInfo }): string {
|
||||
const parents = Array.from(getTopLevelPages(id, ctx));
|
||||
return createNameHash(
|
||||
getFirstParentId(parents),
|
||||
parents.map(([page]) => page.id)
|
||||
);
|
||||
}
|
||||
const firstParentId = parents[0]?.[0].id;
|
||||
const firstParentName = firstParentId ? npath.parse(firstParentId).name : 'index';
|
||||
|
||||
export function createNameHash(baseId: string | undefined, hashIds: string[]): string {
|
||||
const baseName = baseId ? prettifyBaseName(npath.parse(baseId).name) : 'index';
|
||||
const hash = crypto.createHash('sha256');
|
||||
for (const id of hashIds) {
|
||||
hash.update(id, 'utf-8');
|
||||
for (const [page] of parents) {
|
||||
hash.update(page.id, 'utf-8');
|
||||
}
|
||||
const h = hash.digest('hex').slice(0, 8);
|
||||
const proposedName = baseName + '.' + h;
|
||||
const proposedName = firstParentName + '.' + h;
|
||||
return proposedName;
|
||||
}
|
||||
|
||||
|
@ -43,7 +34,7 @@ export function createSlugger(settings: AstroSettings) {
|
|||
.map(([page]) => page.id)
|
||||
.sort()
|
||||
.join('-');
|
||||
const firstParentId = getFirstParentId(parents) || indexPage;
|
||||
const firstParentId = parents[0]?.[0].id || indexPage;
|
||||
|
||||
// Use the last two segments, for ex /docs/index
|
||||
let dir = firstParentId;
|
||||
|
@ -54,7 +45,7 @@ export function createSlugger(settings: AstroSettings) {
|
|||
break;
|
||||
}
|
||||
|
||||
const name = prettifyBaseName(npath.parse(npath.basename(dir)).name);
|
||||
const name = npath.parse(npath.basename(dir)).name;
|
||||
key = key.length ? name + sep + key : name;
|
||||
dir = npath.dirname(dir);
|
||||
i++;
|
||||
|
@ -85,32 +76,3 @@ export function createSlugger(settings: AstroSettings) {
|
|||
return name;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first parent id from `parents` where its name is not confusing.
|
||||
* Returns undefined if there's no parents.
|
||||
*/
|
||||
function getFirstParentId(parents: [ModuleInfo, number, number][]) {
|
||||
for (const parent of parents) {
|
||||
const id = parent[0].id;
|
||||
const baseName = npath.parse(id).name;
|
||||
if (!confusingBaseNames.includes(baseName)) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
// If all parents are confusing, just use the first one. Or if there's no
|
||||
// parents, this will return undefined.
|
||||
return parents[0]?.[0].id;
|
||||
}
|
||||
|
||||
const charsToReplaceRe = /[.\[\]]/g;
|
||||
const underscoresRe = /_+/g;
|
||||
/**
|
||||
* Prettify base names so they're easier to read:
|
||||
* - index -> index
|
||||
* - [slug] -> _slug_
|
||||
* - [...spread] -> _spread_
|
||||
*/
|
||||
function prettifyBaseName(str: string) {
|
||||
return str.replace(charsToReplaceRe, '_').replace(underscoresRe, '_');
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import * as crypto from 'node:crypto';
|
||||
import * as npath from 'node:path';
|
||||
import type { GetModuleInfo } from 'rollup';
|
||||
import { type ResolvedConfig, type Plugin as VitePlugin } from 'vite';
|
||||
import { isBuildableCSSRequest } from '../../../vite-plugin-astro-server/util.js';
|
||||
|
@ -91,7 +93,7 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
|
|||
if (new URL(pageInfo.id, 'file://').searchParams.has(PROPAGATED_ASSET_FLAG)) {
|
||||
// Split delayed assets to separate modules
|
||||
// so they can be injected where needed
|
||||
const chunkId = assetName.createNameHash(id, [id]);
|
||||
const chunkId = createNameHash(id, [id]);
|
||||
internals.cssModuleToChunkIdMap.set(id, chunkId);
|
||||
return chunkId;
|
||||
}
|
||||
|
@ -270,6 +272,17 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
|
|||
|
||||
/***** UTILITY FUNCTIONS *****/
|
||||
|
||||
function createNameHash(baseId: string, hashIds: string[]): string {
|
||||
const baseName = baseId ? npath.parse(baseId).name : 'index';
|
||||
const hash = crypto.createHash('sha256');
|
||||
for (const id of hashIds) {
|
||||
hash.update(id, 'utf-8');
|
||||
}
|
||||
const h = hash.digest('hex').slice(0, 8);
|
||||
const proposedName = baseName + '.' + h;
|
||||
return proposedName;
|
||||
}
|
||||
|
||||
function* getParentClientOnlys(
|
||||
id: string,
|
||||
ctx: { getModuleInfo: GetModuleInfo },
|
||||
|
|
|
@ -32,6 +32,9 @@ const ASTRO_CONFIG_DEFAULTS = {
|
|||
image: {
|
||||
service: { entrypoint: 'astro/assets/services/sharp', config: {} },
|
||||
},
|
||||
devTools: {
|
||||
plugins: [],
|
||||
},
|
||||
compressHTML: true,
|
||||
server: {
|
||||
host: false,
|
||||
|
@ -220,6 +223,9 @@ export const AstroConfigSchema = z.object({
|
|||
.default([]),
|
||||
})
|
||||
.default(ASTRO_CONFIG_DEFAULTS.image),
|
||||
devTools: z
|
||||
.object({ plugins: z.array(z.string()).default([]) })
|
||||
.default(ASTRO_CONFIG_DEFAULTS.devTools),
|
||||
markdown: z
|
||||
.object({
|
||||
drafts: z.boolean().default(false),
|
||||
|
|
|
@ -16,6 +16,7 @@ import astroPostprocessVitePlugin from '../vite-plugin-astro-postprocess/index.j
|
|||
import { vitePluginAstroServer } from '../vite-plugin-astro-server/index.js';
|
||||
import astroVitePlugin from '../vite-plugin-astro/index.js';
|
||||
import configAliasVitePlugin from '../vite-plugin-config-alias/index.js';
|
||||
import astroDevTools from '../vite-plugin-dev-tools/vite-plugin-dev-tools.js';
|
||||
import envVitePlugin from '../vite-plugin-env/index.js';
|
||||
import astroHeadPlugin from '../vite-plugin-head/index.js';
|
||||
import htmlVitePlugin from '../vite-plugin-html/index.js';
|
||||
|
@ -134,6 +135,7 @@ export async function createVite(
|
|||
vitePluginSSRManifest(),
|
||||
astroAssetsPlugin({ settings, logger, mode }),
|
||||
astroTransitions(),
|
||||
astroDevTools({ settings, logger }),
|
||||
],
|
||||
publicDir: fileURLToPath(settings.config.publicDir),
|
||||
root: fileURLToPath(settings.config.root),
|
||||
|
|
189
packages/astro/src/runtime/client/dev-overlay/overlay.ts
Normal file
189
packages/astro/src/runtime/client/dev-overlay/overlay.ts
Normal file
|
@ -0,0 +1,189 @@
|
|||
// @ts-expect-error
|
||||
import { loadDevToolsPlugins } from 'astro:dev-tools';
|
||||
import type { DevOverlayItem as DevOverlayItemDefinition } from '../../../@types/astro.js';
|
||||
import astroDevToolPlugin from './plugins/astro.js';
|
||||
import astroAuditPlugin from './plugins/audit.js';
|
||||
import astroXrayPlugin from './plugins/xray.js';
|
||||
import { DevOverlayHighlight, DevOverlayTooltip, DevOverlayWindow } from './ui-toolkit.js';
|
||||
|
||||
type DevOverlayItem = DevOverlayItemDefinition & {
|
||||
active: boolean;
|
||||
inited: boolean;
|
||||
eventTarget: EventTarget;
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const builtinPlugins: DevOverlayItem[] = [
|
||||
astroDevToolPlugin,
|
||||
astroXrayPlugin,
|
||||
astroAuditPlugin,
|
||||
].map((plugin) => ({ ...plugin, active: false, inited: false, eventTarget: new EventTarget() }));
|
||||
const customPluginsImports = (await loadDevToolsPlugins()) as DevOverlayItem[];
|
||||
const customPlugins: DevOverlayItem[] = [];
|
||||
customPlugins.push(...customPluginsImports.map((plugin) => ({ ...plugin, active: false })));
|
||||
|
||||
const plugins: DevOverlayItem[] = [...builtinPlugins, ...customPlugins];
|
||||
|
||||
class AstroDevOverlay extends HTMLElement {
|
||||
shadowRoot: ShadowRoot;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.shadowRoot = this.attachShadow({ mode: 'closed' });
|
||||
}
|
||||
|
||||
// connect component
|
||||
async connectedCallback() {
|
||||
this.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
#dev-overlay {
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
bottom: 7.5%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0%);
|
||||
height: 56px;
|
||||
overflow: hidden;
|
||||
|
||||
background: linear-gradient(180deg, #13151A 0%, rgba(19, 21, 26, 0.88) 100%);
|
||||
box-shadow: 0px 0px 0px 0px #13151A4D;
|
||||
border: 1px solid #343841;
|
||||
border-radius: 9999px;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
#dev-overlay .item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
#dev-overlay #bar-container .item:hover {
|
||||
background: rgba(27, 30, 36, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#dev-overlay #bar-container .item.active {
|
||||
background: rgba(71, 78, 94, 1);
|
||||
}
|
||||
|
||||
#dev-overlay .item svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#dev-overlay #bar-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#dev-overlay .separator {
|
||||
background: rgba(52, 56, 65, 1);
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
astro-overlay-plugin-canvas:not([data-active]) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="dev-overlay">
|
||||
<div id="bar-container">
|
||||
${builtinPlugins.map((plugin) => this.getPluginTemplate(plugin)).join('')}
|
||||
<div class="separator"></div>
|
||||
${customPluginsImports.map((plugin) => this.getPluginTemplate(plugin)).join('')}
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
this.attachClickEvents();
|
||||
}
|
||||
|
||||
attachClickEvents() {
|
||||
const items = this.shadowRoot.querySelectorAll<HTMLDivElement>('.item');
|
||||
if (!items) return;
|
||||
items.forEach((item) => {
|
||||
item.addEventListener('click', async (e) => {
|
||||
const target = e.currentTarget;
|
||||
if (!target || !(target instanceof HTMLElement)) return;
|
||||
|
||||
const id = target.dataset.pluginId;
|
||||
if (!id) return;
|
||||
|
||||
const plugin = this.getPluginById(id);
|
||||
if (!plugin) return;
|
||||
const shadowRoot = this.getPluginCanvasById(plugin.id)!.shadowRoot!;
|
||||
if (!plugin.inited) {
|
||||
await plugin.init?.(shadowRoot, plugin.eventTarget);
|
||||
plugin.inited = true;
|
||||
}
|
||||
|
||||
this.togglePluginStatus(plugin);
|
||||
plugin.eventTarget.dispatchEvent(
|
||||
new CustomEvent('plugin-toggle', {
|
||||
detail: {
|
||||
state: plugin.active,
|
||||
plugin,
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getPluginTemplate(plugin: DevOverlayItem) {
|
||||
return `<div class="item" data-plugin-id="${plugin.id}">
|
||||
<div class="icon">${plugin.icon}</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
getPluginById(id: string) {
|
||||
return plugins.find((plugin) => plugin.id === id);
|
||||
}
|
||||
|
||||
getPluginCanvasById(id: string) {
|
||||
return this.shadowRoot.querySelector(`astro-overlay-plugin-canvas[data-plugin-id="${id}"]`);
|
||||
}
|
||||
|
||||
togglePluginStatus(plugin: DevOverlayItem, status?: boolean) {
|
||||
plugin.active = status ?? !plugin.active;
|
||||
const target = this.shadowRoot.querySelector(`[data-plugin-id="${plugin.id}"]`);
|
||||
if (!target) return;
|
||||
target.classList.toggle('active', plugin.active);
|
||||
this.getPluginCanvasById(plugin.id)?.toggleAttribute('data-active', plugin.active);
|
||||
}
|
||||
}
|
||||
|
||||
class DevOverlayCanvas extends HTMLElement {
|
||||
shadowRoot: ShadowRoot;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.shadowRoot = this.attachShadow({ mode: 'closed' });
|
||||
}
|
||||
|
||||
// connect component
|
||||
async connectedCallback() {
|
||||
this.shadowRoot.innerHTML = ``;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('astro-dev-overlay', AstroDevOverlay);
|
||||
customElements.define('astro-dev-overlay-window', DevOverlayWindow);
|
||||
customElements.define('astro-overlay-plugin-canvas', DevOverlayCanvas);
|
||||
customElements.define('astro-overlay-tooltip', DevOverlayTooltip);
|
||||
customElements.define('astro-overlay-highlight', DevOverlayHighlight);
|
||||
|
||||
const overlay = document.createElement('astro-dev-overlay');
|
||||
overlay.style.zIndex = '999999';
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
// Create plugin canvases
|
||||
plugins.forEach((plugin) => {
|
||||
const pluginCanvas = document.createElement('astro-overlay-plugin-canvas');
|
||||
pluginCanvas.dataset.pluginId = plugin.id;
|
||||
overlay.shadowRoot?.appendChild(pluginCanvas);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
import type { DevOverlayItem } from '../../../../@types/astro.js';
|
||||
|
||||
export default {
|
||||
id: 'astro',
|
||||
name: 'Astro',
|
||||
icon: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 24"><path fill="#fff" d="M6.45385 20.9419c-1.08694-.9911-1.40425-3.0736-.9514-4.5823.78522.9512 1.8732 1.2525 3.00013 1.4226 1.73972.2625 3.44832.1643 5.06442-.6289.1849-.0908.3557-.2115.5578-.3338.1516.4388.1911.8819.1381 1.3328-.1288 1.0982-.6767 1.9465-1.5481 2.5896-.3485.2572-.7172.4871-1.0771.7297-1.1056.7454-1.4047 1.6194-.9893 2.8909.0099.0309.0187.0619.041.1375-.5645-.252-.9768-.6189-1.29099-1.1013-.33185-.5092-.48972-1.0725-.49803-1.682-.00416-.2966-.00416-.5958-.04414-.8882-.09764-.7129-.43312-1.032-1.06513-1.0504-.64864-.0189-1.16173.3811-1.29779 1.011-.01039.0483-.02545.0961-.04051.1523l.00104.0005Z"/><path fill="url(#a)" d="M6.45385 20.9419c-1.08694-.9911-1.40425-3.0736-.9514-4.5823.78522.9512 1.8732 1.2525 3.00013 1.4226 1.73972.2625 3.44832.1643 5.06442-.6289.1849-.0908.3557-.2115.5578-.3338.1516.4388.1911.8819.1381 1.3328-.1288 1.0982-.6767 1.9465-1.5481 2.5896-.3485.2572-.7172.4871-1.0771.7297-1.1056.7454-1.4047 1.6194-.9893 2.8909.0099.0309.0187.0619.041.1375-.5645-.252-.9768-.6189-1.29099-1.1013-.33185-.5092-.48972-1.0725-.49803-1.682-.00416-.2966-.00416-.5958-.04414-.8882-.09764-.7129-.43312-1.032-1.06513-1.0504-.64864-.0189-1.16173.3811-1.29779 1.011-.01039.0483-.02545.0961-.04051.1523l.00104.0005Z"/><path fill="#fff" d="M.25 16.1083s3.21861-1.5641 6.44622-1.5641l2.43351-7.51249c.0911-.36331.35712-.61021.65744-.61021.30033 0 .56633.2469.65743.61021l2.4335 7.51249c3.8226 0 6.4462 1.5641 6.4462 1.5641s-5.467-14.85637-5.4777-14.88618C13.6897.782887 13.4248.5 13.0676.5H6.50726c-.35713 0-.61133.282887-.77893.72212C5.71652 1.25137.25 16.1083.25 16.1083Z"/><defs><linearGradient id="a" x1="9.7873" x2="12.2634" y1="23.3025" y2="15.1217" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient></defs></svg>',
|
||||
init(canvas, eventTarget) {
|
||||
eventTarget.addEventListener('plugin-toggle', (e) => {
|
||||
if ((e as CustomEvent).detail.state === true) {
|
||||
window.open('https://astro.build', '_blank');
|
||||
}
|
||||
});
|
||||
},
|
||||
} satisfies DevOverlayItem;
|
121
packages/astro/src/runtime/client/dev-overlay/plugins/audit.ts
Normal file
121
packages/astro/src/runtime/client/dev-overlay/plugins/audit.ts
Normal file
|
@ -0,0 +1,121 @@
|
|||
import type { DevOverlayItem } from '../../../../@types/astro.js';
|
||||
import type { DevOverlayTooltip } from '../ui-toolkit.js';
|
||||
|
||||
interface AuditRule {
|
||||
title: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
const selectorBasedRules: (AuditRule & { selector: string })[] = [
|
||||
{
|
||||
title: 'Missing `alt` tag',
|
||||
message: 'The alt attribute is important for accessibility.',
|
||||
selector: 'img:not([alt])',
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
id: 'astro:audit',
|
||||
name: 'Audit',
|
||||
icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 16" fill="none"><path fill="#fff" d="M.625 2c0-.29837.118526-.58452.329505-.7955C1.16548.993526 1.45163.875 1.75.875h16.5c.2984 0 .5845.118526.7955.3295.211.21098.3295.49713.3295.7955 0 .29837-.1185.58452-.3295.7955-.211.21097-.4971.3295-.7955.3295H1.75c-.29837 0-.58452-.11853-.795495-.3295C.743526 2.58452.625 2.29837.625 2ZM1.75 9.125h6c.29837 0 .58452-.11853.7955-.32951.21097-.21097.3295-.49712.3295-.79549s-.11853-.58452-.3295-.7955c-.21098-.21097-.49713-.3295-.7955-.3295h-6c-.29837 0-.58452.11853-.795495.3295C.743526 7.41548.625 7.70163.625 8c0 .29837.118526.58452.329505.79549.210975.21098.497125.32951.795495.32951Zm7.5 3.75h-7.5c-.29837 0-.58452.1185-.795495.3295C.743526 13.4155.625 13.7016.625 14s.118526.5845.329505.7955c.210975.211.497125.3295.795495.3295h7.5c.29837 0 .58452-.1185.7955-.3295.211-.211.3295-.4971.3295-.7955s-.1185-.5845-.3295-.7955c-.21098-.211-.49713-.3295-.7955-.3295Zm11.2959 1.9209c-.1045.1049-.2287.1881-.3654.2449-.1368.0568-.2834.086-.4314.086-.1481 0-.2947-.0292-.4315-.086-.1367-.0568-.2609-.14-.3654-.2449l-1.695-1.695c-.8694.4849-1.8849.6389-2.859.4338s-1.8411-.7556-2.4412-1.5498c-.6001-.7943-.8927-1.7787-.8239-2.77183.0688-.99308.4944-1.92778 1.1983-2.63167.7039-.7039 1.6386-1.12951 2.6317-1.19832.9931-.06881 1.9775.22382 2.7718.82391.7942.60009 1.3447 1.46716 1.5498 2.44126.2051.9741.0511 1.98955-.4338 2.85895l1.695 1.6941c.1051.1045.1884.2287.2453.3656.0568.1368.0861.2835.0861.4317s-.0293.2949-.0861.4317c-.0569.1369-.1402.2611-.2453.3656ZM15.25 11.375c.3708 0 .7334-.11 1.0417-.316.3083-.206.5487-.4989.6906-.8415.1419-.34258.179-.71958.1067-1.0833-.0724-.36371-.251-.6978-.5132-.96003-.2622-.26222-.5963-.4408-.96-.51314-.3637-.07235-.7407-.03522-1.0833.1067-.3426.14191-.6355.38223-.8415.69058-.206.30834-.316.67085-.316 1.04169 0 .24623.0485.49005.1427.7175.0943.2275.2324.4342.4065.6083.1741.1741.3808.3122.6083.4065.2275.0942.4713.1427.7175.1427Z"/></svg>',
|
||||
init(canvas) {
|
||||
createBase();
|
||||
|
||||
selectorBasedRules.forEach((rule) => {
|
||||
document.querySelectorAll(rule.selector).forEach((el) => {
|
||||
canvas.appendChild(createAuditProblem(rule, el));
|
||||
});
|
||||
});
|
||||
|
||||
function createAuditProblem(rule: AuditRule, originalElement: Element) {
|
||||
const el = document.createElement('div');
|
||||
el.className = 'astro-audit-problem';
|
||||
el.style.position = 'absolute';
|
||||
|
||||
const rect = originalElement.getBoundingClientRect();
|
||||
el.style.top = `${Math.max(rect.top - 10, 0)}px`;
|
||||
el.style.left = `${Math.max(rect.left - 10, 0)}px`;
|
||||
el.style.width = `${rect.width + 15}px`;
|
||||
el.style.height = `${rect.height + 15}px`;
|
||||
|
||||
el.innerHTML = `
|
||||
<div class="icon" style="left: ${rect.width}px;">
|
||||
<svg width="16px" height="16px">
|
||||
<use xlink:href="#astro:audit:warning" width="16px" height="16px"></use>
|
||||
</svg>
|
||||
</div>
|
||||
<astro-overlay-highlight></astro-overlay-highlight>
|
||||
`;
|
||||
|
||||
const tooltip = document.createElement('astro-overlay-tooltip') as DevOverlayTooltip;
|
||||
tooltip.sections = [
|
||||
{
|
||||
icon: '<svg width="16px" height="16px"><use xlink:href="#astro:audit:warning" width="16px" height="16px"></use></svg>',
|
||||
title: rule.title,
|
||||
},
|
||||
{
|
||||
content: rule.message,
|
||||
},
|
||||
{
|
||||
content: '/src/somewhere/component.astro',
|
||||
clickDescription: 'Click to go to file',
|
||||
clickAction() {
|
||||
// TODO: Implement this
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
tooltip.style.position = 'absolute';
|
||||
tooltip.style.top = `${rect.height}px`;
|
||||
tooltip.style.left = `${Math.max(rect.left - 10, 5)}px`;
|
||||
tooltip.style.margin = '0';
|
||||
|
||||
el.appendChild(tooltip);
|
||||
|
||||
el.addEventListener('mouseover', () => {
|
||||
tooltip.dialog.show();
|
||||
});
|
||||
|
||||
el.addEventListener('mouseout', () => {
|
||||
tooltip.dialog.close();
|
||||
});
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
function createBase() {
|
||||
// Create style
|
||||
const style = document.createElement('style');
|
||||
// TODO: Should this be in the astro-overlay-highlight component?
|
||||
style.innerHTML = `
|
||||
.astro-audit-problem .icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: linear-gradient(0deg, #B33E66, #B33E66), linear-gradient(0deg, #351722, #351722);
|
||||
border: 1px solid rgba(53, 23, 34, 1);
|
||||
border-radius: 9999px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
}
|
||||
`;
|
||||
|
||||
const svgSymbols = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
svgSymbols.setAttribute('aria-hidden', 'true');
|
||||
svgSymbols.setAttribute(
|
||||
'style',
|
||||
'position: absolute; width: 0; height: 0; overflow: hidden;'
|
||||
);
|
||||
svgSymbols.innerHTML = `
|
||||
<symbol viewBox="0 0 16 16" id="astro:audit:warning">
|
||||
<path fill="#fff" d="M8 .40625c-1.5019 0-2.97007.445366-4.21886 1.27978C2.53236 2.52044 1.55905 3.70642.984293 5.094.40954 6.48157.259159 8.00842.552165 9.48147.845172 10.9545 1.56841 12.3076 2.63041 13.3696c1.06201 1.062 2.41508 1.7852 3.88813 2.0782 1.47304.293 2.99989.1427 4.38746-.4321 1.3876-.5747 2.5736-1.5481 3.408-2.7968.8344-1.2488 1.2798-2.717 1.2798-4.2189-.0023-2.0133-.8031-3.9435-2.2267-5.36713C11.9435 1.20925 10.0133.408483 8 .40625ZM8 13.9062c-1.16814 0-2.31006-.3463-3.28133-.9953-.97128-.649-1.7283-1.5715-2.17533-2.6507-.44703-1.0792-.56399-2.26675-.3361-3.41245.22789-1.1457.79041-2.1981 1.61641-3.0241.82601-.826 1.8784-1.38852 3.0241-1.61641 1.1457-.2279 2.33325-.11093 3.41245.3361 1.0793.44703 2.0017 1.20405 2.6507 2.17532.649.97128.9954 2.11319.9954 3.28134-.0017 1.56592-.6245 3.0672-1.7318 4.1745S9.56592 13.9046 8 13.9062Zm-.84375-5.62495V4.625c0-.22378.0889-.43839.24713-.59662.15824-.15824.37285-.24713.59662-.24713.22378 0 .43839.08889.59662.24713.15824.15823.24713.37284.24713.59662v3.65625c0 .22378-.08889.43839-.24713.59662C8.43839 9.03611 8.22378 9.125 8 9.125c-.22377 0-.43838-.08889-.59662-.24713-.15823-.15823-.24713-.37284-.24713-.59662ZM9.125 11.0938c0 .2225-.06598.44-.18959.625-.12362.185-.29932.3292-.50489.4143-.20556.0852-.43176.1074-.64999.064-.21823-.0434-.41869-.1505-.57602-.3079-.15734-.1573-.26448-.3577-.30789-.576-.04341-.2182-.02113-.4444.06402-.65.08515-.2055.22934-.3812.41435-.5049.185-.1236.40251-.18955.62501-.18955.29837 0 .58452.11855.7955.32955.21098.2109.3295.4971.3295.7955Z"/>
|
||||
</symbol>
|
||||
`;
|
||||
|
||||
canvas.appendChild(style);
|
||||
canvas.appendChild(svgSymbols);
|
||||
}
|
||||
},
|
||||
} satisfies DevOverlayItem;
|
|
@ -0,0 +1,84 @@
|
|||
import type { DevOverlayItem } from '../../../../@types/astro.js';
|
||||
import type { DevOverlayTooltip } from '../ui-toolkit.js';
|
||||
|
||||
export default {
|
||||
id: 'astro:xray',
|
||||
name: 'Xray',
|
||||
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="#fff" d="M7.875 1.5v-.375c0-.298369.11853-.584517.3295-.795495C8.41548.118526 8.70163 0 9 0c.29837 0 .58452.118526.7955.329505.211.210978.3295.497126.3295.795495V1.5c0 .29837-.1185.58452-.3295.7955-.21098.21097-.49713.3295-.7955.3295-.29837 0-.58452-.11853-.7955-.3295-.21097-.21098-.3295-.49713-.3295-.7955ZM1.5 10.125c.29837 0 .58452-.1185.7955-.3295.21097-.21098.3295-.49713.3295-.7955 0-.29837-.11853-.58452-.3295-.7955-.21098-.21097-.49713-.3295-.7955-.3295h-.375c-.298369 0-.584517.11853-.795495.3295C.118526 8.41548 0 8.70163 0 9c0 .29837.118526.58452.329505.7955.210978.211.497126.3295.795495.3295H1.5Zm10.5187-6.43313c.1402.04674.2882.0654.4356.05493.1474-.01046.2912-.04986.4234-.11594.1321-.06607.25-.15753.3468-.26916.0968-.11162.1707-.24122.2174-.38139l.375-1.125c.084-.28016.0555-.58202-.0793-.84158-.1348-.259563-.3654-.45642-.6429-.548838-.2775-.092417-.58-.07313-.8436.053773-.2635.126903-.4672.351445-.568.626025l-.375 1.125c-.0941.28283-.0721.59146.0611.85812.1332.26665.3669.46952.6495.56406ZM2.26875 11.3081l-1.125.375c-.144256.0433-.27836.115-.394363.2111-.116003.096-.211543.2144-.280956.348-.069412.1337-.111285.2799-.123135.43-.01185.1502.006564.3011.054149.444.047586.1429.123375.2748.222875.3878.099499.1131.220683.205.356368.2703.135682.0654.283112.1028.433532.1101.15042.0073.30078-.0156.44216-.0675l1.125-.375c.14425-.0433.27836-.115.39436-.2111.116-.096.21154-.2144.28095-.348.06942-.1337.11129-.2799.12314-.43.01185-.1502-.00656-.3011-.05415-.444-.04759-.1429-.12338-.2748-.22287-.3878-.0995-.1131-.22069-.205-.35637-.2703-.13569-.0654-.28311-.1028-.43353-.1101-.15042-.0073-.30078.0156-.44216.0675Zm18.55595 5.6766c.1742.1741.3124.3808.4066.6084.0943.2275.1428.4714.1428.7177 0 .2463-.0485.4902-.1428.7177-.0942.2275-.2324.4343-.4066.6084l-1.1888 1.1887c-.1741.1742-.3808.3124-.6084.4067-.2275.0942-.4714.1428-.7177.1428-.2462 0-.4901-.0486-.7177-.1428-.2275-.0943-.4342-.2325-.6084-.4067l-4.2665-4.2665-1.6041 3.6909c-.1436.3349-.3826.6201-.6872.8201-.3045.2001-.66121.3061-1.02559.3049h-.09375c-.3792-.0165-.74423-.1489-1.04594-.3792-.30172-.2303-.52562-.5475-.64156-.9089L2.71875 5.0775c-.10548-.32823-.11842-.6792-.0374-1.01431s.25287-.64139.49666-.88518c.24379-.24379.55007-.41564.88518-.49666.33511-.08102.68608-.06808 1.01431.0374L20.085 7.61906c.3591.11962.6736.34511.9021.64684.2286.30172.3604.66555.3783 1.04363.0178.37808-.0792.75267-.2782 1.07467-.1991.3219-.491.576-.8372.7289l-3.6909 1.605 4.2656 4.2666Zm-1.8563 1.3256-4.3903-4.3912c-.2158-.2161-.3755-.4817-.4653-.7736-.0898-.2919-.1069-.6013-.0499-.9013.057-.3001.1864-.5816.377-.8202.1906-.2387.4366-.4271.7167-.549l3.2812-1.42594L5.08969 5.08969 9.44812 18.4369l1.42598-3.2813c.122-.28.3105-.5259.5492-.7164.2388-.1905.5204-.3198.8205-.3767.1155-.0224.2329-.0337.3506-.0338.4969.0004.9733.198 1.3247.5494l4.3912 4.3913.6581-.6591Z"/></svg>',
|
||||
init(canvas) {
|
||||
const islands = document.querySelectorAll<HTMLElement>('astro-island');
|
||||
|
||||
islands.forEach((island) => {
|
||||
const el = document.createElement('div');
|
||||
el.style.position = 'absolute';
|
||||
|
||||
const rect = island.children[0]
|
||||
? island.children[0].getBoundingClientRect()
|
||||
: island.getBoundingClientRect();
|
||||
|
||||
el.style.top = `${Math.max(rect.top - 10, 0)}px`;
|
||||
el.style.left = `${Math.max(rect.left - 10, 0)}px`;
|
||||
el.style.width = `${rect.width + 15}px`;
|
||||
el.style.height = `${rect.height + 15}px`;
|
||||
|
||||
el.innerHTML = `
|
||||
<astro-overlay-highlight></astro-overlay-highlight>
|
||||
`;
|
||||
|
||||
const islandProps = island.getAttribute('props')
|
||||
? JSON.parse(island.getAttribute('props')!)
|
||||
: {};
|
||||
const islandClientDirective = island.getAttribute('client');
|
||||
|
||||
const tooltip = document.createElement('astro-overlay-tooltip') as DevOverlayTooltip;
|
||||
tooltip.sections = [];
|
||||
|
||||
if (islandClientDirective) {
|
||||
tooltip.sections.push({
|
||||
title: 'Client directive',
|
||||
content: `client:${islandClientDirective}`,
|
||||
});
|
||||
}
|
||||
|
||||
if (Object.keys(islandProps).length > 0) {
|
||||
tooltip.sections.push({
|
||||
title: 'Props',
|
||||
content: `${Object.entries(islandProps)
|
||||
.map((prop) => `<code>${prop[0]}=${getPropValue(prop[1] as any)}</code>`)
|
||||
.join(', ')}`,
|
||||
});
|
||||
}
|
||||
|
||||
tooltip.sections.push({
|
||||
content: '/src/somewhere/component.astro',
|
||||
clickDescription: 'Click to go to file',
|
||||
clickAction() {
|
||||
// TODO: Implement this
|
||||
},
|
||||
});
|
||||
|
||||
tooltip.style.position = 'absolute';
|
||||
tooltip.style.top = `${rect.height}px`;
|
||||
tooltip.style.left = `${Math.max(rect.left - 10, 5)}px`;
|
||||
tooltip.style.margin = '0';
|
||||
|
||||
el.appendChild(tooltip);
|
||||
|
||||
el.addEventListener('mouseover', () => {
|
||||
tooltip.dialog.show();
|
||||
});
|
||||
|
||||
el.addEventListener('mouseout', () => {
|
||||
tooltip.dialog.close();
|
||||
});
|
||||
|
||||
canvas.appendChild(el);
|
||||
});
|
||||
|
||||
function getPropValue(prop: [number, any]) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [_, value] = prop;
|
||||
return JSON.stringify(value, null, 2);
|
||||
}
|
||||
},
|
||||
} satisfies DevOverlayItem;
|
148
packages/astro/src/runtime/client/dev-overlay/ui-toolkit.ts
Normal file
148
packages/astro/src/runtime/client/dev-overlay/ui-toolkit.ts
Normal file
|
@ -0,0 +1,148 @@
|
|||
export class DevOverlayWindow extends HTMLElement {
|
||||
title: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.title = 'World';
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
const shadow = this.attachShadow({ mode: 'closed' });
|
||||
shadow.innerHTML = `
|
||||
<style>
|
||||
#astro-dev-window {
|
||||
background: linear-gradient(0deg, #13151A, #13151A), linear-gradient(0deg, #343841, #343841);
|
||||
}
|
||||
|
||||
#astro-dev-window h1 {
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="astro-dev-window">
|
||||
<h1>${this.title}</h1>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
interface DevOverlayTooltipSection {
|
||||
title?: string;
|
||||
icon?: string;
|
||||
content?: string;
|
||||
clickAction?: () => void;
|
||||
clickDescription?: string;
|
||||
}
|
||||
|
||||
export class DevOverlayTooltip extends HTMLElement {
|
||||
sections: DevOverlayTooltipSection[] = [];
|
||||
dialog: HTMLDialogElement;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.dialog = document.createElement('dialog');
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.style.width = '100%';
|
||||
this.innerHTML = `
|
||||
<style>
|
||||
dialog {
|
||||
color: white;
|
||||
background: linear-gradient(0deg, #310A65, #310A65), linear-gradient(0deg, #7118E2, #7118E2);
|
||||
border: 1px solid rgba(113, 24, 226, 1);
|
||||
border-radius: 4px;
|
||||
padding: 0;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
dialog svg {
|
||||
vertical-align: bottom;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
dialog hr {
|
||||
border: 1px solid rgba(136, 58, 234, 0.33);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
dialog section {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.modal-title + div {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.modal-cta {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.clickable-section {
|
||||
background: rgba(113, 24, 226, 1);
|
||||
}
|
||||
|
||||
code {
|
||||
background: rgba(136, 58, 234, 0.33);
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
border-radius: 2px;
|
||||
font-size: 14px;
|
||||
padding: 2px;
|
||||
}
|
||||
`;
|
||||
|
||||
this.sections.forEach((section, index) => {
|
||||
const el = document.createElement('section');
|
||||
if (section.clickAction) {
|
||||
el.classList.add('clickable-section');
|
||||
el.addEventListener('click', section.clickAction);
|
||||
}
|
||||
|
||||
el.innerHTML = `
|
||||
${section.icon ? `${section.icon}` : ''}
|
||||
${section.title ? `<span class="modal-title">${section.title}</span>` : ''}
|
||||
${section.content ? `<div>${section.content}</div>` : ''}
|
||||
${section.clickDescription ? `<span class="modal-cta">${section.clickDescription}</span>` : ''}
|
||||
`;
|
||||
this.dialog.appendChild(el);
|
||||
|
||||
if (index < this.sections.length - 1) {
|
||||
this.dialog.appendChild(document.createElement('hr'));
|
||||
}
|
||||
});
|
||||
|
||||
this.appendChild(this.dialog);
|
||||
}
|
||||
}
|
||||
|
||||
export class DevOverlayHighlight extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<style>
|
||||
astro-overlay-highlight {
|
||||
background: linear-gradient(180deg, rgba(224, 204, 250, 0.33) 0%, rgba(224, 204, 250, 0.0825) 100%);
|
||||
border: 1px solid rgba(113, 24, 226, 1);
|
||||
border-radius: 4px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
}
|
||||
}
|
|
@ -15,13 +15,10 @@ export interface HydrationMetadata {
|
|||
componentExport: { value: string };
|
||||
}
|
||||
|
||||
type Props = Record<string | number | symbol, any>;
|
||||
|
||||
interface ExtractedProps {
|
||||
isPage: boolean;
|
||||
hydration: HydrationMetadata | null;
|
||||
props: Props;
|
||||
propsWithoutTransitionAttributes: Props;
|
||||
props: Record<string | number | symbol, any>;
|
||||
}
|
||||
|
||||
const transitionDirectivesToCopyOnIsland = Object.freeze([
|
||||
|
@ -32,14 +29,13 @@ const transitionDirectivesToCopyOnIsland = Object.freeze([
|
|||
// Used to extract the directives, aka `client:load` information about a component.
|
||||
// Finds these special props and removes them from what gets passed into the component.
|
||||
export function extractDirectives(
|
||||
inputProps: Props,
|
||||
inputProps: Record<string | number | symbol, any>,
|
||||
clientDirectives: SSRResult['clientDirectives']
|
||||
): ExtractedProps {
|
||||
let extracted: ExtractedProps = {
|
||||
isPage: false,
|
||||
hydration: null,
|
||||
props: {},
|
||||
propsWithoutTransitionAttributes: {},
|
||||
};
|
||||
for (const [key, value] of Object.entries(inputProps)) {
|
||||
if (key.startsWith('server:')) {
|
||||
|
@ -100,14 +96,10 @@ export function extractDirectives(
|
|||
}
|
||||
} else {
|
||||
extracted.props[key] = value;
|
||||
if (!transitionDirectivesToCopyOnIsland.includes(key)) {
|
||||
extracted.propsWithoutTransitionAttributes[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const sym of Object.getOwnPropertySymbols(inputProps)) {
|
||||
extracted.props[sym] = inputProps[sym];
|
||||
extracted.propsWithoutTransitionAttributes[sym] = inputProps[sym];
|
||||
}
|
||||
|
||||
return extracted;
|
||||
|
|
|
@ -92,10 +92,7 @@ async function renderFrameworkComponent(
|
|||
displayName,
|
||||
};
|
||||
|
||||
const { hydration, isPage, props, propsWithoutTransitionAttributes } = extractDirectives(
|
||||
_props,
|
||||
clientDirectives
|
||||
);
|
||||
const { hydration, isPage, props } = extractDirectives(_props, clientDirectives);
|
||||
let html = '';
|
||||
let attrs: Record<string, string> | undefined = undefined;
|
||||
|
||||
|
@ -220,7 +217,7 @@ async function renderFrameworkComponent(
|
|||
({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call(
|
||||
{ result },
|
||||
Component,
|
||||
propsWithoutTransitionAttributes,
|
||||
props,
|
||||
children,
|
||||
metadata
|
||||
));
|
||||
|
@ -245,7 +242,7 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr
|
|||
({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call(
|
||||
{ result },
|
||||
Component,
|
||||
propsWithoutTransitionAttributes,
|
||||
props,
|
||||
children,
|
||||
metadata
|
||||
));
|
||||
|
|
|
@ -13,14 +13,9 @@ type Events = 'astro:page-load' | 'astro:after-swap';
|
|||
// only update history entries that are managed by us
|
||||
// leave other entries alone and do not accidently add state.
|
||||
const persistState = (state: State) => history.state && history.replaceState(state, '');
|
||||
|
||||
const inBrowser = import.meta.env.SSR === false;
|
||||
|
||||
export const supportsViewTransitions = inBrowser && !!document.startViewTransition;
|
||||
|
||||
export const supportsViewTransitions = !!document.startViewTransition;
|
||||
export const transitionEnabledOnThisPage = () =>
|
||||
inBrowser && !!document.querySelector('[name="astro-view-transitions-enabled"]');
|
||||
|
||||
!!document.querySelector('[name="astro-view-transitions-enabled"]');
|
||||
const samePage = (otherLocation: URL) =>
|
||||
location.pathname === otherLocation.pathname && location.search === otherLocation.search;
|
||||
const triggerEvent = (name: Events) => document.dispatchEvent(new Event(name));
|
||||
|
@ -45,27 +40,26 @@ const announce = () => {
|
|||
60
|
||||
);
|
||||
};
|
||||
|
||||
const PERSIST_ATTR = 'data-astro-transition-persist';
|
||||
|
||||
let parser: DOMParser;
|
||||
const parser = new DOMParser();
|
||||
// explained at its usage
|
||||
let noopEl: HTMLDivElement;
|
||||
if (import.meta.env.DEV) {
|
||||
noopEl = document.createElement('div');
|
||||
}
|
||||
|
||||
// The History API does not tell you if navigation is forward or back, so
|
||||
// you can figure it using an index. On pushState the index is incremented so you
|
||||
// can use that to determine popstate if going forward or back.
|
||||
let currentHistoryIndex = 0;
|
||||
|
||||
if (inBrowser) {
|
||||
if (history.state) {
|
||||
// we reloaded a page with history state
|
||||
// (e.g. history navigation from non-transition page or browser reload)
|
||||
currentHistoryIndex = history.state.index;
|
||||
scrollTo({ left: history.state.scrollX, top: history.state.scrollY });
|
||||
} else if (transitionEnabledOnThisPage()) {
|
||||
history.replaceState({ index: currentHistoryIndex, scrollX, scrollY, intraPage: false }, '');
|
||||
}
|
||||
if (history.state) {
|
||||
// we reloaded a page with history state
|
||||
// (e.g. history navigation from non-transition page or browser reload)
|
||||
currentHistoryIndex = history.state.index;
|
||||
scrollTo({ left: history.state.scrollX, top: history.state.scrollY });
|
||||
} else if (transitionEnabledOnThisPage()) {
|
||||
history.replaceState({ index: currentHistoryIndex, scrollX, scrollY, intraPage: false }, '');
|
||||
}
|
||||
|
||||
const throttle = (cb: (...args: any[]) => any, delay: number) => {
|
||||
let wait = false;
|
||||
// During the waiting time additional events are lost.
|
||||
|
@ -157,24 +151,18 @@ function isInfinite(animation: Animation) {
|
|||
|
||||
const updateHistoryAndScrollPosition = (toLocation: URL, replace: boolean, intraPage: boolean) => {
|
||||
const fresh = !samePage(toLocation);
|
||||
let scrolledToTop = false;
|
||||
if (toLocation.href !== location.href) {
|
||||
if (replace) {
|
||||
history.replaceState({ ...history.state }, '', toLocation.href);
|
||||
} else {
|
||||
history.replaceState({ ...history.state, intraPage }, '');
|
||||
history.pushState(
|
||||
{ index: ++currentHistoryIndex, scrollX: 0, scrollY: 0 },
|
||||
'',
|
||||
toLocation.href
|
||||
);
|
||||
history.pushState({ index: ++currentHistoryIndex, scrollX, scrollY }, '', toLocation.href);
|
||||
}
|
||||
// now we are on the new page for non-history navigations!
|
||||
// (with history navigation page change happens before popstate is fired)
|
||||
// freshly loaded pages start from the top
|
||||
if (fresh) {
|
||||
scrollTo({ left: 0, top: 0, behavior: 'instant' });
|
||||
scrolledToTop = true;
|
||||
}
|
||||
}
|
||||
if (toLocation.hash) {
|
||||
|
@ -183,9 +171,7 @@ const updateHistoryAndScrollPosition = (toLocation: URL, replace: boolean, intra
|
|||
// that won't reload the page but instead scroll to the fragment
|
||||
location.href = toLocation.href;
|
||||
} else {
|
||||
if (!scrolledToTop) {
|
||||
scrollTo({ left: 0, top: 0, behavior: 'instant' });
|
||||
}
|
||||
scrollTo({ left: 0, top: 0, behavior: 'instant' });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -212,6 +198,22 @@ async function updateDOM(
|
|||
const href = el.getAttribute('href');
|
||||
return newDocument.head.querySelector(`link[rel=stylesheet][href="${href}"]`);
|
||||
}
|
||||
// What follows is a fix for an issue (#8472) with missing client:only styles after transition.
|
||||
// That problem exists only in dev mode where styles are injected into the page by Vite.
|
||||
// Returning a noop element ensures that the styles are not removed from the old document.
|
||||
// Guarding the code below with the dev mode check
|
||||
// allows tree shaking to remove this code in production.
|
||||
if (import.meta.env.DEV) {
|
||||
if (el.tagName === 'STYLE' && el.dataset.viteDevId) {
|
||||
const devId = el.dataset.viteDevId;
|
||||
// If this same style tag exists, remove it from the new page
|
||||
return (
|
||||
newDocument.querySelector(`style[data-vite-dev-id="${devId}"]`) ||
|
||||
// Otherwise, keep it anyways. This is client:only styles.
|
||||
noopEl
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
@ -347,8 +349,6 @@ async function transition(
|
|||
toLocation = new URL(response.redirected);
|
||||
}
|
||||
|
||||
parser ??= new DOMParser();
|
||||
|
||||
const newDocument = parser.parseFromString(response.html, response.mediaType);
|
||||
// The next line might look like a hack,
|
||||
// but it is actually necessary as noscript elements
|
||||
|
@ -385,22 +385,7 @@ async function transition(
|
|||
}
|
||||
}
|
||||
|
||||
let navigateOnServerWarned = false;
|
||||
|
||||
export function navigate(href: string, options?: Options) {
|
||||
if (inBrowser === false) {
|
||||
if (!navigateOnServerWarned) {
|
||||
// instantiate an error for the stacktrace to show to user.
|
||||
const warning = new Error(
|
||||
'The view transtions client API was called during a server side render. This may be unintentional as the navigate() function is expected to be called in response to user interactions. Please make sure that your usage is correct.'
|
||||
);
|
||||
warning.name = 'Warning';
|
||||
console.warn(warning);
|
||||
navigateOnServerWarned = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// not ours
|
||||
if (!transitionEnabledOnThisPage()) {
|
||||
location.href = href;
|
||||
|
@ -418,61 +403,58 @@ export function navigate(href: string, options?: Options) {
|
|||
}
|
||||
}
|
||||
|
||||
function onPopState(ev: PopStateEvent) {
|
||||
if (!transitionEnabledOnThisPage() && ev.state) {
|
||||
// The current page doesn't have View Transitions enabled
|
||||
// but the page we navigate to does (because it set the state).
|
||||
// Do a full page refresh to reload the client-side router from the new page.
|
||||
// Scroll restauration will then happen during the reload when the router's code is re-executed
|
||||
if (supportsViewTransitions || getFallback() !== 'none') {
|
||||
addEventListener('popstate', (ev) => {
|
||||
if (!transitionEnabledOnThisPage() && ev.state) {
|
||||
// The current page doesn't have View Transitions enabled
|
||||
// but the page we navigate to does (because it set the state).
|
||||
// Do a full page refresh to reload the client-side router from the new page.
|
||||
// Scroll restauration will then happen during the reload when the router's code is re-executed
|
||||
if (history.scrollRestoration) {
|
||||
history.scrollRestoration = 'manual';
|
||||
}
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
// History entries without state are created by the browser (e.g. for hash links)
|
||||
// Our view transition entries always have state.
|
||||
// Just ignore stateless entries.
|
||||
// The browser will handle navigation fine without our help
|
||||
if (ev.state === null) {
|
||||
if (history.scrollRestoration) {
|
||||
history.scrollRestoration = 'auto';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// With the default "auto", the browser will jump to the old scroll position
|
||||
// before the ViewTransition is complete.
|
||||
if (history.scrollRestoration) {
|
||||
history.scrollRestoration = 'manual';
|
||||
}
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
// History entries without state are created by the browser (e.g. for hash links)
|
||||
// Our view transition entries always have state.
|
||||
// Just ignore stateless entries.
|
||||
// The browser will handle navigation fine without our help
|
||||
if (ev.state === null) {
|
||||
if (history.scrollRestoration) {
|
||||
history.scrollRestoration = 'auto';
|
||||
const state: State = history.state;
|
||||
if (state.intraPage) {
|
||||
// this is non transition intra-page scrolling
|
||||
scrollTo(state.scrollX, state.scrollY);
|
||||
} else {
|
||||
const nextIndex = state.index;
|
||||
const direction: Direction = nextIndex > currentHistoryIndex ? 'forward' : 'back';
|
||||
currentHistoryIndex = nextIndex;
|
||||
transition(direction, new URL(location.href), {}, state);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// With the default "auto", the browser will jump to the old scroll position
|
||||
// before the ViewTransition is complete.
|
||||
if (history.scrollRestoration) {
|
||||
history.scrollRestoration = 'manual';
|
||||
}
|
||||
addEventListener('load', onPageLoad);
|
||||
// There's not a good way to record scroll position before a back button.
|
||||
// So the way we do it is by listening to scrollend if supported, and if not continuously record the scroll position.
|
||||
const updateState = () => {
|
||||
persistState({ ...history.state, scrollX, scrollY });
|
||||
};
|
||||
|
||||
const state: State = history.state;
|
||||
if (state.intraPage) {
|
||||
// this is non transition intra-page scrolling
|
||||
scrollTo(state.scrollX, state.scrollY);
|
||||
} else {
|
||||
const nextIndex = state.index;
|
||||
const direction: Direction = nextIndex > currentHistoryIndex ? 'forward' : 'back';
|
||||
currentHistoryIndex = nextIndex;
|
||||
transition(direction, new URL(location.href), {}, state);
|
||||
}
|
||||
}
|
||||
|
||||
if (inBrowser) {
|
||||
if (supportsViewTransitions || getFallback() !== 'none') {
|
||||
addEventListener('popstate', onPopState);
|
||||
addEventListener('load', onPageLoad);
|
||||
// There's not a good way to record scroll position before a back button.
|
||||
// So the way we do it is by listening to scrollend if supported, and if not continuously record the scroll position.
|
||||
const updateState = () => {
|
||||
persistState({ ...history.state, scrollX, scrollY });
|
||||
};
|
||||
|
||||
if ('onscrollend' in window) addEventListener('scrollend', updateState);
|
||||
else addEventListener('scroll', throttle(updateState, 300));
|
||||
|
||||
markScriptsExec();
|
||||
}
|
||||
if ('onscrollend' in window) addEventListener('scrollend', updateState);
|
||||
else addEventListener('scroll', throttle(updateState, 300));
|
||||
|
||||
markScriptsExec();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { loadMiddleware } from '../core/middleware/loadMiddleware.js';
|
|||
import { createRenderContext, getParamsAndProps, type SSROptions } from '../core/render/index.js';
|
||||
import { createRequest } from '../core/request.js';
|
||||
import { matchAllRoutes } from '../core/routing/index.js';
|
||||
import { isPage } from '../core/util.js';
|
||||
import { isPage, resolveIdToUrl } from '../core/util.js';
|
||||
import { getSortedPreloadedMatches } from '../prerender/routing.js';
|
||||
import { isServerLikeOutput } from '../prerender/utils.js';
|
||||
import { PAGE_SCRIPT_ID } from '../vite-plugin-scripts/index.js';
|
||||
|
@ -275,6 +275,13 @@ async function getScriptsAndStyles({ pipeline, filePath }: GetScriptsAndStylesPa
|
|||
props: { type: 'module', src: '/@vite/client' },
|
||||
children: '',
|
||||
});
|
||||
scripts.add({
|
||||
props: {
|
||||
type: 'module',
|
||||
src: await resolveIdToUrl(moduleLoader, 'astro/runtime/client/dev-overlay/overlay.js'),
|
||||
},
|
||||
children: '',
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: We should allow adding generic HTML elements to the head, not just scripts
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import type * as vite from 'vite';
|
||||
import type { AstroPluginOptions } from '../@types/astro.js';
|
||||
|
||||
const VIRTUAL_MODULE_ID = 'astro:dev-tools';
|
||||
const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;
|
||||
|
||||
export default function astroDevTools({ settings }: AstroPluginOptions): vite.Plugin {
|
||||
return {
|
||||
name: 'astro:dev-tools',
|
||||
resolveId(id) {
|
||||
if (id === VIRTUAL_MODULE_ID) {
|
||||
return resolvedVirtualModuleId;
|
||||
}
|
||||
},
|
||||
load(id) {
|
||||
if (id === resolvedVirtualModuleId) {
|
||||
return `
|
||||
export const loadDevToolsPlugins = async () => {
|
||||
return [${settings.config.devTools.plugins.map((p) => `(await import('${p}')).default`).join(',')}];
|
||||
};
|
||||
`;
|
||||
}
|
||||
},
|
||||
configureServer(server) {
|
||||
// Example: wait for a client to connect before sending a message
|
||||
server.ws.on('connection', () => {
|
||||
server.ws.send('astro-dev-tools', { msg: 'hello' });
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import react from '@astrojs/react';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [react()],
|
||||
});
|
|
@ -3,9 +3,6 @@
|
|||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"astro": "workspace:*",
|
||||
"@astrojs/react": "workspace:*",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0"
|
||||
"astro": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
.counter {
|
||||
display: grid;
|
||||
font-size: 2em;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
margin-top: 2em;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.counter-message {
|
||||
text-align: center;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import React, { useState } from 'react';
|
||||
import './Island.css';
|
||||
|
||||
export default function Counter({ children, count: initialCount, id }) {
|
||||
const [count, setCount] = useState(initialCount);
|
||||
const add = () => setCount((i) => i + 1);
|
||||
const subtract = () => setCount((i) => i - 1);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id={id} className="counter">
|
||||
<button className="decrement" onClick={subtract}>-</button>
|
||||
<pre>{count}</pre>
|
||||
<button className="increment" onClick={add}>+</button>
|
||||
</div>
|
||||
<div className="counter-message">{children}</div>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
import Island from '../components/Island.jsx';
|
||||
---
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<Island id="1" count="{1}" children="Greetings!" transition:persist="here" client:load/>
|
||||
</body>
|
||||
</html>
|
|
@ -22,14 +22,4 @@ describe('View Transitions styles', () => {
|
|||
|
||||
expect($('head style')).to.have.a.lengthOf(3);
|
||||
});
|
||||
|
||||
it('should not duplicate transition attributes on island contents', async () => {
|
||||
let res = await fixture.fetch('/hasIsland');
|
||||
let html = await res.text();
|
||||
let $ = cheerio.load(html);
|
||||
expect($('astro-island[data-astro-transition-persist]')).to.have.a.lengthOf(1);
|
||||
expect(
|
||||
$('astro-island[data-astro-transition-persist] > [data-astro-transition-persist]')
|
||||
).to.have.a.lengthOf(0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,17 +1,5 @@
|
|||
# @astrojs/cloudflare
|
||||
|
||||
## 7.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#8766](https://github.com/withastro/astro/pull/8766) [`054c5c644`](https://github.com/withastro/astro/commit/054c5c6447d79dd4ea7ab6ce0f9ec836abebd211) Thanks [@jadbox](https://github.com/jadbox)! - Adds `cloudflare:sockets` compile support
|
||||
|
||||
- [#8788](https://github.com/withastro/astro/pull/8788) [`0ab6bad7d`](https://github.com/withastro/astro/commit/0ab6bad7dffd413c975ab00e545f8bc150f6a92f) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Adds support for `node:crypto`
|
||||
|
||||
- Updated dependencies [[`160d1cd75`](https://github.com/withastro/astro/commit/160d1cd755e70af1d8ec294d01dd2cb32d60db50), [`30de32436`](https://github.com/withastro/astro/commit/30de324361bc261956eb9fc08fe60a82ff602a9b), [`c4a7ec425`](https://github.com/withastro/astro/commit/c4a7ec4255e7acb9555cb8bb74ea13c5fbb2ac17), [`c24f70d91`](https://github.com/withastro/astro/commit/c24f70d91601dd3a6b5a84f04d61824e775e9b44), [`93b092266`](https://github.com/withastro/astro/commit/93b092266febfad16a48575f8eee12d5910bf071), [`29cdfa024`](https://github.com/withastro/astro/commit/29cdfa024886dd581cb207586f7dfec6966bdd4e), [`eaed844ea`](https://github.com/withastro/astro/commit/eaed844ea8f2f52e0c9caa40bb3ec7377e10595f)]:
|
||||
- astro@3.2.4
|
||||
- @astrojs/underscore-redirects@0.3.1
|
||||
|
||||
## 7.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
|
|
@ -169,7 +169,7 @@ default: `false`
|
|||
|
||||
Whether or not to import `.wasm` files [directly as ES modules](https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration) using the `.wasm?module` import syntax.
|
||||
|
||||
Add `wasmModuleImports: true` to `astro.config.mjs` to enable this functionality in both the Cloudflare build and the Astro dev server. Read more about [using Wasm modules](#use-wasm-modules).
|
||||
Add `wasmModuleImports: true` to `astro.config.mjs` to enable this functionality in both the Cloudflare build and the Astro dev server. Read more about [using Wasm modules](#use-wasm-modules)
|
||||
|
||||
```diff lang="js"
|
||||
// astro.config.mjs
|
||||
|
@ -221,7 +221,7 @@ Currently supported bindings:
|
|||
- [Cloudflare Workers KV](https://developers.cloudflare.com/kv/)
|
||||
- [Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/)
|
||||
|
||||
You can access the runtime from Astro components through `Astro.locals` inside any `.astro` file.
|
||||
You can access the runtime from Astro components through `Astro.locals` inside any .astro` file.
|
||||
|
||||
```astro
|
||||
---
|
||||
|
@ -339,7 +339,6 @@ Astro's Cloudflare adapter allows you to use any Node.js runtime API supported b
|
|||
- assert
|
||||
- AsyncLocalStorage
|
||||
- Buffer
|
||||
- Crypto
|
||||
- Diagnostics Channel
|
||||
- EventEmitter
|
||||
- path
|
||||
|
@ -358,10 +357,6 @@ import { Buffer } from 'node:buffer';
|
|||
|
||||
Additionally, you'll need to enable the Compatibility Flag in Cloudflare. The configuration for this flag may vary based on where you deploy your Astro site. For detailed guidance, please refer to the [Cloudflare documentation on enabling Node.js compatibility](https://developers.cloudflare.com/workers/runtime-apis/nodejs).
|
||||
|
||||
## Cloudflare module support
|
||||
|
||||
All Cloudflare namespaced packages (e.g. `cloudflare:sockets`) are allowlisted for use. Note that the package `cloudflare:sockets` does not work locally without using Wrangler dev mode.
|
||||
|
||||
## Preview with Wrangler
|
||||
|
||||
To use [`wrangler`](https://developers.cloudflare.com/workers/wrangler/) to run your application locally, update the preview script:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@astrojs/cloudflare",
|
||||
"description": "Deploy your site to Cloudflare Workers/Pages",
|
||||
"version": "7.5.2",
|
||||
"version": "7.5.1",
|
||||
"type": "module",
|
||||
"types": "./dist/index.d.ts",
|
||||
"author": "withastro",
|
||||
|
@ -48,7 +48,7 @@
|
|||
"vite": "^4.4.9"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "workspace:^3.2.4"
|
||||
"astro": "workspace:^3.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/iarna__toml": "^2.0.2",
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
import type {
|
||||
Request as CFRequest,
|
||||
CacheStorage,
|
||||
ExecutionContext,
|
||||
} from '@cloudflare/workers-types';
|
||||
import type { Request as CFRequest, ExecutionContext } from '@cloudflare/workers-types';
|
||||
import type { SSRManifest } from 'astro';
|
||||
import { App } from 'astro/app';
|
||||
import { getProcessEnvProxy, isNode } from '../util.js';
|
||||
|
@ -20,7 +16,7 @@ export interface AdvancedRuntime<T extends object = object> {
|
|||
waitUntil: (promise: Promise<any>) => void;
|
||||
env: Env & T;
|
||||
cf: CFRequest['cf'];
|
||||
caches: CacheStorage;
|
||||
caches: typeof caches;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -54,7 +50,7 @@ export function createExports(manifest: SSRManifest) {
|
|||
},
|
||||
env: env,
|
||||
cf: request.cf,
|
||||
caches: caches as unknown as CacheStorage,
|
||||
caches: caches,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { Request as CFRequest, CacheStorage, EventContext } from '@cloudflare/workers-types';
|
||||
import type { Request as CFRequest, EventContext } from '@cloudflare/workers-types';
|
||||
import type { SSRManifest } from 'astro';
|
||||
import { App } from 'astro/app';
|
||||
import { getProcessEnvProxy, isNode } from '../util.js';
|
||||
|
@ -6,12 +6,13 @@ import { getProcessEnvProxy, isNode } from '../util.js';
|
|||
if (!isNode) {
|
||||
process.env = getProcessEnvProxy();
|
||||
}
|
||||
|
||||
export interface DirectoryRuntime<T extends object = object> {
|
||||
runtime: {
|
||||
waitUntil: (promise: Promise<any>) => void;
|
||||
env: EventContext<unknown, string, unknown>['env'] & T;
|
||||
cf: CFRequest['cf'];
|
||||
caches: CacheStorage;
|
||||
caches: typeof caches;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -47,7 +48,7 @@ export function createExports(manifest: SSRManifest) {
|
|||
},
|
||||
env: context.env,
|
||||
cf: request.cf,
|
||||
caches: caches as unknown as CacheStorage,
|
||||
caches: caches,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -283,7 +283,6 @@ export default function createIntegration(args?: Options): AstroIntegration {
|
|||
'node:assert',
|
||||
'node:async_hooks',
|
||||
'node:buffer',
|
||||
'node:crypto',
|
||||
'node:diagnostics_channel',
|
||||
'node:events',
|
||||
'node:path',
|
||||
|
@ -291,7 +290,6 @@ export default function createIntegration(args?: Options): AstroIntegration {
|
|||
'node:stream',
|
||||
'node:string_decoder',
|
||||
'node:util',
|
||||
'cloudflare:*',
|
||||
],
|
||||
entryPoints: pathsGroup,
|
||||
outbase: absolutePagesDirname,
|
||||
|
@ -366,7 +364,6 @@ export default function createIntegration(args?: Options): AstroIntegration {
|
|||
'node:assert',
|
||||
'node:async_hooks',
|
||||
'node:buffer',
|
||||
'node:crypto',
|
||||
'node:diagnostics_channel',
|
||||
'node:events',
|
||||
'node:path',
|
||||
|
@ -374,7 +371,6 @@ export default function createIntegration(args?: Options): AstroIntegration {
|
|||
'node:stream',
|
||||
'node:string_decoder',
|
||||
'node:util',
|
||||
'cloudflare:*',
|
||||
],
|
||||
entryPoints: [entryPath],
|
||||
outfile: buildPath,
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
"zod": "3.21.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "workspace:^3.2.4"
|
||||
"astro": "workspace:^3.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/markdown-remark": "workspace:*",
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
"vfile": "^5.3.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "workspace:^3.2.4"
|
||||
"astro": "workspace:^3.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.3.5",
|
||||
|
|
|
@ -116,14 +116,14 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
|
|||
if (!id.endsWith('.mdx')) return;
|
||||
|
||||
// Read code from file manually to prevent Vite from parsing `import.meta.env` expressions
|
||||
const { fileId, fileUrl } = getFileInfo(id, config);
|
||||
const { fileId } = getFileInfo(id, config);
|
||||
const code = await fs.readFile(fileId, 'utf-8');
|
||||
|
||||
const { data: frontmatter, content: pageContent } = parseFrontmatter(code, id);
|
||||
|
||||
const vfile = new VFile({ value: pageContent, path: id });
|
||||
// Ensure `data.astro` is available to all remark plugins
|
||||
setVfileFrontmatter(vfile, frontmatter, { fileURL: new URL(fileUrl) });
|
||||
setVfileFrontmatter(vfile, frontmatter);
|
||||
|
||||
try {
|
||||
const compiled = await processor.process(vfile);
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
"server-destroy": "^1.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "workspace:^3.2.4"
|
||||
"astro": "workspace:^3.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.17.8",
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
"vite": "^4.4.9"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "workspace:^3.2.4",
|
||||
"astro": "workspace:^3.2.3",
|
||||
"svelte": "^3.55.0 || ^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
# @astrojs/tailwind
|
||||
|
||||
## 5.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#8638](https://github.com/withastro/astro/pull/8638) [`160d1cd75`](https://github.com/withastro/astro/commit/160d1cd755e70af1d8ec294d01dd2cb32d60db50) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - The `@astrojs/tailwind` integration now creates a `tailwind.config.mjs` file by default
|
||||
|
||||
- Updated dependencies [[`160d1cd75`](https://github.com/withastro/astro/commit/160d1cd755e70af1d8ec294d01dd2cb32d60db50), [`30de32436`](https://github.com/withastro/astro/commit/30de324361bc261956eb9fc08fe60a82ff602a9b), [`c4a7ec425`](https://github.com/withastro/astro/commit/c4a7ec4255e7acb9555cb8bb74ea13c5fbb2ac17), [`c24f70d91`](https://github.com/withastro/astro/commit/c24f70d91601dd3a6b5a84f04d61824e775e9b44), [`93b092266`](https://github.com/withastro/astro/commit/93b092266febfad16a48575f8eee12d5910bf071), [`29cdfa024`](https://github.com/withastro/astro/commit/29cdfa024886dd581cb207586f7dfec6966bdd4e), [`eaed844ea`](https://github.com/withastro/astro/commit/eaed844ea8f2f52e0c9caa40bb3ec7377e10595f)]:
|
||||
- astro@3.2.4
|
||||
|
||||
## 5.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
|
|
@ -94,7 +94,7 @@ https://user-images.githubusercontent.com/4033662/169918388-8ed153b2-0ba0-4b24-b
|
|||
|
||||
### Configuring Tailwind
|
||||
|
||||
If you used the Quick Install instructions and said yes to each prompt, you'll see a `tailwind.config.mjs` file in your project's root directory. Use this file for your Tailwind configuration changes. You can learn how to customize Tailwind using this file [in the Tailwind docs](https://tailwindcss.com/docs/configuration).
|
||||
If you used the Quick Install instructions and said yes to each prompt, you'll see a `tailwind.config.cjs` file in your project's root directory. Use this file for your Tailwind configuration changes. You can learn how to customize Tailwind using this file [in the Tailwind docs](https://tailwindcss.com/docs/configuration).
|
||||
|
||||
If it isn't there, you add your own `tailwind.config.(js|cjs|mjs)` file to the root directory and the integration will use its configurations. This can be great if you already have Tailwind configured in another project and want to bring those settings over to this one.
|
||||
|
||||
|
@ -178,8 +178,8 @@ error The `text-special` class does not exist. If `text-special` is a custom c
|
|||
[Instead of using `@layer` directives in a global stylesheet](https://tailwindcss.com/docs/functions-and-directives#using-apply-with-per-component-css), define your custom styles by adding a plugin to your Tailwind config to fix it:
|
||||
|
||||
```js
|
||||
// tailwind.config.mjs
|
||||
export default {
|
||||
// tailwind.config.cjs
|
||||
module.exports = {
|
||||
// ...
|
||||
plugins: [
|
||||
function ({ addComponents, theme }) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue