diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 5b02b63..3e93681 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,5 +1,5 @@ --- -name: 🚨 Bug report +name: "\U0001F6A8 Bug report" about: Report a bug report to help improve the package. title: "" labels: "bug" @@ -16,13 +16,13 @@ assignees: "" ### Versions -- `@prismicio/next`: -- `next`: -- node: +- @prismicio/next: +- next: +- node: ### Reproduction - +
Additional Details diff --git a/.github/workflows/prerelease-canary.yml b/.github/workflows/prerelease-canary.yml deleted file mode 100644 index 1b9c097..0000000 --- a/.github/workflows/prerelease-canary.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: prerelease-canary - -permissions: - contents: read - id-token: write - -on: - push: - branches: - - main - -jobs: - publish: - if: github.repository_owner == 'prismicio' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 - with: - node-version: 24 - registry-url: "https://registry.npmjs.org" - - name: "Deprecate previous canary" - run: | - PACKAGE_NAME=$(jq -r ".name" package.json) - PREVIOUS_VERSION=$(npm view "$PACKAGE_NAME" dist-tags.canary 2>/dev/null) - if [ -n "$PREVIOUS_VERSION" ]; then - npm deprecate "$PACKAGE_NAME@$PREVIOUS_VERSION" "Replaced by newer canary version" - fi - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - run: npm ci - - name: "Generate new version" - run: | - SHORT_SHA=$(git rev-parse --short HEAD) - CURRENT_VERSION=$(jq -r '.version' package.json) - VERSION="${CURRENT_VERSION}-canary.${SHORT_SHA}" - npm version $VERSION --no-git-tag-version - - run: npm publish --provenance --tag canary - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/prerelease-pr-cleanup.yml b/.github/workflows/prerelease-pr-cleanup.yml deleted file mode 100644 index 42ab764..0000000 --- a/.github/workflows/prerelease-pr-cleanup.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: prerelease-pr-cleanup - -permissions: - contents: read - id-token: write - -on: - pull_request: - types: [closed] - -jobs: - cleanup: - if: github.repository_owner == 'prismicio' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 - with: - node-version: 24 - registry-url: "https://registry.npmjs.org" - - name: "Deprecate PR prerelease" - run: | - PACKAGE_NAME=$(jq -r ".name" package.json) - TAG="pr-${{ github.event.number }}" - VERSION=$(npm view "$PACKAGE_NAME" dist-tags."$TAG" 2>/dev/null || echo "") - if [ -n "$VERSION" ]; then - npm deprecate "$PACKAGE_NAME@$VERSION" "PR ${{ github.event.number }} was closed" - npm dist-tag rm "$PACKAGE_NAME" "$TAG" - fi - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/prerelease-pr.yml b/.github/workflows/prerelease-pr.yml deleted file mode 100644 index 8d5b13c..0000000 --- a/.github/workflows/prerelease-pr.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: prerelease-pr - -permissions: - contents: read - id-token: write - -on: - pull_request: - -jobs: - publish: - if: github.repository_owner == 'prismicio' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 - with: - node-version: 24 - registry-url: "https://registry.npmjs.org" - - name: "Deprecate previous PR prerelease" - run: | - PACKAGE_NAME=$(jq -r ".name" package.json) - TAG="pr-${{ github.event.number }}" - PREVIOUS_VERSION=$(npm view "$PACKAGE_NAME" dist-tags."$TAG" 2>/dev/null) - if [ -n "$PREVIOUS_VERSION" ]; then - npm deprecate "$PACKAGE_NAME@$PREVIOUS_VERSION" "Replaced by newer prerelease version" - fi - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - run: npm ci - - name: "Generate new version" - run: | - SHORT_SHA=$(git rev-parse --short HEAD) - CURRENT_VERSION=$(jq -r '.version' package.json) - VERSION="${CURRENT_VERSION}-pr.${{ github.event.number }}.${SHORT_SHA}" - npm version $VERSION --no-git-tag-version - - run: npm publish --provenance --tag pr-${{ github.event.number }} - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ac6d3b7 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,120 @@ +name: publish + +on: + push: + branches: [main] + pull_request: + types: [opened, synchronize, reopened, closed] + +jobs: + release: + if: github.event_name == 'push' && github.repository_owner == 'prismicio' + runs-on: ubuntu-latest + permissions: + contents: write + issues: write + pull-requests: write + id-token: write + env: + MODE: production + outputs: + release_created: ${{ steps.release.outputs.release_created }} + steps: + - uses: googleapis/release-please-action@v4 + id: release + continue-on-error: true + with: + release-type: node + - uses: actions/checkout@v6 + if: steps.release.outputs.release_created == 'true' + - uses: actions/setup-node@v6 + if: steps.release.outputs.release_created == 'true' + with: + node-version: 24 + registry-url: "https://registry.npmjs.org" + - if: steps.release.outputs.release_created == 'true' + run: npm ci + - name: "Publish release" + if: steps.release.outputs.release_created == 'true' + run: npm publish --provenance + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + prerelease: + if: "!cancelled() && github.repository_owner == 'prismicio'" + needs: [release] + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + env: + MODE: production + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: 24 + registry-url: "https://registry.npmjs.org" + + # Canary + - name: "Deprecate previous canary" + if: github.event_name == 'push' && needs.release.outputs.release_created != 'true' + continue-on-error: true + run: | + PACKAGE_NAME=$(jq -r ".name" package.json) + PREVIOUS_VERSION=$(npm view "$PACKAGE_NAME" dist-tags.canary 2>/dev/null || true) + if [ -n "$PREVIOUS_VERSION" ]; then + npm deprecate "$PACKAGE_NAME@$PREVIOUS_VERSION" "Replaced by newer canary version" + fi + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: "Publish canary" + if: github.event_name == 'push' && needs.release.outputs.release_created != 'true' + run: | + SHORT_SHA=$(git rev-parse --short HEAD) + CURRENT_VERSION=$(jq -r '.version' package.json) + npm ci + npm version "${CURRENT_VERSION}-canary.${SHORT_SHA}" --no-git-tag-version + npm publish --provenance --tag canary + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + # Pull request + - name: "Deprecate previous PR prerelease" + if: github.event_name == 'pull_request' && github.event.action != 'closed' + continue-on-error: true + run: | + PACKAGE_NAME=$(jq -r ".name" package.json) + TAG="pr-${{ github.event.number }}" + PREVIOUS_VERSION=$(npm view "$PACKAGE_NAME" dist-tags."$TAG" 2>/dev/null || true) + if [ -n "$PREVIOUS_VERSION" ]; then + npm deprecate "$PACKAGE_NAME@$PREVIOUS_VERSION" "Replaced by newer prerelease version" + fi + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: "Publish PR prerelease" + if: github.event_name == 'pull_request' && github.event.action != 'closed' + run: | + SHORT_SHA=$(git rev-parse --short HEAD) + CURRENT_VERSION=$(jq -r '.version' package.json) + npm ci + npm version "${CURRENT_VERSION}-pr.${{ github.event.number }}.${SHORT_SHA}" --no-git-tag-version + npm publish --provenance --tag pr-${{ github.event.number }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: "Clean up PR prerelease" + if: github.event_name == 'pull_request' && github.event.action == 'closed' + continue-on-error: true + run: | + PACKAGE_NAME=$(jq -r ".name" package.json) + TAG="pr-${{ github.event.number }}" + VERSION=$(npm view "$PACKAGE_NAME" dist-tags."$TAG" 2>/dev/null || echo "") + if [ -n "$VERSION" ]; then + npm deprecate "$PACKAGE_NAME@$VERSION" "PR ${{ github.event.number }} was closed" + npm dist-tag rm "$PACKAGE_NAME" "$TAG" + fi + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 7756bb0..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: release - -permissions: - contents: write - issues: write - pull-requests: write - id-token: write - -on: - push: - branches: - - main - -jobs: - release-please: - runs-on: ubuntu-latest - steps: - - uses: googleapis/release-please-action@v4 - id: release - with: - release-type: node - - uses: actions/checkout@v6 - if: ${{ steps.release.outputs.release_created }} - - uses: actions/setup-node@v6 - if: ${{ steps.release.outputs.release_created }} - with: - node-version: 24 - registry-url: "https://registry.npmjs.org" - - run: npm ci - if: ${{ steps.release.outputs.release_created }} - - run: npm publish --provenance - if: ${{ steps.release.outputs.release_created }} - env: - NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 39abcd9..1aea4c5 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -16,6 +16,8 @@ jobs: build: runs-on: ubuntu-latest + env: + MODE: production steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 0000000..eca1254 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,6 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "semi": false, + "sortImports": true, + "jsdoc": true +} diff --git a/.oxlintrc.json b/.oxlintrc.json index 47166cc..983ce1f 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -1,8 +1,10 @@ { + "$schema": "./node_modules/oxlint/configuration_schema.json", "plugins": ["unicorn", "typescript", "oxc", "jsdoc", "react"], "rules": { "no-console": ["warn", { "allow": ["info", "warn", "error"] }], "no-debugger": "warn", + "prefer-const": "error", "no-unused-vars": [ "error", { diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 7f5c090..0000000 --- a/.prettierignore +++ /dev/null @@ -1,46 +0,0 @@ -# custom -dist -examples/**/package-lock.json -*.tgz -CHANGELOG.md -e2e-projects/**/.next - -# os -.DS_Store -._* - -# node -logs -*.log -node_modules - -# yarn -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.yarn-integrity -yarn.lock - -# npm -npm-debug.log* - -# tests -coverage -.eslintcache -.nyc_output - -# .env -.env -.env.test -.env*.local - -# vscode -.vscode/* -!.vscode/tasks.json -!.vscode/launch.json -*.code-workspace -/test-results/ -/playwright-report/ -/blob-report/ -/playwright/.cache/ -/tests/.storage-state.json diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index dbea890..0000000 --- a/.prettierrc +++ /dev/null @@ -1,21 +0,0 @@ -{ - "plugins": ["prettier-plugin-jsdoc", "@trivago/prettier-plugin-sort-imports"], - "jsdocSeparateReturnsFromParam": true, - "jsdocSeparateTagGroups": true, - "jsdocSingleLineComment": false, - "tsdoc": true, - "printWidth": 80, - "useTabs": true, - "semi": true, - "singleQuote": false, - "quoteProps": "as-needed", - "jsxSingleQuote": false, - "trailingComma": "all", - "bracketSpacing": true, - "bracketSameLine": false, - "arrowParens": "always", - "requirePragma": false, - "insertPragma": false, - "htmlWhitespaceSensitivity": "css", - "endOfLine": "lf" -} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 639dc3a..1c866fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -This package is primarily maintained by [Prismic](https://prismic.io)[^1]. External contributions are welcome. Ask for help by [opening an issue](https://github.com/prismicio/prismic-client/issues/new/choose), or request a review by opening a pull request. +This package is primarily maintained by [Prismic](https://prismic.io)[^1]. External contributions are welcome. Ask for help by [opening an issue](https://github.com/prismicio/prismic-next/issues/new/choose), or request a review by opening a pull request. ## :gear: Setup @@ -8,7 +8,7 @@ This package is primarily maintained by [Prismic](https://prismic.io)[^1]. Exter The following setup is required to work on this project: -- Node.js +- Node.js 24 or later - npm CLI ## :memo: Project-specific notes @@ -16,9 +16,6 @@ The following setup is required to work on this project: -> [!TIP] -> Please update this section with helpful notes for contributors. - #### App Router and Pages Router support - This package prioritizes the App Router. The top-level package (`@prismicio/next`) exports components and helpers designed for the App Router. @@ -34,7 +31,7 @@ The following setup is required to work on this project: ## :construction_worker: Develop > [!NOTE] -> It's highly recommended to discuss your changes with the Prismic team before starting by [opening an issue](https://github.com/prismicio/prismic-client/issues/new/choose).[^2] +> It's highly recommended to discuss your changes with the Prismic team before starting by [opening an issue](https://github.com/prismicio/prismic-next/issues/new/choose).[^2] > > A short discussion can accellerate your work and ship it faster. @@ -49,19 +46,19 @@ git checkout -b / # Start the development watcher. # Run this command while you are working on your changes. -npm run dev +node --run dev # Build the project for production. # Run this command when you want to see the production version. -npm run build +node --run build # Lint your changes before requesting a review. No errors are allowed. -npm run lint +node --run lint # Some errors can be fixed automatically: -npm run lint -- --fix +node --run lint -- --fix # Format your changes before requesting a review. No errors are allowed. -npm run format +node --run format # Create a .env.test.local file and provide a Prismic username and password. # They will be used to run E2E tests. @@ -70,12 +67,12 @@ cp .env.test.example .env.test.local # Test your changes before requesting a review. # All changes should be tested. No failing tests are allowed. -npm run test +node --run test # Run only E2E tests (optionally in UI mode): -npm run e2e -npm run e2e:ui +node --run e2e +node --run e2e:ui # Run only type tests -npm run types +node --run types ``` ## :building_construction: Submit a pull request @@ -92,6 +89,10 @@ gh pr create # Someone from the Prismic team will review your work. This review will at # least consider the PR's general direction, code style, and test coverage. +# Prereleases are published to npm automatically to upon pushing commits. +# Install the prerelease using the `pr-${number}` tag. +npm install @prismicio/next@pr-101 + # When ready, PRs should be merged using the "Squash and merge" option. ``` @@ -100,28 +101,9 @@ gh pr create > [!CAUTION] > Publishing is restricted to the Prismic team.[^4] -```sh -# Checkout the main branch and pull the latest changes. -git checkout main -git pull - -# Perform a dry-run and verify the output. -# If it looks good, release a new version. -npm run release:dry -npm run release - -# Or release an alpha. -# Perform a dry-run and verify the output. -# If it looks good, release a new alpha version. -npm run release:alpha:dry -npm run release:alpha -``` - -After publishing a new release, publish the tags as releases. This will show the latest release on the repository's homepage. +This repository uses [Release Please](https://github.com/googleapis/release-please). To publish changes in `main`, merge [the pending Release Please PR](https://github.com/prismicio/prismic-next/pulls?q=is%3Apr+is%3Aopen+label%3A%22autorelease%3A+pending%22). -1. Go to the repository's [Tags page](https://github.com/prismicio/prismic-next/tags). -2. Open the options for the tag you just published to NPM and select "Create release." -3. Ensure that the "Set as the latest release" box is checked, then publish the release. +If you don't see a pending PR, there are no changes to publish from `main`. [^1]: This package is maintained by the DevX team. Prismic employees can ask for help or a review in the [#team-devx](https://prismic-team.slack.com/archives/C014VAACCQL) Slack channel. diff --git a/e2e-projects/app-router/app/PrismicNextImage/client/ClientTest.tsx b/e2e-projects/app-router/app/PrismicNextImage/client/ClientTest.tsx index a1f55f0..370785c 100644 --- a/e2e-projects/app-router/app/PrismicNextImage/client/ClientTest.tsx +++ b/e2e-projects/app-router/app/PrismicNextImage/client/ClientTest.tsx @@ -1,19 +1,19 @@ -"use client"; +"use client" -import type { JSX } from "react"; -import { useState } from "react"; -import type { ImageField } from "@prismicio/client"; -import { PrismicNextImage } from "@prismicio/next"; +import type { ImageField } from "@prismicio/client" +import { PrismicNextImage } from "@prismicio/next" +import type { JSX } from "react" +import { useState } from "react" export function ClientTest(props: { field: ImageField }): JSX.Element { - const { field } = props; + const { field } = props - const [ref, setRef] = useState(null); + const [ref, setRef] = useState(null) return (

