Compare commits

...

24 commits

Author SHA1 Message Date
993c085952 expose file url to markdown renderer 2023-10-11 11:46:58 -05:00
Alexander Niebuhr
3f231cefed
port https://github.com/withastro/docs/pull/4980 (#8799) 2023-10-11 07:06:20 +02:00
lilnasy
a8b979ef40 [ci] format 2023-10-10 16:40:46 +00:00
Arsh
bd5aa1cd35
fix(transitions router): no-op on the server (#8771)
* fix(transitions router): no-op on the server

* factor out onPopState

* add e2e test case

* Apply suggestions from code review

Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com>

* use supportsViewTransitions

* add changeset

* warn on navigate() use during ssr

* switch supportsViewTransitions to import.meta.env

* correct typo

* bring back import.meta.env

* !import.meta.env.SSR -> inBrowser

* Apply suggestions from code review

Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com>

---------

Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com>
2023-10-10 22:08:35 +05:30
alexanderniebuhr
03e6979c28 [ci] format 2023-10-10 16:11:20 +00:00
Mikkel Ricafrente
75781643a2
fix(cloudflare): runtime types for Cloudflare caches (#8782)
* fix cachestorage reference in cloudflare integration

* add cachestorage to serverdirectorymode

* add changeset

* remove global caches type

* update unlucky-avocados-brake.md
2023-10-10 18:08:17 +02:00
Houston (Bot)
9cd6a6657b
[ci] release (#8768)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-10-10 22:30:52 +08:00
Arsh
c071458257
chore: removed adapters cleanup (#8726)
* update ci, readme, comments, remote workspaces

* fix hosted test fixture

* keep adapter config typedocs
2023-10-10 19:36:35 +05:30
Alexander Niebuhr
0ab6bad7df
fix(cloudflare): esbuild settings for cloudflare (#8788)
---------

Co-authored-by: Jonathan Dunlap <595843+jadbox@users.noreply.github.com>
2023-10-10 09:16:32 +02:00
alexanderniebuhr
90d70eb7c4 [ci] format 2023-10-09 17:16:02 +00:00
Jonathan Dunlap
054c5c6447
fix(cloudflare): support for 'cloudflare:*' imports (#8766)
* chore: add 'cloudflare:sockets' to external list

* chore: add Changeset

* patch: wildcard cloudflare packages

* chore: updated Readme for cloudflare module support

* Update .changeset/heavy-elephants-tan.md

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* Update packages/integrations/cloudflare/README.md

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

---------

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Co-authored-by: Alexander Niebuhr <alexander@nbhr.io>
2023-10-09 19:13:46 +02:00
ematipico
7ea27f6319 [ci] format 2023-10-09 16:00:28 +00:00
Arsh
c4a7ec4255
fix(windows): ensure drive letter is uppercase (#8741) 2023-10-09 16:58:09 +01:00
bluwy
a0dc79b946 [ci] format 2023-10-09 14:23:53 +00:00
Florian Lefebvre
160d1cd755
feat(tailwind): create a tailwind.config.mjs file by default (#8638) 2023-10-09 22:21:26 +08:00
Martin Trapp
29cdfa0248
Fix transition attributes on islands (#8776)
* Fix transition attributes on islands

* Incorporate comments from review
2023-10-09 16:19:46 +02:00
Martin Trapp
c24f70d916
Fix flickering during view transitions (#8772)
* Fix for #8711

* more descriptive changeset

* chores, while we are at it ...
2023-10-09 16:15:23 +02:00
Bjorn Lu
33d0be50be
Fix snapshot release permissions (#8777) 2023-10-09 20:47:06 +08:00
Bjorn Lu
93b092266f
Make CSS chunk names less confusing (#8754) 2023-10-09 17:29:28 +08:00
Makito
eaed844ea8
fix(assets): add the missing await to getHTMLAttributes (#8773) 2023-10-07 21:22:47 +02:00
Martin Trapp
30de324361
Revert fix #8472 (#8767) 2023-10-06 23:17:27 +02:00
Matthew Phillips
2262814a92 Give snapshot releases the issues: write permission 2023-10-06 16:11:29 -04:00
Matthew Phillips
f9131003d7 Give the snapshot release the right permissions 2023-10-06 16:00:29 -04:00
Matthew Phillips
d51cf5e707 Snapshot release: prevent setting output 2023-10-06 15:50:36 -04:00
84 changed files with 530 additions and 285 deletions

View file

@ -1,8 +0,0 @@
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

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fixed an issue where the transitions router did not work within framework components.

View file

@ -0,0 +1,5 @@
---
'@astrojs/cloudflare': patch
---
fixes `AdvancedRuntime` & `DirectoryRuntime` types to work woth Cloudflare caches

View file

@ -6,10 +6,6 @@ RUN npm install -g @playwright/test
# Install latest pnpm # Install latest pnpm
RUN npm install -g 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 \ 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 \ && 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 && apt-get -y install /tmp/chrome.deb

View file

@ -1,34 +0,0 @@
{
"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"]
}
}
}

View file

@ -1,10 +0,0 @@
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

View file

@ -133,11 +133,6 @@ jobs:
node-version: ${{ matrix.NODE_VERSION }} node-version: ${{ matrix.NODE_VERSION }}
cache: "pnpm" cache: "pnpm"
- name: Use Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.35.0
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install

View file

@ -19,6 +19,11 @@ jobs:
name: Create a snapshot release of a pull request 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') }} if: ${{ github.repository_owner == 'withastro' && github.event.issue.pull_request && startsWith(github.event.comment.body, '!preview') }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
issues: write
pull-requests: write
steps: steps:
- name: "Check if user has admin access (only admins can publish snapshot releases)." - name: "Check if user has admin access (only admins can publish snapshot releases)."
uses: "lannonbr/repo-permission-check-action@2.0.0" uses: "lannonbr/repo-permission-check-action@2.0.0"

View file

@ -11,8 +11,6 @@ env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_TEST_ORG_ID }} VERCEL_ORG_ID: ${{ secrets.VERCEL_TEST_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_TEST_PROJECT_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_TEST_PROJECT_ID }}
VERCEL_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }} 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 FORCE_COLOR: true
jobs: jobs:
@ -35,21 +33,19 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Install Hosts CLIs - name: Build Astro
run: pnpm install --global netlify-cli vercel run: pnpm turbo build --filter astro --filter @astrojs/vercel
- name: Deploy Vercel - name: Build test project
working-directory: ./packages/integrations/vercel/test/hosted/hosted-astro-project working-directory: ./packages/integrations/vercel/test/hosted/hosted-astro-project
run: run:
pnpm run build pnpm run build
vercel --prod --prebuilt
- name: Deploy Netlify - name: Deploy to Vercel
working-directory: ./packages/integrations/netlify/test/hosted/hosted-astro-project working-directory: ./packages/integrations/vercel/test/hosted/hosted-astro-project
run: run:
pnpm run build pnpm dlx vercel --prod --prebuilt
netlify deploy --prod
- name: Test both hosts - name: Test
run: run:
pnpm run test:e2e:hosts pnpm run test:e2e:hosts

View file

@ -1,6 +1,4 @@
--- ---
image:
file: .Dockerfile
# Commands to start on workspace startup # Commands to start on workspace startup
tasks: tasks:
- before: | - before: |

View file

@ -3,6 +3,9 @@
# Convert context URL to an array # Convert context URL to an array
mapfile -t CONTEXT_URL_ITEMS < <(echo "$GITPOD_WORKSPACE_CONTEXT_URL" | tr '/' '\n') 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 # Check if Gitpod started from a specific example directory in the repository
if [ "${CONTEXT_URL_ITEMS[7]}" = "examples" ]; then if [ "${CONTEXT_URL_ITEMS[7]}" = "examples" ]; then
EXAMPLE_PROJECT=${CONTEXT_URL_ITEMS[8]} EXAMPLE_PROJECT=${CONTEXT_URL_ITEMS[8]}

View file

@ -52,8 +52,6 @@ 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/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/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/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/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/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) | | [@astrojs/cloudflare](packages/integrations/cloudflare) | [![astro version](https://img.shields.io/npm/v/@astrojs/cloudflare.svg?label=%20)](packages/integrations/cloudflare/CHANGELOG.md) |

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -14,6 +14,6 @@
"@astrojs/mdx": "^1.1.1", "@astrojs/mdx": "^1.1.1",
"@astrojs/rss": "^3.0.0", "@astrojs/rss": "^3.0.0",
"@astrojs/sitemap": "^3.0.1", "@astrojs/sitemap": "^3.0.1",
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -15,7 +15,7 @@
], ],
"scripts": {}, "scripts": {},
"devDependencies": { "devDependencies": {
"astro": "^3.2.3" "astro": "^3.2.4"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "^2.0.0-beta.0" "astro": "^2.0.0-beta.0"

View file

@ -14,6 +14,6 @@
"@astrojs/alpinejs": "^0.3.1", "@astrojs/alpinejs": "^0.3.1",
"@types/alpinejs": "^3.7.2", "@types/alpinejs": "^3.7.2",
"alpinejs": "^3.12.3", "alpinejs": "^3.12.3",
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@astrojs/lit": "^3.0.1", "@astrojs/lit": "^3.0.1",
"@webcomponents/template-shadowroot": "^0.2.1", "@webcomponents/template-shadowroot": "^0.2.1",
"astro": "^3.2.3", "astro": "^3.2.4",
"lit": "^2.8.0" "lit": "^2.8.0"
} }
} }

View file

@ -16,7 +16,7 @@
"@astrojs/solid-js": "^3.0.2", "@astrojs/solid-js": "^3.0.2",
"@astrojs/svelte": "^4.0.3", "@astrojs/svelte": "^4.0.3",
"@astrojs/vue": "^3.0.1", "@astrojs/vue": "^3.0.1",
"astro": "^3.2.3", "astro": "^3.2.4",
"preact": "^10.17.1", "preact": "^10.17.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",

View file

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@astrojs/preact": "^3.0.1", "@astrojs/preact": "^3.0.1",
"@preact/signals": "^1.2.1", "@preact/signals": "^1.2.1",
"astro": "^3.2.3", "astro": "^3.2.4",
"preact": "^10.17.1" "preact": "^10.17.1"
} }
} }

