mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
Merge branch 'main' into main
This commit is contained in:
commit
35e8572b63
@ -1,4 +1,4 @@
|
|||||||
FROM node:lts@sha256:fffa89e023a3351904c04284029105d9e2ac7020886d683775a298569591e5bb
|
FROM node:lts@sha256:a5e0ed56f2c20b9689e0f7dd498cac7e08d2a3a283e92d9304e7b9b83e3c6ff3
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -fy libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdbus-1-3 libdrm2 libxkbcommon0 libatspi2.0-0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 && \
|
apt-get install -fy libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdbus-1-3 libdrm2 libxkbcommon0 libatspi2.0-0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 && \
|
||||||
|
4
.github/workflows/autofix-docs.yml
vendored
4
.github/workflows/autofix-docs.yml
vendored
@ -17,9 +17,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
4
.github/workflows/autofix.yml
vendored
4
.github/workflows/autofix.yml
vendored
@ -13,9 +13,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
6
.github/workflows/benchmark.yml
vendored
6
.github/workflows/benchmark.yml
vendored
@ -29,9 +29,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -46,7 +46,7 @@ jobs:
|
|||||||
run: pnpm build
|
run: pnpm build
|
||||||
|
|
||||||
- name: Run benchmarks
|
- name: Run benchmarks
|
||||||
uses: CodSpeedHQ/action@ab07afd34cbbb7a1306e8d14b7cc44e029eee37a # v3.0.0
|
uses: CodSpeedHQ/action@b587655f756aab640e742fec141261bc6f0a569d # v3.0.1
|
||||||
with:
|
with:
|
||||||
run: pnpm vitest bench
|
run: pnpm vitest bench
|
||||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||||
|
4
.github/workflows/changelog.yml
vendored
4
.github/workflows/changelog.yml
vendored
@ -22,11 +22,11 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
34
.github/workflows/ci.yml
vendored
34
.github/workflows/ci.yml
vendored
@ -37,9 +37,9 @@ jobs:
|
|||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -72,10 +72,10 @@ jobs:
|
|||||||
security-events: write
|
security-events: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
uses: github/codeql-action/init@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
||||||
with:
|
with:
|
||||||
config: |
|
config: |
|
||||||
paths:
|
paths:
|
||||||
@ -91,7 +91,7 @@ jobs:
|
|||||||
queries: +security-and-quality
|
queries: +security-and-quality
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
uses: github/codeql-action/analyze@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
||||||
with:
|
with:
|
||||||
category: "/language:javascript-typescript"
|
category: "/language:javascript-typescript"
|
||||||
|
|
||||||
@ -107,9 +107,9 @@ jobs:
|
|||||||
module: ["bundler", "node"]
|
module: ["bundler", "node"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -138,9 +138,9 @@ jobs:
|
|||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -162,9 +162,9 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- build
|
- build
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -219,9 +219,9 @@ jobs:
|
|||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -271,11 +271,11 @@ jobs:
|
|||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -312,11 +312,11 @@ jobs:
|
|||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
4
.github/workflows/dependency-review.yml
vendored
4
.github/workflows/dependency-review.yml
vendored
@ -17,6 +17,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout Repository'
|
- name: 'Checkout Repository'
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- name: 'Dependency Review'
|
- name: 'Dependency Review'
|
||||||
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
|
uses: actions/dependency-review-action@a6993e2c61fd5dc440b409aa1d6904921c5e1894 # v4.3.5
|
||||||
|
6
.github/workflows/docs-check-links.yml
vendored
6
.github/workflows/docs-check-links.yml
vendored
@ -19,17 +19,17 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# Cache lychee results (e.g. to avoid hitting rate limits)
|
# Cache lychee results (e.g. to avoid hitting rate limits)
|
||||||
- name: Restore lychee cache
|
- name: Restore lychee cache
|
||||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
|
||||||
with:
|
with:
|
||||||
path: .lycheecache
|
path: .lycheecache
|
||||||
key: cache-lychee-${{ github.sha }}
|
key: cache-lychee-${{ github.sha }}
|
||||||
restore-keys: cache-lychee-
|
restore-keys: cache-lychee-
|
||||||
|
|
||||||
# check links with Lychee
|
# check links with Lychee
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Lychee link checker
|
- name: Lychee link checker
|
||||||
uses: lycheeverse/lychee-action@7cd0af4c74a61395d455af97419279d86aafaede # for v1.8.0
|
uses: lycheeverse/lychee-action@ae4699150ab670dcfb64cc74e8680e776d9caae2 # for v1.8.0
|
||||||
with:
|
with:
|
||||||
# arguments with file types to check
|
# arguments with file types to check
|
||||||
args: >-
|
args: >-
|
||||||
|
4
.github/workflows/docs.yml
vendored
4
.github/workflows/docs.yml
vendored
@ -21,9 +21,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
4
.github/workflows/lint-sherif.yml
vendored
4
.github/workflows/lint-sherif.yml
vendored
@ -23,9 +23,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/lint-workflows.yml
vendored
2
.github/workflows/lint-workflows.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
# From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions
|
# From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions
|
||||||
- name: Check workflow files
|
- name: Check workflow files
|
||||||
uses: docker://rhysd/actionlint:1.7.3@sha256:7617f05bd698cd2f1c3aedc05bc733ccec92cca0738f3e8722c32c5b42c70ae6
|
uses: docker://rhysd/actionlint:1.7.3@sha256:7617f05bd698cd2f1c3aedc05bc733ccec92cca0738f3e8722c32c5b42c70ae6
|
||||||
|
4
.github/workflows/release-pr.yml
vendored
4
.github/workflows/release-pr.yml
vendored
@ -48,13 +48,13 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT"
|
echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT"
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ steps.pr.outputs.head_sha }}
|
ref: ${{ steps.pr.outputs.head_sha }}
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -19,11 +19,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
registry-url: "https://registry.npmjs.org/"
|
registry-url: "https://registry.npmjs.org/"
|
||||||
|
2
.github/workflows/reproduire.yml
vendored
2
.github/workflows/reproduire.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
reproduire:
|
reproduire:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp
|
- uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp
|
||||||
with:
|
with:
|
||||||
label: needs reproduction
|
label: needs reproduction
|
||||||
|
4
.github/workflows/scorecards.yml
vendored
4
.github/workflows/scorecards.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout code"
|
- name: "Checkout code"
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ jobs:
|
|||||||
|
|
||||||
# Upload the results to GitHub's code scanning dashboard.
|
# Upload the results to GitHub's code scanning dashboard.
|
||||||
- name: "Upload to code-scanning"
|
- name: "Upload to code-scanning"
|
||||||
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
|
||||||
if: github.repository == 'nuxt/nuxt' && success()
|
if: github.repository == 'nuxt/nuxt' && success()
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
2
.github/workflows/stackblitz-link.yml
vendored
2
.github/workflows/stackblitz-link.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
stackblitz:
|
stackblitz:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- uses: huang-julien/reproduire-sur-stackblitz@9ceccbfbb0f2f9a9a8db2d1f0dd909cf5cfe67aa # v1.0.2
|
- uses: huang-julien/reproduire-sur-stackblitz@9ceccbfbb0f2f9a9a8db2d1f0dd909cf5cfe67aa # v1.0.2
|
||||||
with:
|
with:
|
||||||
reproduction-heading: '### Reproduction'
|
reproduction-heading: '### Reproduction'
|
||||||
|
@ -289,7 +289,7 @@ import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|||||||
|
|
||||||
const { useStorageMock } = vi.hoisted(() => {
|
const { useStorageMock } = vi.hoisted(() => {
|
||||||
return {
|
return {
|
||||||
useStorageMock: vi.fn().mockImplementation(() => {
|
useStorageMock: vi.fn(() => {
|
||||||
return { value: 'mocked storage'}
|
return { value: 'mocked storage'}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ export default defineNuxtConfig({
|
|||||||
// app: 'app'
|
// app: 'app'
|
||||||
// },
|
// },
|
||||||
// experimental: {
|
// experimental: {
|
||||||
|
// scanPageMeta: 'after-resolve',
|
||||||
// sharedPrerenderData: false,
|
// sharedPrerenderData: false,
|
||||||
// compileTemplate: true,
|
// compileTemplate: true,
|
||||||
// resetAsyncDataToUndefined: true,
|
// resetAsyncDataToUndefined: true,
|
||||||
@ -236,6 +237,45 @@ export default defineNuxtConfig({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Scan Page Meta After Resolution
|
||||||
|
|
||||||
|
🚦 **Impact Level**: Minimal
|
||||||
|
|
||||||
|
##### What Changed
|
||||||
|
|
||||||
|
We now scan page metadata (defined in `definePageMeta`) _after_ calling the `pages:extend` hook rather than before.
|
||||||
|
|
||||||
|
##### Reasons for Change
|
||||||
|
|
||||||
|
This was to allow scanning metadata for pages that users wanted to add in `pages:extend`. We still offer an opportunity to change or override page metadata in a new `pages:resolved` hook.
|
||||||
|
|
||||||
|
##### Migration Steps
|
||||||
|
|
||||||
|
If you want to override page metadata, do that in `pages:resolved` rather than in `pages:extend`.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
hooks: {
|
||||||
|
- 'pages:extend'(pages) {
|
||||||
|
+ 'pages:resolved'(pages) {
|
||||||
|
const myPage = pages.find(page => page.path === '/')
|
||||||
|
myPage.meta ||= {}
|
||||||
|
myPage.meta.layout = 'overridden-layout'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can revert to the previous behaviour with:
|
||||||
|
|
||||||
|
```ts twoslash [nuxt.config.ts]
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
experimental: {
|
||||||
|
scanPageMeta: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
#### Shared Prerender Data
|
#### Shared Prerender Data
|
||||||
|
|
||||||
🚦 **Impact Level**: Medium
|
🚦 **Impact Level**: Medium
|
||||||
|
@ -334,6 +334,8 @@ This option allows exposing some route metadata defined in `definePageMeta` at b
|
|||||||
|
|
||||||
This only works with static or strings/arrays rather than variables or conditional assignment. See [original issue](https://github.com/nuxt/nuxt/issues/24770) for more information and context.
|
This only works with static or strings/arrays rather than variables or conditional assignment. See [original issue](https://github.com/nuxt/nuxt/issues/24770) for more information and context.
|
||||||
|
|
||||||
|
It is also possible to scan page metadata only after all routes have been registered in `pages:extend`. Then another hook, `pages:resolved` will be called. To enable this behavior, set `scanPageMeta: 'after-resolve'`.
|
||||||
|
|
||||||
You can disable this feature if it causes issues in your project.
|
You can disable this feature if it causes issues in your project.
|
||||||
|
|
||||||
```ts twoslash [nuxt.config.ts]
|
```ts twoslash [nuxt.config.ts]
|
||||||
|
@ -61,6 +61,7 @@ export default defineNuxtConfig({
|
|||||||
app: 'app'
|
app: 'app'
|
||||||
},
|
},
|
||||||
experimental: {
|
experimental: {
|
||||||
|
scanPageMeta: 'after-resolve',
|
||||||
sharedPrerenderData: false,
|
sharedPrerenderData: false,
|
||||||
compileTemplate: true,
|
compileTemplate: true,
|
||||||
resetAsyncDataToUndefined: true,
|
resetAsyncDataToUndefined: true,
|
||||||
|
@ -30,6 +30,7 @@ interface PageMeta {
|
|||||||
redirect?: RouteRecordRedirectOption
|
redirect?: RouteRecordRedirectOption
|
||||||
name?: string
|
name?: string
|
||||||
path?: string
|
path?: string
|
||||||
|
props?: RouteRecordRaw['props']
|
||||||
alias?: string | string[]
|
alias?: string | string[]
|
||||||
pageTransition?: boolean | TransitionProps
|
pageTransition?: boolean | TransitionProps
|
||||||
layoutTransition?: boolean | TransitionProps
|
layoutTransition?: boolean | TransitionProps
|
||||||
@ -63,6 +64,12 @@ interface PageMeta {
|
|||||||
|
|
||||||
You may define a [custom regular expression](#using-a-custom-regular-expression) if you have a more complex pattern than can be expressed with the file name.
|
You may define a [custom regular expression](#using-a-custom-regular-expression) if you have a more complex pattern than can be expressed with the file name.
|
||||||
|
|
||||||
|
**`props`**
|
||||||
|
|
||||||
|
- **Type**: [`RouteRecordRaw['props']`](https://router.vuejs.org/guide/essentials/passing-props)
|
||||||
|
|
||||||
|
Allows accessing the route `params` as props passed to the page component.
|
||||||
|
|
||||||
**`alias`**
|
**`alias`**
|
||||||
|
|
||||||
- **Type**: `string | string[]`
|
- **Type**: `string | string[]`
|
||||||
|
@ -125,6 +125,19 @@ Make sure to always use `await` or `return` on result of `navigateTo` when calli
|
|||||||
|
|
||||||
`to` can be a plain string or a route object to redirect to. When passed as `undefined` or `null`, it will default to `'/'`.
|
`to` can be a plain string or a route object to redirect to. When passed as `undefined` or `null`, it will default to `'/'`.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Passing the URL directly will redirect to the '/blog' page
|
||||||
|
await navigateTo('/blog')
|
||||||
|
|
||||||
|
// Using the route object, will redirect to the route with the name 'blog'
|
||||||
|
await navigateTo({ name: 'blog' })
|
||||||
|
|
||||||
|
// Redirects to the 'product' route while passing a parameter (id = 1) using the route object.
|
||||||
|
await navigateTo({ name: 'product', params: { id: 1 } })
|
||||||
|
```
|
||||||
|
|
||||||
### `options` (optional)
|
### `options` (optional)
|
||||||
|
|
||||||
**Type**: `NavigateToOptions`
|
**Type**: `NavigateToOptions`
|
||||||
|
@ -52,7 +52,8 @@ Hook | Arguments | Description
|
|||||||
`build:manifest` | `manifest` | Called during the manifest build by Vite and webpack. This allows customizing the manifest that Nitro will use to render `<script>` and `<link>` tags in the final HTML.
|
`build:manifest` | `manifest` | Called during the manifest build by Vite and webpack. This allows customizing the manifest that Nitro will use to render `<script>` and `<link>` tags in the final HTML.
|
||||||
`builder:generateApp` | `options` | Called before generating the app.
|
`builder:generateApp` | `options` | Called before generating the app.
|
||||||
`builder:watch` | `event, path` | Called at build time in development when the watcher spots a change to a file or directory in the project.
|
`builder:watch` | `event, path` | Called at build time in development when the watcher spots a change to a file or directory in the project.
|
||||||
`pages:extend` | `pages` | Called after pages routes are resolved.
|
`pages:extend` | `pages` | Called after page routes are scanned from the file system.
|
||||||
|
`pages:resolved` | `pages` | Called after page routes have been augmented with scanned metadata.
|
||||||
`pages:routerOptions` | `{ files: Array<{ path: string, optional?: boolean }> }` | Called when resolving `router.options` files. Later items in the array override earlier ones.
|
`pages:routerOptions` | `{ files: Array<{ path: string, optional?: boolean }> }` | Called when resolving `router.options` files. Later items in the array override earlier ones.
|
||||||
`server:devHandler` | `handler` | Called when the dev middleware is being registered on the Nitro dev server.
|
`server:devHandler` | `handler` | Called when the dev middleware is being registered on the Nitro dev server.
|
||||||
`imports:sources` | `presets` | Called at setup allowing modules to extend sources.
|
`imports:sources` | `presets` | Called at setup allowing modules to extend sources.
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
import { addPluginTemplate, addRouteMiddleware } from 'nuxt/kit'
|
import { addPluginTemplate, addRouteMiddleware } from 'nuxt/kit'
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
typescript: { shim: process.env.DOCS_TYPECHECK === 'true' },
|
|
||||||
pages: process.env.DOCS_TYPECHECK === 'true',
|
|
||||||
modules: [
|
modules: [
|
||||||
function () {
|
function () {
|
||||||
if (!process.env.DOCS_TYPECHECK) { return }
|
if (!process.env.DOCS_TYPECHECK) { return }
|
||||||
@ -18,4 +16,6 @@ export default defineNuxtConfig({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
pages: process.env.DOCS_TYPECHECK === 'true',
|
||||||
|
typescript: { shim: process.env.DOCS_TYPECHECK === 'true' },
|
||||||
})
|
})
|
||||||
|
40
package.json
40
package.json
@ -40,7 +40,7 @@
|
|||||||
"@nuxt/ui-templates": "workspace:*",
|
"@nuxt/ui-templates": "workspace:*",
|
||||||
"@nuxt/vite-builder": "workspace:*",
|
"@nuxt/vite-builder": "workspace:*",
|
||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
"@types/node": "20.16.11",
|
"@types/node": "20.17.1",
|
||||||
"@vue/compiler-core": "3.5.12",
|
"@vue/compiler-core": "3.5.12",
|
||||||
"@vue/compiler-dom": "3.5.12",
|
"@vue/compiler-dom": "3.5.12",
|
||||||
"@vue/shared": "3.5.12",
|
"@vue/shared": "3.5.12",
|
||||||
@ -52,29 +52,29 @@
|
|||||||
"nuxt": "workspace:*",
|
"nuxt": "workspace:*",
|
||||||
"ohash": "1.1.4",
|
"ohash": "1.1.4",
|
||||||
"postcss": "8.4.47",
|
"postcss": "8.4.47",
|
||||||
"rollup": "4.24.0",
|
"rollup": "4.24.2",
|
||||||
"send": ">=1.1.0",
|
"send": ">=1.1.0",
|
||||||
"typescript": "5.6.3",
|
"typescript": "5.6.3",
|
||||||
"ufo": "1.5.4",
|
"ufo": "1.5.4",
|
||||||
"unbuild": "3.0.0-rc.11",
|
"unbuild": "3.0.0-rc.11",
|
||||||
"vite": "5.4.8",
|
"vite": "5.4.10",
|
||||||
"vue": "3.5.12"
|
"vue": "3.5.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "9.12.0",
|
"@eslint/js": "9.13.0",
|
||||||
"@nuxt/eslint-config": "0.5.7",
|
"@nuxt/eslint-config": "0.6.0",
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
"@nuxt/rspack-builder": "workspace:*",
|
"@nuxt/rspack-builder": "workspace:*",
|
||||||
"@nuxt/test-utils": "3.14.3",
|
"@nuxt/test-utils": "3.14.4",
|
||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/eslint__js": "8.42.3",
|
"@types/eslint__js": "8.42.3",
|
||||||
"@types/node": "20.16.11",
|
"@types/node": "20.17.1",
|
||||||
"@types/semver": "7.5.8",
|
"@types/semver": "7.5.8",
|
||||||
"@unhead/schema": "1.11.7",
|
"@unhead/schema": "1.11.10",
|
||||||
"@unhead/vue": "1.11.7",
|
"@unhead/vue": "1.11.10",
|
||||||
"@vitejs/plugin-vue": "5.1.4",
|
"@vitejs/plugin-vue": "5.1.4",
|
||||||
"@vitest/coverage-v8": "2.1.2",
|
"@vitest/coverage-v8": "2.1.3",
|
||||||
"@vue/test-utils": "2.4.6",
|
"@vue/test-utils": "2.4.6",
|
||||||
"autoprefixer": "10.4.20",
|
"autoprefixer": "10.4.20",
|
||||||
"case-police": "0.7.0",
|
"case-police": "0.7.0",
|
||||||
@ -83,36 +83,36 @@
|
|||||||
"cssnano": "7.0.6",
|
"cssnano": "7.0.6",
|
||||||
"destr": "2.0.3",
|
"destr": "2.0.3",
|
||||||
"devalue": "5.1.1",
|
"devalue": "5.1.1",
|
||||||
"eslint": "9.12.0",
|
"eslint": "9.13.0",
|
||||||
"eslint-plugin-no-only-tests": "3.3.0",
|
"eslint-plugin-no-only-tests": "3.3.0",
|
||||||
"eslint-plugin-perfectionist": "3.8.0",
|
"eslint-plugin-perfectionist": "3.9.1",
|
||||||
"eslint-typegen": "0.3.2",
|
"eslint-typegen": "0.3.2",
|
||||||
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
||||||
"happy-dom": "15.7.4",
|
"happy-dom": "15.7.4",
|
||||||
"jiti": "2.3.3",
|
"jiti": "2.3.3",
|
||||||
"markdownlint-cli": "0.42.0",
|
"markdownlint-cli": "0.42.0",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"nuxi": "3.14.0",
|
"nuxi": "3.15.0",
|
||||||
"nuxt": "workspace:*",
|
"nuxt": "workspace:*",
|
||||||
"nuxt-content-twoslash": "0.1.1",
|
"nuxt-content-twoslash": "0.1.1",
|
||||||
"ofetch": "1.4.1",
|
"ofetch": "1.4.1",
|
||||||
"pathe": "1.1.2",
|
"pathe": "1.1.2",
|
||||||
"playwright-core": "1.48.0",
|
"playwright-core": "1.48.2",
|
||||||
"rimraf": "6.0.1",
|
"rimraf": "6.0.1",
|
||||||
"semver": "7.6.3",
|
"semver": "7.6.3",
|
||||||
"sherif": "1.0.0",
|
"sherif": "1.0.1",
|
||||||
"std-env": "3.7.0",
|
"std-env": "3.7.0",
|
||||||
"tinyexec": "0.3.0",
|
"tinyexec": "0.3.1",
|
||||||
"tinyglobby": "0.2.9",
|
"tinyglobby": "0.2.10",
|
||||||
"typescript": "5.6.3",
|
"typescript": "5.6.3",
|
||||||
"ufo": "1.5.4",
|
"ufo": "1.5.4",
|
||||||
"vitest": "2.1.2",
|
"vitest": "2.1.3",
|
||||||
"vitest-environment-nuxt": "1.0.1",
|
"vitest-environment-nuxt": "1.0.1",
|
||||||
"vue": "3.5.12",
|
"vue": "3.5.12",
|
||||||
"vue-router": "4.4.5",
|
"vue-router": "4.4.5",
|
||||||
"vue-tsc": "2.1.6"
|
"vue-tsc": "2.1.8"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.12.1",
|
"packageManager": "pnpm@9.12.2",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^16.10.0 || >=18.0.0"
|
"node": "^16.10.0 || >=18.0.0"
|
||||||
},
|
},
|
||||||
|
@ -48,13 +48,13 @@
|
|||||||
"untyped": "^1.5.1"
|
"untyped": "^1.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rspack/core": "1.0.10",
|
"@rspack/core": "1.0.14",
|
||||||
"@types/hash-sum": "1.0.2",
|
"@types/hash-sum": "1.0.2",
|
||||||
"@types/semver": "7.5.8",
|
"@types/semver": "7.5.8",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"unbuild": "3.0.0-rc.11",
|
"unbuild": "3.0.0-rc.11",
|
||||||
"vite": "5.4.8",
|
"vite": "5.4.10",
|
||||||
"vitest": "2.1.2",
|
"vitest": "2.1.3",
|
||||||
"webpack": "5.95.0"
|
"webpack": "5.95.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3,8 +3,9 @@ import { readPackageJSON } from 'pkg-types'
|
|||||||
import type { Nuxt, NuxtCompatibility, NuxtCompatibilityIssues } from '@nuxt/schema'
|
import type { Nuxt, NuxtCompatibility, NuxtCompatibilityIssues } from '@nuxt/schema'
|
||||||
import { useNuxt } from './context'
|
import { useNuxt } from './context'
|
||||||
|
|
||||||
|
const SEMANTIC_VERSION_RE = /-\d+\.[0-9a-f]+/
|
||||||
export function normalizeSemanticVersion (version: string) {
|
export function normalizeSemanticVersion (version: string) {
|
||||||
return version.replace(/-\d+\.[0-9a-f]+/, '') // Remove edge prefix
|
return version.replace(SEMANTIC_VERSION_RE, '') // Remove edge prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
const builderMap = {
|
const builderMap = {
|
||||||
@ -104,6 +105,7 @@ export function isNuxt3 (nuxt: Nuxt = useNuxt()) {
|
|||||||
return isNuxtMajorVersion(3, nuxt)
|
return isNuxtMajorVersion(3, nuxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NUXT_VERSION_RE = /^v/g
|
||||||
/**
|
/**
|
||||||
* Get nuxt version
|
* Get nuxt version
|
||||||
*/
|
*/
|
||||||
@ -112,5 +114,5 @@ export function getNuxtVersion (nuxt: Nuxt | any = useNuxt() /* TODO: LegacyNuxt
|
|||||||
if (typeof rawVersion !== 'string') {
|
if (typeof rawVersion !== 'string') {
|
||||||
throw new TypeError('Cannot determine nuxt version! Is current instance passed?')
|
throw new TypeError('Cannot determine nuxt version! Is current instance passed?')
|
||||||
}
|
}
|
||||||
return rawVersion.replace(/^v/g, '')
|
return rawVersion.replace(NUXT_VERSION_RE, '')
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import type { Component, ComponentsDir } from '@nuxt/schema'
|
|||||||
import { useNuxt } from './context'
|
import { useNuxt } from './context'
|
||||||
import { assertNuxtCompatibility } from './compatibility'
|
import { assertNuxtCompatibility } from './compatibility'
|
||||||
import { logger } from './logger'
|
import { logger } from './logger'
|
||||||
|
import { MODE_RE } from './utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a directory to be scanned for components and imported only when used.
|
* Register a directory to be scanned for components and imported only when used.
|
||||||
@ -28,7 +29,7 @@ export async function addComponent (opts: AddComponentOptions) {
|
|||||||
nuxt.options.components = nuxt.options.components || []
|
nuxt.options.components = nuxt.options.components || []
|
||||||
|
|
||||||
if (!opts.mode) {
|
if (!opts.mode) {
|
||||||
const [, mode = 'all'] = opts.filePath.match(/\.(server|client)(\.\w+)*$/) || []
|
const [, mode = 'all'] = opts.filePath.match(MODE_RE) || []
|
||||||
opts.mode = mode as 'all' | 'client' | 'server'
|
opts.mode = mode as 'all' | 'client' | 'server'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,11 @@ import { useNuxt } from './context'
|
|||||||
import { logger } from './logger'
|
import { logger } from './logger'
|
||||||
import { addTemplate } from './template'
|
import { addTemplate } from './template'
|
||||||
|
|
||||||
|
const LAYOUT_RE = /["']/g
|
||||||
export function addLayout (template: NuxtTemplate | string, name?: string) {
|
export function addLayout (template: NuxtTemplate | string, name?: string) {
|
||||||
const nuxt = useNuxt()
|
const nuxt = useNuxt()
|
||||||
const { filename, src } = addTemplate(template)
|
const { filename, src } = addTemplate(template)
|
||||||
const layoutName = kebabCase(name || parse(filename).name).replace(/["']/g, '')
|
const layoutName = kebabCase(name || parse(filename).name).replace(LAYOUT_RE, '')
|
||||||
|
|
||||||
// Nuxt 3 adds layouts on app
|
// Nuxt 3 adds layouts on app
|
||||||
nuxt.hook('app:templates', (app) => {
|
nuxt.hook('app:templates', (app) => {
|
||||||
|
@ -4,13 +4,14 @@ import { normalize } from 'pathe'
|
|||||||
import { useNuxt } from './context'
|
import { useNuxt } from './context'
|
||||||
import { toArray } from './utils'
|
import { toArray } from './utils'
|
||||||
|
|
||||||
|
const HANDLER_METHOD_RE = /\.(get|head|patch|post|put|delete|connect|options|trace)(\.\w+)*$/
|
||||||
/**
|
/**
|
||||||
* normalize handler object
|
* normalize handler object
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function normalizeHandlerMethod (handler: NitroEventHandler) {
|
function normalizeHandlerMethod (handler: NitroEventHandler) {
|
||||||
// retrieve method from handler file name
|
// retrieve method from handler file name
|
||||||
const [, method = undefined] = handler.handler.match(/\.(get|head|patch|post|put|delete|connect|options|trace)(\.\w+)*$/) || []
|
const [, method = undefined] = handler.handler.match(HANDLER_METHOD_RE) || []
|
||||||
return {
|
return {
|
||||||
method: method as 'get' | 'head' | 'patch' | 'post' | 'put' | 'delete' | 'connect' | 'options' | 'trace' | undefined,
|
method: method as 'get' | 'head' | 'patch' | 'post' | 'put' | 'delete' | 'connect' | 'options' | 'trace' | undefined,
|
||||||
...handler,
|
...handler,
|
||||||
|
@ -3,6 +3,7 @@ import type { NuxtPlugin, NuxtPluginTemplate } from '@nuxt/schema'
|
|||||||
import { useNuxt } from './context'
|
import { useNuxt } from './context'
|
||||||
import { addTemplate } from './template'
|
import { addTemplate } from './template'
|
||||||
import { resolveAlias } from './resolve'
|
import { resolveAlias } from './resolve'
|
||||||
|
import { MODE_RE } from './utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize a nuxt plugin object
|
* Normalize a nuxt plugin object
|
||||||
@ -27,7 +28,7 @@ export function normalizePlugin (plugin: NuxtPlugin | string): NuxtPlugin {
|
|||||||
plugin.mode = 'server'
|
plugin.mode = 'server'
|
||||||
}
|
}
|
||||||
if (!plugin.mode) {
|
if (!plugin.mode) {
|
||||||
const [, mode = 'all'] = plugin.src.match(/\.(server|client)(\.\w+)*$/) || []
|
const [, mode = 'all'] = plugin.src.match(MODE_RE) || []
|
||||||
plugin.mode = mode as 'all' | 'client' | 'server'
|
plugin.mode = mode as 'all' | 'client' | 'server'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +123,9 @@ export async function updateTemplates (options?: { filter?: (template: ResolvedN
|
|||||||
return await tryUseNuxt()?.hooks.callHook('builder:generateApp', options)
|
return await tryUseNuxt()?.hooks.callHook('builder:generateApp', options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const EXTENSION_RE = /\b\.\w+$/g
|
||||||
|
// Exclude bridge alias types to support Volar
|
||||||
|
const excludedAlias = [/^@vue\/.*$/, /^#internal\/nuxt/]
|
||||||
export async function _generateTypes (nuxt: Nuxt) {
|
export async function _generateTypes (nuxt: Nuxt) {
|
||||||
const rootDirWithSlash = withTrailingSlash(nuxt.options.rootDir)
|
const rootDirWithSlash = withTrailingSlash(nuxt.options.rootDir)
|
||||||
const relativeRootDir = relativeWithDot(nuxt.options.buildDir, nuxt.options.rootDir)
|
const relativeRootDir = relativeWithDot(nuxt.options.buildDir, nuxt.options.rootDir)
|
||||||
@ -225,9 +228,6 @@ export async function _generateTypes (nuxt: Nuxt) {
|
|||||||
|
|
||||||
const aliases: Record<string, string> = nuxt.options.alias
|
const aliases: Record<string, string> = nuxt.options.alias
|
||||||
|
|
||||||
// Exclude bridge alias types to support Volar
|
|
||||||
const excludedAlias = [/^@vue\/.*$/, /^#internal\/nuxt/]
|
|
||||||
|
|
||||||
const basePath = tsConfig.compilerOptions!.baseUrl
|
const basePath = tsConfig.compilerOptions!.baseUrl
|
||||||
? resolve(nuxt.options.buildDir, tsConfig.compilerOptions!.baseUrl)
|
? resolve(nuxt.options.buildDir, tsConfig.compilerOptions!.baseUrl)
|
||||||
: nuxt.options.buildDir
|
: nuxt.options.buildDir
|
||||||
@ -260,7 +260,7 @@ export async function _generateTypes (nuxt: Nuxt) {
|
|||||||
} else {
|
} else {
|
||||||
const path = stats?.isFile()
|
const path = stats?.isFile()
|
||||||
// remove extension
|
// remove extension
|
||||||
? relativePath.replace(/\b\.\w+$/g, '')
|
? relativePath.replace(EXTENSION_RE, '')
|
||||||
// non-existent file probably shouldn't be resolved
|
// non-existent file probably shouldn't be resolved
|
||||||
: aliases[alias]!
|
: aliases[alias]!
|
||||||
|
|
||||||
@ -289,7 +289,7 @@ export async function _generateTypes (nuxt: Nuxt) {
|
|||||||
tsConfig.compilerOptions!.paths[alias] = await Promise.all(paths.map(async (path: string) => {
|
tsConfig.compilerOptions!.paths[alias] = await Promise.all(paths.map(async (path: string) => {
|
||||||
if (!isAbsolute(path)) { return path }
|
if (!isAbsolute(path)) { return path }
|
||||||
const stats = await fsp.stat(path).catch(() => null /* file does not exist */)
|
const stats = await fsp.stat(path).catch(() => null /* file does not exist */)
|
||||||
return relativeWithDot(nuxt.options.buildDir, stats?.isFile() ? path.replace(/\b\.\w+$/g, '') /* remove extension */ : path)
|
return relativeWithDot(nuxt.options.buildDir, stats?.isFile() ? path.replace(EXTENSION_RE, '') /* remove extension */ : path)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +344,7 @@ function renderAttr (key: string, value?: string) {
|
|||||||
return value ? `${key}="${value}"` : ''
|
return value ? `${key}="${value}"` : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RELATIVE_WITH_DOT_RE = /^([^.])/
|
||||||
function relativeWithDot (from: string, to: string) {
|
function relativeWithDot (from: string, to: string) {
|
||||||
return relative(from, to).replace(/^([^.])/, './$1') || '.'
|
return relative(from, to).replace(RELATIVE_WITH_DOT_RE, './$1') || '.'
|
||||||
}
|
}
|
||||||
|
@ -2,3 +2,5 @@
|
|||||||
export function toArray<T> (value: T | T[]): T[] {
|
export function toArray<T> (value: T | T[]): T[] {
|
||||||
return Array.isArray(value) ? value : [value]
|
return Array.isArray(value) ? value : [value]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const MODE_RE = /\.(server|client)(\.\w+)*$/
|
||||||
|
@ -65,12 +65,12 @@
|
|||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"@nuxt/telemetry": "^2.6.0",
|
"@nuxt/telemetry": "^2.6.0",
|
||||||
"@nuxt/vite-builder": "workspace:*",
|
"@nuxt/vite-builder": "workspace:*",
|
||||||
"@unhead/dom": "^1.11.7",
|
"@unhead/dom": "^1.11.10",
|
||||||
"@unhead/shared": "^1.11.7",
|
"@unhead/shared": "^1.11.10",
|
||||||
"@unhead/ssr": "^1.11.7",
|
"@unhead/ssr": "^1.11.10",
|
||||||
"@unhead/vue": "^1.11.7",
|
"@unhead/vue": "^1.11.10",
|
||||||
"@vue/shared": "^3.5.12",
|
"@vue/shared": "^3.5.12",
|
||||||
"acorn": "8.12.1",
|
"acorn": "8.14.0",
|
||||||
"c12": "^2.0.1",
|
"c12": "^2.0.1",
|
||||||
"chokidar": "^4.0.1",
|
"chokidar": "^4.0.1",
|
||||||
"compatx": "^0.1.8",
|
"compatx": "^0.1.8",
|
||||||
@ -95,7 +95,7 @@
|
|||||||
"mlly": "^1.7.2",
|
"mlly": "^1.7.2",
|
||||||
"nanotar": "^0.1.1",
|
"nanotar": "^0.1.1",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"nuxi": "^3.14.0",
|
"nuxi": "^3.15.0",
|
||||||
"nypm": "^0.3.12",
|
"nypm": "^0.3.12",
|
||||||
"ofetch": "^1.4.1",
|
"ofetch": "^1.4.1",
|
||||||
"ohash": "^1.1.4",
|
"ohash": "^1.1.4",
|
||||||
@ -107,13 +107,13 @@
|
|||||||
"semver": "^7.6.3",
|
"semver": "^7.6.3",
|
||||||
"std-env": "^3.7.0",
|
"std-env": "^3.7.0",
|
||||||
"strip-literal": "^2.1.0",
|
"strip-literal": "^2.1.0",
|
||||||
"tinyglobby": "0.2.9",
|
"tinyglobby": "0.2.10",
|
||||||
"ufo": "^1.5.4",
|
"ufo": "^1.5.4",
|
||||||
"ultrahtml": "^1.5.3",
|
"ultrahtml": "^1.5.3",
|
||||||
"uncrypto": "^0.1.3",
|
"uncrypto": "^0.1.3",
|
||||||
"unctx": "^2.3.1",
|
"unctx": "^2.3.1",
|
||||||
"unenv": "^1.10.0",
|
"unenv": "^1.10.0",
|
||||||
"unhead": "^1.11.7",
|
"unhead": "^1.11.10",
|
||||||
"unimport": "^3.13.1",
|
"unimport": "^3.13.1",
|
||||||
"unplugin": "^1.14.1",
|
"unplugin": "^1.14.1",
|
||||||
"unplugin-vue-router": "^0.10.8",
|
"unplugin-vue-router": "^0.10.8",
|
||||||
@ -125,15 +125,15 @@
|
|||||||
"vue-router": "^4.4.5"
|
"vue-router": "^4.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/scripts": "0.9.4",
|
"@nuxt/scripts": "0.9.5",
|
||||||
"@nuxt/ui-templates": "1.3.4",
|
"@nuxt/ui-templates": "1.3.4",
|
||||||
"@parcel/watcher": "2.4.1",
|
"@parcel/watcher": "2.4.1",
|
||||||
"@types/estree": "1.0.6",
|
"@types/estree": "1.0.6",
|
||||||
"@vitejs/plugin-vue": "5.1.4",
|
"@vitejs/plugin-vue": "5.1.4",
|
||||||
"@vue/compiler-sfc": "3.5.12",
|
"@vue/compiler-sfc": "3.5.12",
|
||||||
"unbuild": "3.0.0-rc.11",
|
"unbuild": "3.0.0-rc.11",
|
||||||
"vite": "5.4.8",
|
"vite": "5.4.10",
|
||||||
"vitest": "2.1.2"
|
"vitest": "2.1.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@parcel/watcher": "^2.1.0",
|
"@parcel/watcher": "^2.1.0",
|
||||||
|
@ -22,6 +22,7 @@ const SSR_UID_RE = /data-island-uid="([^"]*)"/
|
|||||||
const DATA_ISLAND_UID_RE = /data-island-uid(="")?(?!="[^"])/g
|
const DATA_ISLAND_UID_RE = /data-island-uid(="")?(?!="[^"])/g
|
||||||
const SLOTNAME_RE = /data-island-slot="([^"]*)"/g
|
const SLOTNAME_RE = /data-island-slot="([^"]*)"/g
|
||||||
const SLOT_FALLBACK_RE = / data-island-slot="([^"]*)"[^>]*>/g
|
const SLOT_FALLBACK_RE = / data-island-slot="([^"]*)"[^>]*>/g
|
||||||
|
const ISLAND_SCOPE_ID_RE = /^<[^> ]*/
|
||||||
|
|
||||||
let id = 1
|
let id = 1
|
||||||
const getId = import.meta.client ? () => (id++).toString() : randomUUID
|
const getId = import.meta.client ? () => (id++).toString() : randomUUID
|
||||||
@ -142,7 +143,7 @@ export default defineComponent({
|
|||||||
let html = ssrHTML.value
|
let html = ssrHTML.value
|
||||||
|
|
||||||
if (props.scopeId) {
|
if (props.scopeId) {
|
||||||
html = html.replace(/^<[^> ]*/, full => full + ' ' + props.scopeId)
|
html = html.replace(ISLAND_SCOPE_ID_RE, full => full + ' ' + props.scopeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import.meta.client && !canLoadClientComponent.value) {
|
if (import.meta.client && !canLoadClientComponent.value) {
|
||||||
|
@ -521,11 +521,12 @@ function useObserver (): { observe: ObserveFn } | undefined {
|
|||||||
return _observer
|
return _observer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IS_2G_RE = /2g/
|
||||||
function isSlowConnection () {
|
function isSlowConnection () {
|
||||||
if (import.meta.server) { return }
|
if (import.meta.server) { return }
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
|
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
|
||||||
const cn = (navigator as any).connection as { saveData: boolean, effectiveType: string } | null
|
const cn = (navigator as any).connection as { saveData: boolean, effectiveType: string } | null
|
||||||
if (cn && (cn.saveData || /2g/.test(cn.effectiveType))) { return true }
|
if (cn && (cn.saveData || IS_2G_RE.test(cn.effectiveType))) { return true }
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,16 @@ export const _wrapIf = (component: Component, props: any, slots: any) => {
|
|||||||
return { default: () => props ? h(component, props, slots) : slots.default?.() }
|
return { default: () => props ? h(component, props, slots) : slots.default?.() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ROUTE_KEY_PARENTHESES_RE = /(:\w+)\([^)]+\)/g
|
||||||
|
const ROUTE_KEY_SYMBOLS_RE = /(:\w+)[?+*]/g
|
||||||
|
const ROUTE_KEY_NORMAL_RE = /:\w+/g
|
||||||
// TODO: consider refactoring into single utility
|
// TODO: consider refactoring into single utility
|
||||||
// See https://github.com/nuxt/nuxt/tree/main/packages/nuxt/src/pages/runtime/utils.ts#L8-L19
|
// See https://github.com/nuxt/nuxt/tree/main/packages/nuxt/src/pages/runtime/utils.ts#L8-L19
|
||||||
function generateRouteKey (route: RouteLocationNormalized) {
|
function generateRouteKey (route: RouteLocationNormalized) {
|
||||||
const source = route?.meta.key ?? route.path
|
const source = route?.meta.key ?? route.path
|
||||||
.replace(/(:\w+)\([^)]+\)/g, '$1')
|
.replace(ROUTE_KEY_PARENTHESES_RE, '$1')
|
||||||
.replace(/(:\w+)[?+*]/g, '$1')
|
.replace(ROUTE_KEY_SYMBOLS_RE, '$1')
|
||||||
.replace(/:\w+/g, r => route.params[r.slice(1)]?.toString() || '')
|
.replace(ROUTE_KEY_NORMAL_RE, r => route.params[r.slice(1)]?.toString() || '')
|
||||||
return typeof source === 'function' ? source(route) : source
|
return typeof source === 'function' ? source(route) : source
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ export interface NavigateToOptions {
|
|||||||
open?: OpenOptions
|
open?: OpenOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const URL_QUOTE_RE = /"/g
|
||||||
/** @since 3.0.0 */
|
/** @since 3.0.0 */
|
||||||
export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: NavigateToOptions): Promise<void | NavigationFailure | false> | false | void | RouteLocationRaw => {
|
export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: NavigateToOptions): Promise<void | NavigationFailure | false> | false | void | RouteLocationRaw => {
|
||||||
if (!to) {
|
if (!to) {
|
||||||
@ -166,7 +167,7 @@ export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: Na
|
|||||||
const redirect = async function (response: any) {
|
const redirect = async function (response: any) {
|
||||||
// TODO: consider deprecating in favour of `app:rendered` and removing
|
// TODO: consider deprecating in favour of `app:rendered` and removing
|
||||||
await nuxtApp.callHook('app:redirected')
|
await nuxtApp.callHook('app:redirected')
|
||||||
const encodedLoc = location.replace(/"/g, '%22')
|
const encodedLoc = location.replace(URL_QUOTE_RE, '%22')
|
||||||
const encodedHeader = encodeURL(location, isExternalHost)
|
const encodedHeader = encodeURL(location, isExternalHost)
|
||||||
|
|
||||||
nuxtApp.ssrContext!._renderResponse = {
|
nuxtApp.ssrContext!._renderResponse = {
|
||||||
|
@ -16,11 +16,13 @@ import { ComponentNamePlugin } from './plugins/component-names'
|
|||||||
|
|
||||||
const isPureObjectOrString = (val: any) => (!Array.isArray(val) && typeof val === 'object') || typeof val === 'string'
|
const isPureObjectOrString = (val: any) => (!Array.isArray(val) && typeof val === 'object') || typeof val === 'string'
|
||||||
const isDirectory = (p: string) => { try { return statSync(p).isDirectory() } catch { return false } }
|
const isDirectory = (p: string) => { try { return statSync(p).isDirectory() } catch { return false } }
|
||||||
|
const SLASH_SEPARATOR_RE = /[\\/]/
|
||||||
function compareDirByPathLength ({ path: pathA }: { path: string }, { path: pathB }: { path: string }) {
|
function compareDirByPathLength ({ path: pathA }: { path: string }, { path: pathB }: { path: string }) {
|
||||||
return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length
|
return pathB.split(SLASH_SEPARATOR_RE).filter(Boolean).length - pathA.split(SLASH_SEPARATOR_RE).filter(Boolean).length
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_COMPONENTS_DIRS_RE = /\/components(?:\/(?:global|islands))?$/
|
const DEFAULT_COMPONENTS_DIRS_RE = /\/components(?:\/(?:global|islands))?$/
|
||||||
|
const STARTER_DOT_RE = /^\./g
|
||||||
|
|
||||||
export type getComponentsT = (mode?: 'client' | 'server' | 'all') => Component[]
|
export type getComponentsT = (mode?: 'client' | 'server' | 'all') => Component[]
|
||||||
|
|
||||||
@ -89,7 +91,7 @@ export default defineNuxtModule<ComponentsOptions>({
|
|||||||
const dirOptions: ComponentsDir = typeof dir === 'object' ? dir : { path: dir }
|
const dirOptions: ComponentsDir = typeof dir === 'object' ? dir : { path: dir }
|
||||||
const dirPath = resolveAlias(dirOptions.path)
|
const dirPath = resolveAlias(dirOptions.path)
|
||||||
const transpile = typeof dirOptions.transpile === 'boolean' ? dirOptions.transpile : 'auto'
|
const transpile = typeof dirOptions.transpile === 'boolean' ? dirOptions.transpile : 'auto'
|
||||||
const extensions = (dirOptions.extensions || nuxt.options.extensions).map(e => e.replace(/^\./g, ''))
|
const extensions = (dirOptions.extensions || nuxt.options.extensions).map(e => e.replace(STARTER_DOT_RE, ''))
|
||||||
|
|
||||||
const present = isDirectory(dirPath)
|
const present = isDirectory(dirPath)
|
||||||
if (!present && !DEFAULT_COMPONENTS_DIRS_RE.test(dirOptions.path)) {
|
if (!present && !DEFAULT_COMPONENTS_DIRS_RE.test(dirOptions.path)) {
|
||||||
|
@ -12,6 +12,7 @@ interface LoaderOptions {
|
|||||||
}
|
}
|
||||||
const CLIENT_FALLBACK_RE = /<(?:NuxtClientFallback|nuxt-client-fallback)(?: [^>]*)?>/
|
const CLIENT_FALLBACK_RE = /<(?:NuxtClientFallback|nuxt-client-fallback)(?: [^>]*)?>/
|
||||||
const CLIENT_FALLBACK_GLOBAL_RE = /<(NuxtClientFallback|nuxt-client-fallback)( [^>]*)?>/g
|
const CLIENT_FALLBACK_GLOBAL_RE = /<(NuxtClientFallback|nuxt-client-fallback)( [^>]*)?>/g
|
||||||
|
const UID_RE = / :?uid=/
|
||||||
export const ClientFallbackAutoIdPlugin = (options: LoaderOptions) => createUnplugin(() => {
|
export const ClientFallbackAutoIdPlugin = (options: LoaderOptions) => createUnplugin(() => {
|
||||||
const exclude = options.transform?.exclude || []
|
const exclude = options.transform?.exclude || []
|
||||||
const include = options.transform?.include || []
|
const include = options.transform?.include || []
|
||||||
@ -37,7 +38,7 @@ export const ClientFallbackAutoIdPlugin = (options: LoaderOptions) => createUnpl
|
|||||||
|
|
||||||
s.replace(CLIENT_FALLBACK_GLOBAL_RE, (full, name, attrs) => {
|
s.replace(CLIENT_FALLBACK_GLOBAL_RE, (full, name, attrs) => {
|
||||||
count++
|
count++
|
||||||
if (/ :?uid=/.test(attrs)) { return full }
|
if (UID_RE.test(attrs)) { return full }
|
||||||
return `<${name} :uid="'${hash(relativeID)}' + JSON.stringify($props) + '${count}'" ${attrs ?? ''}>`
|
return `<${name} :uid="'${hash(relativeID)}' + JSON.stringify($props) + '${count}'" ${attrs ?? ''}>`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { createUnplugin } from 'unplugin'
|
import { createUnplugin } from 'unplugin'
|
||||||
import MagicString from 'magic-string'
|
import MagicString from 'magic-string'
|
||||||
import type { Component } from 'nuxt/schema'
|
import type { Component } from 'nuxt/schema'
|
||||||
import { isVue } from '../../core/utils'
|
import { SX_RE, isVue } from '../../core/utils'
|
||||||
|
|
||||||
interface NameDevPluginOptions {
|
interface NameDevPluginOptions {
|
||||||
sourcemap: boolean
|
sourcemap: boolean
|
||||||
getComponents: () => Component[]
|
getComponents: () => Component[]
|
||||||
}
|
}
|
||||||
|
const FILENAME_RE = /([^/\\]+)\.\w+$/
|
||||||
/**
|
/**
|
||||||
* Set the default name of components to their PascalCase name
|
* Set the default name of components to their PascalCase name
|
||||||
*/
|
*/
|
||||||
@ -15,10 +16,10 @@ export const ComponentNamePlugin = (options: NameDevPluginOptions) => createUnpl
|
|||||||
name: 'nuxt:component-name-plugin',
|
name: 'nuxt:component-name-plugin',
|
||||||
enforce: 'post',
|
enforce: 'post',
|
||||||
transformInclude (id) {
|
transformInclude (id) {
|
||||||
return isVue(id) || !!id.match(/\.[tj]sx$/)
|
return isVue(id) || !!id.match(SX_RE)
|
||||||
},
|
},
|
||||||
transform (code, id) {
|
transform (code, id) {
|
||||||
const filename = id.match(/([^/\\]+)\.\w+$/)?.[1]
|
const filename = id.match(FILENAME_RE)?.[1]
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ const TEMPLATE_RE = /<template>([\s\S]*)<\/template>/
|
|||||||
const NUXTCLIENT_ATTR_RE = /\s:?nuxt-client(="[^"]*")?/g
|
const NUXTCLIENT_ATTR_RE = /\s:?nuxt-client(="[^"]*")?/g
|
||||||
const IMPORT_CODE = '\nimport { mergeProps as __mergeProps } from \'vue\'' + '\nimport { vforToArray as __vforToArray } from \'#app/components/utils\'' + '\nimport NuxtTeleportIslandComponent from \'#app/components/nuxt-teleport-island-component\'' + '\nimport NuxtTeleportSsrSlot from \'#app/components/nuxt-teleport-island-slot\''
|
const IMPORT_CODE = '\nimport { mergeProps as __mergeProps } from \'vue\'' + '\nimport { vforToArray as __vforToArray } from \'#app/components/utils\'' + '\nimport NuxtTeleportIslandComponent from \'#app/components/nuxt-teleport-island-component\'' + '\nimport NuxtTeleportSsrSlot from \'#app/components/nuxt-teleport-island-slot\''
|
||||||
const EXTRACTED_ATTRS_RE = /v-(?:if|else-if|else)(="[^"]*")?/g
|
const EXTRACTED_ATTRS_RE = /v-(?:if|else-if|else)(="[^"]*")?/g
|
||||||
|
const KEY_RE = /:?key="[^"]"/g
|
||||||
|
|
||||||
function wrapWithVForDiv (code: string, vfor: string): string {
|
function wrapWithVForDiv (code: string, vfor: string): string {
|
||||||
return `<div v-for="${vfor}" style="display: contents;">${code}</div>`
|
return `<div v-for="${vfor}" style="display: contents;">${code}</div>`
|
||||||
@ -90,7 +91,7 @@ export const IslandsTransformPlugin = (options: ServerOnlyComponentTransformPlug
|
|||||||
if (children.length) {
|
if (children.length) {
|
||||||
// pass slot fallback to NuxtTeleportSsrSlot fallback
|
// pass slot fallback to NuxtTeleportSsrSlot fallback
|
||||||
const attrString = attributeToString(attributes)
|
const attrString = attributeToString(attributes)
|
||||||
const slice = code.slice(startingIndex + loc[0].end, startingIndex + loc[1].start).replaceAll(/:?key="[^"]"/g, '')
|
const slice = code.slice(startingIndex + loc[0].end, startingIndex + loc[1].start).replaceAll(KEY_RE, '')
|
||||||
s.overwrite(startingIndex + loc[0].start, startingIndex + loc[1].end, `<slot${attrString.replaceAll(EXTRACTED_ATTRS_RE, '')}/><template #fallback>${attributes['v-for'] ? wrapWithVForDiv(slice, attributes['v-for']) : slice}</template>`)
|
s.overwrite(startingIndex + loc[0].start, startingIndex + loc[1].end, `<slot${attrString.replaceAll(EXTRACTED_ATTRS_RE, '')}/><template #fallback>${attributes['v-for'] ? wrapWithVForDiv(slice, attributes['v-for']) : slice}</template>`)
|
||||||
} else {
|
} else {
|
||||||
s.overwrite(startingIndex + loc[0].start, startingIndex + loc[0].end, code.slice(startingIndex + loc[0].start, startingIndex + loc[0].end).replaceAll(EXTRACTED_ATTRS_RE, ''))
|
s.overwrite(startingIndex + loc[0].start, startingIndex + loc[0].end, code.slice(startingIndex + loc[0].start, startingIndex + loc[0].end).replaceAll(EXTRACTED_ATTRS_RE, ''))
|
||||||
|
@ -6,7 +6,7 @@ import { relative } from 'pathe'
|
|||||||
import type { Component, ComponentsOptions } from 'nuxt/schema'
|
import type { Component, ComponentsOptions } from 'nuxt/schema'
|
||||||
|
|
||||||
import { logger, tryUseNuxt } from '@nuxt/kit'
|
import { logger, tryUseNuxt } from '@nuxt/kit'
|
||||||
import { isVue } from '../../core/utils'
|
import { QUOTE_RE, SX_RE, isVue } from '../../core/utils'
|
||||||
|
|
||||||
interface LoaderOptions {
|
interface LoaderOptions {
|
||||||
getComponents (): Component[]
|
getComponents (): Component[]
|
||||||
@ -17,6 +17,7 @@ interface LoaderOptions {
|
|||||||
experimentalComponentIslands?: boolean
|
experimentalComponentIslands?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const REPLACE_COMPONENT_TO_DIRECT_IMPORT_RE = /(?<=[ (])_?resolveComponent\(\s*["'](lazy-|Lazy(?=[A-Z]))?([^'"]*)["'][^)]*\)/g
|
||||||
export const LoaderPlugin = (options: LoaderOptions) => createUnplugin(() => {
|
export const LoaderPlugin = (options: LoaderOptions) => createUnplugin(() => {
|
||||||
const exclude = options.transform?.exclude || []
|
const exclude = options.transform?.exclude || []
|
||||||
const include = options.transform?.include || []
|
const include = options.transform?.include || []
|
||||||
@ -32,7 +33,7 @@ export const LoaderPlugin = (options: LoaderOptions) => createUnplugin(() => {
|
|||||||
if (include.some(pattern => pattern.test(id))) {
|
if (include.some(pattern => pattern.test(id))) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return isVue(id, { type: ['template', 'script'] }) || !!id.match(/\.[tj]sx$/)
|
return isVue(id, { type: ['template', 'script'] }) || !!id.match(SX_RE)
|
||||||
},
|
},
|
||||||
transform (code, id) {
|
transform (code, id) {
|
||||||
const components = options.getComponents()
|
const components = options.getComponents()
|
||||||
@ -43,7 +44,7 @@ export const LoaderPlugin = (options: LoaderOptions) => createUnplugin(() => {
|
|||||||
const s = new MagicString(code)
|
const s = new MagicString(code)
|
||||||
|
|
||||||
// replace `_resolveComponent("...")` to direct import
|
// replace `_resolveComponent("...")` to direct import
|
||||||
s.replace(/(?<=[ (])_?resolveComponent\(\s*["'](lazy-|Lazy(?=[A-Z]))?([^'"]*)["'][^)]*\)/g, (full: string, lazy: string, name: string) => {
|
s.replace(REPLACE_COMPONENT_TO_DIRECT_IMPORT_RE, (full: string, lazy: string, name: string) => {
|
||||||
const component = findComponent(components, name, options.mode)
|
const component = findComponent(components, name, options.mode)
|
||||||
if (component) {
|
if (component) {
|
||||||
// TODO: refactor to nuxi
|
// TODO: refactor to nuxi
|
||||||
@ -111,7 +112,7 @@ export const LoaderPlugin = (options: LoaderOptions) => createUnplugin(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
function findComponent (components: Component[], name: string, mode: LoaderOptions['mode']) {
|
function findComponent (components: Component[], name: string, mode: LoaderOptions['mode']) {
|
||||||
const id = pascalCase(name).replace(/["']/g, '')
|
const id = pascalCase(name).replace(QUOTE_RE, '')
|
||||||
// Prefer exact match
|
// Prefer exact match
|
||||||
const component = components.find(component => id === component.pascalName && ['all', mode, undefined].includes(component.mode))
|
const component = components.find(component => id === component.pascalName && ['all', mode, undefined].includes(component.mode))
|
||||||
if (component) { return component }
|
if (component) { return component }
|
||||||
|
@ -6,8 +6,12 @@ import { isIgnored, logger, useNuxt } from '@nuxt/kit'
|
|||||||
import { withTrailingSlash } from 'ufo'
|
import { withTrailingSlash } from 'ufo'
|
||||||
import type { Component, ComponentsDir } from 'nuxt/schema'
|
import type { Component, ComponentsDir } from 'nuxt/schema'
|
||||||
|
|
||||||
import { resolveComponentNameSegments } from '../core/utils'
|
import { QUOTE_RE, resolveComponentNameSegments } from '../core/utils'
|
||||||
|
|
||||||
|
const ISLAND_RE = /\.island(?:\.global)?$/
|
||||||
|
const GLOBAL_RE = /\.global(?:\.island)?$/
|
||||||
|
const COMPONENT_MODE_RE = /(?<=\.)(client|server)(\.global|\.island)*$/
|
||||||
|
const MODE_REPLACEMENT_RE = /(\.(client|server))?(\.global|\.island)*$/
|
||||||
/**
|
/**
|
||||||
* Scan the components inside different components folders
|
* Scan the components inside different components folders
|
||||||
* and return a unique list of components
|
* and return a unique list of components
|
||||||
@ -83,17 +87,17 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr
|
|||||||
*/
|
*/
|
||||||
let fileName = basename(filePath, extname(filePath))
|
let fileName = basename(filePath, extname(filePath))
|
||||||
|
|
||||||
const island = /\.island(?:\.global)?$/.test(fileName) || dir.island
|
const island = ISLAND_RE.test(fileName) || dir.island
|
||||||
const global = /\.global(?:\.island)?$/.test(fileName) || dir.global
|
const global = GLOBAL_RE.test(fileName) || dir.global
|
||||||
const mode = island ? 'server' : (fileName.match(/(?<=\.)(client|server)(\.global|\.island)*$/)?.[1] || 'all') as 'client' | 'server' | 'all'
|
const mode = island ? 'server' : (fileName.match(COMPONENT_MODE_RE)?.[1] || 'all') as 'client' | 'server' | 'all'
|
||||||
fileName = fileName.replace(/(\.(client|server))?(\.global|\.island)*$/, '')
|
fileName = fileName.replace(MODE_REPLACEMENT_RE, '')
|
||||||
|
|
||||||
if (fileName.toLowerCase() === 'index') {
|
if (fileName.toLowerCase() === 'index') {
|
||||||
fileName = dir.pathPrefix === false ? basename(dirname(filePath)) : '' /* inherits from path */
|
fileName = dir.pathPrefix === false ? basename(dirname(filePath)) : '' /* inherits from path */
|
||||||
}
|
}
|
||||||
|
|
||||||
const suffix = (mode !== 'all' ? `-${mode}` : '')
|
const suffix = (mode !== 'all' ? `-${mode}` : '')
|
||||||
const componentNameSegments = resolveComponentNameSegments(fileName.replace(/["']/g, ''), prefixParts)
|
const componentNameSegments = resolveComponentNameSegments(fileName.replace(QUOTE_RE, ''), prefixParts)
|
||||||
const pascalName = pascalCase(componentNameSegments)
|
const pascalName = pascalCase(componentNameSegments)
|
||||||
|
|
||||||
if (LAZY_COMPONENT_NAME_REGEX.test(pascalName)) {
|
if (LAZY_COMPONENT_NAME_REGEX.test(pascalName)) {
|
||||||
|
@ -102,14 +102,15 @@ export const componentsIslandsTemplate: NuxtTemplate = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NON_VUE_RE = /\b\.(?!vue)\w+$/g
|
||||||
export const componentsTypeTemplate = {
|
export const componentsTypeTemplate = {
|
||||||
filename: 'components.d.ts' as const,
|
filename: 'components.d.ts' as const,
|
||||||
getContents: ({ app, nuxt }) => {
|
getContents: ({ app, nuxt }) => {
|
||||||
const buildDir = nuxt.options.buildDir
|
const buildDir = nuxt.options.buildDir
|
||||||
const componentTypes = app.components.filter(c => !c.island).map((c) => {
|
const componentTypes = app.components.filter(c => !c.island).map((c) => {
|
||||||
const type = `typeof ${genDynamicImport(isAbsolute(c.filePath)
|
const type = `typeof ${genDynamicImport(isAbsolute(c.filePath)
|
||||||
? relative(buildDir, c.filePath).replace(/\b\.(?!vue)\w+$/g, '')
|
? relative(buildDir, c.filePath).replace(NON_VUE_RE, '')
|
||||||
: c.filePath.replace(/\b\.(?!vue)\w+$/g, ''), { wrapper: false })}['${c.export}']`
|
: c.filePath.replace(NON_VUE_RE, ''), { wrapper: false })}['${c.export}']`
|
||||||
return [
|
return [
|
||||||
c.pascalName,
|
c.pascalName,
|
||||||
c.island || c.mode === 'server' ? `IslandComponent<${type}>` : type,
|
c.island || c.mode === 'server' ? `IslandComponent<${type}>` : type,
|
||||||
|
@ -57,7 +57,7 @@ export async function generateApp (nuxt: Nuxt, app: NuxtApp, options: { filter?:
|
|||||||
|
|
||||||
const writes: Array<() => void> = []
|
const writes: Array<() => void> = []
|
||||||
const changedTemplates: Array<ResolvedNuxtTemplate<any>> = []
|
const changedTemplates: Array<ResolvedNuxtTemplate<any>> = []
|
||||||
|
const FORWARD_SLASH_RE = /\//g
|
||||||
async function processTemplate (template: ResolvedNuxtTemplate) {
|
async function processTemplate (template: ResolvedNuxtTemplate) {
|
||||||
const fullPath = template.dst || resolve(nuxt.options.buildDir, template.filename!)
|
const fullPath = template.dst || resolve(nuxt.options.buildDir, template.filename!)
|
||||||
const start = performance.now()
|
const start = performance.now()
|
||||||
@ -77,7 +77,7 @@ export async function generateApp (nuxt: Nuxt, app: NuxtApp, options: { filter?:
|
|||||||
|
|
||||||
// In case a non-normalized absolute path is called for on Windows
|
// In case a non-normalized absolute path is called for on Windows
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
nuxt.vfs[fullPath.replace(/\//g, '\\')] = contents
|
nuxt.vfs[fullPath.replace(FORWARD_SLASH_RE, '\\')] = contents
|
||||||
}
|
}
|
||||||
|
|
||||||
changedTemplates.push(template)
|
changedTemplates.push(template)
|
||||||
|
@ -10,6 +10,7 @@ import { generateApp as _generateApp, createApp } from './app'
|
|||||||
import { checkForExternalConfigurationFiles } from './external-config-files'
|
import { checkForExternalConfigurationFiles } from './external-config-files'
|
||||||
import { cleanupCaches, getVueHash } from './cache'
|
import { cleanupCaches, getVueHash } from './cache'
|
||||||
|
|
||||||
|
const IS_RESTART_PATH_RE = /^(?:app\.|error\.|plugins\/|middleware\/|layouts\/)/i
|
||||||
export async function build (nuxt: Nuxt) {
|
export async function build (nuxt: Nuxt) {
|
||||||
const app = createApp(nuxt)
|
const app = createApp(nuxt)
|
||||||
nuxt.apps.default = app
|
nuxt.apps.default = app
|
||||||
@ -23,7 +24,7 @@ export async function build (nuxt: Nuxt) {
|
|||||||
if (event === 'change') { return }
|
if (event === 'change') { return }
|
||||||
const path = resolve(nuxt.options.srcDir, relativePath)
|
const path = resolve(nuxt.options.srcDir, relativePath)
|
||||||
const relativePaths = nuxt.options._layers.map(l => relative(l.config.srcDir || l.cwd, path))
|
const relativePaths = nuxt.options._layers.map(l => relative(l.config.srcDir || l.cwd, path))
|
||||||
const restartPath = relativePaths.find(relativePath => /^(?:app\.|error\.|plugins\/|middleware\/|layouts\/)/i.test(relativePath))
|
const restartPath = relativePaths.find(relativePath => IS_RESTART_PATH_RE.test(relativePath))
|
||||||
if (restartPath) {
|
if (restartPath) {
|
||||||
if (restartPath.startsWith('app')) {
|
if (restartPath.startsWith('app')) {
|
||||||
app.mainComponent = undefined
|
app.mainComponent = undefined
|
||||||
|
@ -18,6 +18,7 @@ import { distDir } from '../dirs'
|
|||||||
import { toArray } from '../utils'
|
import { toArray } from '../utils'
|
||||||
import { template as defaultSpaLoadingTemplate } from '../../../ui-templates/dist/templates/spa-loading-icon'
|
import { template as defaultSpaLoadingTemplate } from '../../../ui-templates/dist/templates/spa-loading-icon'
|
||||||
import { nuxtImportProtections } from './plugins/import-protection'
|
import { nuxtImportProtections } from './plugins/import-protection'
|
||||||
|
import { EXTENSION_RE } from './utils'
|
||||||
|
|
||||||
const logLevelMapReverse = {
|
const logLevelMapReverse = {
|
||||||
silent: 0,
|
silent: 0,
|
||||||
@ -25,12 +26,14 @@ const logLevelMapReverse = {
|
|||||||
verbose: 3,
|
verbose: 3,
|
||||||
} satisfies Record<NuxtOptions['logLevel'], NitroConfig['logLevel']>
|
} satisfies Record<NuxtOptions['logLevel'], NitroConfig['logLevel']>
|
||||||
|
|
||||||
|
const NODE_MODULES_RE = /(?<=\/)node_modules\/(.+)$/
|
||||||
|
const PNPM_NODE_MODULES_RE = /\.pnpm\/.+\/node_modules\/(.+)$/
|
||||||
export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
||||||
// Resolve config
|
// Resolve config
|
||||||
const excludePaths = nuxt.options._layers
|
const excludePaths = nuxt.options._layers
|
||||||
.flatMap(l => [
|
.flatMap(l => [
|
||||||
l.cwd.match(/(?<=\/)node_modules\/(.+)$/)?.[1],
|
l.cwd.match(NODE_MODULES_RE)?.[1],
|
||||||
l.cwd.match(/\.pnpm\/.+\/node_modules\/(.+)$/)?.[1],
|
l.cwd.match(PNPM_NODE_MODULES_RE)?.[1],
|
||||||
])
|
])
|
||||||
.filter((dir): dir is string => Boolean(dir))
|
.filter((dir): dir is string => Boolean(dir))
|
||||||
.map(dir => escapeRE(dir))
|
.map(dir => escapeRE(dir))
|
||||||
@ -339,11 +342,12 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add fallback server for `ssr: false`
|
// Add fallback server for `ssr: false`
|
||||||
|
const FORWARD_SLASH_RE = /\//g
|
||||||
if (!nuxt.options.ssr) {
|
if (!nuxt.options.ssr) {
|
||||||
nitroConfig.virtual!['#build/dist/server/server.mjs'] = 'export default () => {}'
|
nitroConfig.virtual!['#build/dist/server/server.mjs'] = 'export default () => {}'
|
||||||
// In case a non-normalized absolute path is called for on Windows
|
// In case a non-normalized absolute path is called for on Windows
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
nitroConfig.virtual!['#build/dist/server/server.mjs'.replace(/\//g, '\\')] = 'export default () => {}'
|
nitroConfig.virtual!['#build/dist/server/server.mjs'.replace(FORWARD_SLASH_RE, '\\')] = 'export default () => {}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +355,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
nitroConfig.virtual!['#build/dist/server/styles.mjs'] = 'export default {}'
|
nitroConfig.virtual!['#build/dist/server/styles.mjs'] = 'export default {}'
|
||||||
// In case a non-normalized absolute path is called for on Windows
|
// In case a non-normalized absolute path is called for on Windows
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
nitroConfig.virtual!['#build/dist/server/styles.mjs'.replace(/\//g, '\\')] = 'export default {}'
|
nitroConfig.virtual!['#build/dist/server/styles.mjs'.replace(FORWARD_SLASH_RE, '\\')] = 'export default {}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +393,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
tsConfig.compilerOptions.paths[alias] = [absolutePath]
|
tsConfig.compilerOptions.paths[alias] = [absolutePath]
|
||||||
tsConfig.compilerOptions.paths[`${alias}/*`] = [`${absolutePath}/*`]
|
tsConfig.compilerOptions.paths[`${alias}/*`] = [`${absolutePath}/*`]
|
||||||
} else {
|
} else {
|
||||||
tsConfig.compilerOptions.paths[alias] = [absolutePath.replace(/\b\.\w+$/g, '')] /* remove extension */
|
tsConfig.compilerOptions.paths[alias] = [absolutePath.replace(EXTENSION_RE, '')] /* remove extension */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,8 +570,9 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RELATIVE_RE = /^([^.])/
|
||||||
function relativeWithDot (from: string, to: string) {
|
function relativeWithDot (from: string, to: string) {
|
||||||
return relative(from, to).replace(/^([^.])/, './$1') || '.'
|
return relative(from, to).replace(RELATIVE_RE, './$1') || '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function spaLoadingTemplatePath (nuxt: Nuxt) {
|
async function spaLoadingTemplatePath (nuxt: Nuxt) {
|
||||||
|
@ -178,9 +178,10 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
|
|
||||||
const coreTypePackages = nuxt.options.typescript.hoist || []
|
const coreTypePackages = nuxt.options.typescript.hoist || []
|
||||||
const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(() => ({}) as PackageJson)
|
const packageJSON = await readPackageJSON(nuxt.options.rootDir).catch(() => ({}) as PackageJson)
|
||||||
|
const NESTED_PKG_RE = /^[^@]+\//
|
||||||
nuxt._dependencies = new Set([...Object.keys(packageJSON.dependencies || {}), ...Object.keys(packageJSON.devDependencies || {})])
|
nuxt._dependencies = new Set([...Object.keys(packageJSON.dependencies || {}), ...Object.keys(packageJSON.devDependencies || {})])
|
||||||
const paths = Object.fromEntries(await Promise.all(coreTypePackages.map(async (pkg) => {
|
const paths = Object.fromEntries(await Promise.all(coreTypePackages.map(async (pkg) => {
|
||||||
const [_pkg = pkg, _subpath] = /^[^@]+\//.test(pkg) ? pkg.split('/') : [pkg]
|
const [_pkg = pkg, _subpath] = NESTED_PKG_RE.test(pkg) ? pkg.split('/') : [pkg]
|
||||||
const subpath = _subpath ? '/' + _subpath : ''
|
const subpath = _subpath ? '/' + _subpath : ''
|
||||||
|
|
||||||
// ignore packages that exist in `package.json` as these can be resolved by TypeScript
|
// ignore packages that exist in `package.json` as these can be resolved by TypeScript
|
||||||
|
@ -10,6 +10,7 @@ interface VirtualFSPluginOptions {
|
|||||||
alias?: Record<string, string>
|
alias?: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RELATIVE_ID_RE = /^\.{1,2}[\\/]/
|
||||||
export const VirtualFSPlugin = (nuxt: Nuxt, options: VirtualFSPluginOptions) => createUnplugin(() => {
|
export const VirtualFSPlugin = (nuxt: Nuxt, options: VirtualFSPluginOptions) => createUnplugin(() => {
|
||||||
const extensions = ['', ...nuxt.options.extensions]
|
const extensions = ['', ...nuxt.options.extensions]
|
||||||
const alias = { ...nuxt.options.alias, ...options.alias }
|
const alias = { ...nuxt.options.alias, ...options.alias }
|
||||||
@ -40,7 +41,7 @@ export const VirtualFSPlugin = (nuxt: Nuxt, options: VirtualFSPluginOptions) =>
|
|||||||
return PREFIX + resolvedId
|
return PREFIX + resolvedId
|
||||||
}
|
}
|
||||||
|
|
||||||
if (importer && /^\.{1,2}[\\/]/.test(id)) {
|
if (importer && RELATIVE_ID_RE.test(id)) {
|
||||||
const path = resolve(dirname(withoutPrefix(importer)), id)
|
const path = resolve(dirname(withoutPrefix(importer)), id)
|
||||||
const resolved = resolveWithExt(path)
|
const resolved = resolveWithExt(path)
|
||||||
if (resolved) {
|
if (resolved) {
|
||||||
|
@ -11,6 +11,7 @@ import type { NuxtTemplate } from 'nuxt/schema'
|
|||||||
import type { Nitro } from 'nitro/types'
|
import type { Nitro } from 'nitro/types'
|
||||||
|
|
||||||
import { annotatePlugins, checkForCircularDependencies } from './app'
|
import { annotatePlugins, checkForCircularDependencies } from './app'
|
||||||
|
import { EXTENSION_RE } from './utils'
|
||||||
|
|
||||||
export const vueShim: NuxtTemplate = {
|
export const vueShim: NuxtTemplate = {
|
||||||
filename: 'types/vue-shim.d.ts',
|
filename: 'types/vue-shim.d.ts',
|
||||||
@ -57,6 +58,7 @@ export const cssTemplate: NuxtTemplate = {
|
|||||||
getContents: ctx => ctx.nuxt.options.css.map(i => genImport(i)).join('\n'),
|
getContents: ctx => ctx.nuxt.options.css.map(i => genImport(i)).join('\n'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PLUGIN_TEMPLATE_RE = /_(45|46|47)/g
|
||||||
export const clientPluginTemplate: NuxtTemplate = {
|
export const clientPluginTemplate: NuxtTemplate = {
|
||||||
filename: 'plugins.client.mjs',
|
filename: 'plugins.client.mjs',
|
||||||
async getContents (ctx) {
|
async getContents (ctx) {
|
||||||
@ -66,7 +68,7 @@ export const clientPluginTemplate: NuxtTemplate = {
|
|||||||
const imports: string[] = []
|
const imports: string[] = []
|
||||||
for (const plugin of clientPlugins) {
|
for (const plugin of clientPlugins) {
|
||||||
const path = relative(ctx.nuxt.options.rootDir, plugin.src)
|
const path = relative(ctx.nuxt.options.rootDir, plugin.src)
|
||||||
const variable = genSafeVariableName(filename(plugin.src)).replace(/_(45|46|47)/g, '_') + '_' + hash(path)
|
const variable = genSafeVariableName(filename(plugin.src)).replace(PLUGIN_TEMPLATE_RE, '_') + '_' + hash(path)
|
||||||
exports.push(variable)
|
exports.push(variable)
|
||||||
imports.push(genImport(plugin.src, variable))
|
imports.push(genImport(plugin.src, variable))
|
||||||
}
|
}
|
||||||
@ -86,7 +88,7 @@ export const serverPluginTemplate: NuxtTemplate = {
|
|||||||
const imports: string[] = []
|
const imports: string[] = []
|
||||||
for (const plugin of serverPlugins) {
|
for (const plugin of serverPlugins) {
|
||||||
const path = relative(ctx.nuxt.options.rootDir, plugin.src)
|
const path = relative(ctx.nuxt.options.rootDir, plugin.src)
|
||||||
const variable = genSafeVariableName(filename(path)).replace(/_(45|46|47)/g, '_') + '_' + hash(path)
|
const variable = genSafeVariableName(filename(path)).replace(PLUGIN_TEMPLATE_RE, '_') + '_' + hash(path)
|
||||||
exports.push(variable)
|
exports.push(variable)
|
||||||
imports.push(genImport(plugin.src, variable))
|
imports.push(genImport(plugin.src, variable))
|
||||||
}
|
}
|
||||||
@ -98,7 +100,9 @@ export const serverPluginTemplate: NuxtTemplate = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TS_RE = /\.[cm]?tsx?$/
|
const TS_RE = /\.[cm]?tsx?$/
|
||||||
|
const JS_LETTER_RE = /\.(?<letter>[cm])?jsx?$/
|
||||||
|
const JS_RE = /\.[cm]jsx?$/
|
||||||
|
const JS_CAPTURE_RE = /\.[cm](jsx?)$/
|
||||||
export const pluginsDeclaration: NuxtTemplate = {
|
export const pluginsDeclaration: NuxtTemplate = {
|
||||||
filename: 'types/plugins.d.ts',
|
filename: 'types/plugins.d.ts',
|
||||||
getContents: async ({ nuxt, app }) => {
|
getContents: async ({ nuxt, app }) => {
|
||||||
@ -120,18 +124,18 @@ export const pluginsDeclaration: NuxtTemplate = {
|
|||||||
const pluginPath = resolve(typesDir, plugin.src)
|
const pluginPath = resolve(typesDir, plugin.src)
|
||||||
const relativePath = relative(typesDir, pluginPath)
|
const relativePath = relative(typesDir, pluginPath)
|
||||||
|
|
||||||
const correspondingDeclaration = pluginPath.replace(/\.(?<letter>[cm])?jsx?$/, '.d.$<letter>ts')
|
const correspondingDeclaration = pluginPath.replace(JS_LETTER_RE, '.d.$<letter>ts')
|
||||||
// if `.d.ts` file exists alongside a `.js` plugin, or if `.d.mts` file exists alongside a `.mjs` plugin, we can use the entire path
|
// if `.d.ts` file exists alongside a `.js` plugin, or if `.d.mts` file exists alongside a `.mjs` plugin, we can use the entire path
|
||||||
if (correspondingDeclaration !== pluginPath && exists(correspondingDeclaration)) {
|
if (correspondingDeclaration !== pluginPath && exists(correspondingDeclaration)) {
|
||||||
tsImports.push(relativePath)
|
tsImports.push(relativePath)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const incorrectDeclaration = pluginPath.replace(/\.[cm]jsx?$/, '.d.ts')
|
const incorrectDeclaration = pluginPath.replace(JS_RE, '.d.ts')
|
||||||
// if `.d.ts` file exists, but plugin is `.mjs`, add `.js` extension to the import
|
// if `.d.ts` file exists, but plugin is `.mjs`, add `.js` extension to the import
|
||||||
// to hotfix issue until ecosystem updates to `@nuxt/module-builder@>=0.8.0`
|
// to hotfix issue until ecosystem updates to `@nuxt/module-builder@>=0.8.0`
|
||||||
if (incorrectDeclaration !== pluginPath && exists(incorrectDeclaration)) {
|
if (incorrectDeclaration !== pluginPath && exists(incorrectDeclaration)) {
|
||||||
tsImports.push(relativePath.replace(/\.[cm](jsx?)$/, '.$1'))
|
tsImports.push(relativePath.replace(JS_CAPTURE_RE, '.$1'))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,11 +178,13 @@ export { }
|
|||||||
}
|
}
|
||||||
|
|
||||||
const adHocModules = ['router', 'pages', 'imports', 'meta', 'components', 'nuxt-config-schema']
|
const adHocModules = ['router', 'pages', 'imports', 'meta', 'components', 'nuxt-config-schema']
|
||||||
|
const IMPORT_NAME_RE = /\.\w+$/
|
||||||
|
const GIT_RE = /^git\+/
|
||||||
export const schemaTemplate: NuxtTemplate = {
|
export const schemaTemplate: NuxtTemplate = {
|
||||||
filename: 'types/schema.d.ts',
|
filename: 'types/schema.d.ts',
|
||||||
getContents: async ({ nuxt }) => {
|
getContents: async ({ nuxt }) => {
|
||||||
const relativeRoot = relative(resolve(nuxt.options.buildDir, 'types'), nuxt.options.rootDir)
|
const relativeRoot = relative(resolve(nuxt.options.buildDir, 'types'), nuxt.options.rootDir)
|
||||||
const getImportName = (name: string) => (name[0] === '.' ? './' + join(relativeRoot, name) : name).replace(/\.\w+$/, '')
|
const getImportName = (name: string) => (name[0] === '.' ? './' + join(relativeRoot, name) : name).replace(IMPORT_NAME_RE, '')
|
||||||
|
|
||||||
const modules = nuxt.options._installedModules
|
const modules = nuxt.options._installedModules
|
||||||
.filter(m => m.meta && m.meta.configKey && m.meta.name && !adHocModules.includes(m.meta.name))
|
.filter(m => m.meta && m.meta.configKey && m.meta.name && !adHocModules.includes(m.meta.name))
|
||||||
@ -210,7 +216,7 @@ export const schemaTemplate: NuxtTemplate = {
|
|||||||
}
|
}
|
||||||
if (link) {
|
if (link) {
|
||||||
if (link.startsWith('git+')) {
|
if (link.startsWith('git+')) {
|
||||||
link = link.replace(/^git\+/, '')
|
link = link.replace(GIT_RE, '')
|
||||||
}
|
}
|
||||||
if (!link.startsWith('http')) {
|
if (!link.startsWith('http')) {
|
||||||
link = 'https://github.com/' + link
|
link = 'https://github.com/' + link
|
||||||
@ -377,7 +383,7 @@ export const appConfigDeclarationTemplate: NuxtTemplate = {
|
|||||||
filename: 'types/app.config.d.ts',
|
filename: 'types/app.config.d.ts',
|
||||||
getContents ({ app, nuxt }) {
|
getContents ({ app, nuxt }) {
|
||||||
const typesDir = join(nuxt.options.buildDir, 'types')
|
const typesDir = join(nuxt.options.buildDir, 'types')
|
||||||
const configPaths = app.configs.map(path => relative(typesDir, path).replace(/\b\.\w+$/g, ''))
|
const configPaths = app.configs.map(path => relative(typesDir, path).replace(EXTENSION_RE, ''))
|
||||||
|
|
||||||
return `
|
return `
|
||||||
import type { CustomAppConfig } from 'nuxt/schema'
|
import type { CustomAppConfig } from 'nuxt/schema'
|
||||||
|
@ -14,3 +14,7 @@ export function uniqueBy<T, K extends keyof T> (arr: T[], key: K) {
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const QUOTE_RE = /["']/g
|
||||||
|
export const EXTENSION_RE = /\b\.\w+$/g
|
||||||
|
export const SX_RE = /\.[tj]sx$/
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { basename, dirname, extname, normalize } from 'pathe'
|
import { basename, dirname, extname, normalize } from 'pathe'
|
||||||
import { kebabCase, splitByCase } from 'scule'
|
import { kebabCase, splitByCase } from 'scule'
|
||||||
import { withTrailingSlash } from 'ufo'
|
import { withTrailingSlash } from 'ufo'
|
||||||
|
import { QUOTE_RE } from '.'
|
||||||
|
|
||||||
export function getNameFromPath (path: string, relativeTo?: string) {
|
export function getNameFromPath (path: string, relativeTo?: string) {
|
||||||
const relativePath = relativeTo
|
const relativePath = relativeTo
|
||||||
@ -9,7 +10,7 @@ export function getNameFromPath (path: string, relativeTo?: string) {
|
|||||||
const prefixParts = splitByCase(dirname(relativePath))
|
const prefixParts = splitByCase(dirname(relativePath))
|
||||||
const fileName = basename(relativePath, extname(relativePath))
|
const fileName = basename(relativePath, extname(relativePath))
|
||||||
const segments = resolveComponentNameSegments(fileName.toLowerCase() === 'index' ? '' : fileName, prefixParts).filter(Boolean)
|
const segments = resolveComponentNameSegments(fileName.toLowerCase() === 'index' ? '' : fileName, prefixParts).filter(Boolean)
|
||||||
return kebabCase(segments).replace(/["']/g, '')
|
return kebabCase(segments).replace(QUOTE_RE, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasSuffix (path: string, suffix: string) {
|
export function hasSuffix (path: string, suffix: string) {
|
||||||
|
@ -503,7 +503,7 @@ export default defineNuxtModule({
|
|||||||
const { routes, imports } = normalizeRoutes(app.pages, new Set(), {
|
const { routes, imports } = normalizeRoutes(app.pages, new Set(), {
|
||||||
serverComponentRuntime,
|
serverComponentRuntime,
|
||||||
clientComponentRuntime,
|
clientComponentRuntime,
|
||||||
overrideMeta: nuxt.options.experimental.scanPageMeta,
|
overrideMeta: !!nuxt.options.experimental.scanPageMeta,
|
||||||
})
|
})
|
||||||
return [...imports, `export default ${routes}`].join('\n')
|
return [...imports, `export default ${routes}`].join('\n')
|
||||||
},
|
},
|
||||||
|
@ -176,8 +176,10 @@ export const PageMetaPlugin = (options: PageMetaPluginOptions) => createUnplugin
|
|||||||
|
|
||||||
// https://github.com/vuejs/vue-loader/pull/1911
|
// https://github.com/vuejs/vue-loader/pull/1911
|
||||||
// https://github.com/vitejs/vite/issues/8473
|
// https://github.com/vitejs/vite/issues/8473
|
||||||
|
const QUERY_START_RE = /^\?/
|
||||||
|
const MACRO_RE = /¯o=true/
|
||||||
function rewriteQuery (id: string) {
|
function rewriteQuery (id: string) {
|
||||||
return id.replace(/\?.+$/, r => '?macro=true&' + r.replace(/^\?/, '').replace(/¯o=true/, ''))
|
return id.replace(/\?.+$/, r => '?macro=true&' + r.replace(QUERY_START_RE, '').replace(MACRO_RE, ''))
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseMacroQuery (id: string) {
|
function parseMacroQuery (id: string) {
|
||||||
@ -189,6 +191,7 @@ function parseMacroQuery (id: string) {
|
|||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QUOTED_SPECIFIER_RE = /(["']).*\1/
|
||||||
function getQuotedSpecifier (id: string) {
|
function getQuotedSpecifier (id: string) {
|
||||||
return id.match(/(["']).*\1/)?.[0]
|
return id.match(QUOTED_SPECIFIER_RE)?.[0]
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { KeepAliveProps, TransitionProps, UnwrapRef } from 'vue'
|
import type { KeepAliveProps, TransitionProps, UnwrapRef } from 'vue'
|
||||||
import { getCurrentInstance } from 'vue'
|
import { getCurrentInstance } from 'vue'
|
||||||
import type { RouteLocationNormalized, RouteLocationNormalizedLoaded, RouteRecordRedirectOption } from 'vue-router'
|
import type { RouteLocationNormalized, RouteLocationNormalizedLoaded, RouteRecordRaw, RouteRecordRedirectOption } from 'vue-router'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import type { NitroRouteConfig } from 'nitro/types'
|
import type { NitroRouteConfig } from 'nitro/types'
|
||||||
import { useNuxtApp } from '#app/nuxt'
|
import { useNuxtApp } from '#app/nuxt'
|
||||||
@ -37,6 +37,11 @@ export interface PageMeta {
|
|||||||
name?: string
|
name?: string
|
||||||
/** You may define a path matcher, if you have a more complex pattern than can be expressed with the file name. */
|
/** You may define a path matcher, if you have a more complex pattern than can be expressed with the file name. */
|
||||||
path?: string
|
path?: string
|
||||||
|
/**
|
||||||
|
* Allows accessing the route `params` as props passed to the page component.
|
||||||
|
* @see https://router.vuejs.org/guide/essentials/passing-props
|
||||||
|
*/
|
||||||
|
props?: RouteRecordRaw['props']
|
||||||
/** Set to `false` to avoid scrolling to top on page navigations */
|
/** Set to `false` to avoid scrolling to top on page navigations */
|
||||||
scrollToTop?: boolean | ((to: RouteLocationNormalizedLoaded, from: RouteLocationNormalizedLoaded) => boolean)
|
scrollToTop?: boolean | ((to: RouteLocationNormalizedLoaded, from: RouteLocationNormalizedLoaded) => boolean)
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,14 @@ type InstanceOf<T> = T extends new (...args: any[]) => infer R ? R : never
|
|||||||
type RouterViewSlot = Exclude<InstanceOf<typeof RouterView>['$slots']['default'], undefined>
|
type RouterViewSlot = Exclude<InstanceOf<typeof RouterView>['$slots']['default'], undefined>
|
||||||
export type RouterViewSlotProps = Parameters<RouterViewSlot>[0]
|
export type RouterViewSlotProps = Parameters<RouterViewSlot>[0]
|
||||||
|
|
||||||
|
const ROUTE_KEY_PARENTHESES_RE = /(:\w+)\([^)]+\)/g
|
||||||
|
const ROUTE_KEY_SYMBOLS_RE = /(:\w+)[?+*]/g
|
||||||
|
const ROUTE_KEY_NORMAL_RE = /:\w+/g
|
||||||
const interpolatePath = (route: RouteLocationNormalizedLoaded, match: RouteLocationMatched) => {
|
const interpolatePath = (route: RouteLocationNormalizedLoaded, match: RouteLocationMatched) => {
|
||||||
return match.path
|
return match.path
|
||||||
.replace(/(:\w+)\([^)]+\)/g, '$1')
|
.replace(ROUTE_KEY_PARENTHESES_RE, '$1')
|
||||||
.replace(/(:\w+)[?+*]/g, '$1')
|
.replace(ROUTE_KEY_SYMBOLS_RE, '$1')
|
||||||
.replace(/:\w+/g, r => route.params[r.slice(1)]?.toString() || '')
|
.replace(ROUTE_KEY_NORMAL_RE, r => route.params[r.slice(1)]?.toString() || '')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateRouteKey = (routeProps: RouterViewSlotProps, override?: string | ((route: RouteLocationNormalizedLoaded) => string)) => {
|
export const generateRouteKey = (routeProps: RouterViewSlotProps, override?: string | ((route: RouteLocationNormalizedLoaded) => string)) => {
|
||||||
|
@ -64,18 +64,25 @@ export async function resolvePagesRoutes (): Promise<NuxtPage[]> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const pages = uniqueBy(allRoutes, 'path')
|
const pages = uniqueBy(allRoutes, 'path')
|
||||||
|
|
||||||
const shouldAugment = nuxt.options.experimental.scanPageMeta || nuxt.options.experimental.typedPages
|
const shouldAugment = nuxt.options.experimental.scanPageMeta || nuxt.options.experimental.typedPages
|
||||||
|
|
||||||
if (shouldAugment) {
|
if (shouldAugment === false) {
|
||||||
|
await nuxt.callHook('pages:extend', pages)
|
||||||
|
return pages
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldAugment === 'after-resolve') {
|
||||||
|
await nuxt.callHook('pages:extend', pages)
|
||||||
|
await augmentPages(pages, nuxt.vfs)
|
||||||
|
} else {
|
||||||
const augmentedPages = await augmentPages(pages, nuxt.vfs)
|
const augmentedPages = await augmentPages(pages, nuxt.vfs)
|
||||||
await nuxt.callHook('pages:extend', pages)
|
await nuxt.callHook('pages:extend', pages)
|
||||||
await augmentPages(pages, nuxt.vfs, augmentedPages)
|
await augmentPages(pages, nuxt.vfs, augmentedPages)
|
||||||
augmentedPages.clear()
|
augmentedPages.clear()
|
||||||
} else {
|
|
||||||
await nuxt.callHook('pages:extend', pages)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await nuxt.callHook('pages:resolved', pages)
|
||||||
|
|
||||||
return pages
|
return pages
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +90,7 @@ type GenerateRoutesFromFilesOptions = {
|
|||||||
shouldUseServerComponents?: boolean
|
shouldUseServerComponents?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const INDEX_PAGE_RE = /\/index$/
|
||||||
export function generateRoutesFromFiles (files: ScannedFile[], options: GenerateRoutesFromFilesOptions = {}): NuxtPage[] {
|
export function generateRoutesFromFiles (files: ScannedFile[], options: GenerateRoutesFromFilesOptions = {}): NuxtPage[] {
|
||||||
const routes: NuxtPage[] = []
|
const routes: NuxtPage[] = []
|
||||||
|
|
||||||
@ -128,7 +136,7 @@ export function generateRoutesFromFiles (files: ScannedFile[], options: Generate
|
|||||||
route.name += (route.name && '/') + segmentName
|
route.name += (route.name && '/') + segmentName
|
||||||
|
|
||||||
// ex: parent.vue + parent/child.vue
|
// ex: parent.vue + parent/child.vue
|
||||||
const path = withLeadingSlash(joinURL(route.path, getRoutePath(tokens).replace(/\/index$/, '/')))
|
const path = withLeadingSlash(joinURL(route.path, getRoutePath(tokens).replace(INDEX_PAGE_RE, '/')))
|
||||||
const child = parent.find(parentRoute => parentRoute.name === route.name && parentRoute.path === path)
|
const child = parent.find(parentRoute => parentRoute.name === route.name && parentRoute.path === path)
|
||||||
|
|
||||||
if (child && child.children) {
|
if (child && child.children) {
|
||||||
@ -183,7 +191,7 @@ export function extractScriptContent (html: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const PAGE_META_RE = /definePageMeta\([\s\S]*?\)/
|
const PAGE_META_RE = /definePageMeta\([\s\S]*?\)/
|
||||||
const extractionKeys = ['name', 'path', 'alias', 'redirect'] as const
|
const extractionKeys = ['name', 'path', 'props', 'alias', 'redirect'] as const
|
||||||
const DYNAMIC_META_KEY = '__nuxt_dynamic_meta_key' as const
|
const DYNAMIC_META_KEY = '__nuxt_dynamic_meta_key' as const
|
||||||
|
|
||||||
const pageContentsCache: Record<string, string> = {}
|
const pageContentsCache: Record<string, string> = {}
|
||||||
@ -265,7 +273,7 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.value.type !== 'Literal' || typeof property.value.value !== 'string') {
|
if (property.value.type !== 'Literal' || (typeof property.value.value !== 'string' && typeof property.value.value !== 'boolean')) {
|
||||||
console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not a string literal or array of string literals (reading \`${absolutePath}\`).`)
|
console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not a string literal or array of string literals (reading \`${absolutePath}\`).`)
|
||||||
dynamicProperties.add(key)
|
dynamicProperties.add(key)
|
||||||
continue
|
continue
|
||||||
@ -300,6 +308,7 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro
|
|||||||
return extractedMeta
|
return extractedMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const COLON_RE = /:/g
|
||||||
function getRoutePath (tokens: SegmentToken[]): string {
|
function getRoutePath (tokens: SegmentToken[]): string {
|
||||||
return tokens.reduce((path, token) => {
|
return tokens.reduce((path, token) => {
|
||||||
return (
|
return (
|
||||||
@ -312,7 +321,7 @@ function getRoutePath (tokens: SegmentToken[]): string {
|
|||||||
? `:${token.value}(.*)*`
|
? `:${token.value}(.*)*`
|
||||||
: token.type === SegmentTokenType.group
|
: token.type === SegmentTokenType.group
|
||||||
? ''
|
? ''
|
||||||
: encodePath(token.value).replace(/:/g, '\\:'))
|
: encodePath(token.value).replace(COLON_RE, '\\:'))
|
||||||
)
|
)
|
||||||
}, '/')
|
}, '/')
|
||||||
}
|
}
|
||||||
@ -432,13 +441,14 @@ function findRouteByName (name: string, routes: NuxtPage[]): NuxtPage | undefine
|
|||||||
return findRouteByName(name, routes)
|
return findRouteByName(name, routes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NESTED_PAGE_RE = /\//g
|
||||||
function prepareRoutes (routes: NuxtPage[], parent?: NuxtPage, names = new Set<string>()) {
|
function prepareRoutes (routes: NuxtPage[], parent?: NuxtPage, names = new Set<string>()) {
|
||||||
for (const route of routes) {
|
for (const route of routes) {
|
||||||
// Remove -index
|
// Remove -index
|
||||||
if (route.name) {
|
if (route.name) {
|
||||||
route.name = route.name
|
route.name = route.name
|
||||||
.replace(/\/index$/, '')
|
.replace(INDEX_PAGE_RE, '')
|
||||||
.replace(/\//g, '-')
|
.replace(NESTED_PAGE_RE, '-')
|
||||||
|
|
||||||
if (names.has(route.name)) {
|
if (names.has(route.name)) {
|
||||||
const existingRoute = findRouteByName(route.name, routes)
|
const existingRoute = findRouteByName(route.name, routes)
|
||||||
@ -532,6 +542,7 @@ export function normalizeRoutes (routes: NuxtPage[], metaImports: Set<string> =
|
|||||||
const metaRoute: NormalizedRoute = {
|
const metaRoute: NormalizedRoute = {
|
||||||
name: `${metaImportName}?.name ?? ${route.name}`,
|
name: `${metaImportName}?.name ?? ${route.name}`,
|
||||||
path: `${metaImportName}?.path ?? ${route.path}`,
|
path: `${metaImportName}?.path ?? ${route.path}`,
|
||||||
|
props: `${metaImportName}?.props ?? false`,
|
||||||
meta: `${metaImportName} || {}`,
|
meta: `${metaImportName} || {}`,
|
||||||
alias: `${metaImportName}?.alias || []`,
|
alias: `${metaImportName}?.alias || []`,
|
||||||
redirect: `${metaImportName}?.redirect`,
|
redirect: `${metaImportName}?.redirect`,
|
||||||
@ -575,7 +586,7 @@ async function createClientPage(loader) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set to extracted value or delete if none extracted
|
// set to extracted value or delete if none extracted
|
||||||
for (const key of ['meta', 'alias', 'redirect'] satisfies NormalizedRouteKeys) {
|
for (const key of ['meta', 'alias', 'redirect', 'props'] satisfies NormalizedRouteKeys) {
|
||||||
if (markedDynamic.has(key)) { continue }
|
if (markedDynamic.has(key)) { continue }
|
||||||
|
|
||||||
if (route[key] == null) {
|
if (route[key] == null) {
|
||||||
@ -600,6 +611,7 @@ async function createClientPage(loader) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PATH_TO_NITRO_GLOB_RE = /\/[^:/]*:\w.*$/
|
||||||
export function pathToNitroGlob (path: string) {
|
export function pathToNitroGlob (path: string) {
|
||||||
if (!path) {
|
if (!path) {
|
||||||
return null
|
return null
|
||||||
@ -609,7 +621,7 @@ export function pathToNitroGlob (path: string) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return path.replace(/\/[^:/]*:\w.*$/, '/**')
|
return path.replace(PATH_TO_NITRO_GLOB_RE, '/**')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveRoutePaths (page: NuxtPage, parent = '/'): string[] {
|
export function resolveRoutePaths (page: NuxtPage, parent = '/'): string[] {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"meta": "{ ...(mockMeta || {}), ...{"someMetaData":true} }",
|
"meta": "{ ...(mockMeta || {}), ...{"someMetaData":true} }",
|
||||||
"name": "mockMeta?.name ?? "pushed-route"",
|
"name": "mockMeta?.name ?? "pushed-route"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -24,6 +25,18 @@
|
|||||||
"meta": "{ ...(mockMeta || {}), ...{"test":1} }",
|
"meta": "{ ...(mockMeta || {}), ...{"test":1} }",
|
||||||
"name": "mockMeta?.name ?? "page-with-meta"",
|
"name": "mockMeta?.name ?? "page-with-meta"",
|
||||||
"path": "mockMeta?.path ?? "/page-with-meta"",
|
"path": "mockMeta?.path ?? "/page-with-meta"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
|
"redirect": "mockMeta?.redirect",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"route.meta props generate by file": [
|
||||||
|
{
|
||||||
|
"alias": "mockMeta?.alias || []",
|
||||||
|
"component": "() => import("pages/page-with-props.vue")",
|
||||||
|
"meta": "mockMeta || {}",
|
||||||
|
"name": "mockMeta?.name ?? "page-with-props"",
|
||||||
|
"path": "mockMeta?.path ?? "/page-with-props"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -34,6 +47,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "test:name"",
|
"name": "mockMeta?.name ?? "test:name"",
|
||||||
"path": "mockMeta?.path ?? "/test\\:name"",
|
"path": "mockMeta?.path ?? "/test\\:name"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -50,6 +64,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "param-index"",
|
"name": "mockMeta?.name ?? "param-index"",
|
||||||
"path": "mockMeta?.path ?? """,
|
"path": "mockMeta?.path ?? """,
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -58,6 +73,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "param-index-sibling"",
|
"name": "mockMeta?.name ?? "param-index-sibling"",
|
||||||
"path": "mockMeta?.path ?? "sibling"",
|
"path": "mockMeta?.path ?? "sibling"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -65,6 +81,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? undefined",
|
"name": "mockMeta?.name ?? undefined",
|
||||||
"path": "mockMeta?.path ?? """,
|
"path": "mockMeta?.path ?? """,
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -73,6 +90,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "param-sibling"",
|
"name": "mockMeta?.name ?? "param-sibling"",
|
||||||
"path": "mockMeta?.path ?? "sibling"",
|
"path": "mockMeta?.path ?? "sibling"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -80,6 +98,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? undefined",
|
"name": "mockMeta?.name ?? undefined",
|
||||||
"path": "mockMeta?.path ?? "/param"",
|
"path": "mockMeta?.path ?? "/param"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -91,6 +110,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "wrapper-expose-other"",
|
"name": "mockMeta?.name ?? "wrapper-expose-other"",
|
||||||
"path": "mockMeta?.path ?? """,
|
"path": "mockMeta?.path ?? """,
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -99,6 +119,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "wrapper-expose-other-sibling"",
|
"name": "mockMeta?.name ?? "wrapper-expose-other-sibling"",
|
||||||
"path": "mockMeta?.path ?? "sibling"",
|
"path": "mockMeta?.path ?? "sibling"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -106,6 +127,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? undefined",
|
"name": "mockMeta?.name ?? undefined",
|
||||||
"path": "mockMeta?.path ?? "/wrapper-expose/other"",
|
"path": "mockMeta?.path ?? "/wrapper-expose/other"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -116,6 +138,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "home"",
|
"name": "mockMeta?.name ?? "home"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": ""/"",
|
"redirect": ""/"",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -126,6 +149,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "slug"",
|
"name": "mockMeta?.name ?? "slug"",
|
||||||
"path": "mockMeta?.path ?? "/:slug(.*)*"",
|
"path": "mockMeta?.path ?? "/:slug(.*)*"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -134,6 +158,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "index"",
|
"name": "mockMeta?.name ?? "index"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -144,6 +169,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "index"",
|
"name": "mockMeta?.name ?? "index"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -152,6 +178,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "slug"",
|
"name": "mockMeta?.name ?? "slug"",
|
||||||
"path": "mockMeta?.path ?? "/:slug()"",
|
"path": "mockMeta?.path ?? "/:slug()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -163,6 +190,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "foo"",
|
"name": "mockMeta?.name ?? "foo"",
|
||||||
"path": "mockMeta?.path ?? """,
|
"path": "mockMeta?.path ?? """,
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -170,6 +198,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? undefined",
|
"name": "mockMeta?.name ?? undefined",
|
||||||
"path": "mockMeta?.path ?? "/:foo?"",
|
"path": "mockMeta?.path ?? "/:foo?"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -178,6 +207,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "optional-opt"",
|
"name": "mockMeta?.name ?? "optional-opt"",
|
||||||
"path": "mockMeta?.path ?? "/optional/:opt?"",
|
"path": "mockMeta?.path ?? "/optional/:opt?"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -186,6 +216,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "optional-prefix-opt"",
|
"name": "mockMeta?.name ?? "optional-prefix-opt"",
|
||||||
"path": "mockMeta?.path ?? "/optional/prefix-:opt?"",
|
"path": "mockMeta?.path ?? "/optional/prefix-:opt?"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -194,6 +225,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "optional-opt-postfix"",
|
"name": "mockMeta?.name ?? "optional-opt-postfix"",
|
||||||
"path": "mockMeta?.path ?? "/optional/:opt?-postfix"",
|
"path": "mockMeta?.path ?? "/optional/:opt?-postfix"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -202,6 +234,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "optional-prefix-opt-postfix"",
|
"name": "mockMeta?.name ?? "optional-prefix-opt-postfix"",
|
||||||
"path": "mockMeta?.path ?? "/optional/prefix-:opt?-postfix"",
|
"path": "mockMeta?.path ?? "/optional/prefix-:opt?-postfix"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -210,6 +243,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "bar"",
|
"name": "mockMeta?.name ?? "bar"",
|
||||||
"path": "mockMeta?.path ?? "/:bar()"",
|
"path": "mockMeta?.path ?? "/:bar()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -218,6 +252,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "nonopt-slug"",
|
"name": "mockMeta?.name ?? "nonopt-slug"",
|
||||||
"path": "mockMeta?.path ?? "/nonopt/:slug()"",
|
"path": "mockMeta?.path ?? "/nonopt/:slug()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -226,6 +261,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "opt-slug"",
|
"name": "mockMeta?.name ?? "opt-slug"",
|
||||||
"path": "mockMeta?.path ?? "/opt/:slug?"",
|
"path": "mockMeta?.path ?? "/opt/:slug?"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -234,6 +270,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "sub-route-slug"",
|
"name": "mockMeta?.name ?? "sub-route-slug"",
|
||||||
"path": "mockMeta?.path ?? "/:sub?/route-:slug()"",
|
"path": "mockMeta?.path ?? "/:sub?/route-:slug()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -244,6 +281,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "stories"",
|
"name": "mockMeta?.name ?? "stories"",
|
||||||
"path": "mockMeta?.path ?? "/:stories(.*)*"",
|
"path": "mockMeta?.path ?? "/:stories(.*)*"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -252,6 +290,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "stories-id"",
|
"name": "mockMeta?.name ?? "stories-id"",
|
||||||
"path": "mockMeta?.path ?? "/stories/:id()"",
|
"path": "mockMeta?.path ?? "/stories/:id()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -262,6 +301,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "stories-id"",
|
"name": "mockMeta?.name ?? "stories-id"",
|
||||||
"path": "mockMeta?.path ?? "/stories/:id()"",
|
"path": "mockMeta?.path ?? "/stories/:id()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -270,6 +310,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "stories"",
|
"name": "mockMeta?.name ?? "stories"",
|
||||||
"path": "mockMeta?.path ?? "/:stories(.*)*"",
|
"path": "mockMeta?.path ?? "/:stories(.*)*"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -280,6 +321,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "kebab-case"",
|
"name": "mockMeta?.name ?? "kebab-case"",
|
||||||
"path": "mockMeta?.path ?? "/kebab-case"",
|
"path": "mockMeta?.path ?? "/kebab-case"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -290,6 +332,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "snake_case"",
|
"name": "mockMeta?.name ?? "snake_case"",
|
||||||
"path": "mockMeta?.path ?? "/snake_case"",
|
"path": "mockMeta?.path ?? "/snake_case"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -300,6 +343,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "index"",
|
"name": "mockMeta?.name ?? "index"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -308,6 +352,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "parent"",
|
"name": "mockMeta?.name ?? "parent"",
|
||||||
"path": "mockMeta?.path ?? "/parent"",
|
"path": "mockMeta?.path ?? "/parent"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -316,6 +361,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "parent-child"",
|
"name": "mockMeta?.name ?? "parent-child"",
|
||||||
"path": "mockMeta?.path ?? "/parent/child"",
|
"path": "mockMeta?.path ?? "/parent/child"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -329,6 +375,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "parent-child"",
|
"name": "mockMeta?.name ?? "parent-child"",
|
||||||
"path": "mockMeta?.path ?? "child"",
|
"path": "mockMeta?.path ?? "child"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -336,6 +383,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "parent"",
|
"name": "mockMeta?.name ?? "parent"",
|
||||||
"path": "mockMeta?.path ?? "/parent"",
|
"path": "mockMeta?.path ?? "/parent"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -346,6 +394,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "index"",
|
"name": "mockMeta?.name ?? "index"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -357,6 +406,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "about"",
|
"name": "mockMeta?.name ?? "about"",
|
||||||
"path": "mockMeta?.path ?? """,
|
"path": "mockMeta?.path ?? """,
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -364,6 +414,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? undefined",
|
"name": "mockMeta?.name ?? undefined",
|
||||||
"path": "mockMeta?.path ?? "/about"",
|
"path": "mockMeta?.path ?? "/about"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -377,6 +428,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "index-index-all"",
|
"name": "mockMeta?.name ?? "index-index-all"",
|
||||||
"path": "mockMeta?.path ?? "all"",
|
"path": "mockMeta?.path ?? "all"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -384,6 +436,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "index"",
|
"name": "mockMeta?.name ?? "index"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -394,6 +447,7 @@
|
|||||||
"meta": "{ ...(mockMeta || {}), ...{"test":1} }",
|
"meta": "{ ...(mockMeta || {}), ...{"test":1} }",
|
||||||
"name": "mockMeta?.name ?? "page-with-meta"",
|
"name": "mockMeta?.name ?? "page-with-meta"",
|
||||||
"path": "mockMeta?.path ?? "/page-with-meta"",
|
"path": "mockMeta?.path ?? "/page-with-meta"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -404,6 +458,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "parent-child"",
|
"name": "mockMeta?.name ?? "parent-child"",
|
||||||
"path": "mockMeta?.path ?? "/parent/:child()"",
|
"path": "mockMeta?.path ?? "/parent/:child()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -412,6 +467,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "parent-child"",
|
"name": "mockMeta?.name ?? "parent-child"",
|
||||||
"path": "mockMeta?.path ?? "/parent-:child()"",
|
"path": "mockMeta?.path ?? "/parent-:child()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -422,6 +478,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "foo"",
|
"name": "mockMeta?.name ?? "foo"",
|
||||||
"path": "mockMeta?.path ?? "/:foo?"",
|
"path": "mockMeta?.path ?? "/:foo?"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -430,6 +487,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "foo"",
|
"name": "mockMeta?.name ?? "foo"",
|
||||||
"path": "mockMeta?.path ?? "/:foo()"",
|
"path": "mockMeta?.path ?? "/:foo()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -440,6 +498,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "a1_1a"",
|
"name": "mockMeta?.name ?? "a1_1a"",
|
||||||
"path": "mockMeta?.path ?? "/:a1_1a()"",
|
"path": "mockMeta?.path ?? "/:a1_1a()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -448,6 +507,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "b2.2b"",
|
"name": "mockMeta?.name ?? "b2.2b"",
|
||||||
"path": "mockMeta?.path ?? "/:b2.2b()"",
|
"path": "mockMeta?.path ?? "/:b2.2b()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -456,6 +516,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "b2_2b"",
|
"name": "mockMeta?.name ?? "b2_2b"",
|
||||||
"path": "mockMeta?.path ?? "/:b2()_:2b()"",
|
"path": "mockMeta?.path ?? "/:b2()_:2b()"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -464,6 +525,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "c33c"",
|
"name": "mockMeta?.name ?? "c33c"",
|
||||||
"path": "mockMeta?.path ?? "/:c33c?"",
|
"path": "mockMeta?.path ?? "/:c33c?"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -472,6 +534,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "d44d"",
|
"name": "mockMeta?.name ?? "d44d"",
|
||||||
"path": "mockMeta?.path ?? "/:d44d?"",
|
"path": "mockMeta?.path ?? "/:d44d?"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -482,6 +545,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "home"",
|
"name": "mockMeta?.name ?? "home"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -492,6 +556,7 @@
|
|||||||
"meta": "mockMeta || {}",
|
"meta": "mockMeta || {}",
|
||||||
"name": "mockMeta?.name ?? "index"",
|
"name": "mockMeta?.name ?? "index"",
|
||||||
"path": "mockMeta?.path ?? "/"",
|
"path": "mockMeta?.path ?? "/"",
|
||||||
|
"props": "mockMeta?.props ?? false",
|
||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -24,6 +24,13 @@
|
|||||||
"path": ""/page-with-meta"",
|
"path": ""/page-with-meta"",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
"route.meta props generate by file": [
|
||||||
|
{
|
||||||
|
"component": "() => import("pages/page-with-props.vue")",
|
||||||
|
"name": ""page-with-props"",
|
||||||
|
"path": ""/page-with-props"",
|
||||||
|
},
|
||||||
|
],
|
||||||
"should allow pages with `:` in their path": [
|
"should allow pages with `:` in their path": [
|
||||||
{
|
{
|
||||||
"component": "() => import("pages/test:name.vue")",
|
"component": "() => import("pages/test:name.vue")",
|
||||||
|
@ -211,6 +211,7 @@ describe('normalizeRoutes', () => {
|
|||||||
{
|
{
|
||||||
name: indexN6pT4Un8hYMeta?.name ?? undefined,
|
name: indexN6pT4Un8hYMeta?.name ?? undefined,
|
||||||
path: indexN6pT4Un8hYMeta?.path ?? "/",
|
path: indexN6pT4Un8hYMeta?.path ?? "/",
|
||||||
|
props: indexN6pT4Un8hYMeta?.props ?? false,
|
||||||
meta: { ...(indexN6pT4Un8hYMeta || {}), ...{"layout":"test","foo":"bar"} },
|
meta: { ...(indexN6pT4Un8hYMeta || {}), ...{"layout":"test","foo":"bar"} },
|
||||||
alias: indexN6pT4Un8hYMeta?.alias || [],
|
alias: indexN6pT4Un8hYMeta?.alias || [],
|
||||||
redirect: indexN6pT4Un8hYMeta?.redirect,
|
redirect: indexN6pT4Un8hYMeta?.redirect,
|
||||||
|
@ -601,6 +601,30 @@ describe('pages:generateRoutesFromFiles', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: 'route.meta props generate by file',
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
path: `${pagesDir}/page-with-props.vue`,
|
||||||
|
template: `
|
||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
props: true
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
name: 'page-with-props',
|
||||||
|
path: '/page-with-props',
|
||||||
|
file: `${pagesDir}/page-with-props.vue`,
|
||||||
|
children: [],
|
||||||
|
props: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: 'should handle route groups',
|
description: 'should handle route groups',
|
||||||
files: [
|
files: [
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/friendly-errors-webpack-plugin": "^2.6.0",
|
"@nuxt/friendly-errors-webpack-plugin": "^2.6.0",
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
"@rspack/core": "^1.0.10",
|
"@rspack/core": "^1.0.14",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"css-minimizer-webpack-plugin": "^7.0.0",
|
"css-minimizer-webpack-plugin": "^7.0.0",
|
||||||
@ -81,7 +81,7 @@
|
|||||||
"@types/pify": "5.0.4",
|
"@types/pify": "5.0.4",
|
||||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||||
"@types/webpack-hot-middleware": "2.25.9",
|
"@types/webpack-hot-middleware": "2.25.9",
|
||||||
"rollup": "4.24.0",
|
"rollup": "4.24.2",
|
||||||
"unbuild": "3.0.0-rc.11",
|
"unbuild": "3.0.0-rc.11",
|
||||||
"vue": "3.5.12"
|
"vue": "3.5.12"
|
||||||
},
|
},
|
||||||
|
@ -39,12 +39,12 @@
|
|||||||
"@types/file-loader": "5.0.4",
|
"@types/file-loader": "5.0.4",
|
||||||
"@types/pug": "2.0.10",
|
"@types/pug": "2.0.10",
|
||||||
"@types/sass-loader": "8.0.9",
|
"@types/sass-loader": "8.0.9",
|
||||||
"@unhead/schema": "1.11.7",
|
"@unhead/schema": "1.11.10",
|
||||||
"@vitejs/plugin-vue": "5.1.4",
|
"@vitejs/plugin-vue": "5.1.4",
|
||||||
"@vitejs/plugin-vue-jsx": "4.0.1",
|
"@vitejs/plugin-vue-jsx": "4.0.1",
|
||||||
"@vue/compiler-core": "3.5.12",
|
"@vue/compiler-core": "3.5.12",
|
||||||
"@vue/compiler-sfc": "3.5.12",
|
"@vue/compiler-sfc": "3.5.12",
|
||||||
"@vue/language-core": "2.1.6",
|
"@vue/language-core": "2.1.8",
|
||||||
"esbuild-loader": "4.2.2",
|
"esbuild-loader": "4.2.2",
|
||||||
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
||||||
"ignore": "6.0.2",
|
"ignore": "6.0.2",
|
||||||
@ -53,7 +53,7 @@
|
|||||||
"unbuild": "3.0.0-rc.11",
|
"unbuild": "3.0.0-rc.11",
|
||||||
"unctx": "2.3.1",
|
"unctx": "2.3.1",
|
||||||
"unenv": "1.10.0",
|
"unenv": "1.10.0",
|
||||||
"vite": "5.4.8",
|
"vite": "5.4.10",
|
||||||
"vue": "3.5.12",
|
"vue": "3.5.12",
|
||||||
"vue-bundle-renderer": "2.1.1",
|
"vue-bundle-renderer": "2.1.1",
|
||||||
"vue-loader": "17.4.2",
|
"vue-loader": "17.4.2",
|
||||||
|
@ -297,8 +297,13 @@ export default defineUntypedSchema({
|
|||||||
* This only works with static or strings/arrays rather than variables or conditional assignment.
|
* This only works with static or strings/arrays rather than variables or conditional assignment.
|
||||||
*
|
*
|
||||||
* @see [Nuxt Issues #24770](https://github.com/nuxt/nuxt/issues/24770)
|
* @see [Nuxt Issues #24770](https://github.com/nuxt/nuxt/issues/24770)
|
||||||
|
* @type {boolean | 'after-resolve'}
|
||||||
*/
|
*/
|
||||||
scanPageMeta: true,
|
scanPageMeta: {
|
||||||
|
async $resolve (val, get) {
|
||||||
|
return val ?? ((await get('future') as Record<string, unknown>).compatibilityVersion === 4 ? 'after-resolve' : true)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Automatically share payload _data_ between pages that are prerendered. This can result in a significant
|
* Automatically share payload _data_ between pages that are prerendered. This can result in a significant
|
||||||
|
@ -68,6 +68,7 @@ export type NuxtConfigLayer = ResolvedConfig<NuxtConfig & {
|
|||||||
rootDir: ConfigSchema['rootDir']
|
rootDir: ConfigSchema['rootDir']
|
||||||
}> & {
|
}> & {
|
||||||
cwd: string
|
cwd: string
|
||||||
|
configFile: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NuxtBuilder {
|
export interface NuxtBuilder {
|
||||||
|
@ -8,7 +8,7 @@ import type { Import, InlinePreset, Unimport } from 'unimport'
|
|||||||
import type { Compiler, Configuration, Stats } from 'webpack'
|
import type { Compiler, Configuration, Stats } from 'webpack'
|
||||||
import type { Nitro, NitroConfig } from 'nitro/types'
|
import type { Nitro, NitroConfig } from 'nitro/types'
|
||||||
import type { Schema, SchemaDefinition } from 'untyped'
|
import type { Schema, SchemaDefinition } from 'untyped'
|
||||||
import type { RouteLocationRaw } from 'vue-router'
|
import type { RouteLocationRaw, RouteRecordRaw } from 'vue-router'
|
||||||
import type { VueCompilerOptions } from '@vue/language-core'
|
import type { VueCompilerOptions } from '@vue/language-core'
|
||||||
import type { NuxtCompatibility, NuxtCompatibilityIssues, ViteConfig } from '..'
|
import type { NuxtCompatibility, NuxtCompatibilityIssues, ViteConfig } from '..'
|
||||||
import type { Component, ComponentsOptions } from './components'
|
import type { Component, ComponentsOptions } from './components'
|
||||||
@ -28,6 +28,7 @@ export type VueTSConfig = 0 extends 1 & VueCompilerOptions ? TSConfig : TSConfig
|
|||||||
export type NuxtPage = {
|
export type NuxtPage = {
|
||||||
name?: string
|
name?: string
|
||||||
path: string
|
path: string
|
||||||
|
props?: RouteRecordRaw['props']
|
||||||
file?: string
|
file?: string
|
||||||
meta?: Record<string, any>
|
meta?: Record<string, any>
|
||||||
alias?: string[] | string
|
alias?: string[] | string
|
||||||
@ -183,12 +184,19 @@ export interface NuxtHooks {
|
|||||||
'builder:watch': (event: WatchEvent, path: string) => HookResult
|
'builder:watch': (event: WatchEvent, path: string) => HookResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called after pages routes are resolved.
|
* Called after page routes are scanned from the file system.
|
||||||
* @param pages Array containing resolved pages
|
* @param pages Array containing scanned pages
|
||||||
* @returns Promise
|
* @returns Promise
|
||||||
*/
|
*/
|
||||||
'pages:extend': (pages: NuxtPage[]) => HookResult
|
'pages:extend': (pages: NuxtPage[]) => HookResult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after page routes have been augmented with scanned metadata.
|
||||||
|
* @param pages Array containing resolved pages
|
||||||
|
* @returns Promise
|
||||||
|
*/
|
||||||
|
'pages:resolved': (pages: NuxtPage[]) => HookResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when resolving `app/router.options` files. It allows modifying the detected router options files
|
* Called when resolving `app/router.options` files. It allows modifying the detected router options files
|
||||||
* and adding new ones.
|
* and adding new ones.
|
||||||
|
@ -18,18 +18,18 @@
|
|||||||
"test": "pnpm lint && pnpm build"
|
"test": "pnpm lint && pnpm build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@unocss/reset": "0.63.4",
|
"@unocss/reset": "0.63.6",
|
||||||
"critters": "0.0.25",
|
"critters": "0.0.25",
|
||||||
"html-validate": "8.24.1",
|
"html-validate": "8.24.2",
|
||||||
"htmlnano": "2.1.1",
|
"htmlnano": "2.1.1",
|
||||||
"jiti": "2.3.3",
|
"jiti": "2.3.3",
|
||||||
"knitwork": "1.1.0",
|
"knitwork": "1.1.0",
|
||||||
"pathe": "1.1.2",
|
"pathe": "1.1.2",
|
||||||
"prettier": "3.3.3",
|
"prettier": "3.3.3",
|
||||||
"scule": "1.3.0",
|
"scule": "1.3.0",
|
||||||
"tinyexec": "0.3.0",
|
"tinyexec": "0.3.1",
|
||||||
"tinyglobby": "0.2.9",
|
"tinyglobby": "0.2.10",
|
||||||
"unocss": "0.63.4",
|
"unocss": "0.63.6",
|
||||||
"vite": "5.4.8"
|
"vite": "5.4.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
|||||||
import { exec } from 'tinyexec'
|
import { exec } from 'tinyexec'
|
||||||
import { format } from 'prettier'
|
import { format } from 'prettier'
|
||||||
import { createJiti } from 'jiti'
|
import { createJiti } from 'jiti'
|
||||||
// @ts-expect-error types not valid for bundler resolution
|
|
||||||
import { HtmlValidate } from 'html-validate'
|
import { HtmlValidate } from 'html-validate'
|
||||||
|
|
||||||
const distDir = fileURLToPath(new URL('../node_modules/.temp/dist/templates', import.meta.url))
|
const distDir = fileURLToPath(new URL('../node_modules/.temp/dist/templates', import.meta.url))
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"@types/clear": "0.1.4",
|
"@types/clear": "0.1.4",
|
||||||
"@types/estree": "1.0.6",
|
"@types/estree": "1.0.6",
|
||||||
"rollup": "4.24.0",
|
"rollup": "4.24.2",
|
||||||
"unbuild": "3.0.0-rc.11",
|
"unbuild": "3.0.0-rc.11",
|
||||||
"vue": "3.5.12"
|
"vue": "3.5.12"
|
||||||
},
|
},
|
||||||
@ -62,8 +62,8 @@
|
|||||||
"ufo": "^1.5.4",
|
"ufo": "^1.5.4",
|
||||||
"unenv": "^1.10.0",
|
"unenv": "^1.10.0",
|
||||||
"unplugin": "^1.14.1",
|
"unplugin": "^1.14.1",
|
||||||
"vite": "^5.4.8",
|
"vite": "^5.4.10",
|
||||||
"vite-node": "^2.1.2",
|
"vite-node": "^2.1.3",
|
||||||
"vite-plugin-checker": "^0.8.0",
|
"vite-plugin-checker": "^0.8.0",
|
||||||
"vue-bundle-renderer": "^2.1.1"
|
"vue-bundle-renderer": "^2.1.1"
|
||||||
},
|
},
|
||||||
|
@ -9,13 +9,12 @@ function sortPlugins ({ plugins, order }: NuxtOptions['postcss']): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function resolveCSSOptions (nuxt: Nuxt): Promise<ViteConfig['css']> {
|
export async function resolveCSSOptions (nuxt: Nuxt): Promise<ViteConfig['css']> {
|
||||||
const css: ViteConfig['css'] & { postcss: NonNullable<Exclude<NonNullable<ViteConfig['css']>['postcss'], string>> } = {
|
const css: ViteConfig['css'] & { postcss: NonNullable<Exclude<NonNullable<ViteConfig['css']>['postcss'], string>> & { plugins: Plugin[] } } = {
|
||||||
postcss: {
|
postcss: {
|
||||||
plugins: [],
|
plugins: [],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
css.postcss.plugins = []
|
|
||||||
const postcssOptions = nuxt.options.postcss
|
const postcssOptions = nuxt.options.postcss
|
||||||
|
|
||||||
const jiti = createJiti(nuxt.options.rootDir, { alias: nuxt.options.alias })
|
const jiti = createJiti(nuxt.options.rootDir, { alias: nuxt.options.alias })
|
||||||
|
@ -20,6 +20,7 @@ interface ComposableKeysOptions {
|
|||||||
const stringTypes: Array<string | undefined> = ['Literal', 'TemplateLiteral']
|
const stringTypes: Array<string | undefined> = ['Literal', 'TemplateLiteral']
|
||||||
const NUXT_LIB_RE = /node_modules\/(?:nuxt|nuxt3|nuxt-nightly)\//
|
const NUXT_LIB_RE = /node_modules\/(?:nuxt|nuxt3|nuxt-nightly)\//
|
||||||
const SUPPORTED_EXT_RE = /\.(?:m?[jt]sx?|vue)/
|
const SUPPORTED_EXT_RE = /\.(?:m?[jt]sx?|vue)/
|
||||||
|
const SCRIPT_RE = /(?<=<script[^>]*>)[\s\S]*?(?=<\/script>)/i
|
||||||
|
|
||||||
export const composableKeysPlugin = createUnplugin((options: ComposableKeysOptions) => {
|
export const composableKeysPlugin = createUnplugin((options: ComposableKeysOptions) => {
|
||||||
const composableMeta: Record<string, any> = {}
|
const composableMeta: Record<string, any> = {}
|
||||||
@ -43,7 +44,7 @@ export const composableKeysPlugin = createUnplugin((options: ComposableKeysOptio
|
|||||||
},
|
},
|
||||||
transform (code, id) {
|
transform (code, id) {
|
||||||
if (!KEYED_FUNCTIONS_RE.test(code)) { return }
|
if (!KEYED_FUNCTIONS_RE.test(code)) { return }
|
||||||
const { 0: script = code, index: codeIndex = 0 } = code.match(/(?<=<script[^>]*>)[\s\S]*?(?=<\/script>)/i) || { index: 0, 0: code }
|
const { 0: script = code, index: codeIndex = 0 } = code.match(SCRIPT_RE) || { index: 0, 0: code }
|
||||||
const s = new MagicString(code)
|
const s = new MagicString(code)
|
||||||
// https://github.com/unjs/unplugin/issues/90
|
// https://github.com/unjs/unplugin/issues/90
|
||||||
let imports: Set<string> | undefined
|
let imports: Set<string> | undefined
|
||||||
|
@ -10,6 +10,7 @@ import { isCSSRequest } from 'vite'
|
|||||||
const PREFIX = 'virtual:public?'
|
const PREFIX = 'virtual:public?'
|
||||||
const CSS_URL_RE = /url\((\/[^)]+)\)/g
|
const CSS_URL_RE = /url\((\/[^)]+)\)/g
|
||||||
const CSS_URL_SINGLE_RE = /url\(\/[^)]+\)/
|
const CSS_URL_SINGLE_RE = /url\(\/[^)]+\)/
|
||||||
|
const RENDER_CHUNK_RE = /(?<= = )['"`]/
|
||||||
|
|
||||||
interface VitePublicDirsPluginOptions {
|
interface VitePublicDirsPluginOptions {
|
||||||
dev?: boolean
|
dev?: boolean
|
||||||
@ -70,7 +71,7 @@ export const VitePublicDirsPlugin = createUnplugin((options: VitePublicDirsPlugi
|
|||||||
if (!chunk.facadeModuleId?.includes('?inline&used')) { return }
|
if (!chunk.facadeModuleId?.includes('?inline&used')) { return }
|
||||||
|
|
||||||
const s = new MagicString(code)
|
const s = new MagicString(code)
|
||||||
const q = code.match(/(?<= = )['"`]/)?.[0] || '"'
|
const q = code.match(RENDER_CHUNK_RE)?.[0] || '"'
|
||||||
for (const [full, url] of code.matchAll(CSS_URL_RE)) {
|
for (const [full, url] of code.matchAll(CSS_URL_RE)) {
|
||||||
if (url && resolveFromPublicAssets(url)) {
|
if (url && resolveFromPublicAssets(url)) {
|
||||||
s.replace(full, `url(${q} + publicAssetsURL(${q}${url}${q}) + ${q})`)
|
s.replace(full, `url(${q} + publicAssetsURL(${q}${url}${q}) + ${q})`)
|
||||||
@ -108,13 +109,14 @@ export const VitePublicDirsPlugin = createUnplugin((options: VitePublicDirsPlugi
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const PUBLIC_ASSETS_RE = /[?#].*$/
|
||||||
export function useResolveFromPublicAssets () {
|
export function useResolveFromPublicAssets () {
|
||||||
const nitro = useNitro()
|
const nitro = useNitro()
|
||||||
|
|
||||||
function resolveFromPublicAssets (id: string) {
|
function resolveFromPublicAssets (id: string) {
|
||||||
for (const dir of nitro.options.publicAssets) {
|
for (const dir of nitro.options.publicAssets) {
|
||||||
if (!id.startsWith(withTrailingSlash(dir.baseURL || '/'))) { continue }
|
if (!id.startsWith(withTrailingSlash(dir.baseURL || '/'))) { continue }
|
||||||
const path = id.replace(/[?#].*$/, '').replace(withTrailingSlash(dir.baseURL || '/'), withTrailingSlash(dir.dir))
|
const path = id.replace(PUBLIC_ASSETS_RE, '').replace(withTrailingSlash(dir.baseURL || '/'), withTrailingSlash(dir.dir))
|
||||||
if (existsSync(path)) {
|
if (existsSync(path)) {
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ const logLevelMapReverse: Record<NonNullable<vite.UserConfig['logLevel']>, numbe
|
|||||||
info: 3,
|
info: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RUNTIME_RESOLVE_REF_RE = /^([^ ]+) referenced in/m
|
||||||
export function createViteLogger (config: vite.InlineConfig): vite.Logger {
|
export function createViteLogger (config: vite.InlineConfig): vite.Logger {
|
||||||
const loggedErrors = new WeakSet<any>()
|
const loggedErrors = new WeakSet<any>()
|
||||||
const canClearScreen = hasTTY && !isCI && config.clearScreen
|
const canClearScreen = hasTTY && !isCI && config.clearScreen
|
||||||
@ -37,7 +38,7 @@ export function createViteLogger (config: vite.InlineConfig): vite.Logger {
|
|||||||
if (msg.startsWith('Sourcemap') && msg.includes('node_modules')) { return }
|
if (msg.startsWith('Sourcemap') && msg.includes('node_modules')) { return }
|
||||||
// Hide warnings about externals produced by https://github.com/vitejs/vite/blob/v5.2.11/packages/vite/src/node/plugins/css.ts#L350-L355
|
// Hide warnings about externals produced by https://github.com/vitejs/vite/blob/v5.2.11/packages/vite/src/node/plugins/css.ts#L350-L355
|
||||||
if (msg.includes('didn\'t resolve at build time, it will remain unchanged to be resolved at runtime')) {
|
if (msg.includes('didn\'t resolve at build time, it will remain unchanged to be resolved at runtime')) {
|
||||||
const id = msg.trim().match(/^([^ ]+) referenced in/m)?.[1]
|
const id = msg.trim().match(RUNTIME_RESOLVE_REF_RE)?.[1]
|
||||||
if (id && resolveFromPublicAssets(id)) { return }
|
if (id && resolveFromPublicAssets(id)) { return }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,13 +76,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"@rspack/core": "1.0.10",
|
"@rspack/core": "1.0.14",
|
||||||
"@types/hash-sum": "1.0.2",
|
"@types/hash-sum": "1.0.2",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "4.17.12",
|
||||||
"@types/pify": "5.0.4",
|
"@types/pify": "5.0.4",
|
||||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||||
"@types/webpack-hot-middleware": "2.25.9",
|
"@types/webpack-hot-middleware": "2.25.9",
|
||||||
"rollup": "4.24.0",
|
"rollup": "4.24.2",
|
||||||
"unbuild": "3.0.0-rc.11",
|
"unbuild": "3.0.0-rc.11",
|
||||||
"vue": "3.5.12"
|
"vue": "3.5.12"
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,7 @@ import { importModule } from '@nuxt/kit'
|
|||||||
const PLUGIN_NAME = 'dynamic-require'
|
const PLUGIN_NAME = 'dynamic-require'
|
||||||
const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.mjs`
|
const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.mjs`
|
||||||
const DYNAMIC_REQUIRE_RE = /import\("\.\/" ?\+(.*)\).then/g
|
const DYNAMIC_REQUIRE_RE = /import\("\.\/" ?\+(.*)\).then/g
|
||||||
|
const BACKWARD_SLASH_RE = /\\/g
|
||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
dir: string
|
dir: string
|
||||||
@ -75,7 +76,7 @@ export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
|
|||||||
await Promise.all(
|
await Promise.all(
|
||||||
files.map(async id => ({
|
files.map(async id => ({
|
||||||
id,
|
id,
|
||||||
src: resolve(dir, id).replace(/\\/g, '/'),
|
src: resolve(dir, id).replace(BACKWARD_SLASH_RE, '/'),
|
||||||
name: genSafeVariableName(id),
|
name: genSafeVariableName(id),
|
||||||
meta: await getWebpackChunkMeta(resolve(dir, id)),
|
meta: await getWebpackChunkMeta(resolve(dir, id)),
|
||||||
})),
|
})),
|
||||||
|
@ -24,6 +24,8 @@ export const isJS = (file: string) => isJSRegExp.test(file)
|
|||||||
|
|
||||||
export const extractQueryPartJS = (file: string) => isJSRegExp.exec(file)?.[1]
|
export const extractQueryPartJS = (file: string) => isJSRegExp.exec(file)?.[1]
|
||||||
|
|
||||||
export const isCSS = (file: string) => /\.css(?:\?[^.]+)?$/.test(file)
|
const isCSSRegExp = /\.css(?:\?[^.]+)?$/
|
||||||
|
|
||||||
|
export const isCSS = (file: string) => isCSSRegExp.test(file)
|
||||||
|
|
||||||
export const isHotUpdate = (file: string) => file.includes('hot-update')
|
export const isHotUpdate = (file: string) => file.includes('hot-update')
|
||||||
|
@ -34,6 +34,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
/** Inject rollup plugin for Nitro to handle dynamic imports from webpack chunks */
|
/** Inject rollup plugin for Nitro to handle dynamic imports from webpack chunks */
|
||||||
|
if (!nuxt.options.dev) {
|
||||||
const nitro = useNitro()
|
const nitro = useNitro()
|
||||||
const dynamicRequirePlugin = dynamicRequire({
|
const dynamicRequirePlugin = dynamicRequire({
|
||||||
dir: resolve(nuxt.options.buildDir, 'dist/server'),
|
dir: resolve(nuxt.options.buildDir, 'dist/server'),
|
||||||
@ -52,6 +53,7 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => {
|
|||||||
|
|
||||||
prerenderRollupPlugins.push(dynamicRequirePlugin)
|
prerenderRollupPlugins.push(dynamicRequirePlugin)
|
||||||
rollupPlugins.push(dynamicRequirePlugin)
|
rollupPlugins.push(dynamicRequirePlugin)
|
||||||
|
}
|
||||||
|
|
||||||
await nuxt.callHook(`${builder}:config`, webpackConfigs)
|
await nuxt.callHook(`${builder}:config`, webpackConfigs)
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-06-28',
|
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
|
compatibilityDate: '2024-06-28',
|
||||||
})
|
})
|
||||||
|
2097
pnpm-lock.yaml
2097
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -2374,7 +2374,7 @@ describe('component islands', () => {
|
|||||||
"link": [],
|
"link": [],
|
||||||
"style": [
|
"style": [
|
||||||
{
|
{
|
||||||
"innerHTML": "pre[data-v-xxxxx]{color:blue}",
|
"innerHTML": "pre[data-v-xxxxx]{color:#00f}",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@ -2743,7 +2743,11 @@ function normaliseIslandResult (result: NuxtIslandResponse) {
|
|||||||
for (const style of result.head.style) {
|
for (const style of result.head.style) {
|
||||||
if (typeof style !== 'string') {
|
if (typeof style !== 'string') {
|
||||||
if (style.innerHTML) {
|
if (style.innerHTML) {
|
||||||
style.innerHTML = (style.innerHTML as string).replace(/data-v-[a-z0-9]+/g, 'data-v-xxxxx')
|
style.innerHTML =
|
||||||
|
(style.innerHTML as string)
|
||||||
|
.replace(/data-v-[a-z0-9]+/g, 'data-v-xxxxx')
|
||||||
|
// Vite 6 enables CSS minify by default for SSR
|
||||||
|
.replace(/blue/, '#00f')
|
||||||
}
|
}
|
||||||
if (style.key) {
|
if (style.key) {
|
||||||
style.key = style.key.replace(/-[a-z0-9]+$/i, '')
|
style.key = style.key.replace(/-[a-z0-9]+$/i, '')
|
||||||
|
@ -81,7 +81,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
|||||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"557k"`)
|
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"557k"`)
|
||||||
|
|
||||||
const modules = await analyzeSizes(['node_modules/**/*'], serverDir)
|
const modules = await analyzeSizes(['node_modules/**/*'], serverDir)
|
||||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"93.8k"`)
|
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"94.2k"`)
|
||||||
|
|
||||||
const packages = modules.files
|
const packages = modules.files
|
||||||
.filter(m => m.endsWith('package.json'))
|
.filter(m => m.endsWith('package.json'))
|
||||||
|
100
test/fixtures/basic-types/nuxt.config.ts
vendored
100
test/fixtures/basic-types/nuxt.config.ts
vendored
@ -1,59 +1,10 @@
|
|||||||
import { addTypeTemplate, installModule } from 'nuxt/kit'
|
import { addTypeTemplate, installModule } from 'nuxt/kit'
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-06-28',
|
|
||||||
experimental: {
|
|
||||||
typedPages: true,
|
|
||||||
appManifest: true,
|
|
||||||
},
|
|
||||||
future: {
|
|
||||||
typescriptBundlerResolution: process.env.MODULE_RESOLUTION === 'bundler',
|
|
||||||
},
|
|
||||||
builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite',
|
|
||||||
theme: './extends/bar',
|
|
||||||
extends: [
|
extends: [
|
||||||
'./extends/node_modules/foo',
|
'./extends/node_modules/foo',
|
||||||
],
|
],
|
||||||
app: {
|
theme: './extends/bar',
|
||||||
head: {
|
|
||||||
// @ts-expect-error Promises are not allowed
|
|
||||||
title: Promise.resolve('Nuxt Fixture'),
|
|
||||||
// @ts-expect-error Functions are not allowed
|
|
||||||
titleTemplate: title => 'test',
|
|
||||||
meta: [
|
|
||||||
{
|
|
||||||
// Allows unknown property
|
|
||||||
property: 'og:thing',
|
|
||||||
content: '1234567890',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
pageTransition: {
|
|
||||||
// @ts-expect-error Functions are not allowed
|
|
||||||
onBeforeEnter: el => console.log(el),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
runtimeConfig: {
|
|
||||||
baseURL: '',
|
|
||||||
baseAPIToken: '',
|
|
||||||
privateConfig: 'secret_key',
|
|
||||||
public: {
|
|
||||||
ids: [1, 2, 3],
|
|
||||||
needsFallback: undefined,
|
|
||||||
testConfig: 123,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
appConfig: {
|
|
||||||
fromNuxtConfig: true,
|
|
||||||
nested: {
|
|
||||||
val: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
routeRules: {
|
|
||||||
'/param': {
|
|
||||||
redirect: '/param/1',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
modules: [
|
modules: [
|
||||||
function () {
|
function () {
|
||||||
addTypeTemplate({
|
addTypeTemplate({
|
||||||
@ -90,6 +41,55 @@ export default defineNuxtConfig({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
app: {
|
||||||
|
head: {
|
||||||
|
// @ts-expect-error Promises are not allowed
|
||||||
|
title: Promise.resolve('Nuxt Fixture'),
|
||||||
|
// @ts-expect-error Functions are not allowed
|
||||||
|
titleTemplate: title => 'test',
|
||||||
|
meta: [
|
||||||
|
{
|
||||||
|
// Allows unknown property
|
||||||
|
property: 'og:thing',
|
||||||
|
content: '1234567890',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
pageTransition: {
|
||||||
|
// @ts-expect-error Functions are not allowed
|
||||||
|
onBeforeEnter: el => console.log(el),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
appConfig: {
|
||||||
|
fromNuxtConfig: true,
|
||||||
|
nested: {
|
||||||
|
val: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
runtimeConfig: {
|
||||||
|
baseURL: '',
|
||||||
|
baseAPIToken: '',
|
||||||
|
privateConfig: 'secret_key',
|
||||||
|
public: {
|
||||||
|
ids: [1, 2, 3],
|
||||||
|
needsFallback: undefined,
|
||||||
|
testConfig: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite',
|
||||||
|
routeRules: {
|
||||||
|
'/param': {
|
||||||
|
redirect: '/param/1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
future: {
|
||||||
|
typescriptBundlerResolution: process.env.MODULE_RESOLUTION === 'bundler',
|
||||||
|
},
|
||||||
|
experimental: {
|
||||||
|
typedPages: true,
|
||||||
|
appManifest: true,
|
||||||
|
},
|
||||||
|
compatibilityDate: '2024-06-28',
|
||||||
telemetry: false, // for testing telemetry types - it is auto-disabled in tests
|
telemetry: false, // for testing telemetry types - it is auto-disabled in tests
|
||||||
hooks: {
|
hooks: {
|
||||||
'schema:extend' (schemas) {
|
'schema:extend' (schemas) {
|
||||||
|
@ -13,13 +13,18 @@ export default defineNuxtModule({
|
|||||||
name: 'page-extend',
|
name: 'page-extend',
|
||||||
path: '/page-extend',
|
path: '/page-extend',
|
||||||
file: resolver.resolve('../runtime/page.vue'),
|
file: resolver.resolve('../runtime/page.vue'),
|
||||||
}, {
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
nuxt.hook('pages:resolved', (pages) => {
|
||||||
|
pages.push({
|
||||||
path: '/big-page-1',
|
path: '/big-page-1',
|
||||||
file: resolver.resolve('./pages/big-page.vue'),
|
file: resolver.resolve('./pages/big-page.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
layout: false,
|
layout: false,
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
path: '/big-page-2',
|
path: '/big-page-2',
|
||||||
file: resolver.resolve('./pages/big-page.vue'),
|
file: resolver.resolve('./pages/big-page.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
218
test/fixtures/basic/nuxt.config.ts
vendored
218
test/fixtures/basic/nuxt.config.ts
vendored
@ -12,86 +12,12 @@ declare module 'nitro/types' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-06-28',
|
|
||||||
app: {
|
|
||||||
pageTransition: true,
|
|
||||||
layoutTransition: true,
|
|
||||||
teleportId: 'nuxt-teleport',
|
|
||||||
teleportTag: 'span',
|
|
||||||
head: {
|
|
||||||
charset: 'utf-8',
|
|
||||||
link: [undefined],
|
|
||||||
meta: [
|
|
||||||
{ name: 'viewport', content: 'width=1024, initial-scale=1' },
|
|
||||||
{ charset: 'utf-8' },
|
|
||||||
{ name: 'description', content: 'Nuxt Fixture' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
keepalive: {
|
|
||||||
include: ['keepalive-in-config', 'not-keepalive-in-nuxtpage'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite',
|
|
||||||
appId: 'nuxt-app-basic',
|
appId: 'nuxt-app-basic',
|
||||||
build: {
|
|
||||||
transpile: [
|
|
||||||
(ctx) => {
|
|
||||||
if (typeof ctx.isDev !== 'boolean') { throw new TypeError('context not passed') }
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
css: ['~/assets/global.css'],
|
|
||||||
// this produces an order of `~` > `~/extends/bar` > `~/extends/node_modules/foo`
|
|
||||||
theme: './extends/bar',
|
|
||||||
extends: [
|
extends: [
|
||||||
'./extends/node_modules/foo',
|
'./extends/node_modules/foo',
|
||||||
],
|
],
|
||||||
nitro: {
|
// this produces an order of `~` > `~/extends/bar` > `~/extends/node_modules/foo`
|
||||||
publicAssets: [
|
theme: './extends/bar',
|
||||||
{
|
|
||||||
dir: '../custom-public',
|
|
||||||
baseURL: '/custom',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
esbuild: {
|
|
||||||
options: {
|
|
||||||
// in order to test bigint serialization
|
|
||||||
target: 'es2022',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
routeRules: {
|
|
||||||
'/route-rules/spa': { ssr: false },
|
|
||||||
'/redirect/catchall': { ssr: false },
|
|
||||||
'/head-spa': { ssr: false },
|
|
||||||
'/route-rules/middleware': { appMiddleware: 'route-rules-middleware' },
|
|
||||||
'/hydration/spa-redirection/**': { ssr: false },
|
|
||||||
'/no-scripts': { experimentalNoScripts: true },
|
|
||||||
'/prerender/**': { prerender: true },
|
|
||||||
},
|
|
||||||
prerender: {
|
|
||||||
routes: [
|
|
||||||
'/random/a',
|
|
||||||
'/random/b',
|
|
||||||
'/random/c',
|
|
||||||
'/prefetch/server-components',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
optimization: {
|
|
||||||
keyedComposables: [
|
|
||||||
{
|
|
||||||
name: 'useCustomKeyedComposable',
|
|
||||||
source: '~/other-composables-folder/custom-keyed-composable',
|
|
||||||
argumentLength: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
runtimeConfig: {
|
|
||||||
public: {
|
|
||||||
needsFallback: undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
modules: [
|
modules: [
|
||||||
function (_options, nuxt) {
|
function (_options, nuxt) {
|
||||||
// ensure setting `runtimeConfig` also sets `nitro.runtimeConfig`
|
// ensure setting `runtimeConfig` also sets `nitro.runtimeConfig`
|
||||||
@ -149,7 +75,7 @@ export default defineNuxtConfig({
|
|||||||
_layout: page.meta?.layout,
|
_layout: page.meta?.layout,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
nuxt.hook('pages:extend', (pages) => {
|
nuxt.hook('pages:resolved', (pages) => {
|
||||||
const newPages = []
|
const newPages = []
|
||||||
for (const page of pages) {
|
for (const page of pages) {
|
||||||
if (routesToDuplicate.includes(page.path)) {
|
if (routesToDuplicate.includes(page.path)) {
|
||||||
@ -162,7 +88,7 @@ export default defineNuxtConfig({
|
|||||||
},
|
},
|
||||||
function (_options, nuxt) {
|
function (_options, nuxt) {
|
||||||
// to check that page metadata is preserved
|
// to check that page metadata is preserved
|
||||||
nuxt.hook('pages:extend', (pages) => {
|
nuxt.hook('pages:resolved', (pages) => {
|
||||||
const customName = pages.find(page => page.name === 'some-custom-name')
|
const customName = pages.find(page => page.name === 'some-custom-name')
|
||||||
if (!customName) { throw new Error('Page with custom name not found') }
|
if (!customName) { throw new Error('Page with custom name not found') }
|
||||||
if (customName.path !== '/some-custom-path') { throw new Error('Page path not extracted') }
|
if (customName.path !== '/some-custom-path') { throw new Error('Page path not extracted') }
|
||||||
@ -174,6 +100,111 @@ export default defineNuxtConfig({
|
|||||||
// To test falsy module values
|
// To test falsy module values
|
||||||
undefined,
|
undefined,
|
||||||
],
|
],
|
||||||
|
app: {
|
||||||
|
pageTransition: true,
|
||||||
|
layoutTransition: true,
|
||||||
|
teleportId: 'nuxt-teleport',
|
||||||
|
teleportTag: 'span',
|
||||||
|
head: {
|
||||||
|
charset: 'utf-8',
|
||||||
|
link: [undefined],
|
||||||
|
meta: [
|
||||||
|
{ name: 'viewport', content: 'width=1024, initial-scale=1' },
|
||||||
|
{ charset: 'utf-8' },
|
||||||
|
{ name: 'description', content: 'Nuxt Fixture' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
keepalive: {
|
||||||
|
include: ['keepalive-in-config', 'not-keepalive-in-nuxtpage'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
css: ['~/assets/global.css'],
|
||||||
|
vue: {
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag) => {
|
||||||
|
return tag === 'custom-component'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
appConfig: {
|
||||||
|
fromNuxtConfig: true,
|
||||||
|
nested: {
|
||||||
|
val: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
runtimeConfig: {
|
||||||
|
public: {
|
||||||
|
needsFallback: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite',
|
||||||
|
build: {
|
||||||
|
transpile: [
|
||||||
|
(ctx) => {
|
||||||
|
if (typeof ctx.isDev !== 'boolean') { throw new TypeError('context not passed') }
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
keyedComposables: [
|
||||||
|
{
|
||||||
|
name: 'useCustomKeyedComposable',
|
||||||
|
source: '~/other-composables-folder/custom-keyed-composable',
|
||||||
|
argumentLength: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
features: {
|
||||||
|
inlineStyles: id => !!id && !id.includes('assets.vue'),
|
||||||
|
},
|
||||||
|
experimental: {
|
||||||
|
serverAppConfig: true,
|
||||||
|
typedPages: true,
|
||||||
|
clientFallback: true,
|
||||||
|
restoreState: true,
|
||||||
|
clientNodeCompat: true,
|
||||||
|
componentIslands: {
|
||||||
|
selectiveClient: 'deep',
|
||||||
|
},
|
||||||
|
asyncContext: process.env.TEST_CONTEXT === 'async',
|
||||||
|
appManifest: process.env.TEST_MANIFEST !== 'manifest-off',
|
||||||
|
renderJsonPayloads: process.env.TEST_PAYLOAD !== 'js',
|
||||||
|
headNext: true,
|
||||||
|
inlineRouteRules: true,
|
||||||
|
},
|
||||||
|
compatibilityDate: '2024-06-28',
|
||||||
|
nitro: {
|
||||||
|
publicAssets: [
|
||||||
|
{
|
||||||
|
dir: '../custom-public',
|
||||||
|
baseURL: '/custom',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
esbuild: {
|
||||||
|
options: {
|
||||||
|
// in order to test bigint serialization
|
||||||
|
target: 'es2022',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
routeRules: {
|
||||||
|
'/route-rules/spa': { ssr: false },
|
||||||
|
'/redirect/catchall': { ssr: false },
|
||||||
|
'/head-spa': { ssr: false },
|
||||||
|
'/route-rules/middleware': { appMiddleware: 'route-rules-middleware' },
|
||||||
|
'/hydration/spa-redirection/**': { ssr: false },
|
||||||
|
'/no-scripts': { experimentalNoScripts: true },
|
||||||
|
'/prerender/**': { prerender: true },
|
||||||
|
},
|
||||||
|
prerender: {
|
||||||
|
routes: [
|
||||||
|
'/random/a',
|
||||||
|
'/random/b',
|
||||||
|
'/random/c',
|
||||||
|
'/prefetch/server-components',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
vite: {
|
vite: {
|
||||||
logLevel: 'silent',
|
logLevel: 'silent',
|
||||||
build: {
|
build: {
|
||||||
@ -232,35 +263,4 @@ export default defineNuxtConfig({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
vue: {
|
|
||||||
compilerOptions: {
|
|
||||||
isCustomElement: (tag) => {
|
|
||||||
return tag === 'custom-component'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
features: {
|
|
||||||
inlineStyles: id => !!id && !id.includes('assets.vue'),
|
|
||||||
},
|
|
||||||
experimental: {
|
|
||||||
serverAppConfig: true,
|
|
||||||
typedPages: true,
|
|
||||||
clientFallback: true,
|
|
||||||
restoreState: true,
|
|
||||||
clientNodeCompat: true,
|
|
||||||
componentIslands: {
|
|
||||||
selectiveClient: 'deep',
|
|
||||||
},
|
|
||||||
asyncContext: process.env.TEST_CONTEXT === 'async',
|
|
||||||
appManifest: process.env.TEST_MANIFEST !== 'manifest-off',
|
|
||||||
renderJsonPayloads: process.env.TEST_PAYLOAD !== 'js',
|
|
||||||
headNext: true,
|
|
||||||
inlineRouteRules: true,
|
|
||||||
},
|
|
||||||
appConfig: {
|
|
||||||
fromNuxtConfig: true,
|
|
||||||
nested: {
|
|
||||||
val: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
2
test/fixtures/minimal-types/nuxt.config.ts
vendored
2
test/fixtures/minimal-types/nuxt.config.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-06-28',
|
|
||||||
experimental: { appManifest: true },
|
experimental: { appManifest: true },
|
||||||
|
compatibilityDate: '2024-06-28',
|
||||||
})
|
})
|
||||||
|
18
test/fixtures/minimal/nuxt.config.ts
vendored
18
test/fixtures/minimal/nuxt.config.ts
vendored
@ -7,14 +7,6 @@ const nuxtEntry = fileURLToPath(new URL('../../../packages/nuxt/dist/index.mjs',
|
|||||||
const isStubbed = readFileSync(nuxtEntry, 'utf-8').includes('const _module = await jiti')
|
const isStubbed = readFileSync(nuxtEntry, 'utf-8').includes('const _module = await jiti')
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-06-28',
|
|
||||||
typescript: {
|
|
||||||
typeCheck: isStubbed ? false : 'build',
|
|
||||||
},
|
|
||||||
pages: false,
|
|
||||||
experimental: {
|
|
||||||
externalVue: !testWithInlineVue,
|
|
||||||
},
|
|
||||||
$production: {
|
$production: {
|
||||||
vite: {
|
vite: {
|
||||||
$client: {
|
$client: {
|
||||||
@ -29,9 +21,17 @@ export default defineNuxtConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
pages: false,
|
||||||
buildDir: testWithInlineVue ? '.nuxt-inline' : '.nuxt',
|
buildDir: testWithInlineVue ? '.nuxt-inline' : '.nuxt',
|
||||||
|
sourcemap: false,
|
||||||
|
experimental: {
|
||||||
|
externalVue: !testWithInlineVue,
|
||||||
|
},
|
||||||
|
compatibilityDate: '2024-06-28',
|
||||||
nitro: {
|
nitro: {
|
||||||
output: { dir: fileURLToPath(new URL(testWithInlineVue ? './.output-inline' : './.output', import.meta.url)) },
|
output: { dir: fileURLToPath(new URL(testWithInlineVue ? './.output-inline' : './.output', import.meta.url)) },
|
||||||
},
|
},
|
||||||
sourcemap: false,
|
typescript: {
|
||||||
|
typeCheck: isStubbed ? false : 'build',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// https://nuxt.com/docs/api/nuxt-config
|
// https://nuxt.com/docs/api/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-06-28',
|
|
||||||
experimental: {
|
|
||||||
externalVue: false,
|
|
||||||
},
|
|
||||||
vue: {
|
vue: {
|
||||||
runtimeCompiler: true,
|
runtimeCompiler: true,
|
||||||
},
|
},
|
||||||
builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite',
|
builder: process.env.TEST_BUILDER as 'webpack' | 'rspack' | 'vite' ?? 'vite',
|
||||||
|
experimental: {
|
||||||
|
externalVue: false,
|
||||||
|
},
|
||||||
|
compatibilityDate: '2024-06-28',
|
||||||
})
|
})
|
||||||
|
6
test/fixtures/suspense/nuxt.config.ts
vendored
6
test/fixtures/suspense/nuxt.config.ts
vendored
@ -3,13 +3,13 @@ import { fileURLToPath } from 'node:url'
|
|||||||
const testWithInlineVue = process.env.EXTERNAL_VUE === 'false'
|
const testWithInlineVue = process.env.EXTERNAL_VUE === 'false'
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-06-28',
|
buildDir: testWithInlineVue ? '.nuxt-inline' : '.nuxt',
|
||||||
|
sourcemap: false,
|
||||||
experimental: {
|
experimental: {
|
||||||
externalVue: !testWithInlineVue,
|
externalVue: !testWithInlineVue,
|
||||||
},
|
},
|
||||||
buildDir: testWithInlineVue ? '.nuxt-inline' : '.nuxt',
|
compatibilityDate: '2024-06-28',
|
||||||
nitro: {
|
nitro: {
|
||||||
output: { dir: fileURLToPath(new URL(testWithInlineVue ? './.output-inline' : './.output', import.meta.url)) },
|
output: { dir: fileURLToPath(new URL(testWithInlineVue ? './.output-inline' : './.output', import.meta.url)) },
|
||||||
},
|
},
|
||||||
sourcemap: false,
|
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user