tagname: {ref?.tagName}

- ); + ) } diff --git a/e2e-projects/app-router/app/PrismicNextImage/client/page.tsx b/e2e-projects/app-router/app/PrismicNextImage/client/page.tsx index f99e984..f621ad4 100644 --- a/e2e-projects/app-router/app/PrismicNextImage/client/page.tsx +++ b/e2e-projects/app-router/app/PrismicNextImage/client/page.tsx @@ -1,15 +1,17 @@ -import type { JSX } from "react"; -import { isFilled } from "@prismicio/client"; -import assert from "assert"; +import assert from "assert" -import { createClient } from "@/prismicio"; -import { ClientTest } from "./ClientTest"; +import { isFilled } from "@prismicio/client" +import type { JSX } from "react" + +import { createClient } from "@/prismicio" + +import { ClientTest } from "./ClientTest" export default async function Page(): Promise { - const client = await createClient(); - const { data: tests } = await client.getSingle("image_test"); + const client = await createClient() + const { data: tests } = await client.getSingle("image_test") - assert(isFilled.image(tests.filled)); + assert(isFilled.image(tests.filled)) - return ; + return } diff --git a/e2e-projects/app-router/app/PrismicNextImage/page.tsx b/e2e-projects/app-router/app/PrismicNextImage/page.tsx index 9a8a459..3ad8cc4 100644 --- a/e2e-projects/app-router/app/PrismicNextImage/page.tsx +++ b/e2e-projects/app-router/app/PrismicNextImage/page.tsx @@ -1,27 +1,23 @@ -import type { JSX } from "react"; -import { isFilled } from "@prismicio/client"; -import { PrismicNextImage } from "@prismicio/next"; -import assert from "assert"; +import assert from "assert" -import { createClient } from "@/prismicio"; +import { isFilled } from "@prismicio/client" +import { PrismicNextImage } from "@prismicio/next" +import type { JSX } from "react" + +import { createClient } from "@/prismicio" export default async function Page(): Promise { - const client = await createClient(); - const { data: tests } = await client.getSingle("image_test"); + const client = await createClient() + const { data: tests } = await client.getSingle("image_test") - assert( - isFilled.image(tests.with_alt_text) && tests.with_alt_text.alt !== null, - ); - assert( - isFilled.image(tests.without_alt_text) && - tests.without_alt_text.alt === null, - ); - assert(isFilled.image(tests.filled)); - assert(!isFilled.image(tests.empty)); + assert(isFilled.image(tests.with_alt_text) && tests.with_alt_text.alt !== null) + assert(isFilled.image(tests.without_alt_text) && tests.without_alt_text.alt === null) + assert(isFilled.image(tests.filled)) + assert(!isFilled.image(tests.empty)) assert( isFilled.image(tests.with_crop) && new URL(tests.with_crop.url).searchParams.get("rect") !== null, - ); + ) return ( <> @@ -32,16 +28,8 @@ export default async function Page(): Promise { - - + + { sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" /> - + - + - + - + - + { imgixParams={{ sat: -100 }} /> - ); + ) } diff --git a/e2e-projects/app-router/app/PrismicNextLink/client/page.tsx b/e2e-projects/app-router/app/PrismicNextLink/client/page.tsx index 9413ed6..d8df5f8 100644 --- a/e2e-projects/app-router/app/PrismicNextLink/client/page.tsx +++ b/e2e-projects/app-router/app/PrismicNextLink/client/page.tsx @@ -1,15 +1,15 @@ -"use client"; +"use client" -import type { JSX } from "react"; -import { useState } from "react"; -import { PrismicNextLink } from "@prismicio/next"; +import { PrismicNextLink } from "@prismicio/next" +import type { JSX } from "react" +import { useState } from "react" export default function Page(): JSX.Element { - const [ref, setRef] = useState(null); + const [ref, setRef] = useState(null) return ( tagname: {ref?.tagName} - ); + ) } diff --git a/e2e-projects/app-router/app/PrismicNextLink/page.tsx b/e2e-projects/app-router/app/PrismicNextLink/page.tsx index d0e5488..9544948 100644 --- a/e2e-projects/app-router/app/PrismicNextLink/page.tsx +++ b/e2e-projects/app-router/app/PrismicNextLink/page.tsx @@ -1,42 +1,40 @@ -import type { JSX } from "react"; -import Link from "next/link"; -import { isFilled } from "@prismicio/client"; -import { PrismicNextLink } from "@prismicio/next"; -import assert from "assert"; +import assert from "assert" -import { createClient } from "@/prismicio"; +import { isFilled } from "@prismicio/client" +import { PrismicNextLink } from "@prismicio/next" +import Link from "next/link" +import type { JSX } from "react" + +import { createClient } from "@/prismicio" export default async function Page(): Promise { - const client = await createClient(); - const { data: tests } = await client.getSingle("link_test"); - assert(isFilled.contentRelationship(tests.document) && tests.document.url); - const doc = await client.getByID(tests.document.id); + const client = await createClient() + const { data: tests } = await client.getSingle("link_test") + assert(isFilled.contentRelationship(tests.document) && tests.document.url) + const doc = await client.getByID(tests.document.id) - assert(isFilled.linkToMedia(tests.media)); + assert(isFilled.linkToMedia(tests.media)) assert( isFilled.link(tests.internal_web) && tests.internal_web.link_type === "Web" && !tests.internal_web.url.startsWith("http"), - ); + ) assert( isFilled.link(tests.external_web) && tests.external_web.link_type === "Web" && tests.external_web.url.startsWith("http"), - ); + ) assert( isFilled.link(tests.external_web_with_target) && tests.external_web_with_target.link_type === "Web" && tests.external_web_with_target.url.startsWith("http") && tests.external_web_with_target.target, - ); - assert(isFilled.link(tests.with_text) && tests.with_text.text); + ) + assert(isFilled.link(tests.with_text) && tests.with_text.text) return ( <> - + { - + { rel={(payload) => JSON.stringify(payload)} /> - + {/* @ts-expect-error - We are purposely providing an invalid `href` value. */} @@ -96,5 +88,5 @@ export default async function Page(): Promise { override - ); + ) } diff --git a/e2e-projects/app-router/app/[uid]/page.tsx b/e2e-projects/app-router/app/[uid]/page.tsx index 6863c31..fcc073a 100644 --- a/e2e-projects/app-router/app/[uid]/page.tsx +++ b/e2e-projects/app-router/app/[uid]/page.tsx @@ -1,22 +1,22 @@ -import type { JSX } from "react"; -import { PrismicPreview } from "@prismicio/next"; +import { PrismicPreview } from "@prismicio/next" +import type { JSX } from "react" -import { createClient } from "@/prismicio"; +import { createClient } from "@/prismicio" export default async function Page({ params, }: { - params: Promise<{ uid: string }>; + params: Promise<{ uid: string }> }): Promise { - const { uid } = await params; + const { uid } = await params - const client = await createClient(); - const page = await client.getByUID("page", uid); + const client = await createClient() + const page = await client.getByUID("page", uid) return ( <>
{page.data.payload}
- ); + ) } diff --git a/e2e-projects/app-router/app/api/custom-exit-preview/route.ts b/e2e-projects/app-router/app/api/custom-exit-preview/route.ts index bbff106..35c763f 100644 --- a/e2e-projects/app-router/app/api/custom-exit-preview/route.ts +++ b/e2e-projects/app-router/app/api/custom-exit-preview/route.ts @@ -1,5 +1,5 @@ -import { exitPreview } from "@prismicio/next"; +import { exitPreview } from "@prismicio/next" export function GET(): Promise { - return exitPreview(); + return exitPreview() } diff --git a/e2e-projects/app-router/app/api/custom-preview/route.ts b/e2e-projects/app-router/app/api/custom-preview/route.ts index 6e90930..3e98557 100644 --- a/e2e-projects/app-router/app/api/custom-preview/route.ts +++ b/e2e-projects/app-router/app/api/custom-preview/route.ts @@ -1,12 +1,12 @@ -import type { NextRequest } from "next/server"; -import { redirectToPreviewURL } from "@prismicio/next"; +import { redirectToPreviewURL } from "@prismicio/next" +import type { NextRequest } from "next/server" -import { createClient } from "@/prismicio"; +import { createClient } from "@/prismicio" export async function GET(request: NextRequest): Promise { const client = await createClient({ routes: [{ type: "page", path: "/:uid" }], - }); + }) - return await redirectToPreviewURL({ client, request }); + return await redirectToPreviewURL({ client, request }) } diff --git a/e2e-projects/app-router/app/api/exit-preview/route.ts b/e2e-projects/app-router/app/api/exit-preview/route.ts index bbff106..35c763f 100644 --- a/e2e-projects/app-router/app/api/exit-preview/route.ts +++ b/e2e-projects/app-router/app/api/exit-preview/route.ts @@ -1,5 +1,5 @@ -import { exitPreview } from "@prismicio/next"; +import { exitPreview } from "@prismicio/next" export function GET(): Promise { - return exitPreview(); + return exitPreview() } diff --git a/e2e-projects/app-router/app/api/preview/route.ts b/e2e-projects/app-router/app/api/preview/route.ts index 6e90930..3e98557 100644 --- a/e2e-projects/app-router/app/api/preview/route.ts +++ b/e2e-projects/app-router/app/api/preview/route.ts @@ -1,12 +1,12 @@ -import type { NextRequest } from "next/server"; -import { redirectToPreviewURL } from "@prismicio/next"; +import { redirectToPreviewURL } from "@prismicio/next" +import type { NextRequest } from "next/server" -import { createClient } from "@/prismicio"; +import { createClient } from "@/prismicio" export async function GET(request: NextRequest): Promise { const client = await createClient({ routes: [{ type: "page", path: "/:uid" }], - }); + }) - return await redirectToPreviewURL({ client, request }); + return await redirectToPreviewURL({ client, request }) } diff --git a/e2e-projects/app-router/app/layout.tsx b/e2e-projects/app-router/app/layout.tsx index 9ea4018..49e986e 100644 --- a/e2e-projects/app-router/app/layout.tsx +++ b/e2e-projects/app-router/app/layout.tsx @@ -1,9 +1,9 @@ -import type { JSX, ReactNode } from "react"; +import type { JSX, ReactNode } from "react" export default function RootLayout({ children }: { children: ReactNode }): JSX.Element { return ( {children} - ); + ) } diff --git a/e2e-projects/app-router/app/with-custom-preview-endpoints/[uid]/page.tsx b/e2e-projects/app-router/app/with-custom-preview-endpoints/[uid]/page.tsx index fa37886..a82c8c9 100644 --- a/e2e-projects/app-router/app/with-custom-preview-endpoints/[uid]/page.tsx +++ b/e2e-projects/app-router/app/with-custom-preview-endpoints/[uid]/page.tsx @@ -1,17 +1,17 @@ -import type { JSX } from "react"; -import { PrismicPreview } from "@prismicio/next"; +import { PrismicPreview } from "@prismicio/next" +import type { JSX } from "react" -import { createClient } from "@/prismicio"; +import { createClient } from "@/prismicio" export default async function Page({ params, }: { - params: Promise<{ uid: string }>; + params: Promise<{ uid: string }> }): Promise { - const { uid } = await params; + const { uid } = await params - const client = await createClient(); - const page = await client.getByUID("page", uid); + const client = await createClient() + const page = await client.getByUID("page", uid) return ( <> @@ -22,5 +22,5 @@ export default async function Page({ exitPreviewURL="/api/custom-exit-preview" /> - ); + ) } diff --git a/e2e-projects/app-router/eslint.config.mjs b/e2e-projects/app-router/eslint.config.mjs index 59804ca..064b5db 100644 --- a/e2e-projects/app-router/eslint.config.mjs +++ b/e2e-projects/app-router/eslint.config.mjs @@ -1,18 +1,12 @@ -import nextCoreWebVitals from "eslint-config-next/core-web-vitals"; -import nextTypescript from "eslint-config-next/typescript"; +import nextCoreWebVitals from "eslint-config-next/core-web-vitals" +import nextTypescript from "eslint-config-next/typescript" const eslintConfig = [ ...nextCoreWebVitals, ...nextTypescript, { - ignores: [ - "node_modules/**", - ".next/**", - "out/**", - "build/**", - "next-env.d.ts", - ], + ignores: ["node_modules/**", ".next/**", "out/**", "build/**", "next-env.d.ts"], }, -]; +] -export default eslintConfig; +export default eslintConfig diff --git a/e2e-projects/app-router/next.config.ts b/e2e-projects/app-router/next.config.ts index 34a8907..94013a4 100644 --- a/e2e-projects/app-router/next.config.ts +++ b/e2e-projects/app-router/next.config.ts @@ -1,11 +1,12 @@ -import type { NextConfig } from "next"; -import { fileURLToPath } from "node:url"; +import { fileURLToPath } from "node:url" + +import type { NextConfig } from "next" const nextConfig: NextConfig = { outputFileTracingRoot: fileURLToPath(new URL("../..", import.meta.url)), images: { remotePatterns: [{ hostname: "images.prismic.io" }], }, -}; +} -export default nextConfig; +export default nextConfig diff --git a/e2e-projects/app-router/prismicio-types.d.ts b/e2e-projects/app-router/prismicio-types.d.ts index e3e185c..188beb9 100644 --- a/e2e-projects/app-router/prismicio-types.d.ts +++ b/e2e-projects/app-router/prismicio-types.d.ts @@ -1,8 +1,8 @@ // Code generated by Slice Machine. DO NOT EDIT. -import type * as prismic from "@prismicio/client"; +import type * as prismic from "@prismicio/client" -type Simplify = { [KeyType in keyof T]: T[KeyType] }; +type Simplify = { [KeyType in keyof T]: T[KeyType] } /** Content for Image Test documents */ interface ImageTestDocumentData { @@ -15,7 +15,7 @@ interface ImageTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#image */ - empty: prismic.ImageField; + empty: prismic.ImageField /** * Filled field in _Image Test_ @@ -26,7 +26,7 @@ interface ImageTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#image */ - filled: prismic.ImageField; + filled: prismic.ImageField /** * With Alt Text field in _Image Test_ @@ -37,7 +37,7 @@ interface ImageTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#image */ - with_alt_text: prismic.ImageField; + with_alt_text: prismic.ImageField /** * Without Alt Text field in _Image Test_ @@ -48,7 +48,7 @@ interface ImageTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#image */ - without_alt_text: prismic.ImageField; + without_alt_text: prismic.ImageField /** * With Crop field in _Image Test_ @@ -59,7 +59,7 @@ interface ImageTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#image */ - with_crop: prismic.ImageField; + with_crop: prismic.ImageField } /** @@ -71,12 +71,11 @@ interface ImageTestDocumentData { * * @typeParam Lang - Language API ID of the document. */ -export type ImageTestDocument = - prismic.PrismicDocumentWithoutUID< - Simplify, - "image_test", - Lang - >; +export type ImageTestDocument = prismic.PrismicDocumentWithoutUID< + Simplify, + "image_test", + Lang +> /** Content for Link Test documents */ interface LinkTestDocumentData { @@ -89,7 +88,7 @@ interface LinkTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#link-content-relationship */ - empty: prismic.LinkField; + empty: prismic.LinkField /** * Internal Web field in _Link Test_ @@ -100,7 +99,7 @@ interface LinkTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#link-content-relationship */ - internal_web: prismic.LinkField; + internal_web: prismic.LinkField /** * External Web field in _Link Test_ @@ -111,7 +110,7 @@ interface LinkTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#link-content-relationship */ - external_web: prismic.LinkField; + external_web: prismic.LinkField /** * External Web With Target field in _Link Test_ @@ -122,7 +121,7 @@ interface LinkTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#link-content-relationship */ - external_web_with_target: prismic.LinkField; + external_web_with_target: prismic.LinkField /** * Document field in _Link Test_ @@ -133,7 +132,7 @@ interface LinkTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#link-content-relationship */ - document: prismic.LinkField; + document: prismic.LinkField /** * Media field in _Link Test_ @@ -144,7 +143,7 @@ interface LinkTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#link-content-relationship */ - media: prismic.LinkField; + media: prismic.LinkField /** * With Text field in _Link Test_ @@ -155,7 +154,7 @@ interface LinkTestDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#link-content-relationship */ - with_text: prismic.LinkField; + with_text: prismic.LinkField } /** @@ -167,14 +166,13 @@ interface LinkTestDocumentData { * * @typeParam Lang - Language API ID of the document. */ -export type LinkTestDocument = - prismic.PrismicDocumentWithoutUID< - Simplify, - "link_test", - Lang - >; +export type LinkTestDocument = prismic.PrismicDocumentWithoutUID< + Simplify, + "link_test", + Lang +> -type PageDocumentDataSlicesSlice = never; +type PageDocumentDataSlicesSlice = never /** Content for Page documents */ interface PageDocumentData { @@ -187,7 +185,7 @@ interface PageDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#key-text */ - payload: prismic.KeyTextField; + payload: prismic.KeyTextField /** * `slices` field in _Page_ @@ -198,7 +196,7 @@ interface PageDocumentData { * - **Tab**: Main * - **Documentation**: https://prismic.io/docs/field#slices */ - slices: prismic.SliceZone; + slices: prismic.SliceZone } /** @@ -210,31 +208,31 @@ interface PageDocumentData { * * @typeParam Lang - Language API ID of the document. */ -export type PageDocument = - prismic.PrismicDocumentWithUID, "page", Lang>; +export type PageDocument = prismic.PrismicDocumentWithUID< + Simplify, + "page", + Lang +> -export type AllDocumentTypes = - | ImageTestDocument - | LinkTestDocument - | PageDocument; +export type AllDocumentTypes = ImageTestDocument | LinkTestDocument | PageDocument declare module "@prismicio/client" { interface CreateClient { ( repositoryNameOrEndpoint: string, options?: prismic.ClientConfig, - ): prismic.Client; + ): prismic.Client } interface CreateWriteClient { ( repositoryNameOrEndpoint: string, options: prismic.WriteClientConfig, - ): prismic.WriteClient; + ): prismic.WriteClient } interface CreateMigration { - (): prismic.Migration; + (): prismic.Migration } namespace Content { @@ -247,6 +245,6 @@ declare module "@prismicio/client" { PageDocumentData, PageDocumentDataSlicesSlice, AllDocumentTypes, - }; + } } } diff --git a/e2e-projects/app-router/prismicio.ts b/e2e-projects/app-router/prismicio.ts index 3be247e..5233949 100644 --- a/e2e-projects/app-router/prismicio.ts +++ b/e2e-projects/app-router/prismicio.ts @@ -1,20 +1,21 @@ -import * as prismic from "@prismicio/client"; -import * as prismicNext from "@prismicio/next"; -import { cookies } from "next/headers"; -import assert from "node:assert"; +import assert from "node:assert" + +import * as prismic from "@prismicio/client" +import * as prismicNext from "@prismicio/next" +import { cookies } from "next/headers" export async function createClient(config: prismic.ClientConfig = {}): Promise { - const cookieJar = await cookies(); - const repositoryName = cookieJar.get("repository-name")?.value; - assert(repositoryName, "A repository-name cookie is required."); + const cookieJar = await cookies() + const repositoryName = cookieJar.get("repository-name")?.value + assert(repositoryName, "A repository-name cookie is required.") const client = prismic.createClient(repositoryName, { routes: [{ type: "page", path: "/:uid" }], fetchOptions: { cache: "no-store" }, ...config, - }); + }) - prismicNext.enableAutoPreviews({ client }); + prismicNext.enableAutoPreviews({ client }) - return client; + return client } diff --git a/e2e-projects/pages-router/eslint.config.mjs b/e2e-projects/pages-router/eslint.config.mjs index 59804ca..064b5db 100644 --- a/e2e-projects/pages-router/eslint.config.mjs +++ b/e2e-projects/pages-router/eslint.config.mjs @@ -1,18 +1,12 @@ -import nextCoreWebVitals from "eslint-config-next/core-web-vitals"; -import nextTypescript from "eslint-config-next/typescript"; +import nextCoreWebVitals from "eslint-config-next/core-web-vitals" +import nextTypescript from "eslint-config-next/typescript" const eslintConfig = [ ...nextCoreWebVitals, ...nextTypescript, { - ignores: [ - "node_modules/**", - ".next/**", - "out/**", - "build/**", - "next-env.d.ts", - ], + ignores: ["node_modules/**", ".next/**", "out/**", "build/**", "next-env.d.ts"], }, -]; +] -export default eslintConfig; +export default eslintConfig diff --git a/e2e-projects/pages-router/next.config.ts b/e2e-projects/pages-router/next.config.ts index 34a8907..94013a4 100644 --- a/e2e-projects/pages-router/next.config.ts +++ b/e2e-projects/pages-router/next.config.ts @@ -1,11 +1,12 @@ -import type { NextConfig } from "next"; -import { fileURLToPath } from "node:url"; +import { fileURLToPath } from "node:url" + +import type { NextConfig } from "next" const nextConfig: NextConfig = { outputFileTracingRoot: fileURLToPath(new URL("../..", import.meta.url)), images: { remotePatterns: [{ hostname: "images.prismic.io" }], }, -}; +} -export default nextConfig; +export default nextConfig diff --git a/e2e-projects/pages-router/pages/PrismicNextImage/client.tsx b/e2e-projects/pages-router/pages/PrismicNextImage/client.tsx index 5fc85bf..b3d6c4a 100644 --- a/e2e-projects/pages-router/pages/PrismicNextImage/client.tsx +++ b/e2e-projects/pages-router/pages/PrismicNextImage/client.tsx @@ -1,36 +1,47 @@ -import type { JSX } from "react"; -import { useState } from "react"; -import type { GetServerSidePropsContext, GetServerSidePropsResult, InferGetServerSidePropsType } from "next"; -import { PrismicNextImage } from "@prismicio/next/pages"; -import { isFilled } from "@prismicio/client"; -import assert from "assert"; +import assert from "assert" -import { createClient } from "@/prismicio"; +import { isFilled } from "@prismicio/client" +import { PrismicNextImage } from "@prismicio/next/pages" +import type { + GetServerSidePropsContext, + GetServerSidePropsResult, + InferGetServerSidePropsType, +} from "next" +import type { JSX } from "react" +import { useState } from "react" + +import { createClient } from "@/prismicio" export default function Page({ field, }: InferGetServerSidePropsType): JSX.Element { - const [ref, setRef] = useState(null); + const [ref, setRef] = useState(null) return (