View file

@ -14,7 +14,7 @@
"@astrojs/react": "^3.0.3", "@astrojs/react": "^3.0.3",
"@types/react": "^18.2.21", "@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"astro": "^3.2.3", "astro": "^3.2.4",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
} }

View file

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/solid-js": "^3.0.2", "@astrojs/solid-js": "^3.0.2",
"astro": "^3.2.3", "astro": "^3.2.4",
"solid-js": "^1.7.11" "solid-js": "^1.7.11"
} }
} }

View file

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/svelte": "^4.0.3", "@astrojs/svelte": "^4.0.3",
"astro": "^3.2.3", "astro": "^3.2.4",
"svelte": "^4.2.0" "svelte": "^4.2.0"
} }
} }

View file

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/vue": "^3.0.1", "@astrojs/vue": "^3.0.1",
"astro": "^3.2.3", "astro": "^3.2.4",
"vue": "^3.3.4" "vue": "^3.3.4"
} }
} }

View file

@ -12,6 +12,6 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/node": "^6.0.3", "@astrojs/node": "^6.0.3",
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -10,9 +10,9 @@ export default function createIntegration(): AstroIntegration {
// See the @astrojs/react integration for an example // See the @astrojs/react integration for an example
// https://github.com/withastro/astro/blob/main/packages/integrations/react/src/index.ts // https://github.com/withastro/astro/blob/main/packages/integrations/react/src/index.ts
}, },
'astro:build:setup': ({ config, updateConfig }) => { 'astro:build:setup': ({ pages, updateConfig }) => {
// See the @astrojs/netlify integration for an example // See the @astrojs/lit integration for an example
// https://github.com/withastro/astro/blob/main/packages/integrations/netlify/src/integration-functions.ts // https://github.com/withastro/astro/blob/main/packages/integrations/lit/src/index.ts
}, },
'astro:build:done': ({ dir, routes }) => { 'astro:build:done': ({ dir, routes }) => {
// See the @astrojs/partytown integration for an example // See the @astrojs/partytown integration for an example

View file

@ -15,7 +15,7 @@
], ],
"scripts": {}, "scripts": {},
"devDependencies": { "devDependencies": {
"astro": "^3.2.3" "astro": "^3.2.4"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "^2.0.0-beta.0" "astro": "^2.0.0-beta.0"

View file

@ -13,7 +13,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/node": "^6.0.3", "@astrojs/node": "^6.0.3",
"astro": "^3.2.3", "astro": "^3.2.4",
"html-minifier": "^4.0.0" "html-minifier": "^4.0.0"
} }
} }

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -14,7 +14,7 @@
"dependencies": { "dependencies": {
"@astrojs/node": "^6.0.3", "@astrojs/node": "^6.0.3",
"@astrojs/svelte": "^4.0.3", "@astrojs/svelte": "^4.0.3",
"astro": "^3.2.3", "astro": "^3.2.4",
"svelte": "^4.2.0" "svelte": "^4.2.0"
} }
} }

View file

@ -10,8 +10,8 @@
"astro": "astro" "astro": "astro"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/tailwind": "^5.0.1", "@astrojs/tailwind": "^5.0.2",
"@astrojs/node": "^6.0.3", "@astrojs/node": "^6.0.3",
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -12,6 +12,6 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/markdoc": "^0.5.2", "@astrojs/markdoc": "^0.5.2",
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/markdown-remark": "^3.2.1", "@astrojs/markdown-remark": "^3.2.1",
"astro": "^3.2.3", "astro": "^3.2.4",
"hast-util-select": "^5.0.5", "hast-util-select": "^5.0.5",
"rehype-autolink-headings": "^6.1.1", "rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0", "rehype-slug": "^5.1.0",

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.2.3" "astro": "^3.2.4"
} }
} }

View file

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@astrojs/mdx": "^1.1.1", "@astrojs/mdx": "^1.1.1",
"@astrojs/preact": "^3.0.1", "@astrojs/preact": "^3.0.1",
"astro": "^3.2.3", "astro": "^3.2.4",
"preact": "^10.17.1" "preact": "^10.17.1"
} }
} }

View file

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@astrojs/preact": "^3.0.1", "@astrojs/preact": "^3.0.1",
"@nanostores/preact": "^0.5.0", "@nanostores/preact": "^0.5.0",
"astro": "^3.2.3", "astro": "^3.2.4",
"nanostores": "^0.9.3", "nanostores": "^0.9.3",
"preact": "^10.17.1" "preact": "^10.17.1"
} }

View file

@ -12,9 +12,9 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "^1.1.1", "@astrojs/mdx": "^1.1.1",
"@astrojs/tailwind": "^5.0.1", "@astrojs/tailwind": "^5.0.2",
"@types/canvas-confetti": "^1.6.0", "@types/canvas-confetti": "^1.6.0",
"astro": "^3.2.3", "astro": "^3.2.4",
"autoprefixer": "^10.4.15", "autoprefixer": "^10.4.15",
"canvas-confetti": "^1.6.0", "canvas-confetti": "^1.6.0",
"postcss": "^8.4.28", "postcss": "^8.4.28",

View file

@ -11,7 +11,7 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.2.3", "astro": "^3.2.4",
"vite-plugin-pwa": "0.16.4", "vite-plugin-pwa": "0.16.4",
"workbox-window": "^7.0.0" "workbox-window": "^7.0.0"
} }

View file

@ -12,7 +12,7 @@
"test": "vitest" "test": "vitest"
}, },
"dependencies": { "dependencies": {
"astro": "^3.2.3", "astro": "^3.2.4",
"vitest": "^0.34.2" "vitest": "^0.34.2"
} }
} }

View file

@ -1,5 +1,25 @@
# astro # 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 ## 3.2.3
### Patch Changes ### Patch Changes

View file