tagname: {ref?.tagName}

- ); + ) } -export async function getServerSideProps({ req }: GetServerSidePropsContext): Promise["getSingle"]>>["data"]["filled"] }>> { - const repositoryName = req.cookies["repository-name"]; +export async function getServerSideProps({ + req, +}: GetServerSidePropsContext): Promise< + GetServerSidePropsResult<{ + field: Awaited["getSingle"]>>["data"]["filled"] + }> +> { + const repositoryName = req.cookies["repository-name"] assert( repositoryName && typeof repositoryName === "string", "A repository-name cookie is required.", - ); + ) - const client = createClient(repositoryName); - const { data: tests } = await client.getSingle("image_test"); + const client = createClient(repositoryName) + const { data: tests } = await client.getSingle("image_test") - assert(isFilled.image(tests.filled)); + assert(isFilled.image(tests.filled)) - return { props: { field: tests.filled } }; + return { props: { field: tests.filled } } } diff --git a/e2e-projects/pages-router/pages/PrismicNextImage/index.tsx b/e2e-projects/pages-router/pages/PrismicNextImage/index.tsx index c790274..f8a5a79 100644 --- a/e2e-projects/pages-router/pages/PrismicNextImage/index.tsx +++ b/e2e-projects/pages-router/pages/PrismicNextImage/index.tsx @@ -1,10 +1,15 @@ -import type { JSX } from "react"; -import type { GetServerSidePropsContext, GetServerSidePropsResult, InferGetServerSidePropsType } from "next"; -import { PrismicNextImage } from "@prismicio/next/pages"; -import { isFilled } from "@prismicio/client"; -import assert from "assert"; +import assert from "assert" -import { createClient } from "@/prismicio"; +import { isFilled } from "@prismicio/client" +import { PrismicNextImage } from "@prismicio/next/pages" +import type { + GetServerSidePropsContext, + GetServerSidePropsResult, + InferGetServerSidePropsType, +} from "next" +import type { JSX } from "react" + +import { createClient } from "@/prismicio" export default function Page({ tests, @@ -18,16 +23,8 @@ export default function Page({ - - + + - + - + - + - + - + - ); + ) } -export async function getServerSideProps({ req }: GetServerSidePropsContext): Promise["getSingle"]>>["data"] }>> { - const repositoryName = req.cookies["repository-name"]; +export async function getServerSideProps({ + req, +}: GetServerSidePropsContext): Promise< + GetServerSidePropsResult<{ + tests: Awaited["getSingle"]>>["data"] + }> +> { + const repositoryName = req.cookies["repository-name"] assert( repositoryName && typeof repositoryName === "string", "A repository-name cookie is required.", - ); + ) - const client = createClient(repositoryName); - const { data: tests } = await client.getSingle("image_test"); + const client = createClient(repositoryName) + const { data: tests } = await client.getSingle("image_test") - assert( - isFilled.image(tests.with_alt_text) && tests.with_alt_text.alt !== null, - ); - assert( - isFilled.image(tests.without_alt_text) && - tests.without_alt_text.alt === null, - ); - assert(isFilled.image(tests.filled)); - assert(!isFilled.image(tests.empty)); + assert(isFilled.image(tests.with_alt_text) && tests.with_alt_text.alt !== null) + assert(isFilled.image(tests.without_alt_text) && tests.without_alt_text.alt === null) + assert(isFilled.image(tests.filled)) + assert(!isFilled.image(tests.empty)) assert( isFilled.image(tests.with_crop) && new URL(tests.with_crop.url).searchParams.get("rect") !== null, - ); + ) - return { props: { tests } }; + return { props: { tests } } } diff --git a/e2e-projects/pages-router/pages/PrismicNextLink/client.tsx b/e2e-projects/pages-router/pages/PrismicNextLink/client.tsx index 82c7956..a1d684d 100644 --- a/e2e-projects/pages-router/pages/PrismicNextLink/client.tsx +++ b/e2e-projects/pages-router/pages/PrismicNextLink/client.tsx @@ -1,13 +1,13 @@ -import type { JSX } from "react"; -import { useState } from "react"; -import { PrismicNextLink } from "@prismicio/next/pages"; +import { PrismicNextLink } from "@prismicio/next/pages" +import type { JSX } from "react" +import { useState } from "react" export default function Page(): JSX.Element { - const [ref, setRef] = useState(null); + const [ref, setRef] = useState(null) return ( tagname: {ref?.tagName} - ); + ) } diff --git a/e2e-projects/pages-router/pages/PrismicNextLink/index.tsx b/e2e-projects/pages-router/pages/PrismicNextLink/index.tsx index 0681891..6ffd824 100644 --- a/e2e-projects/pages-router/pages/PrismicNextLink/index.tsx +++ b/e2e-projects/pages-router/pages/PrismicNextLink/index.tsx @@ -1,11 +1,16 @@ -import type { JSX } from "react"; -import type { GetServerSidePropsContext, GetServerSidePropsResult, InferGetServerSidePropsType } from "next"; -import Link from "next/link"; -import { PrismicNextLink } from "@prismicio/next/pages"; -import { isFilled } from "@prismicio/client"; -import assert from "assert"; +import assert from "assert" -import { createClient } from "@/prismicio"; +import { isFilled } from "@prismicio/client" +import { PrismicNextLink } from "@prismicio/next/pages" +import type { + GetServerSidePropsContext, + GetServerSidePropsResult, + InferGetServerSidePropsType, +} from "next" +import Link from "next/link" +import type { JSX } from "react" + +import { createClient } from "@/prismicio" export default function Page({ tests, @@ -13,10 +18,7 @@ export default function Page({ }: InferGetServerSidePropsType): JSX.Element { return ( <> - + - + JSON.stringify(payload)} /> - + {/* @ts-expect-error - We are purposely providing an invalid `href` value. */} @@ -76,39 +72,46 @@ export default function Page({ override - ); + ) } -export async function getServerSideProps({ req }: GetServerSidePropsContext): Promise["getSingle"]>>["data"]; doc: Awaited["getByID"]>> }>> { - const repositoryName = req.cookies["repository-name"]; +export async function getServerSideProps({ + req, +}: GetServerSidePropsContext): Promise< + GetServerSidePropsResult<{ + tests: Awaited["getSingle"]>>["data"] + doc: Awaited["getByID"]>> + }> +> { + const repositoryName = req.cookies["repository-name"] assert( repositoryName && typeof repositoryName === "string", "A repository-name cookie is required.", - ); + ) - const client = createClient(repositoryName); - const { data: tests } = await client.getSingle("link_test"); - assert(isFilled.contentRelationship(tests.document) && tests.document.url); - const doc = await client.getByID(tests.document.id); + const client = createClient(repositoryName) + const { data: tests } = await client.getSingle("link_test") + assert(isFilled.contentRelationship(tests.document) && tests.document.url) + const doc = await client.getByID(tests.document.id) - assert(isFilled.linkToMedia(tests.media)); + assert(isFilled.linkToMedia(tests.media)) assert( isFilled.link(tests.internal_web) && tests.internal_web.link_type === "Web" && !tests.internal_web.url.startsWith("http"), - ); + ) assert( isFilled.link(tests.external_web) && tests.external_web.link_type === "Web" && tests.external_web.url.startsWith("http"), - ); + ) assert( isFilled.link(tests.external_web_with_target) && tests.external_web_with_target.link_type === "Web" && tests.external_web_with_target.url.startsWith("http") && tests.external_web_with_target.target, - ); - assert(isFilled.link(tests.with_text) && tests.with_text.text); + ) + assert(isFilled.link(tests.with_text) && tests.with_text.text) - return { props: { tests, doc } }; + return { props: { tests, doc } } } diff --git a/e2e-projects/pages-router/pages/[uid].tsx b/e2e-projects/pages-router/pages/[uid].tsx index 044b239..aa614c3 100644 --- a/e2e-projects/pages-router/pages/[uid].tsx +++ b/e2e-projects/pages-router/pages/[uid].tsx @@ -1,9 +1,14 @@ -import type { JSX } from "react"; -import type { GetServerSidePropsContext, GetServerSidePropsResult, InferGetServerSidePropsType } from "next"; -import { PrismicPreview } from "@prismicio/next/pages"; -import assert from "node:assert"; +import assert from "node:assert" -import { createClient } from "@/prismicio"; +import { PrismicPreview } from "@prismicio/next/pages" +import type { + GetServerSidePropsContext, + GetServerSidePropsResult, + InferGetServerSidePropsType, +} from "next" +import type { JSX } from "react" + +import { createClient } from "@/prismicio" export default function Page({ repositoryName, @@ -14,22 +19,27 @@ export default function Page({
{page.data.payload}
- ); + ) } export async function getServerSideProps({ req, params, previewData, -}: GetServerSidePropsContext<{ uid: string }>): Promise["getByUID"]>> }>> { - const repositoryName = req.cookies["repository-name"]; +}: GetServerSidePropsContext<{ uid: string }>): Promise< + GetServerSidePropsResult<{ + repositoryName: string + page: Awaited["getByUID"]>> + }> +> { + const repositoryName = req.cookies["repository-name"] assert( repositoryName && typeof repositoryName === "string", "A repository-name cookie is required.", - ); + ) - const client = createClient(repositoryName, { previewData }); - const page = await client.getByUID("page", params!.uid); + const client = createClient(repositoryName, { previewData }) + const page = await client.getByUID("page", params!.uid) - return { props: { repositoryName, page } }; + return { props: { repositoryName, page } } } diff --git a/e2e-projects/pages-router/pages/api/custom-exit-preview.ts b/e2e-projects/pages-router/pages/api/custom-exit-preview.ts index 48c7e86..eebb8b8 100644 --- a/e2e-projects/pages-router/pages/api/custom-exit-preview.ts +++ b/e2e-projects/pages-router/pages/api/custom-exit-preview.ts @@ -1,6 +1,6 @@ -import type { NextApiRequest, NextApiResponse } from "next"; -import { exitPreview } from "@prismicio/next/pages"; +import { exitPreview } from "@prismicio/next/pages" +import type { NextApiRequest, NextApiResponse } from "next" export default function handler(req: NextApiRequest, res: NextApiResponse): void { - return exitPreview({ req, res }); + return exitPreview({ req, res }) } diff --git a/e2e-projects/pages-router/pages/api/custom-preview.ts b/e2e-projects/pages-router/pages/api/custom-preview.ts index add5816..8d038d9 100644 --- a/e2e-projects/pages-router/pages/api/custom-preview.ts +++ b/e2e-projects/pages-router/pages/api/custom-preview.ts @@ -1,25 +1,23 @@ -import type { NextApiRequest, NextApiResponse } from "next"; -import { setPreviewData, redirectToPreviewURL } from "@prismicio/next/pages"; -import assert from "node:assert"; +import assert from "node:assert" -import { createClient } from "@/prismicio"; +import { setPreviewData, redirectToPreviewURL } from "@prismicio/next/pages" +import type { NextApiRequest, NextApiResponse } from "next" -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -): Promise { - const repositoryName = req.cookies["repository-name"]; +import { createClient } from "@/prismicio" + +export default async function handler(req: NextApiRequest, res: NextApiResponse): Promise { + const repositoryName = req.cookies["repository-name"] assert( repositoryName && typeof repositoryName === "string", "A repository-name cookie is required.", - ); + ) const client = createClient(repositoryName, { routes: [{ type: "page", path: "/:uid" }], req, - }); + }) - setPreviewData({ req, res }); + setPreviewData({ req, res }) - return await redirectToPreviewURL({ req, res, client }); + return await redirectToPreviewURL({ req, res, client }) } diff --git a/e2e-projects/pages-router/pages/api/exit-preview.ts b/e2e-projects/pages-router/pages/api/exit-preview.ts index 48c7e86..eebb8b8 100644 --- a/e2e-projects/pages-router/pages/api/exit-preview.ts +++ b/e2e-projects/pages-router/pages/api/exit-preview.ts @@ -1,6 +1,6 @@ -import type { NextApiRequest, NextApiResponse } from "next"; -import { exitPreview } from "@prismicio/next/pages"; +import { exitPreview } from "@prismicio/next/pages" +import type { NextApiRequest, NextApiResponse } from "next" export default function handler(req: NextApiRequest, res: NextApiResponse): void { - return exitPreview({ req, res }); + return exitPreview({ req, res }) } diff --git a/e2e-projects/pages-router/pages/api/preview.ts b/e2e-projects/pages-router/pages/api/preview.ts index add5816..8d038d9 100644 --- a/e2e-projects/pages-router/pages/api/preview.ts +++ b/e2e-projects/pages-router/pages/api/preview.ts @@ -1,25 +1,23 @@ -import type { NextApiRequest, NextApiResponse } from "next"; -import { setPreviewData, redirectToPreviewURL } from "@prismicio/next/pages"; -import assert from "node:assert"; +import assert from "node:assert" -import { createClient } from "@/prismicio"; +import { setPreviewData, redirectToPreviewURL } from "@prismicio/next/pages" +import type { NextApiRequest, NextApiResponse } from "next" -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -): Promise { - const repositoryName = req.cookies["repository-name"]; +import { createClient } from "@/prismicio" + +export default async function handler(req: NextApiRequest, res: NextApiResponse): Promise { + const repositoryName = req.cookies["repository-name"] assert( repositoryName && typeof repositoryName === "string", "A repository-name cookie is required.", - ); + ) const client = createClient(repositoryName, { routes: [{ type: "page", path: "/:uid" }], req, - }); + }) - setPreviewData({ req, res }); + setPreviewData({ req, res }) - return await redirectToPreviewURL({ req, res, client }); + return await redirectToPreviewURL({ req, res, client }) } diff --git a/e2e-projects/pages-router/pages/with-custom-preview-endpoints/[uid].tsx b/e2e-projects/pages-router/pages/with-custom-preview-endpoints/[uid].tsx index c8b7a9b..11b0f7b 100644 --- a/e2e-projects/pages-router/pages/with-custom-preview-endpoints/[uid].tsx +++ b/e2e-projects/pages-router/pages/with-custom-preview-endpoints/[uid].tsx @@ -1,9 +1,14 @@ -import type { JSX } from "react"; -import type { GetServerSidePropsContext, GetServerSidePropsResult, InferGetServerSidePropsType } from "next"; -import { PrismicPreview } from "@prismicio/next/pages"; -import assert from "node:assert"; +import assert from "node:assert" -import { createClient } from "@/prismicio"; +import { PrismicPreview } from "@prismicio/next/pages" +import type { + GetServerSidePropsContext, + GetServerSidePropsResult, + InferGetServerSidePropsType, +} from "next" +import type { JSX } from "react" + +import { createClient } from "@/prismicio" export default function Page({ repositoryName, @@ -18,22 +23,27 @@ export default function Page({ exitPreviewURL="/api/custom-exit-preview" /> - ); + ) } export async function getServerSideProps({ req, params, previewData, -}: GetServerSidePropsContext<{ uid: string }>): Promise["getByUID"]>> }>> { - const repositoryName = req.cookies["repository-name"]; +}: GetServerSidePropsContext<{ uid: string }>): Promise< + GetServerSidePropsResult<{ + repositoryName: string + page: Awaited["getByUID"]>> + }> +> { + const repositoryName = req.cookies["repository-name"] assert( repositoryName && typeof repositoryName === "string", "A repository-name cookie is required.", - ); + ) - const client = createClient(repositoryName, { previewData }); - const page = await client.getByUID("page", params!.uid); + const client = createClient(repositoryName, { previewData }) + const page = await client.getByUID("page", params!.uid) - return { props: { repositoryName, page } }; + return { props: { repositoryName, page } } } diff --git a/e2e-projects/pages-router/prismicio.ts b/e2e-projects/pages-router/prismicio.ts index 743c2f4..5e8aaee 100644 --- a/e2e-projects/pages-router/prismicio.ts +++ b/e2e-projects/pages-router/prismicio.ts @@ -1,5 +1,5 @@ -import * as prismic from "@prismicio/client"; -import * as prismicNext from "@prismicio/next/pages"; +import * as prismic from "@prismicio/client" +import * as prismicNext from "@prismicio/next/pages" export const createClient = ( repositoryName: string, @@ -8,13 +8,13 @@ export const createClient = ( const client = prismic.createClient(repositoryName, { routes: [{ type: "page", path: "/:uid" }], ...config, - }); + }) prismicNext.enableAutoPreviews({ client, previewData: config.previewData, req: config.req, - }); + }) - return client; -}; + return client +} diff --git a/messages/replace-createLocaleRedirect.md b/messages/replace-createLocaleRedirect.md index ba89434..d553888 100644 --- a/messages/replace-createLocaleRedirect.md +++ b/messages/replace-createLocaleRedirect.md @@ -17,9 +17,9 @@ The function should be removed from Next.js projects to ensure the best possible 1. Create an `i18n.ts` file at the root of your project (or within `src` if you use that directory): ```ts - import type { NextRequest } from "next/server"; - import { match } from "@formatjs/intl-localematcher"; - import Negotiator from "negotiator"; + import type { NextRequest } from "next/server" + import { match } from "@formatjs/intl-localematcher" + import Negotiator from "negotiator" /** * A record of locales mapped to a version displayed in URLs. The first entry is @@ -31,27 +31,27 @@ The function should be removed from Next.js projects to ensure the best possible const LOCALES = { "en-us": "en", "fr-fr": "fr", - }; + } /** Creates a redirect with an auto-detected locale prepended to the URL. */ export function createLocaleRedirect(request: NextRequest): Response { const headers = { "accept-language": request.headers.get("accept-language"), - }; - const languages = new Negotiator({ headers }).languages(); - const locales = Object.keys(LOCALES); - const locale = match(languages, locales, locales[0]); + } + const languages = new Negotiator({ headers }).languages() + const locales = Object.keys(LOCALES) + const locale = match(languages, locales, locales[0]) - request.nextUrl.pathname = `/${LOCALES[locale]}${request.nextUrl.pathname}`; + request.nextUrl.pathname = `/${LOCALES[locale]}${request.nextUrl.pathname}` - return Response.redirect(request.nextUrl); + return Response.redirect(request.nextUrl) } /** Determines if a pathname has a locale as its first segment. */ export function pathnameHasLocale(request: NextRequest): boolean { - const regexp = new RegExp(`^/(${Object.values(LOCALES).join("|")})(\/|$)`); + const regexp = new RegExp(`^/(${Object.values(LOCALES).join("|")})(\/|$)`) - return regexp.test(request.nextUrl.pathname); + return regexp.test(request.nextUrl.pathname) } /** @@ -61,7 +61,7 @@ The function should be removed from Next.js projects to ensure the best possible export function reverseLocaleLookup(locale: string): string | undefined { for (const key in LOCALES) { if (LOCALES[key] === locale) { - return key; + return key } } } @@ -70,16 +70,16 @@ The function should be removed from Next.js projects to ensure the best possible 1. Create or modify your `middleware.ts` file with the following: ```ts - import type { NextRequest } from "next/server"; - import { createLocaleRedirect, pathnameHasLocale } from "@/i18n"; + import type { NextRequest } from "next/server" + import { createLocaleRedirect, pathnameHasLocale } from "@/i18n" export async function middleware(request: NextRequest) { if (!pathnameHasLocale(request)) { - return createLocaleRedirect(request); + return createLocaleRedirect(request) } } export const config = { matcher: ["/((?!_next|api|slice-simulator|icon.svg).*)"], - }; + } ``` diff --git a/package-lock.json b/package-lock.json index 14742d9..6e222f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,14 +20,12 @@ "devDependencies": { "@playwright/test": "^1.58.2", "@prismicio/client": "^7.12.0", - "@trivago/prettier-plugin-sort-imports": "^6.0.2", "@types/node": "^25.5.0", "@types/react": "^19.2.14", "next": "16.2.1", + "oxfmt": "^0.43.0", "oxlint": "^1.58.0", "playwright": "^1.58.2", - "prettier": "^3.8.1", - "prettier-plugin-jsdoc": "^1.8.0", "react": "^19.2.4", "react-dom": "^19.2.4", "tsdown": "^0.21.7", @@ -1761,6 +1759,329 @@ "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@oxfmt/binding-android-arm-eabi": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.43.0.tgz", + "integrity": "sha512-CgU2s+/9hHZgo0IxVxrbMPrMj+tJ6VM3mD7Mr/4oiz4FNTISLoCvRmB5nk4wAAle045RtRjd86m673jwPyb1OQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-android-arm64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.43.0.tgz", + "integrity": "sha512-T9OfRwjA/EdYxAqbvR7TtqLv5nIrwPXuCtTwOHtS7aR9uXyn74ZYgzgTo6/ZwvTq9DY4W+DsV09hB2EXgn9EbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-darwin-arm64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.43.0.tgz", + "integrity": "sha512-o3i49ZUSJWANzXMAAVY1wnqb65hn4JVzwlRQ5qfcwhRzIA8lGVaud31Q3by5ALHPrksp5QEaKCQF9aAS3TXpZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-darwin-x64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.43.0.tgz", + "integrity": "sha512-vWECzzCFkb0kK6jaHjbtC5sC3adiNWtqawFCxhpvsWlzVeKmv5bNvkB4nux+o4JKWTpHCM57NDK/MeXt44txmA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-freebsd-x64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.43.0.tgz", + "integrity": "sha512-rgz8JpkKiI/umOf7fl9gwKyQasC8bs5SYHy6g7e4SunfLBY3+8ATcD5caIg8KLGEtKFm5ujKaH8EfjcmnhzTLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.43.0.tgz", + "integrity": "sha512-nWYnF3vIFzT4OM1qL/HSf1Yuj96aBuKWSaObXHSWliwAk2rcj7AWd6Lf7jowEBQMo4wCZVnueIGw/7C4u0KTBQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm-musleabihf": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.43.0.tgz", + "integrity": "sha512-sFg+NWJbLfupYTF4WELHAPSnLPOn1jiDZ33Z1jfDnTaA+cC3iB35x0FMMZTFdFOz3icRIArncwCcemJFGXu6TQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm64-gnu": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.43.0.tgz", + "integrity": "sha512-MelWqv68tX6wZEILDrTc9yewiGXe7im62+5x0bNXlCYFOZdA+VnYiJfAihbROsZ5fm90p9C3haFrqjj43XnlAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm64-musl": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.43.0.tgz", + "integrity": "sha512-ROaWfYh+6BSJ1Arwy5ujijTlwnZetxDxzBpDc1oBR4d7rfrPBqzeyjd5WOudowzQUgyavl2wEpzn1hw3jWcqLA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-ppc64-gnu": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.43.0.tgz", + "integrity": "sha512-PJRs/uNxmFipJJ8+SyKHh7Y7VZIKQicqrrBzvfyM5CtKi8D7yZKTwUOZV3ffxmiC2e7l1SDJpkBEOyue5NAFsg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-riscv64-gnu": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.43.0.tgz", + "integrity": "sha512-j6biGAgzIhj+EtHXlbNumvwG7XqOIdiU4KgIWRXAEj/iUbHKukKW8eXa4MIwpQwW1YkxovduKtzEAPnjlnAhVQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-riscv64-musl": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.43.0.tgz", + "integrity": "sha512-RYWxAcslKxvy7yri24Xm9cmD0RiANaiEPs007EFG6l9h1ChM69Q5SOzACaCoz4Z9dEplnhhneeBaTWMEdpgIbA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-s390x-gnu": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.43.0.tgz", + "integrity": "sha512-DT6Q8zfQQy3jxpezAsBACEHNUUixKSYTwdXeXojNHe4DQOoxjPdjr3Szu6BRNjxLykZM/xMNmp9ElOIyDppwtw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-x64-gnu": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.43.0.tgz", + "integrity": "sha512-R8Yk7iYcuZORXmCfFZClqbDxRZgZ9/HEidUuBNdoX8Ptx07cMePnMVJ/woB84lFIDjh2ROHVaOP40Ds3rBXFqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-x64-musl": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.43.0.tgz", + "integrity": "sha512-F2YYqyvnQNvi320RWZNAvsaWEHwmW3k4OwNJ1hZxRKXupY63expbBaNp6jAgvYs7y/g546vuQnGHQuCBhslhLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-openharmony-arm64": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.43.0.tgz", + "integrity": "sha512-OE6TdietLXV3F6c7pNIhx/9YC1/2YFwjU9DPc/fbjxIX19hNIaP1rS0cFjCGJlGX+cVJwIKWe8Mos+LdQ1yAJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-arm64-msvc": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.43.0.tgz", + "integrity": "sha512-0nWK6a7pGkbdoypfVicmV9k/N1FwjPZENoqhlTU+5HhZnAhpIO3za30nEE33u6l6tuy9OVfpdXUqxUgZ+4lbZw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-ia32-msvc": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.43.0.tgz", + "integrity": "sha512-9aokTR4Ft+tRdvgN/pKzSkVy2ksc4/dCpDm9L/xFrbIw0yhLtASLbvoG/5WOTUh/BRPPnfGTsWznEqv0dlOmhA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-x64-msvc": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.43.0.tgz", + "integrity": "sha512-4bPgdQux2ZLWn3bf2TTXXMHcJB4lenmuxrLqygPmvCJ104Yqzj1UctxSRzR31TiJ4MLaG22RK8dUsVpJtrCz5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@oxlint/binding-android-arm-eabi": { "version": "1.58.0", "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.58.0.tgz", @@ -2419,47 +2740,6 @@ "tslib": "^2.8.0" } }, - "node_modules/@trivago/prettier-plugin-sort-imports": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-6.0.2.tgz", - "integrity": "sha512-3DgfkukFyC/sE/VuYjaUUWoFfuVjPK55vOFDsxD56XXynFMCZDYFogH2l/hDfOsQAm1myoU/1xByJ3tWqtulXA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@babel/generator": "^7.28.0", - "@babel/parser": "^7.28.0", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", - "javascript-natural-sort": "^0.7.1", - "lodash-es": "^4.17.21", - "minimatch": "^9.0.0", - "parse-imports-exports": "^0.2.4" - }, - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "@vue/compiler-sfc": "3.x", - "prettier": "2.x - 3.x", - "prettier-plugin-ember-template-tag": ">= 2.0.0", - "prettier-plugin-svelte": "3.x", - "svelte": "4.x || 5.x" - }, - "peerDependenciesMeta": { - "@vue/compiler-sfc": { - "optional": true - }, - "prettier-plugin-ember-template-tag": { - "optional": true - }, - "prettier-plugin-svelte": { - "optional": true - }, - "svelte": { - "optional": true - } - } - }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -2471,16 +2751,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/debug": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", - "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, "node_modules/@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", @@ -2516,23 +2786,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "25.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", @@ -2570,13 +2823,6 @@ "@types/react": "^19.2.0" } }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.58.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.0.tgz", @@ -3543,13 +3789,6 @@ "node": ">=6.0.0" } }, - "node_modules/binary-searching": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/binary-searching/-/binary-searching-2.0.5.tgz", - "integrity": "sha512-v4N2l3RxL+m4zDxyxz3Ne2aTmiPn8ZUpKFpdPtO+ItW1NcTCXA7JeHG5GMBSvoKSkQZ9ycS+EouDVxYB9ufKWA==", - "dev": true, - "license": "MIT" - }, "node_modules/birpc": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz", @@ -3560,16 +3799,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -3726,17 +3955,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -3765,16 +3983,6 @@ "license": "MIT", "peer": true }, - "node_modules/comment-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz", - "integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12.0.0" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3890,20 +4098,6 @@ } } }, - "node_modules/decode-named-character-reference": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", - "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3954,38 +4148,14 @@ "dev": true, "license": "MIT" }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "optional": true, + "engines": { + "node": ">=8" } }, "node_modules/doctrine": { @@ -5789,13 +5959,6 @@ "node": ">= 0.4" } }, - "node_modules/javascript-natural-sort": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dev": true, - "license": "MIT" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5871,643 +6034,134 @@ "dev": true, "license": "MIT", "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash-es": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", - "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "license": "MIT", - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", - "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" } }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "json-buffer": "3.0.1" } }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "peer": true }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "micromark-util-types": "^2.0.0" + "yallist": "^3.0.2" } }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" + "bin": { + "lz-string": "bin/bin.js" } }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 8" + } }, "node_modules/micromatch": { "version": "4.0.8", @@ -6523,22 +6177,6 @@ "node": ">=8.6" } }, - "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -6846,6 +6484,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oxfmt": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.43.0.tgz", + "integrity": "sha512-KTYNG5ISfHSdmeZ25Xzb3qgz9EmQvkaGAxgBY/p38+ZiAet3uZeu7FnMwcSQJg152Qwl0wnYAxDc+Z/H6cvrwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinypool": "2.1.0" + }, + "bin": { + "oxfmt": "bin/oxfmt" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxfmt/binding-android-arm-eabi": "0.43.0", + "@oxfmt/binding-android-arm64": "0.43.0", + "@oxfmt/binding-darwin-arm64": "0.43.0", + "@oxfmt/binding-darwin-x64": "0.43.0", + "@oxfmt/binding-freebsd-x64": "0.43.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.43.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.43.0", + "@oxfmt/binding-linux-arm64-gnu": "0.43.0", + "@oxfmt/binding-linux-arm64-musl": "0.43.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.43.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.43.0", + "@oxfmt/binding-linux-riscv64-musl": "0.43.0", + "@oxfmt/binding-linux-s390x-gnu": "0.43.0", + "@oxfmt/binding-linux-x64-gnu": "0.43.0", + "@oxfmt/binding-linux-x64-musl": "0.43.0", + "@oxfmt/binding-openharmony-arm64": "0.43.0", + "@oxfmt/binding-win32-arm64-msvc": "0.43.0", + "@oxfmt/binding-win32-ia32-msvc": "0.43.0", + "@oxfmt/binding-win32-x64-msvc": "0.43.0" + } + }, "node_modules/oxlint": { "version": "1.58.0", "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.58.0.tgz", @@ -6941,23 +6619,6 @@ "node": ">=6" } }, - "node_modules/parse-imports-exports": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", - "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-statements": "1.0.11" - } - }, - "node_modules/parse-statements": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", - "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", - "dev": true, - "license": "MIT" - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -7091,40 +6752,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-jsdoc": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-jsdoc/-/prettier-plugin-jsdoc-1.8.0.tgz", - "integrity": "sha512-byW8EBZ1DSA3CPdDGBXfcdqqhh2eq0+HlIOPTGZ6rf9O2p/AwBmtS0e49ot5ZeOdcszj81FyzbyHr/VS0eYpCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-searching": "^2.0.5", - "comment-parser": "^1.4.0", - "mdast-util-from-markdown": "^2.0.0" - }, - "engines": { - "node": ">=14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "prettier": "^3.0.0" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -8047,6 +7674,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinypool": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz", + "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.0.0 || >=22.0.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8369,20 +8006,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unrs-resolver": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", diff --git a/package.json b/package.json index 004e3cd..82c6909 100644 --- a/package.json +++ b/package.json @@ -3,20 +3,30 @@ "version": "2.2.3", "description": "Helpers to integrate Prismic into Next.js apps", "keywords": [ - "typescript", - "prismic", "next", - "vercel", - "preview" + "preview", + "prismic", + "typescript", + "vercel" ], + "license": "Apache-2.0", + "author": "Prismic (https://prismic.io)", "repository": { "type": "git", "url": "git+https://github.com/prismicio/prismic-next.git" }, - "license": "Apache-2.0", - "author": "Prismic (https://prismic.io)", - "sideEffects": false, + "workspaces": [ + ".", + "e2e-projects/*" + ], + "files": [ + "dist", + "src" + ], "type": "module", + "sideEffects": false, + "main": "./dist/index.cjs", + "types": "./dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", @@ -28,22 +38,15 @@ }, "./package.json": "./package.json" }, - "main": "./dist/index.cjs", - "types": "./dist/index.d.ts", - "files": [ - "dist", - "src" - ], - "workspaces": [ - ".", - "e2e-projects/*" - ], + "publishConfig": { + "access": "public" + }, "scripts": { "build": "tsdown", "dev": "tsdown --watch", "e2e": "playwright test", "e2e:ui": "npm run e2e -- --ui", - "format": "prettier --write .", + "format": "oxfmt", "lint": "oxlint --deny-warnings", "prepare": "npm run build", "test": "npm run lint && npm run types && npm run build && npm run e2e", @@ -57,14 +60,12 @@ "devDependencies": { "@playwright/test": "^1.58.2", "@prismicio/client": "^7.12.0", - "@trivago/prettier-plugin-sort-imports": "^6.0.2", "@types/node": "^25.5.0", "@types/react": "^19.2.14", "next": "16.2.1", + "oxfmt": "^0.43.0", "oxlint": "^1.58.0", "playwright": "^1.58.2", - "prettier": "^3.8.1", - "prettier-plugin-jsdoc": "^1.8.0", "react": "^19.2.4", "react-dom": "^19.2.4", "tsdown": "^0.21.7", @@ -77,8 +78,5 @@ }, "engines": { "node": ">=20" - }, - "publishConfig": { - "access": "public" } } diff --git a/playwright.config.ts b/playwright.config.ts index 5602a54..2acc50c 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,17 +1,17 @@ -import { defineConfig, devices } from "@playwright/test"; -import assert from "node:assert"; -import { fileURLToPath } from "node:url"; -import { existsSync, writeFileSync } from "node:fs"; +import assert from "node:assert" +import { existsSync, writeFileSync } from "node:fs" +import { fileURLToPath } from "node:url" + +import { defineConfig, devices } from "@playwright/test" try { - process.loadEnvFile(".env.test.local"); + process.loadEnvFile(".env.test.local") } catch {} export const STORAGE_STATE = fileURLToPath( new URL("./tests/infra/.storage-state.json", import.meta.url), -); -if (!existsSync(STORAGE_STATE)) - writeFileSync(STORAGE_STATE, JSON.stringify({})); +) +if (!existsSync(STORAGE_STATE)) writeFileSync(STORAGE_STATE, JSON.stringify({})) // https://playwright.dev/docs/test-configuration export default defineConfig({ @@ -72,24 +72,18 @@ export default defineConfig({ reuseExistingServer: !process.env.CI, }, ], -}); +}) declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace NodeJS { interface ProcessEnv { - CI: boolean; - E2E_PRISMIC_EMAIL: string; - E2E_PRISMIC_PASSWORD: string; + CI: boolean + E2E_PRISMIC_EMAIL: string + E2E_PRISMIC_PASSWORD: string } } } -assert.ok( - process.env.E2E_PRISMIC_EMAIL, - "Missing E2E_PRISMIC_EMAIL env variable.", -); -assert.ok( - process.env.E2E_PRISMIC_PASSWORD, - "Missing E2E_PRISMIC_PASSWORD env variable.", -); +assert.ok(process.env.E2E_PRISMIC_EMAIL, "Missing E2E_PRISMIC_EMAIL env variable.") +assert.ok(process.env.E2E_PRISMIC_PASSWORD, "Missing E2E_PRISMIC_PASSWORD env variable.") diff --git a/src/PrismicNextImage.tsx b/src/PrismicNextImage.tsx index 7ada3d7..81eb4a5 100644 --- a/src/PrismicNextImage.tsx +++ b/src/PrismicNextImage.tsx @@ -1,185 +1,164 @@ -"use client"; - -import type { - ForwardRefExoticComponent, - PropsWithoutRef, - RefAttributes} from "react"; -import { - forwardRef -} from "react"; -import type { ImageProps } from "next/image"; -import Image from "next/image"; -import type { ImgixURLParams } from "imgix-url-builder"; -import { buildURL } from "imgix-url-builder"; -import type { ImageFieldImage} from "@prismicio/client"; -import { isFilled } from "@prismicio/client"; - -import { devMsg } from "./lib/devMsg"; -import { resolveDefaultExport } from "./lib/resolveDefaultExport"; - -import { imgixLoader } from "./imgixLoader"; +"use client" + +import type { ImageFieldImage } from "@prismicio/client" +import { isFilled } from "@prismicio/client" +import type { ImgixURLParams } from "imgix-url-builder" +import { buildURL } from "imgix-url-builder" +import type { ImageProps } from "next/image" +import Image from "next/image" +import type { ForwardRefExoticComponent, PropsWithoutRef, RefAttributes } from "react" +import { forwardRef } from "react" + +import { imgixLoader } from "./imgixLoader" +import { devMsg } from "./lib/devMsg" +import { resolveDefaultExport } from "./lib/resolveDefaultExport" const castInt = (input: string | number | undefined): number | undefined => { if (typeof input === "number" || typeof input === "undefined") { - return input; + return input } else { - const parsed = Number.parseInt(input); + const parsed = Number.parseInt(input) if (Number.isNaN(parsed)) { - return undefined; + return undefined } else { - return parsed; + return parsed } } -}; +} -export type PrismicNextImageProps = Omit< - ImageProps, - "src" | "alt" | "loader" -> & { +export type PrismicNextImageProps = Omit & { /** The Prismic Image field or thumbnail to render. */ - field: ImageFieldImage | null | undefined; + field: ImageFieldImage | null | undefined /** * An object of Imgix URL API parameters to transform the image. * * @see https://docs.imgix.com/apis/rendering */ - imgixParams?: { [P in keyof ImgixURLParams]: ImgixURLParams[P] | null }; + imgixParams?: { [P in keyof ImgixURLParams]: ImgixURLParams[P] | null } /** * Declare an image as decorative by providing `alt=""`. * - * See: - * https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#decorative_images + * See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#decorative_images */ - alt?: ""; + alt?: "" /** - * Declare an image as decorative only if the Image field does not have - * alternative text by providing `fallbackAlt=""`. + * Declare an image as decorative only if the Image field does not have alternative text by + * providing `fallbackAlt=""`. * - * See: - * https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#decorative_images + * See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#decorative_images */ - fallbackAlt?: ""; + fallbackAlt?: "" - /** - * Rendered when the field is empty. If a fallback is not given, `null` will - * be rendered. - */ - fallback?: React.ReactNode; + /** Rendered when the field is empty. If a fallback is not given, `null` will be rendered. */ + fallback?: React.ReactNode - loader?: ImageProps["loader"] | null; -}; + loader?: ImageProps["loader"] | null +} /** - * React component that renders an image from a Prismic Image field or one of - * its thumbnails using `next/image`. It will automatically set the `alt` - * attribute using the Image field's `alt` property. + * React component that renders an image from a Prismic Image field or one of its thumbnails using + * `next/image`. It will automatically set the `alt` attribute using the Image field's `alt` + * property. * - * It uses an Imgix URL-based loader by default. A custom loader can be provided - * with the `loader` prop. If you would like to use the Next.js Image - * Optimization API instead, set `loader={undefined}`. + * It uses an Imgix URL-based loader by default. A custom loader can be provided with the `loader` + * prop. If you would like to use the Next.js Image Optimization API instead, set + * `loader={undefined}`. * * @param props - Props for the component. - * * @returns A responsive image component using `next/image` for the given Image - * field. - * + * field. * @see To learn more about `next/image`, see: https://nextjs.org/docs/api-reference/next/image */ // The type annotation is necessary to avoid a type reference issue. export const PrismicNextImage: ForwardRefExoticComponent< PropsWithoutRef & RefAttributes -> = forwardRef( - function PrismicNextImage( - { - field, - imgixParams = {}, - alt, - fallbackAlt, - fill, - width, - height, - fallback = null, - loader = imgixLoader, - ...restProps - }, - ref, - ) { - if (process.env.NODE_ENV === "development") { - if (typeof alt === "string" && alt !== "") { - console.warn( - `[PrismicNextImage] The "alt" prop can only be used to declare an image as decorative by passing an empty string (alt="") but was provided a non-empty string. You can resolve this warning by removing the "alt" prop or changing it to alt="". For more details, see ${devMsg( - "alt-must-be-an-empty-string", - )}`, - ); - } - - if (typeof fallbackAlt === "string" && fallbackAlt !== "") { - console.warn( - `[PrismicNextImage] The "fallbackAlt" prop can only be used to declare an image as decorative by passing an empty string (fallbackAlt="") but was provided a non-empty string. You can resolve this warning by removing the "fallbackAlt" prop or changing it to fallbackAlt="". For more details, see ${devMsg( - "alt-must-be-an-empty-string", - )}`, - ); - } +> = forwardRef(function PrismicNextImage( + { + field, + imgixParams = {}, + alt, + fallbackAlt, + fill, + width, + height, + fallback = null, + loader = imgixLoader, + ...restProps + }, + ref, +) { + if (process.env.NODE_ENV === "development") { + if (typeof alt === "string" && alt !== "") { + console.warn( + `[PrismicNextImage] The "alt" prop can only be used to declare an image as decorative by passing an empty string (alt="") but was provided a non-empty string. You can resolve this warning by removing the "alt" prop or changing it to alt="". For more details, see ${devMsg( + "alt-must-be-an-empty-string", + )}`, + ) } - if (!isFilled.imageThumbnail(field)) { - return <>{fallback}; + if (typeof fallbackAlt === "string" && fallbackAlt !== "") { + console.warn( + `[PrismicNextImage] The "fallbackAlt" prop can only be used to declare an image as decorative by passing an empty string (fallbackAlt="") but was provided a non-empty string. You can resolve this warning by removing the "fallbackAlt" prop or changing it to fallbackAlt="". For more details, see ${devMsg( + "alt-must-be-an-empty-string", + )}`, + ) } + } - const resolvedImgixParams = imgixParams; - for (const x in imgixParams) { - if (resolvedImgixParams[x as keyof typeof resolvedImgixParams] === null) { - resolvedImgixParams[x as keyof typeof resolvedImgixParams] = undefined; - } + if (!isFilled.imageThumbnail(field)) { + return <>{fallback} + } + + const resolvedImgixParams = imgixParams + for (const x in imgixParams) { + if (resolvedImgixParams[x as keyof typeof resolvedImgixParams] === null) { + resolvedImgixParams[x as keyof typeof resolvedImgixParams] = undefined } + } - const src = buildURL(field.url, imgixParams as ImgixURLParams); + const src = buildURL(field.url, imgixParams as ImgixURLParams) - const ar = field.dimensions.width / field.dimensions.height; + const ar = field.dimensions.width / field.dimensions.height - const castedWidth = castInt(width); - const castedHeight = castInt(height); + const castedWidth = castInt(width) + const castedHeight = castInt(height) - let resolvedWidth = castedWidth ?? field.dimensions.width; - let resolvedHeight = castedHeight ?? field.dimensions.height; + let resolvedWidth = castedWidth ?? field.dimensions.width + let resolvedHeight = castedHeight ?? field.dimensions.height - if (castedWidth != null && castedHeight == null) { - resolvedHeight = castedWidth / ar; - } else if (castedWidth == null && castedHeight != null) { - resolvedWidth = castedHeight * ar; - } + if (castedWidth != null && castedHeight == null) { + resolvedHeight = castedWidth / ar + } else if (castedWidth == null && castedHeight != null) { + resolvedWidth = castedHeight * ar + } - // A non-null assertion is required since we can't statically - // know if an alt attribute is available. - const resolvedAlt = (alt ?? (field.alt || fallbackAlt))!; - - if ( - process.env.NODE_ENV === "development" && - typeof resolvedAlt !== "string" - ) { - console.error( - `[PrismicNextImage] The following image is missing an "alt" property. Please add Alternative Text to the image in Prismic. To mark the image as decorative instead, add one of \`alt=""\` or \`fallbackAlt=""\`.`, - src, - ); - } + // A non-null assertion is required since we can't statically + // know if an alt attribute is available. + const resolvedAlt = (alt ?? (field.alt || fallbackAlt))! - const ResolvedImage = resolveDefaultExport(Image); - - return ( - - ); - }, -); + if (process.env.NODE_ENV === "development" && typeof resolvedAlt !== "string") { + console.error( + `[PrismicNextImage] The following image is missing an "alt" property. Please add Alternative Text to the image in Prismic. To mark the image as decorative instead, add one of \`alt=""\` or \`fallbackAlt=""\`.`, + src, + ) + } + + const ResolvedImage = resolveDefaultExport(Image) + + return ( + + ) +}) diff --git a/src/PrismicNextLink.tsx b/src/PrismicNextLink.tsx index c5d081d..6873ca3 100644 --- a/src/PrismicNextLink.tsx +++ b/src/PrismicNextLink.tsx @@ -1,67 +1,65 @@ -import type { ComponentProps} from "react"; -import { forwardRef } from "react"; -import Link from "next/link"; import type { AsLinkAttrsConfig, LinkField, LinkResolverFunction, - PrismicDocument} from "@prismicio/client"; -import { - asLinkAttrs, -} from "@prismicio/client"; + PrismicDocument, +} from "@prismicio/client" +import { asLinkAttrs } from "@prismicio/client" +import Link from "next/link" +import type { ComponentProps } from "react" +import { forwardRef } from "react" -import { resolveDefaultExport } from "./lib/resolveDefaultExport"; +import { resolveDefaultExport } from "./lib/resolveDefaultExport" export type PrismicNextLinkProps = Omit< ComponentProps, "field" | "document" | "href" | "rel" > & { - linkResolver?: LinkResolverFunction; - rel?: string | AsLinkAttrsConfig["rel"]; + linkResolver?: LinkResolverFunction + rel?: string | AsLinkAttrsConfig["rel"] } & ( | { - field: LinkField | null | undefined; - document?: never; - href?: never; + field: LinkField | null | undefined + document?: never + href?: never } | { - field?: never; - document: PrismicDocument | null | undefined; - href?: never; + field?: never + document: PrismicDocument | null | undefined + href?: never } | { - field?: never; - document?: never; - href: ComponentProps["href"]; + field?: never + document?: never + href: ComponentProps["href"] } - ); + ) -export const PrismicNextLink = forwardRef< - HTMLAnchorElement, - PrismicNextLinkProps ->(function PrismicNextLink(props, ref) { - const { field, document, linkResolver, children, ...restProps } = props; - const { - href: computedHref, - rel: computedRel, - ...attrs - } = asLinkAttrs(field ?? document, { - linkResolver, - rel: typeof restProps.rel === "function" ? restProps.rel : undefined, - }); +export const PrismicNextLink = forwardRef( + function PrismicNextLink(props, ref) { + const { field, document, linkResolver, children, ...restProps } = props + const { + href: computedHref, + rel: computedRel, + ...attrs + } = asLinkAttrs(field ?? document, { + linkResolver, + rel: typeof restProps.rel === "function" ? restProps.rel : undefined, + }) - const href = ("href" in restProps ? restProps.href : computedHref) || ""; + const href = ("href" in restProps ? restProps.href : computedHref) || "" - let rel = computedRel; - if ("rel" in restProps && typeof restProps.rel !== "function") { - rel = restProps.rel; - } + let rel = computedRel + if ("rel" in restProps && typeof restProps.rel !== "function") { + rel = restProps.rel + } - const ResolvedLink = resolveDefaultExport(Link); + const ResolvedLink = resolveDefaultExport(Link) - return ( - - {"children" in props ? children : field?.text} - - ); -}); + return ( + + {"children" in props ? children : field?.text} + + ) + }, +) diff --git a/src/PrismicPreview.tsx b/src/PrismicPreview.tsx index 6227f97..ade8730 100644 --- a/src/PrismicPreview.tsx +++ b/src/PrismicPreview.tsx @@ -1,55 +1,54 @@ -import type { FC, ReactNode } from "react"; -import Script from "next/script"; -import { getToolbarSrc } from "@prismicio/client"; +import { getToolbarSrc } from "@prismicio/client" +import Script from "next/script" +import type { FC, ReactNode } from "react" -import { resolveDefaultExport } from "./lib/resolveDefaultExport"; -import { PrismicPreviewClient } from "./PrismicPreviewClient"; +import { resolveDefaultExport } from "./lib/resolveDefaultExport" +import { PrismicPreviewClient } from "./PrismicPreviewClient" /** Props for ``. */ export type PrismicPreviewProps = { /** - * The name of your Prismic repository. A Prismic Toolbar will be registered - * using this repository. + * The name of your Prismic repository. A Prismic Toolbar will be registered using this + * repository. */ - repositoryName: string; + repositoryName: string /** - * The URL of your app's Prismic preview endpoint (default: `/api/preview`). - * This URL will be fetched on preview update events. + * The URL of your app's Prismic preview endpoint (default: `/api/preview`). This URL will be + * fetched on preview update events. */ - updatePreviewURL?: string; + updatePreviewURL?: string /** - * The URL of your app's exit preview endpoint (default: `/api/exit-preview`). - * This URL will be fetched on preview exit events. + * The URL of your app's exit preview endpoint (default: `/api/exit-preview`). This URL will be + * fetched on preview exit events. */ - exitPreviewURL?: string; + exitPreviewURL?: string /** Children to render adjacent to the Prismic Toolbar. */ - children?: ReactNode; -}; + children?: ReactNode +} /** - * React component that sets up Prismic Previews using the Prismic Toolbar. When - * the Prismic Toolbar send events to the browser, such as on preview updates - * and exiting, this component will automatically refresh the page with the - * changes. + * React component that sets up Prismic Previews using the Prismic Toolbar. When the Prismic Toolbar + * send events to the browser, such as on preview updates and exiting, this component will + * automatically refresh the page with the changes. * - * This component can be wrapped around your app or added anywhere in your app's - * tree. It must be rendered on every page. + * This component can be wrapped around your app or added anywhere in your app's tree. It must be + * rendered on every page. */ export const PrismicPreview: FC = async (props) => { - const { repositoryName, children, ...otherProps } = props; + const { repositoryName, children, ...otherProps } = props // Need this to avoid the following Next.js build-time error: // You're importing a component that needs next/headers. That only works // in a Server Component which is not supported in the pages/ directory. - const { draftMode } = await import("next/headers"); + const { draftMode } = await import("next/headers") - const toolbarSrc = getToolbarSrc(repositoryName); - const isDraftMode = (await draftMode()).isEnabled; + const toolbarSrc = getToolbarSrc(repositoryName) + const isDraftMode = (await draftMode()).isEnabled - const ResolvedScript = resolveDefaultExport(Script); + const ResolvedScript = resolveDefaultExport(Script) return ( <> @@ -61,5 +60,5 @@ export const PrismicPreview: FC = async (props) => { /> - ); -}; + ) +} diff --git a/src/PrismicPreviewClient.tsx b/src/PrismicPreviewClient.tsx index a4ab5c2..32eb671 100644 --- a/src/PrismicPreviewClient.tsx +++ b/src/PrismicPreviewClient.tsx @@ -1,16 +1,16 @@ -"use client"; +"use client" -import { cookie as prismicCookie } from "@prismicio/client"; -import { useRouter } from "next/navigation"; -import type { FC } from "react"; -import { useEffect } from "react"; +import { cookie as prismicCookie } from "@prismicio/client" +import { useRouter } from "next/navigation" +import type { FC } from "react" +import { useEffect } from "react" type PrismicPreviewClientProps = { - repositoryName: string; - isDraftMode: boolean; - updatePreviewURL?: string; - exitPreviewURL?: string; -}; + repositoryName: string + isDraftMode: boolean + updatePreviewURL?: string + exitPreviewURL?: string +} export const PrismicPreviewClient: FC = (props) => { const { @@ -18,25 +18,25 @@ export const PrismicPreviewClient: FC = (props) => { isDraftMode, updatePreviewURL = "/api/preview", exitPreviewURL = "/api/exit-preview", - } = props; + } = props - const { refresh } = useRouter(); + const { refresh } = useRouter() useEffect(() => { - const controller = new AbortController(); + const controller = new AbortController() window.addEventListener("prismicPreviewUpdate", onUpdate, { signal: controller.signal, - }); + }) window.addEventListener("prismicPreviewEnd", onEnd, { signal: controller.signal, - }); + }) - const cookie = getPrismicPreviewCookie(window.document.cookie); + const cookie = getPrismicPreviewCookie(window.document.cookie) const cookieRepositoryName = cookie ? (decodeURIComponent(cookie).match(/"([^"]+)\.prismic\.io"/) || [])[1] - : undefined; - const hasCookieForRepository = cookieRepositoryName === repositoryName; + : undefined + const hasCookieForRepository = cookieRepositoryName === repositoryName // Start the preview for preview share links. Previews from // share links do not go to the `updatePreviewURL` like a normal @@ -55,75 +55,73 @@ export const PrismicPreviewClient: FC = (props) => { if (res.type !== "opaqueredirect") { console.error( `[] Failed to start the preview using "${updatePreviewURL}". Does it exist?`, - ); + ) - return; + return } - refresh(); + refresh() }) .catch(() => { // noop - }); + }) } function onUpdate(event: Event) { - event.preventDefault(); - refresh(); + event.preventDefault() + refresh() } function onEnd(event: Event) { - event.preventDefault(); + event.preventDefault() globalThis .fetch(exitPreviewURL, { signal: controller.signal }) .then((res) => { if (!res.ok) { console.error( `[] Failed to exit Preview Mode using the "${exitPreviewURL}" API endpoint. Does it exist?`, - ); + ) - return; + return } - refresh(); + refresh() }) .catch(() => { // noop - }); + }) } - return () => controller.abort(); - }, [repositoryName, isDraftMode, updatePreviewURL, exitPreviewURL, refresh]); + return () => controller.abort() + }, [repositoryName, isDraftMode, updatePreviewURL, exitPreviewURL, refresh]) - return null; -}; + return null +} /** * Returns the value of a cookie from a given cookie store. * - * @param cookieJar - The stringified cookie store from which to read the - * cookie. - * + * @param cookieJar - The stringified cookie store from which to read the cookie. * @returns The value of the cookie, if it exists. */ function getPrismicPreviewCookie(cookieJar: string): string | undefined { function readValue(value: string): string { - return value.replace(/%3B/g, ";"); + return value.replace(/%3B/g, ";") } - const cookies = cookieJar.split("; "); + const cookies = cookieJar.split("; ") - let value: string | undefined; + let value: string | undefined for (const cookie of cookies) { - const parts = cookie.split("="); - const name = readValue(parts[0]).replace(/%3D/g, "="); + const parts = cookie.split("=") + const name = readValue(parts[0]).replace(/%3D/g, "=") if (name === prismicCookie.preview) { - value = readValue(parts.slice(1).join("=")); - continue; + value = readValue(parts.slice(1).join("=")) + continue } } - return value; + return value } diff --git a/src/SliceSimulator.tsx b/src/SliceSimulator.tsx index 6f06417..bc804f7 100644 --- a/src/SliceSimulator.tsx +++ b/src/SliceSimulator.tsx @@ -1,39 +1,34 @@ -"use client"; +"use client" -import { SliceSimulatorWrapper } from "./SliceSimulatorWrapper"; -import { getSlices } from "./getSlices"; -import { - SimulatorManager, - StateEventType, - getDefaultMessage, -} from "@prismicio/simulator/kit"; -import type { SliceSimulatorProps as BaseSliceSimulatorProps } from "@prismicio/simulator/kit"; -import { compressToEncodedURIComponent } from "lz-string"; -import { useRouter } from "next/navigation"; -import { useEffect, useState } from "react"; -import type { FC, ReactNode } from "react"; +import { SimulatorManager, StateEventType, getDefaultMessage } from "@prismicio/simulator/kit" +import type { SliceSimulatorProps as BaseSliceSimulatorProps } from "@prismicio/simulator/kit" +import { compressToEncodedURIComponent } from "lz-string" +import { useRouter } from "next/navigation" +import { useEffect, useState } from "react" +import type { FC, ReactNode } from "react" -const STATE_PARAMS_KEY = "state"; +import { getSlices } from "./getSlices" +import { SliceSimulatorWrapper } from "./SliceSimulatorWrapper" -const simulatorManager = new SimulatorManager(); +const STATE_PARAMS_KEY = "state" -/** - * Parameters provided to the Slice Simulator page. - */ +const simulatorManager = new SimulatorManager() + +/** Parameters provided to the Slice Simulator page. */ export type SliceSimulatorParams = { searchParams: Promise<{ - state?: string; - }>; -}; + state?: string + }> +} export type SliceSimulatorProps = BaseSliceSimulatorProps & { - children: ReactNode; - className?: string; -}; + children: ReactNode + className?: string +} /** - * Simulate slices in isolation. The slice simulator enables live slice - * development in Slice Machine and live previews in the Page Builder. + * Simulate slices in isolation. The slice simulator enables live slice development in Slice Machine + * and live previews in the Page Builder. */ export const SliceSimulator: FC = ({ children, @@ -41,45 +36,45 @@ export const SliceSimulator: FC = ({ zIndex, className, }) => { - const [message, setMessage] = useState(() => getDefaultMessage()); - const router = useRouter(); + const [message, setMessage] = useState(() => getDefaultMessage()) + const router = useRouter() const state = typeof window !== "undefined" ? new URL(window.location.href).searchParams.get(STATE_PARAMS_KEY) - : undefined; - const hasSlices = getSlices(state).length > 0; + : undefined + const hasSlices = getSlices(state).length > 0 useEffect(() => { simulatorManager.state.on( StateEventType.Slices, (newSlices) => { - const url = new URL(window.location.href); + const url = new URL(window.location.href) url.searchParams.set( STATE_PARAMS_KEY, compressToEncodedURIComponent(JSON.stringify(newSlices)), - ); + ) - window.history.replaceState(null, "", url); + window.history.replaceState(null, "", url) // Wait until the next tick to prevent URL state race conditions. - setTimeout(() => router.refresh(), 0); + setTimeout(() => router.refresh(), 0) }, "simulator-slices", - ); + ) simulatorManager.state.on( StateEventType.Message, (newMessage) => setMessage(newMessage), "simulator-message", - ); + ) - simulatorManager.init(); + simulatorManager.init() return () => { - simulatorManager.state.off(StateEventType.Slices, "simulator-slices"); + simulatorManager.state.off(StateEventType.Slices, "simulator-slices") - simulatorManager.state.off(StateEventType.Message, "simulator-message"); - }; - }, [router]); + simulatorManager.state.off(StateEventType.Message, "simulator-message") + } + }, [router]) return ( = ({ > {children} - ); -}; + ) +} diff --git a/src/SliceSimulatorWrapper.tsx b/src/SliceSimulatorWrapper.tsx index 15c5b6b..c4d7c8a 100644 --- a/src/SliceSimulatorWrapper.tsx +++ b/src/SliceSimulatorWrapper.tsx @@ -4,21 +4,18 @@ import { onClickHandler, simulatorClass, simulatorRootClass, -} from "@prismicio/simulator/kit"; -import type { SliceSimulatorProps } from "@prismicio/simulator/kit"; -import type { FC, ReactNode } from "react"; +} from "@prismicio/simulator/kit" +import type { SliceSimulatorProps } from "@prismicio/simulator/kit" +import type { FC, ReactNode } from "react" type SliceSimulatorWrapperProps = SliceSimulatorProps & { - children: ReactNode; - className?: string; - message?: string; - hasSlices: boolean; -}; + children: ReactNode + className?: string + message?: string + hasSlices: boolean +} -/** - * A wrapper for the slice simulator that isolates the given children from the - * page's layout. - */ +/** A wrapper for the slice simulator that isolates the given children from the page's layout. */ export const SliceSimulatorWrapper: FC = ({ className, children, @@ -27,16 +24,13 @@ export const SliceSimulatorWrapper: FC = ({ message, hasSlices, }) => { - const defaultProps = getDefaultProps(); + const defaultProps = getDefaultProps() return (
= ({ height: "100vh", overflow: "auto", background: - typeof background === "undefined" - ? defaultProps.background - : (background ?? undefined), + typeof background === "undefined" ? defaultProps.background : (background ?? undefined), }} > {message ? ( @@ -56,13 +48,11 @@ export const SliceSimulatorWrapper: FC = ({ id="root" className={simulatorRootClass} onClickCapture={onClickHandler as unknown as React.MouseEventHandler} - onSubmitCapture={ - disableEventHandler as unknown as React.FormEventHandler - } + onSubmitCapture={disableEventHandler as unknown as React.FormEventHandler} > {children}
) : null} - ); -}; + ) +} diff --git a/src/createLocaleRedirect.ts b/src/createLocaleRedirect.ts index b412de7..e750714 100644 --- a/src/createLocaleRedirect.ts +++ b/src/createLocaleRedirect.ts @@ -1,4 +1,4 @@ -import { devMsg } from "./lib/devMsg"; +import { devMsg } from "./lib/devMsg" /** * @deprecated `createLocaleRedirect()` has been removed due to performance @@ -9,10 +9,10 @@ export function createLocaleRedirect(): never { `createLocaleRedirect() has been removed due to performance issues. See ${devMsg( "replace-createLocaleRedirect", )} for more details.`, - ); + ) } /** * @deprecated `createLocaleRedirect()` has been removed due to performance * issues. */ -export type CreateLocaleRedirectConfig = never; +export type CreateLocaleRedirectConfig = never diff --git a/src/enableAutoPreviews.ts b/src/enableAutoPreviews.ts index b0601a4..72f483a 100644 --- a/src/enableAutoPreviews.ts +++ b/src/enableAutoPreviews.ts @@ -1,4 +1,4 @@ -import { type Client, cookie as prismicCookie } from "@prismicio/client"; +import { type Client, cookie as prismicCookie } from "@prismicio/client" /** Configuration for `enableAutoPreviews`. */ export type EnableAutoPreviewsConfig = { @@ -6,12 +6,11 @@ export type EnableAutoPreviewsConfig = { // `Pick` is used to use the smallest possible subset of // `prismic.Client`. Doing this reduces the surface area for breaking // type changes. - client: Pick; -}; + client: Pick +} /** - * Configures a Prismic client to automatically query draft content during a - * preview session. + * Configures a Prismic client to automatically query draft content during a preview session. * * @param config - Configuration for the function. */ @@ -22,32 +21,32 @@ export function enableAutoPreviews(config: EnableAutoPreviewsConfig): void { // Need this to avoid the following Next.js build-time error: // You're importing a component that needs next/headers. That only works // in a Server Component which is not supported in the pages/ directory. - const { cookies, draftMode } = await import("next/headers"); + const { cookies, draftMode } = await import("next/headers") - let isDraftModeEnabled = false; + let isDraftModeEnabled = false try { - isDraftModeEnabled = (await draftMode()).isEnabled; + isDraftModeEnabled = (await draftMode()).isEnabled } catch { // `draftMode()` may have been called in a palce that // does not have access to its async storage. This // occurs in places like `generateStaticParams()`. We // can ignore this case. - return; + return } if (!isDraftModeEnabled) { - return; + return } - const cookie = (await cookies()).get(prismicCookie.preview)?.value; + const cookie = (await cookies()).get(prismicCookie.preview)?.value if (!cookie) { - return; + return } - const isActiveCookie = cookie.includes("websitePreviewId="); + const isActiveCookie = cookie.includes("websitePreviewId=") if (!isActiveCookie) { - return; + return } - return cookie; - }); + return cookie + }) } diff --git a/src/exitPreview.ts b/src/exitPreview.ts index fe216bf..4974a1c 100644 --- a/src/exitPreview.ts +++ b/src/exitPreview.ts @@ -1,31 +1,30 @@ /** - * Ends a Prismic preview session within a Next.js app. This function should be - * used in a Router Handler. + * Ends a Prismic preview session within a Next.js app. This function should be used in a Router + * Handler. * * @example + * ```typescript + * // src/app/api/exit-preview/route.js * - * ```typescript - * // src/app/api/exit-preview/route.js + * import { exitPreview } from "@prismicio/next" * - * import { exitPreview } from "@prismicio/next"; - * - * export async function GET() { - * return await exitPreview(); - * } - * ``` + * export async function GET() { + * return await exitPreview() + * } + * ``` */ export async function exitPreview(): Promise { // Need this to avoid the following Next.js build-time error: // You're importing a component that needs next/headers. That only works // in a Server Component which is not supported in the pages/ directory. - const { draftMode } = await import("next/headers"); + const { draftMode } = await import("next/headers") - (await draftMode()).disable(); + ;(await draftMode()).disable() // `Cache-Control` header is used to prevent CDN-level caching. return new Response(JSON.stringify({ success: true }), { headers: { "Cache-Control": "no-store", }, - }); + }) } diff --git a/src/getSlices.ts b/src/getSlices.ts index 7ec5cc0..07f2dc9 100644 --- a/src/getSlices.ts +++ b/src/getSlices.ts @@ -1,11 +1,7 @@ -import { getDefaultSlices } from "@prismicio/simulator/kit"; -import type { StateEvents, StateEventType } from "@prismicio/simulator/kit"; -import { decompressFromEncodedURIComponent } from "lz-string"; +import { getDefaultSlices } from "@prismicio/simulator/kit" +import type { StateEvents, StateEventType } from "@prismicio/simulator/kit" +import { decompressFromEncodedURIComponent } from "lz-string" -export const getSlices = ( - state: string | null | undefined, -): StateEvents[StateEventType.Slices] => { - return state - ? JSON.parse(decompressFromEncodedURIComponent(state)) - : getDefaultSlices(); -}; +export const getSlices = (state: string | null | undefined): StateEvents[StateEventType.Slices] => { + return state ? JSON.parse(decompressFromEncodedURIComponent(state)) : getDefaultSlices() +} diff --git a/src/imgixLoader.ts b/src/imgixLoader.ts index 939de11..0a90b3a 100644 --- a/src/imgixLoader.ts +++ b/src/imgixLoader.ts @@ -1,26 +1,26 @@ -import type { ImageLoaderProps } from "next/image"; -import type { ImgixURLParams } from "imgix-url-builder"; -import { buildURL } from "imgix-url-builder"; +import type { ImgixURLParams } from "imgix-url-builder" +import { buildURL } from "imgix-url-builder" +import type { ImageLoaderProps } from "next/image" /** - * A `next/image` loader for Imgix, which Prismic uses, with an optional - * collection of default Imgix parameters. + * A `next/image` loader for Imgix, which Prismic uses, with an optional collection of default Imgix + * parameters. * * @see To learn about `next/image` loaders: https://nextjs.org/docs/api-reference/next/image#loader * @see To learn about Imgix's URL API: https://docs.imgix.com/apis/rendering */ export const imgixLoader = (args: ImageLoaderProps): string => { - const url = new URL(args.src); + const url = new URL(args.src) const params: ImgixURLParams = { fit: (url.searchParams.get("fit") as ImgixURLParams["fit"]) || "max", w: args.width, h: undefined, - }; + } if (args.quality) { - params.q = args.quality; + params.q = args.quality } - return buildURL(args.src, params); -}; + return buildURL(args.src, params) +} diff --git a/src/index.ts b/src/index.ts index 2dfcddb..9a2da99 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,31 +1,28 @@ -export { exitPreview } from "./exitPreview"; +export { exitPreview } from "./exitPreview" -export { PrismicPreview } from "./PrismicPreview"; -export type { PrismicPreviewProps } from "./PrismicPreview"; +export { PrismicPreview } from "./PrismicPreview" +export type { PrismicPreviewProps } from "./PrismicPreview" -export { PrismicNextLink } from "./PrismicNextLink"; -export type { PrismicNextLinkProps } from "./PrismicNextLink"; +export { PrismicNextLink } from "./PrismicNextLink" +export type { PrismicNextLinkProps } from "./PrismicNextLink" -export { enableAutoPreviews } from "./enableAutoPreviews"; -export type { EnableAutoPreviewsConfig } from "./enableAutoPreviews"; +export { enableAutoPreviews } from "./enableAutoPreviews" +export type { EnableAutoPreviewsConfig } from "./enableAutoPreviews" -export { redirectToPreviewURL } from "./redirectToPreviewURL"; -export type { RedirectToPreviewURLConfig } from "./redirectToPreviewURL"; +export { redirectToPreviewURL } from "./redirectToPreviewURL" +export type { RedirectToPreviewURLConfig } from "./redirectToPreviewURL" -export { PrismicNextImage } from "./PrismicNextImage"; -export type { PrismicNextImageProps } from "./PrismicNextImage"; +export { PrismicNextImage } from "./PrismicNextImage" +export type { PrismicNextImageProps } from "./PrismicNextImage" -export { SliceSimulator } from "./SliceSimulator"; -export type { - SliceSimulatorProps, - SliceSimulatorParams, -} from "./SliceSimulator"; +export { SliceSimulator } from "./SliceSimulator" +export type { SliceSimulatorProps, SliceSimulatorParams } from "./SliceSimulator" -export { getSlices } from "./getSlices"; +export { getSlices } from "./getSlices" -export { imgixLoader } from "./imgixLoader"; +export { imgixLoader } from "./imgixLoader" -export type { CreateClientConfig } from "./types"; +export type { CreateClientConfig } from "./types" -export { createLocaleRedirect } from "./createLocaleRedirect"; -export type { CreateLocaleRedirectConfig } from "./createLocaleRedirect"; +export { createLocaleRedirect } from "./createLocaleRedirect" +export type { CreateLocaleRedirectConfig } from "./createLocaleRedirect" diff --git a/src/lib/devMsg.ts b/src/lib/devMsg.ts index b9ec259..07af14a 100644 --- a/src/lib/devMsg.ts +++ b/src/lib/devMsg.ts @@ -1,20 +1,18 @@ -import { version } from "../../package.json"; +import { version } from "../../package.json" /** * Returns a `prismic.dev/msg` URL for a given message slug. * * @example + * ```ts + * devMsg("missing-param") + * // => "https://prismic.dev/msg/next/v1.2.3/missing-param" + * ``` * - * ```ts - * devMsg("missing-param"); - * // => "https://prismic.dev/msg/next/v1.2.3/missing-param" - * ``` - * - * @param slug - Slug for the message. This corresponds to a Markdown file in - * the Git repository's `/messages` directory. - * + * @param slug - Slug for the message. This corresponds to a Markdown file in the Git repository's + * `/messages` directory. * @returns The `prismic.dev/msg` URL for the given slug. */ export const devMsg = (slug: string): string => { - return `https://prismic.dev/msg/next/v${version}/${slug}`; -}; + return `https://prismic.dev/msg/next/v${version}/${slug}` +} diff --git a/src/lib/resolveDefaultExport.ts b/src/lib/resolveDefaultExport.ts index dc7483c..06c7b87 100644 --- a/src/lib/resolveDefaultExport.ts +++ b/src/lib/resolveDefaultExport.ts @@ -1,21 +1,17 @@ /** - * Resolves a module's default export. The module may provide its default export - * as a `default` property on an object. This happens when named and default - * exports are mixed in modules. + * Resolves a module's default export. The module may provide its default export as a `default` + * property on an object. This happens when named and default exports are mixed in modules. * - * In ES Modules, mixing is fine since the module resolver can distinguish - * default and named exports. In transpiled modules, however, all exports are - * put into a single object, and the default export is provided at a property - * called `default`. + * In ES Modules, mixing is fine since the module resolver can distinguish default and named + * exports. In transpiled modules, however, all exports are put into a single object, and the + * default export is provided at a property called `default`. * - * This helper is needed by Next.js uses CJS files with named and default - * exports. + * This helper is needed by Next.js uses CJS files with named and default exports. * - * This helper _should_ be a temporary hack until Next.js and Node.js resolve - * their ESM difficulties. This will likely not be removed any time soon, - * unfortunately. + * This helper _should_ be a temporary hack until Next.js and Node.js resolve their ESM + * difficulties. This will likely not be removed any time soon, unfortunately. */ export function resolveDefaultExport(mod: T): T { // eslint-disable-next-line @typescript-eslint/no-explicit-any - return "default" in (mod as any) ? (mod as any).default : mod; + return "default" in (mod as any) ? (mod as any).default : mod } diff --git a/src/pages/PrismicPreview.tsx b/src/pages/PrismicPreview.tsx index 43d886d..beaf3c8 100644 --- a/src/pages/PrismicPreview.tsx +++ b/src/pages/PrismicPreview.tsx @@ -1,41 +1,40 @@ -import { getToolbarSrc, cookie as prismicCookie } from "@prismicio/client"; -import { useRouter } from "next/router"; -import Script from "next/script"; -import type { FC } from "react"; -import { type ReactNode, useEffect } from "react"; +import { getToolbarSrc, cookie as prismicCookie } from "@prismicio/client" +import { useRouter } from "next/router" +import Script from "next/script" +import type { FC } from "react" +import { type ReactNode, useEffect } from "react" /** Props for ``. */ export type PrismicPreviewProps = { /** - * The name of your Prismic repository. A Prismic Toolbar will be registered - * using this repository. + * The name of your Prismic repository. A Prismic Toolbar will be registered using this + * repository. */ - repositoryName: string; + repositoryName: string /** - * The URL of your app's Prismic preview endpoint (default: `/api/preview`). - * This URL will be fetched on preview update events. + * The URL of your app's Prismic preview endpoint (default: `/api/preview`). This URL will be + * fetched on preview update events. */ - updatePreviewURL?: string; + updatePreviewURL?: string /** - * The URL of your app's exit preview endpoint (default: `/api/exit-preview`). - * This URL will be fetched on preview exit events. + * The URL of your app's exit preview endpoint (default: `/api/exit-preview`). This URL will be + * fetched on preview exit events. */ - exitPreviewURL?: string; + exitPreviewURL?: string /** Children to render adjacent to the Prismic Toolbar. */ - children?: ReactNode; -}; + children?: ReactNode +} /** - * React component that sets up Prismic Previews using the Prismic Toolbar. When - * the Prismic Toolbar send events to the browser, such as on preview updates - * and exiting, this component will automatically refresh the page with the - * changes. + * React component that sets up Prismic Previews using the Prismic Toolbar. When the Prismic Toolbar + * send events to the browser, such as on preview updates and exiting, this component will + * automatically refresh the page with the changes. * - * This component can be wrapped around your app or added anywhere in your app's - * tree. It must be rendered on every page. + * This component can be wrapped around your app or added anywhere in your app's tree. It must be + * rendered on every page. */ export const PrismicPreview: FC = (props) => { const { @@ -43,21 +42,21 @@ export const PrismicPreview: FC = (props) => { updatePreviewURL = "/api/preview", exitPreviewURL = "/api/exit-preview", children, - } = props; + } = props - const router = useRouter(); + const router = useRouter() - const toolbarSrc = getToolbarSrc(repositoryName); + const toolbarSrc = getToolbarSrc(repositoryName) useEffect(() => { - const controller = new AbortController(); + const controller = new AbortController() window.addEventListener("prismicPreviewUpdate", onUpdate, { signal: controller.signal, - }); + }) window.addEventListener("prismicPreviewEnd", onEnd, { signal: controller.signal, - }); + }) // Start the preview for preview share links. Previews from // share links do not go to the `updatePreviewURL` like a normal @@ -66,35 +65,33 @@ export const PrismicPreview: FC = (props) => { // We check that the current URL is a descendant of the base // path to prevent infinite refrehes. if ( - window.location.href.startsWith( - window.location.origin + router.basePath, - ) && + window.location.href.startsWith(window.location.origin + router.basePath) && getPreviewCookieRepositoryName() === repositoryName && !router.isPreview ) { - start(); + start() } function onEnd(event: Event) { - event.preventDefault(); + event.preventDefault() fetch(router.basePath + exitPreviewURL, { signal: controller.signal }) .then((res) => { if (!res.ok) { console.error( `[] Failed to exit Preview Mode using the "${exitPreviewURL}" API endpoint. Does it exist?`, - ); + ) - return; + return } - refresh(); + refresh() }) - .catch(() => {}); + .catch(() => {}) } function onUpdate(event: Event) { - event.preventDefault(); - start(); + event.preventDefault() + start() } function start() { @@ -110,37 +107,36 @@ export const PrismicPreview: FC = (props) => { if (res.type !== "opaqueredirect") { console.error( `[] Failed to start or update the preview using "${updatePreviewURL}". Does it exist?`, - ); + ) - return; + return } - refresh(); + refresh() }) - .catch(() => {}); + .catch(() => {}) } function refresh() { - router.replace(router.asPath, undefined, { scroll: false }); + router.replace(router.asPath, undefined, { scroll: false }) } - return () => controller.abort(); - }, [exitPreviewURL, updatePreviewURL, repositoryName, router]); + return () => controller.abort() + }, [exitPreviewURL, updatePreviewURL, repositoryName, router]) return ( <> {children}