@ -32,6 +32,13 @@ 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') return import('./dist/cli/index.js')
.then(({ cli }) => cli(process.argv)) .then(({ cli }) => cli(process.argv))
.catch((error) => { .catch((error) => {

View file

@ -0,0 +1,5 @@
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>;
}

View file

@ -0,0 +1,34 @@
---
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>

View file

@ -0,0 +1,12 @@
---
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>

View file

@ -0,0 +1,6 @@
---
import ListenerLayout from '../components/listener-layout.astro';
---
<ListenerLayout>
<a id="totwo" href="/listener-two">Go to listener two</a>
</ListenerLayout>

View file

@ -0,0 +1,6 @@
---
import ListenerLayout from '../components/listener-layout.astro';
---
<ListenerLayout>
<a id="toone" href="/listener-one">Go to listener one</a>
</ListenerLayout>

View file

@ -230,6 +230,28 @@ test.describe('View Transitions', () => {
await expect(h, 'imported CSS updated').toHaveCSS('background-color', 'rgba(0, 0, 0, 0)'); 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 }) => { test('click hash links does not do navigation', async ({ page, astro }) => {
// Go to page 1 // Go to page 1
await page.goto(astro.resolveUrl('/one')); await page.goto(astro.resolveUrl('/one'));
@ -648,7 +670,7 @@ test.describe('View Transitions', () => {
expect(loads.length, 'There should be 2 page loads').toEqual(2); expect(loads.length, 'There should be 2 page loads').toEqual(2);
}); });
test('client:only styles are retained on transition', async ({ page, astro }) => { test.skip('client:only styles are retained on transition', async ({ page, astro }) => {
const totalExpectedStyles = 7; const totalExpectedStyles = 7;
// Go to page 1 // Go to page 1
@ -731,6 +753,21 @@ test.describe('View Transitions', () => {
await expect(p, 'should have content').toHaveText('Page 1'); 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 }) => { test('body inline scripts do not re-execute on navigation', async ({ page, astro }) => {
const errors = []; const errors = [];
page.addListener('pageerror', (err) => { page.addListener('pageerror', (err) => {

View file

@ -1,6 +1,6 @@
{ {
"name": "astro", "name": "astro",
"version": "3.2.3", "version": "3.2.4",
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
"type": "module", "type": "module",
"author": "withastro", "author": "withastro",

View file

@ -111,7 +111,7 @@ export async function getImage(
src: imageURL, src: imageURL,
attributes: attributes:
service.getHTMLAttributes !== undefined service.getHTMLAttributes !== undefined
? service.getHTMLAttributes(validatedOptions, imageConfig) ? await service.getHTMLAttributes(validatedOptions, imageConfig)
: {}, : {},
}; };
} }

View file

@ -50,7 +50,7 @@ const ALIASES = new Map([
]); ]);
const ASTRO_CONFIG_STUB = `import { defineConfig } from 'astro/config';\n\nexport default defineConfig({});`; const ASTRO_CONFIG_STUB = `import { defineConfig } from 'astro/config';\n\nexport default defineConfig({});`;
const TAILWIND_CONFIG_STUB = `/** @type {import('tailwindcss').Config} */ const TAILWIND_CONFIG_STUB = `/** @type {import('tailwindcss').Config} */
module.exports = { export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: { theme: {
extend: {}, extend: {},
@ -74,7 +74,6 @@ const OFFICIAL_ADAPTER_TO_IMPORT_MAP: Record<string, string> = {
vercel: '@astrojs/vercel/serverless', vercel: '@astrojs/vercel/serverless',
cloudflare: '@astrojs/cloudflare', cloudflare: '@astrojs/cloudflare',
node: '@astrojs/node', node: '@astrojs/node',
deno: '@astrojs/deno',
}; };
// Users might lack access to the global npm registry, this function // Users might lack access to the global npm registry, this function
@ -160,7 +159,7 @@ export async function add(names: string[], { flags }: AddOptions) {
'./tailwind.config.mjs', './tailwind.config.mjs',
'./tailwind.config.js', './tailwind.config.js',
], ],
defaultConfigFile: './tailwind.config.cjs', defaultConfigFile: './tailwind.config.mjs',
defaultConfigContent: TAILWIND_CONFIG_STUB, defaultConfigContent: TAILWIND_CONFIG_STUB,
}); });
} }

View file

@ -30,7 +30,7 @@ type RawContentEvent = { name: ChokidarEvent; entry: string };
type ContentEvent = { name: ChokidarEvent; entry: URL }; type ContentEvent = { name: ChokidarEvent; entry: URL };
type DataEntryMetadata = Record<string, never>; type DataEntryMetadata = Record<string, never>;
type ContentEntryMetadata = { slug: string }; type ContentEntryMetadata = { slug: string, path: string };
type CollectionEntryMap = { type CollectionEntryMap = {
[collection: string]: [collection: string]:
| { | {
@ -276,7 +276,7 @@ export async function createContentTypesGenerator({
if (!(entryKey in collectionEntryMap[collectionKey].entries)) { if (!(entryKey in collectionEntryMap[collectionKey].entries)) {
collectionEntryMap[collectionKey] = { collectionEntryMap[collectionKey] = {
type: 'content', type: 'content',
entries: { ...collectionInfo.entries, [entryKey]: { slug: addedSlug } }, entries: { ...collectionInfo.entries, [entryKey]: { slug: addedSlug, path: event.entry.toString() } },
}; };
} }
return { shouldGenerateTypes: true }; return { shouldGenerateTypes: true };
@ -453,7 +453,15 @@ async function writeContentFiles({
)}] }`; )}] }`;
const slugType = JSON.stringify(entryMetadata.slug); const slugType = JSON.stringify(entryMetadata.slug);
contentTypesStr += `${entryKey}: {\n id: ${entryKey};\n slug: ${slugType};\n body: string;\n collection: ${collectionKey};\n data: ${dataType}\n} & ${renderType};\n`; contentTypesStr += [
`${entryKey}: {`,
` id: ${entryKey};`,
` slug: ${slugType};`,
` path: ${JSON.stringify(entryMetadata.path)};`,
` body: string;`,
` collection: ${collectionKey};`,
` data: ${dataType}`,
`} & ${renderType};`].join("\n");
} }
contentTypesStr += `};\n`; contentTypesStr += `};\n`;
break; break;

View file

@ -1,4 +1,4 @@
import type { GetModuleInfo } from 'rollup'; import type { GetModuleInfo, ModuleInfo } from 'rollup';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
import npath from 'node:path'; import npath from 'node:path';
@ -6,20 +6,29 @@ import type { AstroSettings } from '../../@types/astro.js';
import { viteID } from '../util.js'; import { viteID } from '../util.js';
import { getTopLevelPages } from './graph.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 // 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 // We could get rid of this and only use the createSlugger implementation, but this creates
// slightly prettier names. // slightly prettier names.
export function shortHashedName(id: string, ctx: { getModuleInfo: GetModuleInfo }): string { export function shortHashedName(id: string, ctx: { getModuleInfo: GetModuleInfo }): string {
const parents = Array.from(getTopLevelPages(id, ctx)); const parents = Array.from(getTopLevelPages(id, ctx));
const firstParentId = parents[0]?.[0].id; return createNameHash(
const firstParentName = firstParentId ? npath.parse(firstParentId).name : 'index'; getFirstParentId(parents),
parents.map(([page]) => page.id)
);
}
export function createNameHash(baseId: string | undefined, hashIds: string[]): string {
const baseName = baseId ? prettifyBaseName(npath.parse(baseId).name) : 'index';
const hash = crypto.createHash('sha256'); const hash = crypto.createHash('sha256');
for (const [page] of parents) { for (const id of hashIds) {
hash.update(page.id, 'utf-8'); hash.update(id, 'utf-8');
} }
const h = hash.digest('hex').slice(0, 8); const h = hash.digest('hex').slice(0, 8);
const proposedName = firstParentName + '.' + h; const proposedName = baseName + '.' + h;
return proposedName; return proposedName;
} }
@ -34,7 +43,7 @@ export function createSlugger(settings: AstroSettings) {
.map(([page]) => page.id) .map(([page]) => page.id)
.sort() .sort()
.join('-'); .join('-');
const firstParentId = parents[0]?.[0].id || indexPage; const firstParentId = getFirstParentId(parents) || indexPage;
// Use the last two segments, for ex /docs/index // Use the last two segments, for ex /docs/index
let dir = firstParentId; let dir = firstParentId;
@ -45,7 +54,7 @@ export function createSlugger(settings: AstroSettings) {
break; break;
} }
const name = npath.parse(npath.basename(dir)).name; const name = prettifyBaseName(npath.parse(npath.basename(dir)).name);
key = key.length ? name + sep + key : name; key = key.length ? name + sep + key : name;
dir = npath.dirname(dir); dir = npath.dirname(dir);
i++; i++;
@ -76,3 +85,32 @@ export function createSlugger(settings: AstroSettings) {
return name; 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, '_');
}

View file

@ -1,5 +1,3 @@
import * as crypto from 'node:crypto';
import * as npath from 'node:path';
import type { GetModuleInfo } from 'rollup'; import type { GetModuleInfo } from 'rollup';
import { type ResolvedConfig, type Plugin as VitePlugin } from 'vite'; import { type ResolvedConfig, type Plugin as VitePlugin } from 'vite';
import { isBuildableCSSRequest } from '../../../vite-plugin-astro-server/util.js'; import { isBuildableCSSRequest } from '../../../vite-plugin-astro-server/util.js';
@ -93,7 +91,7 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
if (new URL(pageInfo.id, 'file://').searchParams.has(PROPAGATED_ASSET_FLAG)) { if (new URL(pageInfo.id, 'file://').searchParams.has(PROPAGATED_ASSET_FLAG)) {
// Split delayed assets to separate modules // Split delayed assets to separate modules
// so they can be injected where needed // so they can be injected where needed
const chunkId = createNameHash(id, [id]); const chunkId = assetName.createNameHash(id, [id]);
internals.cssModuleToChunkIdMap.set(id, chunkId); internals.cssModuleToChunkIdMap.set(id, chunkId);
return chunkId; return chunkId;
} }
@ -272,17 +270,6 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
/***** UTILITY FUNCTIONS *****/ /***** 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( function* getParentClientOnlys(
id: string, id: string,
ctx: { getModuleInfo: GetModuleInfo }, ctx: { getModuleInfo: GetModuleInfo },

View file

@ -15,10 +15,13 @@ export interface HydrationMetadata {
componentExport: { value: string }; componentExport: { value: string };
} }
type Props = Record<string | number | symbol, any>;
interface ExtractedProps { interface ExtractedProps {
isPage: boolean; isPage: boolean;
hydration: HydrationMetadata | null; hydration: HydrationMetadata | null;
props: Record<string | number | symbol, any>; props: Props;
propsWithoutTransitionAttributes: Props;
} }
const transitionDirectivesToCopyOnIsland = Object.freeze([ const transitionDirectivesToCopyOnIsland = Object.freeze([
@ -29,13 +32,14 @@ const transitionDirectivesToCopyOnIsland = Object.freeze([
// Used to extract the directives, aka `client:load` information about a component. // 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. // Finds these special props and removes them from what gets passed into the component.
export function extractDirectives( export function extractDirectives(
inputProps: Record<string | number | symbol, any>, inputProps: Props,
clientDirectives: SSRResult['clientDirectives'] clientDirectives: SSRResult['clientDirectives']
): ExtractedProps { ): ExtractedProps {
let extracted: ExtractedProps = { let extracted: ExtractedProps = {
isPage: false, isPage: false,
hydration: null, hydration: null,
props: {}, props: {},
propsWithoutTransitionAttributes: {},
}; };
for (const [key, value] of Object.entries(inputProps)) { for (const [key, value] of Object.entries(inputProps)) {
if (key.startsWith('server:')) { if (key.startsWith('server:')) {
@ -96,10 +100,14 @@ export function extractDirectives(
} }
} else { } else {
extracted.props[key] = value; extracted.props[key] = value;
if (!transitionDirectivesToCopyOnIsland.includes(key)) {
extracted.propsWithoutTransitionAttributes[key] = value;
}
} }
} }
for (const sym of Object.getOwnPropertySymbols(inputProps)) { for (const sym of Object.getOwnPropertySymbols(inputProps)) {
extracted.props[sym] = inputProps[sym]; extracted.props[sym] = inputProps[sym];
extracted.propsWithoutTransitionAttributes[sym] = inputProps[sym];
} }
return extracted; return extracted;

View file

@ -92,7 +92,10 @@ async function renderFrameworkComponent(
displayName, displayName,
}; };
const { hydration, isPage, props } = extractDirectives(_props, clientDirectives); const { hydration, isPage, props, propsWithoutTransitionAttributes } = extractDirectives(
_props,
clientDirectives
);
let html = ''; let html = '';
let attrs: Record<string, string> | undefined = undefined; let attrs: Record<string, string> | undefined = undefined;
@ -217,7 +220,7 @@ async function renderFrameworkComponent(
({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call( ({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call(
{ result }, { result },
Component, Component,
props, propsWithoutTransitionAttributes,
children, children,
metadata metadata
)); ));
@ -242,7 +245,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( ({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call(
{ result }, { result },
Component, Component,
props, propsWithoutTransitionAttributes,
children, children,
metadata metadata
)); ));

View file

@ -13,9 +13,14 @@ type Events = 'astro:page-load' | 'astro:after-swap';
// only update history entries that are managed by us // only update history entries that are managed by us
// leave other entries alone and do not accidently add state. // leave other entries alone and do not accidently add state.
const persistState = (state: State) => history.state && history.replaceState(state, ''); const persistState = (state: State) => history.state && history.replaceState(state, '');
export const supportsViewTransitions = !!document.startViewTransition;
const inBrowser = import.meta.env.SSR === false;
export const supportsViewTransitions = inBrowser && !!document.startViewTransition;
export const transitionEnabledOnThisPage = () => export const transitionEnabledOnThisPage = () =>
!!document.querySelector('[name="astro-view-transitions-enabled"]'); inBrowser && !!document.querySelector('[name="astro-view-transitions-enabled"]');
const samePage = (otherLocation: URL) => const samePage = (otherLocation: URL) =>
location.pathname === otherLocation.pathname && location.search === otherLocation.search; location.pathname === otherLocation.pathname && location.search === otherLocation.search;
const triggerEvent = (name: Events) => document.dispatchEvent(new Event(name)); const triggerEvent = (name: Events) => document.dispatchEvent(new Event(name));
@ -40,26 +45,27 @@ const announce = () => {
60 60
); );
}; };
const PERSIST_ATTR = 'data-astro-transition-persist'; const PERSIST_ATTR = 'data-astro-transition-persist';
const parser = new DOMParser();
// explained at its usage let parser: DOMParser;
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 // 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 // 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. // can use that to determine popstate if going forward or back.
let currentHistoryIndex = 0; let currentHistoryIndex = 0;
if (history.state) {
// we reloaded a page with history state if (inBrowser) {
// (e.g. history navigation from non-transition page or browser reload) if (history.state) {
currentHistoryIndex = history.state.index; // we reloaded a page with history state
scrollTo({ left: history.state.scrollX, top: history.state.scrollY }); // (e.g. history navigation from non-transition page or browser reload)
} else if (transitionEnabledOnThisPage()) { currentHistoryIndex = history.state.index;
history.replaceState({ index: currentHistoryIndex, scrollX, scrollY, intraPage: false }, ''); 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) => { const throttle = (cb: (...args: any[]) => any, delay: number) => {
let wait = false; let wait = false;
// During the waiting time additional events are lost. // During the waiting time additional events are lost.
@ -151,18 +157,24 @@ function isInfinite(animation: Animation) {
const updateHistoryAndScrollPosition = (toLocation: URL, replace: boolean, intraPage: boolean) => { const updateHistoryAndScrollPosition = (toLocation: URL, replace: boolean, intraPage: boolean) => {
const fresh = !samePage(toLocation); const fresh = !samePage(toLocation);
let scrolledToTop = false;
if (toLocation.href !== location.href) { if (toLocation.href !== location.href) {
if (replace) { if (replace) {
history.replaceState({ ...history.state }, '', toLocation.href); history.replaceState({ ...history.state }, '', toLocation.href);
} else { } else {
history.replaceState({ ...history.state, intraPage }, ''); history.replaceState({ ...history.state, intraPage }, '');
history.pushState({ index: ++currentHistoryIndex, scrollX, scrollY }, '', toLocation.href); history.pushState(
{ index: ++currentHistoryIndex, scrollX: 0, scrollY: 0 },
'',
toLocation.href
);
} }
// now we are on the new page for non-history navigations! // now we are on the new page for non-history navigations!
// (with history navigation page change happens before popstate is fired) // (with history navigation page change happens before popstate is fired)
// freshly loaded pages start from the top // freshly loaded pages start from the top
if (fresh) { if (fresh) {
scrollTo({ left: 0, top: 0, behavior: 'instant' }); scrollTo({ left: 0, top: 0, behavior: 'instant' });
scrolledToTop = true;
} }
} }
if (toLocation.hash) { if (toLocation.hash) {
@ -171,7 +183,9 @@ const updateHistoryAndScrollPosition = (toLocation: URL, replace: boolean, intra
// that won't reload the page but instead scroll to the fragment // that won't reload the page but instead scroll to the fragment
location.href = toLocation.href; location.href = toLocation.href;
} else { } else {
scrollTo({ left: 0, top: 0, behavior: 'instant' }); if (!scrolledToTop) {
scrollTo({ left: 0, top: 0, behavior: 'instant' });
}
} }
}; };
@ -198,22 +212,6 @@ async function updateDOM(
const href = el.getAttribute('href'); const href = el.getAttribute('href');
return newDocument.head.querySelector(`link[rel=stylesheet][href="${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; return null;
}; };
@ -349,6 +347,8 @@ async function transition(
toLocation = new URL(response.redirected); toLocation = new URL(response.redirected);
} }
parser ??= new DOMParser();
const newDocument = parser.parseFromString(response.html, response.mediaType); const newDocument = parser.parseFromString(response.html, response.mediaType);
// The next line might look like a hack, // The next line might look like a hack,
// but it is actually necessary as noscript elements // but it is actually necessary as noscript elements
@ -385,7 +385,22 @@ async function transition(
} }
} }
let navigateOnServerWarned = false;
export function navigate(href: string, options?: Options) { 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 // not ours
if (!transitionEnabledOnThisPage()) { if (!transitionEnabledOnThisPage()) {
location.href = href; location.href = href;
@ -403,58 +418,61 @@ export function navigate(href: string, options?: Options) {
} }
} }
if (supportsViewTransitions || getFallback() !== 'none') { function onPopState(ev: PopStateEvent) {
addEventListener('popstate', (ev) => { if (!transitionEnabledOnThisPage() && ev.state) {
if (!transitionEnabledOnThisPage() && ev.state) { // The current page doesn't have View Transitions enabled
// The current page doesn't have View Transitions enabled // but the page we navigate to does (because it set the state).
// 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.
// 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
// 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) { if (history.scrollRestoration) {
history.scrollRestoration = 'manual'; history.scrollRestoration = 'manual';
} }
location.reload();
return;
}
const state: State = history.state; // History entries without state are created by the browser (e.g. for hash links)
if (state.intraPage) { // Our view transition entries always have state.
// this is non transition intra-page scrolling // Just ignore stateless entries.
scrollTo(state.scrollX, state.scrollY); // The browser will handle navigation fine without our help
} else { if (ev.state === null) {
const nextIndex = state.index; if (history.scrollRestoration) {
const direction: Direction = nextIndex > currentHistoryIndex ? 'forward' : 'back'; history.scrollRestoration = 'auto';
currentHistoryIndex = nextIndex;
transition(direction, new URL(location.href), {}, state);
} }
}); return;
}
addEventListener('load', onPageLoad); // With the default "auto", the browser will jump to the old scroll position
// There's not a good way to record scroll position before a back button. // before the ViewTransition is complete.
// So the way we do it is by listening to scrollend if supported, and if not continuously record the scroll position. if (history.scrollRestoration) {
const updateState = () => { history.scrollRestoration = 'manual';
persistState({ ...history.state, scrollX, scrollY }); }
};
if ('onscrollend' in window) addEventListener('scrollend', updateState); const state: State = history.state;
else addEventListener('scroll', throttle(updateState, 300)); if (state.intraPage) {
// this is non transition intra-page scrolling
markScriptsExec(); 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();
}
} }

View file

@ -0,0 +1,7 @@
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
// https://astro.build/config
export default defineConfig({
integrations: [react()],
});

View file

@ -3,6 +3,9 @@
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"astro": "workspace:*" "astro": "workspace:*",
"@astrojs/react": "workspace:*",
"react": "^18.1.0",
"react-dom": "^18.1.0"
} }
} }

View file

@ -0,0 +1,11 @@
.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;
}

View file

@ -0,0 +1,19 @@
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>
</>
);
}

View file

@ -0,0 +1,10 @@
---
import Island from '../components/Island.jsx';
---
<html>
<head>
</head>
<body>
<Island id="1" count="{1}" children="Greetings!" transition:persist="here" client:load/>
</body>
</html>

View file

@ -22,4 +22,14 @@ describe('View Transitions styles', () => {
expect($('head style')).to.have.a.lengthOf(3); 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);
});
}); });

View file

@ -1,5 +1,17 @@
# @astrojs/cloudflare # @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 ## 7.5.1
### Patch Changes ### Patch Changes

View file

@ -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. 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" ```diff lang="js"
// astro.config.mjs // astro.config.mjs
@ -221,7 +221,7 @@ Currently supported bindings:
- [Cloudflare Workers KV](https://developers.cloudflare.com/kv/) - [Cloudflare Workers KV](https://developers.cloudflare.com/kv/)
- [Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/) - [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 ```astro
--- ---
@ -339,6 +339,7 @@ Astro's Cloudflare adapter allows you to use any Node.js runtime API supported b
- assert - assert
- AsyncLocalStorage - AsyncLocalStorage
- Buffer - Buffer
- Crypto
- Diagnostics Channel - Diagnostics Channel
- EventEmitter - EventEmitter
- path - path
@ -357,6 +358,10 @@ 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). 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 ## Preview with Wrangler
To use [`wrangler`](https://developers.cloudflare.com/workers/wrangler/) to run your application locally, update the preview script: To use [`wrangler`](https://developers.cloudflare.com/workers/wrangler/) to run your application locally, update the preview script:

View file

@ -1,7 +1,7 @@
{ {
"name": "@astrojs/cloudflare", "name": "@astrojs/cloudflare",
"description": "Deploy your site to Cloudflare Workers/Pages", "description": "Deploy your site to Cloudflare Workers/Pages",
"version": "7.5.1", "version": "7.5.2",
"type": "module", "type": "module",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"author": "withastro", "author": "withastro",
@ -48,7 +48,7 @@
"vite": "^4.4.9" "vite": "^4.4.9"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.2.3" "astro": "workspace:^3.2.4"
}, },
"devDependencies": { "devDependencies": {
"@types/iarna__toml": "^2.0.2", "@types/iarna__toml": "^2.0.2",

View file

@ -1,4 +1,8 @@
import type { Request as CFRequest, ExecutionContext } from '@cloudflare/workers-types'; import type {
Request as CFRequest,
CacheStorage,
ExecutionContext,
} from '@cloudflare/workers-types';
import type { SSRManifest } from 'astro'; import type { SSRManifest } from 'astro';
import { App } from 'astro/app'; import { App } from 'astro/app';
import { getProcessEnvProxy, isNode } from '../util.js'; import { getProcessEnvProxy, isNode } from '../util.js';
@ -16,7 +20,7 @@ export interface AdvancedRuntime<T extends object = object> {
waitUntil: (promise: Promise<any>) => void; waitUntil: (promise: Promise<any>) => void;
env: Env & T; env: Env & T;
cf: CFRequest['cf']; cf: CFRequest['cf'];
caches: typeof caches; caches: CacheStorage;
}; };
} }
@ -50,7 +54,7 @@ export function createExports(manifest: SSRManifest) {
}, },
env: env, env: env,
cf: request.cf, cf: request.cf,
caches: caches, caches: caches as unknown as CacheStorage,
}, },
}; };

View file

@ -1,4 +1,4 @@
import type { Request as CFRequest, EventContext } from '@cloudflare/workers-types'; import type { Request as CFRequest, CacheStorage, EventContext } from '@cloudflare/workers-types';
import type { SSRManifest } from 'astro'; import type { SSRManifest } from 'astro';
import { App } from 'astro/app'; import { App } from 'astro/app';
import { getProcessEnvProxy, isNode } from '../util.js'; import { getProcessEnvProxy, isNode } from '../util.js';
@ -6,13 +6,12 @@ import { getProcessEnvProxy, isNode } from '../util.js';
if (!isNode) { if (!isNode) {
process.env = getProcessEnvProxy(); process.env = getProcessEnvProxy();
} }
export interface DirectoryRuntime<T extends object = object> { export interface DirectoryRuntime<T extends object = object> {
runtime: { runtime: {
waitUntil: (promise: Promise<any>) => void; waitUntil: (promise: Promise<any>) => void;
env: EventContext<unknown, string, unknown>['env'] & T; env: EventContext<unknown, string, unknown>['env'] & T;
cf: CFRequest['cf']; cf: CFRequest['cf'];
caches: typeof caches; caches: CacheStorage;
}; };
} }
@ -48,7 +47,7 @@ export function createExports(manifest: SSRManifest) {
}, },
env: context.env, env: context.env,
cf: request.cf, cf: request.cf,
caches: caches, caches: caches as unknown as CacheStorage,
}, },
}; };

View file

@ -283,6 +283,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
'node:assert', 'node:assert',
'node:async_hooks', 'node:async_hooks',
'node:buffer', 'node:buffer',
'node:crypto',
'node:diagnostics_channel', 'node:diagnostics_channel',
'node:events', 'node:events',
'node:path', 'node:path',
@ -290,6 +291,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
'node:stream', 'node:stream',
'node:string_decoder', 'node:string_decoder',
'node:util', 'node:util',
'cloudflare:*',
], ],
entryPoints: pathsGroup, entryPoints: pathsGroup,
outbase: absolutePagesDirname, outbase: absolutePagesDirname,
@ -364,6 +366,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
'node:assert', 'node:assert',
'node:async_hooks', 'node:async_hooks',
'node:buffer', 'node:buffer',
'node:crypto',
'node:diagnostics_channel', 'node:diagnostics_channel',
'node:events', 'node:events',
'node:path', 'node:path',
@ -371,6 +374,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
'node:stream', 'node:stream',
'node:string_decoder', 'node:string_decoder',
'node:util', 'node:util',
'cloudflare:*',
], ],
entryPoints: [entryPath], entryPoints: [entryPath],
outfile: buildPath, outfile: buildPath,

View file

@ -75,7 +75,7 @@
"zod": "3.21.1" "zod": "3.21.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.2.3" "astro": "workspace:^3.2.4"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/markdown-remark": "workspace:*", "@astrojs/markdown-remark": "workspace:*",

View file

@ -51,7 +51,7 @@
"vfile": "^5.3.7" "vfile": "^5.3.7"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.2.3" "astro": "workspace:^3.2.4"
}, },
"devDependencies": { "devDependencies": {
"@types/chai": "^4.3.5", "@types/chai": "^4.3.5",

View file

@ -116,14 +116,14 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
if (!id.endsWith('.mdx')) return; if (!id.endsWith('.mdx')) return;
// Read code from file manually to prevent Vite from parsing `import.meta.env` expressions // Read code from file manually to prevent Vite from parsing `import.meta.env` expressions
const { fileId } = getFileInfo(id, config); const { fileId, fileUrl } = getFileInfo(id, config);
const code = await fs.readFile(fileId, 'utf-8'); const code = await fs.readFile(fileId, 'utf-8');
const { data: frontmatter, content: pageContent } = parseFrontmatter(code, id); const { data: frontmatter, content: pageContent } = parseFrontmatter(code, id);
const vfile = new VFile({ value: pageContent, path: id }); const vfile = new VFile({ value: pageContent, path: id });
// Ensure `data.astro` is available to all remark plugins // Ensure `data.astro` is available to all remark plugins
setVfileFrontmatter(vfile, frontmatter); setVfileFrontmatter(vfile, frontmatter, { fileURL: new URL(fileUrl) });
try { try {
const compiled = await processor.process(vfile); const compiled = await processor.process(vfile);

View file

@ -37,7 +37,7 @@
"server-destroy": "^1.0.1" "server-destroy": "^1.0.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.2.3" "astro": "workspace:^3.2.4"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^18.17.8", "@types/node": "^18.17.8",

View file

@ -48,7 +48,7 @@
"vite": "^4.4.9" "vite": "^4.4.9"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.2.3", "astro": "workspace:^3.2.4",
"svelte": "^3.55.0 || ^4.0.0" "svelte": "^3.55.0 || ^4.0.0"
}, },
"engines": { "engines": {

View file

@ -1,5 +1,14 @@
# @astrojs/tailwind # @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 ## 5.0.1
### Patch Changes ### Patch Changes

View file

@ -94,7 +94,7 @@ https://user-images.githubusercontent.com/4033662/169918388-8ed153b2-0ba0-4b24-b
### Configuring Tailwind ### Configuring Tailwind
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 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 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. 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: [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 ```js
// tailwind.config.cjs // tailwind.config.mjs
module.exports = { export default {
// ... // ...
plugins: [ plugins: [
function ({ addComponents, theme }) { function ({ addComponents, theme }) {

View file

@ -1,7 +1,7 @@
{ {
"name": "@astrojs/tailwind", "name": "@astrojs/tailwind",
"description": "Use Tailwind CSS to style your Astro site", "description": "Use Tailwind CSS to style your Astro site",
"version": "5.0.1", "version": "5.0.2",
"type": "module", "type": "module",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"author": "withastro", "author": "withastro",
@ -43,7 +43,7 @@
"vite": "^4.4.9" "vite": "^4.4.9"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.2.3", "astro": "workspace:^3.2.4",
"tailwindcss": "^3.0.24" "tailwindcss": "^3.0.24"
}, },
"publishConfig": { "publishConfig": {

View file

@ -50,7 +50,7 @@ async function getViteConfiguration(
type TailwindOptions = { type TailwindOptions = {
/** /**
* Path to your tailwind config file * Path to your tailwind config file
* @default 'tailwind.config.js' * @default 'tailwind.config.mjs'
*/ */
configFile?: string; configFile?: string;
/** /**

View file

@ -61,7 +61,7 @@
"web-vitals": "^3.4.0" "web-vitals": "^3.4.0"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.2.3" "astro": "workspace:^3.2.4"
}, },
"devDependencies": { "devDependencies": {
"@types/set-cookie-parser": "^2.4.3", "@types/set-cookie-parser": "^2.4.3",

View file

@ -1 +1 @@
/// <reference types="astro/client-image" /> /// <reference types="astro/client" />

View file

@ -56,7 +56,7 @@
"vue": "^3.3.4" "vue": "^3.3.4"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.2.3", "astro": "workspace:^3.2.4",
"vue": "^3.2.30" "vue": "^3.2.30"
}, },
"engines": { "engines": {

View file

@ -1,5 +1,5 @@
import type { VFileData as Data, VFile } from 'vfile'; import type { VFileData as Data, VFile } from 'vfile';
import type { MarkdownAstroData } from './types.js'; import type { MarkdownAstroData, MarkdownProcessorRenderOptions } from './types.js';
function isValidAstroData(obj: unknown): obj is MarkdownAstroData { function isValidAstroData(obj: unknown): obj is MarkdownAstroData {
if (typeof obj === 'object' && obj !== null && obj.hasOwnProperty('frontmatter')) { if (typeof obj === 'object' && obj !== null && obj.hasOwnProperty('frontmatter')) {
@ -27,10 +27,15 @@ export function safelyGetAstroData(vfileData: Data): MarkdownAstroData | Invalid
return astro; return astro;
} }
export function setVfileFrontmatter(vfile: VFile, frontmatter: Record<string, any>) { export function setVfileFrontmatter(
vfile: VFile,
frontmatter: Record<string, any>,
renderOpts: MarkdownProcessorRenderOptions | undefined
) {
vfile.data ??= {}; vfile.data ??= {};
vfile.data.astro ??= {}; vfile.data.astro ??= {};
(vfile.data.astro as any).frontmatter = frontmatter; (vfile.data.astro as any).frontmatter = frontmatter;
(vfile.data.astro as any).fileURL = renderOpts?.fileURL;
} }
/** /**

View file

@ -124,8 +124,9 @@ export async function createMarkdownProcessor(
return { return {
async render(content, renderOpts) { async render(content, renderOpts) {
console.log('url', renderOpts?.fileURL);
const vfile = new VFile({ value: content, path: renderOpts?.fileURL }); const vfile = new VFile({ value: content, path: renderOpts?.fileURL });
setVfileFrontmatter(vfile, renderOpts?.frontmatter ?? {}); setVfileFrontmatter(vfile, renderOpts?.frontmatter ?? {}, renderOpts);
const result: MarkdownVFile = await parser.process(vfile).catch((err) => { const result: MarkdownVFile = await parser.process(vfile).catch((err) => {
// Ensure that the error message contains the input filename // Ensure that the error message contains the input filename

View file

@ -125,7 +125,7 @@ importers:
examples/basics: examples/basics:
dependencies: dependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/blog: examples/blog:
@ -140,13 +140,13 @@ importers:
specifier: ^3.0.1 specifier: ^3.0.1
version: link:../../packages/integrations/sitemap version: link:../../packages/integrations/sitemap
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/component: examples/component:
devDependencies: devDependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/framework-alpine: examples/framework-alpine:
@ -161,7 +161,7 @@ importers:
specifier: ^3.12.3 specifier: ^3.12.3
version: 3.12.3 version: 3.12.3
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/framework-lit: examples/framework-lit:
@ -173,7 +173,7 @@ importers:
specifier: ^0.2.1 specifier: ^0.2.1
version: 0.2.1 version: 0.2.1
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
lit: lit:
specifier: ^2.8.0 specifier: ^2.8.0
@ -197,7 +197,7 @@ importers:
specifier: ^3.0.1 specifier: ^3.0.1
version: link:../../packages/integrations/vue version: link:../../packages/integrations/vue
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
preact: preact:
specifier: ^10.17.1 specifier: ^10.17.1
@ -227,7 +227,7 @@ importers:
specifier: ^1.2.1 specifier: ^1.2.1
version: 1.2.1(preact@10.17.1) version: 1.2.1(preact@10.17.1)
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
preact: preact:
specifier: ^10.17.1 specifier: ^10.17.1
@ -245,7 +245,7 @@ importers:
specifier: ^18.2.7 specifier: ^18.2.7
version: 18.2.7 version: 18.2.7
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
react: react:
specifier: ^18.2.0 specifier: ^18.2.0
@ -260,7 +260,7 @@ importers:
specifier: ^3.0.2 specifier: ^3.0.2
version: link:../../packages/integrations/solid version: link:../../packages/integrations/solid
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
solid-js: solid-js:
specifier: ^1.7.11 specifier: ^1.7.11
@ -272,7 +272,7 @@ importers:
specifier: ^4.0.3 specifier: ^4.0.3
version: link:../../packages/integrations/svelte version: link:../../packages/integrations/svelte
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
svelte: svelte:
specifier: ^4.2.0 specifier: ^4.2.0
@ -284,7 +284,7 @@ importers:
specifier: ^3.0.1 specifier: ^3.0.1
version: link:../../packages/integrations/vue version: link:../../packages/integrations/vue
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
vue: vue:
specifier: ^3.3.4 specifier: ^3.3.4
@ -296,13 +296,13 @@ importers:
specifier: ^6.0.3 specifier: ^6.0.3
version: link:../../packages/integrations/node version: link:../../packages/integrations/node
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/integration: examples/integration:
devDependencies: devDependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/middleware: examples/middleware:
@ -311,7 +311,7 @@ importers:
specifier: ^6.0.3 specifier: ^6.0.3
version: link:../../packages/integrations/node version: link:../../packages/integrations/node
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
html-minifier: html-minifier:
specifier: ^4.0.0 specifier: ^4.0.0
@ -320,19 +320,19 @@ importers:
examples/minimal: examples/minimal:
dependencies: dependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/non-html-pages: examples/non-html-pages:
dependencies: dependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/portfolio: examples/portfolio:
dependencies: dependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/ssr: examples/ssr:
@ -344,7 +344,7 @@ importers:
specifier: ^4.0.3 specifier: ^4.0.3
version: link:../../packages/integrations/svelte version: link:../../packages/integrations/svelte
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
svelte: svelte:
specifier: ^4.2.0 specifier: ^4.2.0
@ -356,10 +356,10 @@ importers:
specifier: ^6.0.3 specifier: ^6.0.3
version: link:../../packages/integrations/node version: link:../../packages/integrations/node
'@astrojs/tailwind': '@astrojs/tailwind':
specifier: ^5.0.1 specifier: ^5.0.2
version: link:../../packages/integrations/tailwind version: link:../../packages/integrations/tailwind
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/with-markdoc: examples/with-markdoc:
@ -368,7 +368,7 @@ importers:
specifier: ^0.5.2 specifier: ^0.5.2
version: link:../../packages/integrations/markdoc version: link:../../packages/integrations/markdoc
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/with-markdown-plugins: examples/with-markdown-plugins:
@ -377,7 +377,7 @@ importers:
specifier: ^3.2.1 specifier: ^3.2.1
version: link:../../packages/markdown/remark version: link:../../packages/markdown/remark
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
hast-util-select: hast-util-select:
specifier: ^5.0.5 specifier: ^5.0.5
@ -398,7 +398,7 @@ importers:
examples/with-markdown-shiki: examples/with-markdown-shiki:
dependencies: dependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
examples/with-mdx: examples/with-mdx:
@ -410,7 +410,7 @@ importers:
specifier: ^3.0.1 specifier: ^3.0.1
version: link:../../packages/integrations/preact version: link:../../packages/integrations/preact
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
preact: preact:
specifier: ^10.17.1 specifier: ^10.17.1
@ -425,7 +425,7 @@ importers:
specifier: ^0.5.0 specifier: ^0.5.0
version: 0.5.0(nanostores@0.9.3)(preact@10.17.1) version: 0.5.0(nanostores@0.9.3)(preact@10.17.1)
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
nanostores: nanostores:
specifier: ^0.9.3 specifier: ^0.9.3
@ -440,13 +440,13 @@ importers:
specifier: ^1.1.1 specifier: ^1.1.1
version: link:../../packages/integrations/mdx version: link:../../packages/integrations/mdx
'@astrojs/tailwind': '@astrojs/tailwind':
specifier: ^5.0.1 specifier: ^5.0.2
version: link:../../packages/integrations/tailwind version: link:../../packages/integrations/tailwind
'@types/canvas-confetti': '@types/canvas-confetti':
specifier: ^1.6.0 specifier: ^1.6.0
version: 1.6.0 version: 1.6.0
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
autoprefixer: autoprefixer:
specifier: ^10.4.15 specifier: ^10.4.15
@ -464,7 +464,7 @@ importers:
examples/with-vite-plugin-pwa: examples/with-vite-plugin-pwa:
dependencies: dependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
vite-plugin-pwa: vite-plugin-pwa:
specifier: 0.16.4 specifier: 0.16.4
@ -476,7 +476,7 @@ importers:
examples/with-vitest: examples/with-vitest:
dependencies: dependencies:
astro: astro:
specifier: ^3.2.3 specifier: ^3.2.4
version: link:../../packages/astro version: link:../../packages/astro
vitest: vitest:
specifier: ^0.34.2 specifier: ^0.34.2
@ -3531,9 +3531,18 @@ importers:
packages/astro/test/fixtures/view-transitions: packages/astro/test/fixtures/view-transitions:
dependencies: dependencies:
'@astrojs/react':
specifier: workspace:*
version: link:../../../../integrations/react
astro: astro:
specifier: workspace:* specifier: workspace:*
version: link:../../.. version: link:../../..
react:
specifier: ^18.1.0
version: 18.2.0
react-dom:
specifier: ^18.1.0
version: 18.2.0(react@18.2.0)
packages/astro/test/fixtures/virtual-astro-file: packages/astro/test/fixtures/virtual-astro-file:
dependencies: dependencies: