From 7b1b89041f512cfd47ebff0d2cca44b85bf3eb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 5 Jan 2024 19:46:35 +0100 Subject: [PATCH] chore: release Docusaurus v3.1 (#9705) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joshua Chen Co-authored-by: sebastienlorber Co-authored-by: Sébastien Lorber Co-authored-by: Ivan Mar (sOkam!) <7308253+heysokam@users.noreply.github.com> Co-authored-by: c0h1b4 Co-authored-by: Janessa Garrow Co-authored-by: ozaki <29860391+OzakIOne@users.noreply.github.com> Co-authored-by: axmmisaka <6500159+axmmisaka@users.noreply.github.com> Co-authored-by: Tatsunori Uchino Co-authored-by: Simen Bekkhus fix(i18n): complete translations for theme-common.json Brazilian Portuguese (pt-BR) (#9477) fix(content-blog): add baseUrl for author.image_url (#9581) fix(type-aliases): add `title` prop for imported inline SVG React components (#9612) fix(utils): Markdown link replacement with <> but no spaces (#9617) fix(live-codeblock): stabilize react-live transformCode callback, fix editor/preview desync (#9631) fix(cli): output help when no conventional config + no subcommand (#9648) fix CI job (#9604) fix Lint Autofix workflow (#9632) fix(pwa-plugin): upgrade workbox (#9668) fix(create-docusaurus): fix init template code blocks, and little improvements (#9696) fix(theme): allow empty code blocks and live playgrounds (#9704) --- .github/workflows/lint-autofix.yml | 44 + .lintstagedrc.json | 5 +- .prettierignore | 2 +- admin/new.docusaurus.io/package.json | 2 +- argos/package.json | 2 +- lerna.json | 2 +- package.json | 7 +- packages/create-docusaurus/README.md | 4 + packages/create-docusaurus/package.json | 6 +- .../templates/classic-typescript/package.json | 12 +- .../templates/classic/package.json | 10 +- .../tutorial-basics/markdown-features.mdx | 28 +- .../docusaurus-cssnano-preset/package.json | 2 +- packages/docusaurus-logger/package.json | 2 +- packages/docusaurus-mdx-loader/package.json | 10 +- packages/docusaurus-mdx-loader/src/loader.ts | 12 +- .../docusaurus-mdx-loader/src/processor.ts | 1 + .../__snapshots__/index.test.ts.snap | 32 +- .../src/remark/transformLinks/index.ts | 28 + .../package.json | 4 +- .../src/index.d.ts | 13 +- .../package.json | 14 +- .../package.json | 16 +- .../src/__tests__/authors.test.ts | 96 ++ .../src/__tests__/feed.test.ts | 7 + .../src/__tests__/index.test.ts | 21 + .../src/authors.ts | 48 +- .../src/blogUtils.ts | 33 +- .../package.json | 16 +- .../simple-site/docusaurus.config.js | 12 + .../__snapshots__/index.test.ts.snap | 4 +- .../src/__tests__/docs.test.ts | 10 +- .../src/docs.ts | 16 +- .../package.json | 12 +- .../__fixtures__/website/docusaurus.config.js | 7 + .../__snapshots__/index.test.ts.snap | 18 +- .../src/index.ts | 8 +- packages/docusaurus-plugin-debug/package.json | 8 +- .../package.json | 8 +- .../package.json | 8 +- .../package.json | 8 +- .../package.json | 14 +- packages/docusaurus-plugin-pwa/package.json | 22 +- .../docusaurus-plugin-sitemap/package.json | 14 +- .../docusaurus-preset-classic/package.json | 28 +- .../package.json | 2 +- .../docusaurus-theme-classic/package.json | 26 +- .../src/theme-classic.d.ts | 8 + .../src/theme/CodeInline/index.tsx | 16 + .../src/theme/Heading/index.tsx | 4 + .../src/theme/MDXComponents/Code.tsx | 18 +- packages/docusaurus-theme-common/package.json | 20 +- .../src/hooks/useWindowSize.ts | 21 +- .../src/utils/codeBlockUtils.ts | 52 +- .../package.json | 12 +- .../src/theme-live-codeblock.d.ts | 3 +- .../src/theme/Playground/index.tsx | 8 +- .../docusaurus-theme-mermaid/package.json | 12 +- .../package.json | 18 +- .../src/theme/SearchBar/index.tsx | 2 +- .../locales/pt-BR/theme-common.json | 42 +- .../package.json | 6 +- packages/docusaurus-tsconfig/package.json | 2 +- packages/docusaurus-types/package.json | 3 +- packages/docusaurus-types/src/config.d.ts | 39 + packages/docusaurus-types/src/index.d.ts | 2 + packages/docusaurus-utils-common/package.json | 2 +- .../docusaurus-utils-validation/package.json | 6 +- packages/docusaurus-utils/package.json | 6 +- .../__snapshots__/markdownLinks.test.ts.snap | 1 + .../__snapshots__/markdownUtils.test.ts.snap | 46 +- .../src/__tests__/markdownLinks.test.ts | 1 + .../src/__tests__/markdownUtils.test.ts | 212 ++- .../src/__tests__/urlUtils.test.ts | 133 ++ packages/docusaurus-utils/src/constants.ts | 4 +- packages/docusaurus-utils/src/index.ts | 7 +- .../docusaurus-utils/src/markdownLinks.ts | 2 +- .../docusaurus-utils/src/markdownUtils.ts | 55 +- packages/docusaurus-utils/src/urlUtils.ts | 59 + packages/docusaurus/bin/docusaurus.mjs | 28 +- packages/docusaurus/package.json | 18 +- .../src/client/BrokenLinksContext.tsx | 51 + .../docusaurus/src/client/LinksCollector.tsx | 45 - .../docusaurus/src/client/exports/Link.tsx | 6 +- .../src/client/exports/useBrokenLinks.ts | 13 + .../docusaurus/src/client/serverEntry.tsx | 18 +- packages/docusaurus/src/commands/build.ts | 15 +- packages/docusaurus/src/deps.d.ts | 6 +- .../__snapshots__/brokenLinks.test.ts.snap | 86 -- .../__snapshots__/config.test.ts.snap | 30 + .../__snapshots__/index.test.ts.snap | 3 + .../src/server/__tests__/brokenLinks.test.ts | 748 ++++++++--- .../server/__tests__/configValidation.test.ts | 12 + packages/docusaurus/src/server/brokenLinks.ts | 293 +++-- .../docusaurus/src/server/configValidation.ts | 97 +- .../__tests__/__snapshots__/base.test.ts.snap | 1 + .../__snapshots__/index.test.ts.snap | 1 + packages/eslint-plugin/package.json | 2 +- packages/lqip-loader/package.json | 4 +- packages/stylelint-copyright/package.json | 2 +- project-words.txt | 364 +++--- .../tests/visibility/force-unlisted.mdx | 10 + .../_docs tests/tests/visibility/index.mdx | 1 + .../_pages tests/code-block-tests.mdx | 85 ++ website/_dogfooding/dogfooding.config.ts | 9 + website/blog/releases/3.0/index.mdx | 2 +- website/docs/advanced/routing.mdx | 10 +- website/docs/api/docusaurus.config.js.mdx | 31 +- .../docs/api/plugins/plugin-content-docs.mdx | 12 +- website/docs/cli.mdx | 2 +- website/docs/docusaurus-core.mdx | 43 + .../guides/docs/sidebar/autogenerated.mdx | 2 +- website/docs/guides/docs/versioning.mdx | 2 +- .../markdown-features-intro.mdx | 39 + website/docs/i18n/i18n-tutorial.mdx | 2 +- website/docs/seo.mdx | 2 +- website/docs/styling-layout.mdx | 6 + website/docs/using-plugins.mdx | 2 +- website/docusaurus.config.localized.json | 4 + website/docusaurus.config.ts | 19 +- website/package.json | 36 +- .../version-2.x/advanced/routing.mdx | 10 +- .../api/plugins/plugin-content-docs.mdx | 12 +- website/versioned_docs/version-2.x/cli.mdx | 2 +- .../versioned_docs/version-2.x/deployment.mdx | 2 +- .../guides/docs/sidebar/autogenerated.mdx | 2 +- .../version-2.x/guides/docs/versioning.mdx | 2 +- .../markdown-features-react.mdx | 2 +- .../version-2.x/i18n/i18n-tutorial.mdx | 2 +- website/versioned_docs/version-2.x/seo.mdx | 2 +- .../version-2.x/using-plugins.mdx | 2 +- .../version-3.0.0/advanced/routing.mdx | 10 +- .../api/plugins/plugin-content-docs.mdx | 12 +- website/versioned_docs/version-3.0.0/cli.mdx | 2 +- .../guides/docs/sidebar/autogenerated.mdx | 2 +- .../version-3.0.0/guides/docs/versioning.mdx | 2 +- .../version-3.0.0/i18n/i18n-tutorial.mdx | 2 +- website/versioned_docs/version-3.0.0/seo.mdx | 2 +- .../version-3.0.0/using-plugins.mdx | 2 +- yarn.lock | 1156 +++++++++-------- 140 files changed, 3198 insertions(+), 1718 deletions(-) create mode 100644 .github/workflows/lint-autofix.yml create mode 100644 packages/docusaurus-theme-classic/src/theme/CodeInline/index.tsx create mode 100644 packages/docusaurus/src/client/BrokenLinksContext.tsx delete mode 100644 packages/docusaurus/src/client/LinksCollector.tsx create mode 100644 packages/docusaurus/src/client/exports/useBrokenLinks.ts delete mode 100644 packages/docusaurus/src/server/__tests__/__snapshots__/brokenLinks.test.ts.snap create mode 100644 website/_dogfooding/_docs tests/tests/visibility/force-unlisted.mdx diff --git a/.github/workflows/lint-autofix.yml b/.github/workflows/lint-autofix.yml new file mode 100644 index 000000000000..ed857a3e9130 --- /dev/null +++ b/.github/workflows/lint-autofix.yml @@ -0,0 +1,44 @@ +name: Lint AutoFix + +on: + pull_request: + branches: + - main + - docusaurus-v** + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + lint-autofix: + name: Lint AutoFix + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.head_ref }} + + - name: Installation + run: yarn + + - name: AutoFix Format + run: yarn format + + - name: AutoFix JS + run: yarn lint:js:fix + + - name: AutoFix Style + run: yarn lint:style:fix + + - name: AutoFix Spelling + run: yarn lint:spelling:fix + + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: 'refactor: apply lint autofix' diff --git a/.lintstagedrc.json b/.lintstagedrc.json index b25a96cf4886..f526fd4b5bc0 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -1,8 +1,5 @@ { "*.{js,jsx,ts,tsx,mjs}": ["eslint --fix"], "*.css": ["stylelint --allow-empty-input --fix"], - "*": [ - "prettier --ignore-unknown --write", - "cspell --no-must-find-files --no-progress" - ] + "*": ["prettier --ignore-unknown --write"] } diff --git a/.prettierignore b/.prettierignore index 6d600d2aad79..aa68052ce19c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -24,5 +24,5 @@ website/versioned_sidebars/*.json examples/ website/static/katex/katex.min.css -website/changelog/_swizzle_theme_tests +website/changelog website/_dogfooding/_swizzle_theme_tests diff --git a/admin/new.docusaurus.io/package.json b/admin/new.docusaurus.io/package.json index 7bcba51a396a..9ff47cd054d5 100644 --- a/admin/new.docusaurus.io/package.json +++ b/admin/new.docusaurus.io/package.json @@ -1,6 +1,6 @@ { "name": "new.docusaurus.io", - "version": "3.0.1", + "version": "3.1.0", "private": true, "scripts": { "start": "npx --package netlify-cli netlify dev" diff --git a/argos/package.json b/argos/package.json index 286bcd960db9..437f323dcd37 100644 --- a/argos/package.json +++ b/argos/package.json @@ -1,6 +1,6 @@ { "name": "argos", - "version": "3.0.1", + "version": "3.1.0", "description": "Argos visual diff tests", "license": "MIT", "private": true, diff --git a/lerna.json b/lerna.json index 86e15ecaf87e..54946d797440 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "3.0.1", + "version": "3.1.0", "npmClient": "yarn", "useWorkspaces": true, "useNx": false, diff --git a/package.json b/package.json index 66548a0dd340..580d85d1ea70 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,11 @@ "lint": "yarn lint:js && yarn lint:style && yarn lint:spelling", "lint:ci": "yarn lint:js --quiet && yarn lint:style && yarn lint:spelling", "lint:js": "eslint --cache --report-unused-disable-directives \"**/*.{js,jsx,ts,tsx,mjs}\"", - "lint:spelling": "cspell \"**\" --no-progress", + "lint:js:fix": "yarn lint:js --fix", + "lint:spelling": "cspell \"**\" --no-progress --show-context --show-suggestions", + "lint:spelling:fix": "yarn rimraf project-words.txt && echo \"# Project Words - DO NOT TOUCH - This is updated through CI\" >> project-words.txt && yarn -s lint:spelling --words-only --unique --no-exit-code --no-summary \"**\" | sort --ignore-case >> project-words.txt", "lint:style": "stylelint \"**/*.css\"", + "lint:style:fix": "yarn lint:style --fix", "lerna": "lerna", "test": "jest", "test:build:website": "./admin/scripts/test-release.sh", @@ -80,7 +83,7 @@ "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "cross-env": "^7.0.3", - "cspell": "^6.31.2", + "cspell": "^8.1.0", "eslint": "^8.45.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^8.8.0", diff --git a/packages/create-docusaurus/README.md b/packages/create-docusaurus/README.md index f045003ad535..2533546271a8 100644 --- a/packages/create-docusaurus/README.md +++ b/packages/create-docusaurus/README.md @@ -10,6 +10,10 @@ npm init docusaurus yarn create docusaurus ``` +```bash +npx create-docusaurus@latest +``` + ## Usage Please see the [installation documentation](https://docusaurus.io/docs/installation). diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json index b2360d653732..9722cf2c6ab3 100755 --- a/packages/create-docusaurus/package.json +++ b/packages/create-docusaurus/package.json @@ -1,6 +1,6 @@ { "name": "create-docusaurus", - "version": "3.0.1", + "version": "3.1.0", "description": "Create Docusaurus apps easily.", "type": "module", "repository": { @@ -22,8 +22,8 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.0.1", - "@docusaurus/utils": "3.0.1", + "@docusaurus/logger": "3.1.0", + "@docusaurus/utils": "3.1.0", "commander": "^5.1.0", "fs-extra": "^11.1.1", "lodash": "^4.17.21", diff --git a/packages/create-docusaurus/templates/classic-typescript/package.json b/packages/create-docusaurus/templates/classic-typescript/package.json index c4d7834d5a73..b9f64f45d1a5 100644 --- a/packages/create-docusaurus/templates/classic-typescript/package.json +++ b/packages/create-docusaurus/templates/classic-typescript/package.json @@ -1,6 +1,6 @@ { "name": "docusaurus-2-classic-typescript-template", - "version": "3.0.1", + "version": "3.1.0", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -15,8 +15,8 @@ "typecheck": "tsc" }, "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/preset-classic": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/preset-classic": "3.1.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", @@ -24,9 +24,9 @@ "react-dom": "^18.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/tsconfig": "3.0.1", - "@docusaurus/types": "3.0.1", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/tsconfig": "3.1.0", + "@docusaurus/types": "3.1.0", "typescript": "~5.2.2" }, "browserslist": { diff --git a/packages/create-docusaurus/templates/classic/package.json b/packages/create-docusaurus/templates/classic/package.json index d13c4f154242..cd100edb37b4 100644 --- a/packages/create-docusaurus/templates/classic/package.json +++ b/packages/create-docusaurus/templates/classic/package.json @@ -1,6 +1,6 @@ { "name": "docusaurus-2-classic-template", - "version": "3.0.1", + "version": "3.1.0", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -14,8 +14,8 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/preset-classic": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/preset-classic": "3.1.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", @@ -23,8 +23,8 @@ "react-dom": "^18.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/types": "3.0.1" + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/types": "3.1.0" }, "browserslist": { "production": [ diff --git a/packages/create-docusaurus/templates/shared/docs/tutorial-basics/markdown-features.mdx b/packages/create-docusaurus/templates/shared/docs/tutorial-basics/markdown-features.mdx index 0337f34d6a54..35e00825ed77 100644 --- a/packages/create-docusaurus/templates/shared/docs/tutorial-basics/markdown-features.mdx +++ b/packages/create-docusaurus/templates/shared/docs/tutorial-basics/markdown-features.mdx @@ -61,13 +61,13 @@ You can reference images relative to the current file as well. This is particula Markdown code blocks are supported with Syntax highlighting. - ```jsx title="src/components/HelloDocusaurus.js" - function HelloDocusaurus() { - return ( -

Hello, Docusaurus!

- ) - } - ``` +````md +```jsx title="src/components/HelloDocusaurus.js" +function HelloDocusaurus() { + return

Hello, Docusaurus!

; +} +``` +```` ```jsx title="src/components/HelloDocusaurus.js" function HelloDocusaurus() { @@ -79,17 +79,19 @@ function HelloDocusaurus() { Docusaurus has a special syntax to create admonitions and callouts: - :::tip My tip +```md +:::tip My tip - Use this awesome feature option +Use this awesome feature option - ::: +::: - :::danger Take care +:::danger Take care - This action is dangerous +This action is dangerous - ::: +::: +``` :::tip My tip diff --git a/packages/docusaurus-cssnano-preset/package.json b/packages/docusaurus-cssnano-preset/package.json index 50c88876c488..8c39736b9890 100644 --- a/packages/docusaurus-cssnano-preset/package.json +++ b/packages/docusaurus-cssnano-preset/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/cssnano-preset", - "version": "3.0.1", + "version": "3.1.0", "description": "Advanced cssnano preset for maximum optimization.", "main": "lib/index.js", "license": "MIT", diff --git a/packages/docusaurus-logger/package.json b/packages/docusaurus-logger/package.json index 90a9e8a66fea..5aeb4fb18652 100644 --- a/packages/docusaurus-logger/package.json +++ b/packages/docusaurus-logger/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/logger", - "version": "3.0.1", + "version": "3.1.0", "description": "An encapsulated logger for semantically formatting console messages.", "main": "./lib/index.js", "repository": { diff --git a/packages/docusaurus-mdx-loader/package.json b/packages/docusaurus-mdx-loader/package.json index 1fa349f37cc9..8c24743332bd 100644 --- a/packages/docusaurus-mdx-loader/package.json +++ b/packages/docusaurus-mdx-loader/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/mdx-loader", - "version": "3.0.1", + "version": "3.1.0", "description": "Docusaurus Loader for MDX", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -20,9 +20,9 @@ "dependencies": { "@babel/parser": "^7.22.7", "@babel/traverse": "^7.22.8", - "@docusaurus/logger": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/logger": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -46,7 +46,7 @@ "webpack": "^5.88.1" }, "devDependencies": { - "@docusaurus/types": "3.0.1", + "@docusaurus/types": "3.1.0", "@types/escape-html": "^1.0.2", "@types/mdast": "^4.0.2", "@types/stringify-object": "^3.3.1", diff --git a/packages/docusaurus-mdx-loader/src/loader.ts b/packages/docusaurus-mdx-loader/src/loader.ts index a475220cd5c6..bde02542beb3 100644 --- a/packages/docusaurus-mdx-loader/src/loader.ts +++ b/packages/docusaurus-mdx-loader/src/loader.ts @@ -8,7 +8,7 @@ import fs from 'fs-extra'; import logger from '@docusaurus/logger'; import { - parseFrontMatter, + DEFAULT_PARSE_FRONT_MATTER, escapePath, getFileLoaderUtils, getWebpackLoaderCompilerName, @@ -133,7 +133,7 @@ function extractContentTitleData(data: { export async function mdxLoader( this: LoaderContext, - fileString: string, + fileContent: string, ): Promise { const compilerName = getWebpackLoaderCompilerName(this); const callback = this.async(); @@ -143,11 +143,15 @@ export async function mdxLoader( ensureMarkdownConfig(reqOptions); - const {frontMatter} = parseFrontMatter(fileString); + const {frontMatter} = await reqOptions.markdownConfig.parseFrontMatter({ + filePath, + fileContent, + defaultParseFrontMatter: DEFAULT_PARSE_FRONT_MATTER, + }); const mdxFrontMatter = validateMDXFrontMatter(frontMatter.mdx); const preprocessedContent = preprocessor({ - fileContent: fileString, + fileContent, filePath, admonitions: reqOptions.admonitions, markdownConfig: reqOptions.markdownConfig, diff --git a/packages/docusaurus-mdx-loader/src/processor.ts b/packages/docusaurus-mdx-loader/src/processor.ts index 512cd453bfbb..6865f721a999 100644 --- a/packages/docusaurus-mdx-loader/src/processor.ts +++ b/packages/docusaurus-mdx-loader/src/processor.ts @@ -165,6 +165,7 @@ async function createProcessorFactory() { const mdxProcessor = createMdxProcessor({ ...processorOptions, + remarkRehypeOptions: options.markdownConfig.remarkRehypeOptions, format, }); diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap index 06f8fcbcabe7..a0186db7b10b 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/__tests__/__snapshots__/index.test.ts.snap @@ -12,17 +12,17 @@ exports[`transformAsset plugin pathname protocol 1`] = ` exports[`transformAsset plugin transform md links to 1`] = ` "[asset](https://example.com/asset.pdf) -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default} /> +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default} /> -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default}>asset +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default}>asset -in paragraph /node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default}>asset +in paragraph /node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default}>asset -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset (2).pdf").default}>asset with URL encoded chars +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset (2).pdf").default}>asset with URL encoded chars -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default + '#page=2'}>asset with hash +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default + '#page=2'}>asset with hash -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default} title="Title">asset +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default} title="Title">asset [page](noUrl.md) @@ -36,24 +36,24 @@ in paragraph /node_modules/file [assets](/github/!file-loader!/assets.pdf) -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default}>asset +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default}>asset -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static2/asset2.pdf").default}>asset2 +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static2/asset2.pdf").default}>asset2 -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>staticAsset.pdf +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>staticAsset.pdf -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>@site/static/staticAsset.pdf +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>@site/static/staticAsset.pdf -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default + '#page=2'} title="Title">@site/static/staticAsset.pdf +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default + '#page=2'} title="Title">@site/static/staticAsset.pdf -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>Just staticAsset.pdf, and /node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>**awesome** staticAsset 2.pdf 'It is really "AWESOME"', but also /node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>coded \`staticAsset 3.pdf\` +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>Just staticAsset.pdf, and /node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>**awesome** staticAsset 2.pdf 'It is really "AWESOME"', but also /node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAsset.pdf").default}>coded \`staticAsset 3.pdf\` -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAssetImage.png").default}>Clickable Docusaurus logo/node_modules/url-loader/dist/cjs.js?limit=10000&name=assets/images/[name]-[contenthash].[ext]&fallback=/node_modules/file-loader/dist/cjs.js!./static/staticAssetImage.png").default} width="200" height="200" /> +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/staticAssetImage.png").default}>Clickable Docusaurus logo/node_modules/url-loader/dist/cjs.js?limit=10000&name=assets/images/[name]-[contenthash].[ext]&fallback=/node_modules/file-loader/dist/cjs.js!./static/staticAssetImage.png").default} width="200" height="200" /> -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default}>Stylized link to asset file +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./asset.pdf").default}>Stylized link to asset file -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./data.json").default}>JSON +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./data.json").default}>JSON -/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/static-json.json").default}>static JSON +/node_modules/file-loader/dist/cjs.js?name=assets/files/[name]-[contenthash].[ext]!./static/static-json.json").default}>static JSON " `; diff --git a/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts b/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts index 252289f97452..179bcadb770d 100644 --- a/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts +++ b/packages/docusaurus-mdx-loader/src/remark/transformLinks/index.ts @@ -73,6 +73,34 @@ async function toAssetRequireNode( value: '_blank', }); + // Assets are not routes, and are required by Webpack already + // They should not trigger the broken link checker + attributes.push({ + type: 'mdxJsxAttribute', + name: 'data-noBrokenLinkCheck', + value: { + type: 'mdxJsxAttributeValueExpression', + value: 'true', + data: { + estree: { + type: 'Program', + body: [ + { + type: 'ExpressionStatement', + expression: { + type: 'Literal', + value: true, + raw: 'true', + }, + }, + ], + sourceType: 'module', + comments: [], + }, + }, + }, + }); + attributes.push({ type: 'mdxJsxAttribute', name: 'href', diff --git a/packages/docusaurus-module-type-aliases/package.json b/packages/docusaurus-module-type-aliases/package.json index 69ea15c99d5a..1886e871b07b 100644 --- a/packages/docusaurus-module-type-aliases/package.json +++ b/packages/docusaurus-module-type-aliases/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/module-type-aliases", - "version": "3.0.1", + "version": "3.1.0", "description": "Docusaurus module type aliases.", "types": "./src/index.d.ts", "publishConfig": { @@ -13,7 +13,7 @@ }, "dependencies": { "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "3.0.1", + "@docusaurus/types": "3.1.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 09c3f2fb3d59..5cb44f06e402 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -260,6 +260,15 @@ declare module '@docusaurus/useRouteContext' { export default function useRouteContext(): PluginRouteContext; } +declare module '@docusaurus/useBrokenLinks' { + export type BrokenLinks = { + collectLink: (link: string) => void; + collectAnchor: (anchor: string) => void; + }; + + export default function useBrokenLinks(): BrokenLinks; +} + declare module '@docusaurus/useIsBrowser' { export default function useIsBrowser(): boolean; } @@ -356,7 +365,9 @@ declare module '@docusaurus/useGlobalData' { declare module '*.svg' { import type {ComponentType, SVGProps} from 'react'; - const ReactComponent: ComponentType>; + const ReactComponent: ComponentType< + SVGProps & {title?: string} + >; export default ReactComponent; } diff --git a/packages/docusaurus-plugin-client-redirects/package.json b/packages/docusaurus-plugin-client-redirects/package.json index 943b4ee4a8e9..3b9311e0819c 100644 --- a/packages/docusaurus-plugin-client-redirects/package.json +++ b/packages/docusaurus-plugin-client-redirects/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-client-redirects", - "version": "3.0.1", + "version": "3.1.0", "description": "Client redirects plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,18 +18,18 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "eta": "^2.2.0", "fs-extra": "^11.1.1", "lodash": "^4.17.21", "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/types": "3.0.1" + "@docusaurus/types": "3.1.0" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index f424ceb8467b..fcd2680deabe 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-blog", - "version": "3.0.1", + "version": "3.1.0", "description": "Blog plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-blog.d.ts", @@ -19,13 +19,13 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts index 19515459a656..052437c3dec6 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts @@ -19,6 +19,7 @@ describe('getBlogPostAuthors', () => { getBlogPostAuthors({ frontMatter: {}, authorsMap: undefined, + baseUrl: '/', }), ).toEqual([]); expect( @@ -27,6 +28,7 @@ describe('getBlogPostAuthors', () => { authors: [], }, authorsMap: undefined, + baseUrl: '/', }), ).toEqual([]); }); @@ -38,6 +40,7 @@ describe('getBlogPostAuthors', () => { author: 'Sébastien Lorber', }, authorsMap: undefined, + baseUrl: '/', }), ).toEqual([{name: 'Sébastien Lorber'}]); expect( @@ -46,6 +49,7 @@ describe('getBlogPostAuthors', () => { authorTitle: 'maintainer', }, authorsMap: undefined, + baseUrl: '/', }), ).toEqual([{title: 'maintainer'}]); expect( @@ -54,8 +58,27 @@ describe('getBlogPostAuthors', () => { authorImageURL: 'https://github.com/slorber.png', }, authorsMap: undefined, + baseUrl: '/', }), ).toEqual([{imageURL: 'https://github.com/slorber.png'}]); + expect( + getBlogPostAuthors({ + frontMatter: { + authorImageURL: '/img/slorber.png', + }, + authorsMap: undefined, + baseUrl: '/', + }), + ).toEqual([{imageURL: '/img/slorber.png'}]); + expect( + getBlogPostAuthors({ + frontMatter: { + authorImageURL: '/img/slorber.png', + }, + authorsMap: undefined, + baseUrl: '/baseURL', + }), + ).toEqual([{imageURL: '/baseURL/img/slorber.png'}]); expect( getBlogPostAuthors({ frontMatter: { @@ -68,6 +91,7 @@ describe('getBlogPostAuthors', () => { authorURL: 'https://github.com/slorber2', }, authorsMap: undefined, + baseUrl: '/', }), ).toEqual([ { @@ -86,8 +110,69 @@ describe('getBlogPostAuthors', () => { authors: 'slorber', }, authorsMap: {slorber: {name: 'Sébastien Lorber'}}, + baseUrl: '/', }), ).toEqual([{key: 'slorber', name: 'Sébastien Lorber'}]); + expect( + getBlogPostAuthors({ + frontMatter: { + authors: 'slorber', + }, + authorsMap: { + slorber: { + name: 'Sébastien Lorber', + imageURL: 'https://github.com/slorber.png', + }, + }, + baseUrl: '/', + }), + ).toEqual([ + { + key: 'slorber', + name: 'Sébastien Lorber', + imageURL: 'https://github.com/slorber.png', + }, + ]); + expect( + getBlogPostAuthors({ + frontMatter: { + authors: 'slorber', + }, + authorsMap: { + slorber: { + name: 'Sébastien Lorber', + imageURL: '/img/slorber.png', + }, + }, + baseUrl: '/', + }), + ).toEqual([ + { + key: 'slorber', + name: 'Sébastien Lorber', + imageURL: '/img/slorber.png', + }, + ]); + expect( + getBlogPostAuthors({ + frontMatter: { + authors: 'slorber', + }, + authorsMap: { + slorber: { + name: 'Sébastien Lorber', + imageURL: '/img/slorber.png', + }, + }, + baseUrl: '/baseUrl', + }), + ).toEqual([ + { + key: 'slorber', + name: 'Sébastien Lorber', + imageURL: '/baseUrl/img/slorber.png', + }, + ]); }); it('can read authors string[]', () => { @@ -100,6 +185,7 @@ describe('getBlogPostAuthors', () => { slorber: {name: 'Sébastien Lorber', title: 'maintainer'}, yangshun: {name: 'Yangshun Tay'}, }, + baseUrl: '/', }), ).toEqual([ {key: 'slorber', name: 'Sébastien Lorber', title: 'maintainer'}, @@ -114,6 +200,7 @@ describe('getBlogPostAuthors', () => { authors: {name: 'Sébastien Lorber', title: 'maintainer'}, }, authorsMap: undefined, + baseUrl: '/', }), ).toEqual([{name: 'Sébastien Lorber', title: 'maintainer'}]); }); @@ -128,6 +215,7 @@ describe('getBlogPostAuthors', () => { ], }, authorsMap: undefined, + baseUrl: '/', }), ).toEqual([ {name: 'Sébastien Lorber', title: 'maintainer'}, @@ -153,6 +241,7 @@ describe('getBlogPostAuthors', () => { slorber: {name: 'Sébastien Lorber', title: 'maintainer'}, yangshun: {name: 'Yangshun Tay', title: 'Yangshun title original'}, }, + baseUrl: '/', }), ).toEqual([ {key: 'slorber', name: 'Sébastien Lorber', title: 'maintainer'}, @@ -173,6 +262,7 @@ describe('getBlogPostAuthors', () => { authors: 'slorber', }, authorsMap: undefined, + baseUrl: '/', }), ).toThrowErrorMatchingInlineSnapshot(` "Can't reference blog post authors by a key (such as 'slorber') because no authors map file could be loaded. @@ -187,6 +277,7 @@ describe('getBlogPostAuthors', () => { authors: 'slorber', }, authorsMap: {}, + baseUrl: '/', }), ).toThrowErrorMatchingInlineSnapshot(` "Can't reference blog post authors by a key (such as 'slorber') because no authors map file could be loaded. @@ -205,6 +296,7 @@ describe('getBlogPostAuthors', () => { yangshun: {name: 'Yangshun Tay'}, jmarcey: {name: 'Joel Marcey'}, }, + baseUrl: '/', }), ).toThrowErrorMatchingInlineSnapshot(` "Blog author with key "slorber" not found in the authors map file. @@ -225,6 +317,7 @@ describe('getBlogPostAuthors', () => { yangshun: {name: 'Yangshun Tay'}, jmarcey: {name: 'Joel Marcey'}, }, + baseUrl: '/', }), ).toThrowErrorMatchingInlineSnapshot(` "Blog author with key "slorber" not found in the authors map file. @@ -245,6 +338,7 @@ describe('getBlogPostAuthors', () => { yangshun: {name: 'Yangshun Tay'}, jmarcey: {name: 'Joel Marcey'}, }, + baseUrl: '/', }), ).toThrowErrorMatchingInlineSnapshot(` "Blog author with key "slorber" not found in the authors map file. @@ -262,6 +356,7 @@ describe('getBlogPostAuthors', () => { author: 'Yangshun Tay', }, authorsMap: undefined, + baseUrl: '/', }), ).toThrowErrorMatchingInlineSnapshot(` "To declare blog post authors, use the 'authors' front matter in priority. @@ -275,6 +370,7 @@ describe('getBlogPostAuthors', () => { author_title: 'legacy title', }, authorsMap: {slorber: {name: 'Sébastien Lorber'}}, + baseUrl: '/', }), ).toThrowErrorMatchingInlineSnapshot(` "To declare blog post authors, use the 'authors' front matter in priority. diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts index f928296bf9df..022d4ce749a9 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts @@ -8,6 +8,7 @@ import {jest} from '@jest/globals'; import path from 'path'; import fs from 'fs-extra'; +import {DEFAULT_PARSE_FRONT_MATTER} from '@docusaurus/utils'; import {DEFAULT_OPTIONS} from '../options'; import {generateBlogPosts} from '../blogUtils'; import {createBlogFeedFiles} from '../feed'; @@ -31,6 +32,8 @@ const DefaultI18N: I18n = { }, }; +const markdown = {parseFrontMatter: DEFAULT_PARSE_FRONT_MATTER}; + function getBlogContentPaths(siteDir: string): BlogContentPaths { return { contentPath: path.resolve(siteDir, 'blog'), @@ -72,6 +75,7 @@ describe.each(['atom', 'rss', 'json'])('%s', (feedType) => { baseUrl: '/', url: 'https://docusaurus.io', favicon: 'image/favicon.ico', + markdown, }; const outDir = path.join(siteDir, 'build-snap'); @@ -110,6 +114,7 @@ describe.each(['atom', 'rss', 'json'])('%s', (feedType) => { baseUrl: '/myBaseUrl/', url: 'https://docusaurus.io', favicon: 'image/favicon.ico', + markdown, }; // Build is quite difficult to mock, so we built the blog beforehand and @@ -152,6 +157,7 @@ describe.each(['atom', 'rss', 'json'])('%s', (feedType) => { baseUrl: '/myBaseUrl/', url: 'https://docusaurus.io', favicon: 'image/favicon.ico', + markdown, }; // Build is quite difficult to mock, so we built the blog beforehand and @@ -204,6 +210,7 @@ describe.each(['atom', 'rss', 'json'])('%s', (feedType) => { baseUrl: '/myBaseUrl/', url: 'https://docusaurus.io', favicon: 'image/favicon.ico', + markdown, }; // Build is quite difficult to mock, so we built the blog beforehand and diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index 8b392611e741..51b2f63f2fe7 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -16,6 +16,7 @@ import type { LoadContext, I18n, Validate, + MarkdownConfig, } from '@docusaurus/types'; import type { BlogPost, @@ -24,6 +25,24 @@ import type { EditUrlFunction, } from '@docusaurus/plugin-content-blog'; +const markdown: MarkdownConfig = { + format: 'mdx', + mermaid: true, + mdx1Compat: { + comments: true, + headingIds: true, + admonitions: true, + }, + parseFrontMatter: async (params) => { + // Reuse the default parser + const result = await params.defaultParseFrontMatter(params); + if (result.frontMatter.title === 'Complex Slug') { + result.frontMatter.custom_frontMatter = 'added by parseFrontMatter'; + } + return result; + }, +}; + function findByTitle( blogPosts: BlogPost[], title: string, @@ -81,6 +100,7 @@ const getPlugin = async ( title: 'Hello', baseUrl: '/', url: 'https://docusaurus.io', + markdown, } as DocusaurusConfig; return pluginContentBlog( { @@ -242,6 +262,7 @@ describe('blog plugin', () => { slug: '/hey/my super path/héllô', title: 'Complex Slug', tags: ['date', 'complex'], + custom_frontMatter: 'added by parseFrontMatter', }, tags: [ { diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts index 4d8f7b90b3fb..c5fdad61ddfb 100644 --- a/packages/docusaurus-plugin-content-blog/src/authors.ts +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {getDataFileData} from '@docusaurus/utils'; +import {getDataFileData, normalizeUrl} from '@docusaurus/utils'; import {Joi, URISchema} from '@docusaurus/utils-validation'; import type {BlogContentPaths} from './types'; import type { @@ -68,17 +68,37 @@ export async function getAuthorsMap(params: { type AuthorsParam = { frontMatter: BlogPostFrontMatter; authorsMap: AuthorsMap | undefined; + baseUrl: string; }; +function normalizeImageUrl({ + imageURL, + baseUrl, +}: { + imageURL: string | undefined; + baseUrl: string; +}) { + return imageURL?.startsWith('/') + ? normalizeUrl([baseUrl, imageURL]) + : imageURL; +} + // Legacy v1/early-v2 front matter fields // We may want to deprecate those in favor of using only frontMatter.authors -function getFrontMatterAuthorLegacy( - frontMatter: BlogPostFrontMatter, -): Author | undefined { +function getFrontMatterAuthorLegacy({ + baseUrl, + frontMatter, +}: { + baseUrl: string; + frontMatter: BlogPostFrontMatter; +}): Author | undefined { const name = frontMatter.author; const title = frontMatter.author_title ?? frontMatter.authorTitle; const url = frontMatter.author_url ?? frontMatter.authorURL; - const imageURL = frontMatter.author_image_url ?? frontMatter.authorImageURL; + const imageURL = normalizeImageUrl({ + imageURL: frontMatter.author_image_url ?? frontMatter.authorImageURL, + baseUrl, + }); if (name || title || url || imageURL) { return { @@ -148,14 +168,26 @@ ${Object.keys(authorsMap) return frontMatterAuthors.map(toAuthor); } +function fixAuthorImageBaseURL( + authors: Author[], + {baseUrl}: {baseUrl: string}, +) { + return authors.map((author) => ({ + ...author, + imageURL: normalizeImageUrl({imageURL: author.imageURL, baseUrl}), + })); +} + export function getBlogPostAuthors(params: AuthorsParam): Author[] { - const authorLegacy = getFrontMatterAuthorLegacy(params.frontMatter); + const authorLegacy = getFrontMatterAuthorLegacy(params); const authors = getFrontMatterAuthors(params); + const updatedAuthors = fixAuthorImageBaseURL(authors, params); + if (authorLegacy) { // Technically, we could allow mixing legacy/authors front matter, but do we // really want to? - if (authors.length > 0) { + if (updatedAuthors.length > 0) { throw new Error( `To declare blog post authors, use the 'authors' front matter in priority. Don't mix 'authors' with other existing 'author_*' front matter. Choose one or the other, not both at the same time.`, @@ -164,5 +196,5 @@ Don't mix 'authors' with other existing 'author_*' front matter. Choose one or t return [authorLegacy]; } - return authors; + return updatedAuthors; } diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 36028495381c..3bbb5301bf92 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -11,7 +11,7 @@ import _ from 'lodash'; import logger from '@docusaurus/logger'; import readingTime from 'reading-time'; import { - parseMarkdownString, + parseMarkdownFile, normalizeUrl, aliasedSitePath, getEditUrl, @@ -29,7 +29,7 @@ import { } from '@docusaurus/utils'; import {validateBlogPostFrontMatter} from './frontMatter'; import {type AuthorsMap, getAuthorsMap, getBlogPostAuthors} from './authors'; -import type {LoadContext} from '@docusaurus/types'; +import type {LoadContext, ParseFrontMatter} from '@docusaurus/types'; import type { PluginOptions, ReadingTimeFunction, @@ -180,10 +180,19 @@ function formatBlogPostDate( } } -async function parseBlogPostMarkdownFile(blogSourceAbsolute: string) { - const markdownString = await fs.readFile(blogSourceAbsolute, 'utf-8'); +async function parseBlogPostMarkdownFile({ + filePath, + parseFrontMatter, +}: { + filePath: string; + parseFrontMatter: ParseFrontMatter; +}) { + const fileContent = await fs.readFile(filePath, 'utf-8'); try { - const result = parseMarkdownString(markdownString, { + const result = await parseMarkdownFile({ + filePath, + fileContent, + parseFrontMatter, removeContentTitle: true, }); return { @@ -191,7 +200,7 @@ async function parseBlogPostMarkdownFile(blogSourceAbsolute: string) { frontMatter: validateBlogPostFrontMatter(result.frontMatter), }; } catch (err) { - logger.error`Error while parsing blog post file path=${blogSourceAbsolute}.`; + logger.error`Error while parsing blog post file path=${filePath}.`; throw err; } } @@ -207,7 +216,10 @@ async function processBlogSourceFile( authorsMap?: AuthorsMap, ): Promise { const { - siteConfig: {baseUrl}, + siteConfig: { + baseUrl, + markdown: {parseFrontMatter}, + }, siteDir, i18n, } = context; @@ -228,7 +240,10 @@ async function processBlogSourceFile( const blogSourceAbsolute = path.join(blogDirPath, blogSourceRelative); const {frontMatter, content, contentTitle, excerpt} = - await parseBlogPostMarkdownFile(blogSourceAbsolute); + await parseBlogPostMarkdownFile({ + filePath: blogSourceAbsolute, + parseFrontMatter, + }); const aliasedSource = aliasedSitePath(blogSourceAbsolute, siteDir); @@ -319,7 +334,7 @@ async function processBlogSourceFile( routeBasePath, tagsRouteBasePath, ]); - const authors = getBlogPostAuthors({authorsMap, frontMatter}); + const authors = getBlogPostAuthors({authorsMap, frontMatter, baseUrl}); return { id: slug, diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index 8a71dff82f60..daf26de3c6d4 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-docs", - "version": "3.0.1", + "version": "3.1.0", "description": "Docs plugin for Docusaurus.", "main": "lib/index.js", "sideEffects": false, @@ -35,13 +35,13 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docusaurus.config.js b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docusaurus.config.js index ae48be19a450..bd7de0da9fcb 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docusaurus.config.js +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docusaurus.config.js @@ -11,4 +11,16 @@ module.exports = { url: 'https://your-docusaurus-site.example.com', baseUrl: '/', favicon: 'img/favicon.ico', + markdown: { + parseFrontMatter: async (params) => { + // Reuse the default parser + const result = await params.defaultParseFrontMatter(params); + if (result.frontMatter.last_update?.author) { + result.frontMatter.last_update.author = + result.frontMatter.last_update.author + + ' (processed by parseFrontMatter)'; + } + return result; + }, + }, }; diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap index bc57e764ce54..2a8b72873b07 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap @@ -463,7 +463,7 @@ exports[`simple website content: data 1`] = ` "frontMatter": { "title": "Custom Last Update", "last_update": { - "author": "Custom Author", + "author": "Custom Author (processed by parseFrontMatter)", "date": "1/1/2000" } } @@ -686,7 +686,7 @@ exports[`simple website content: data 1`] = ` "frontMatter": { "title": "Last Update Author Only", "last_update": { - "author": "Custom Author" + "author": "Custom Author (processed by parseFrontMatter)" } } }", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts index 026ac0da657a..7309620d737c 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts @@ -567,14 +567,14 @@ describe('simple site', () => { description: 'Custom last update', frontMatter: { last_update: { - author: 'Custom Author', + author: 'Custom Author (processed by parseFrontMatter)', date: '1/1/2000', }, title: 'Custom Last Update', }, lastUpdatedAt: new Date('1/1/2000').getTime() / 1000, formattedLastUpdatedAt: 'Jan 1, 2000', - lastUpdatedBy: 'Custom Author', + lastUpdatedBy: 'Custom Author (processed by parseFrontMatter)', sidebarPosition: undefined, tags: [], unlisted: false, @@ -607,13 +607,13 @@ describe('simple site', () => { description: 'Only custom author, so it will still use the date from Git', frontMatter: { last_update: { - author: 'Custom Author', + author: 'Custom Author (processed by parseFrontMatter)', }, title: 'Last Update Author Only', }, lastUpdatedAt: 1539502055, formattedLastUpdatedAt: 'Oct 14, 2018', - lastUpdatedBy: 'Custom Author', + lastUpdatedBy: 'Custom Author (processed by parseFrontMatter)', sidebarPosition: undefined, tags: [], unlisted: false, @@ -685,7 +685,7 @@ describe('simple site', () => { description: 'Custom last update', frontMatter: { last_update: { - author: 'Custom Author', + author: 'Custom Author (processed by parseFrontMatter)', date: '1/1/2000', }, title: 'Custom Last Update', diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index 8ee73cf40628..2907ac7211f3 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -15,7 +15,7 @@ import { getFolderContainingFile, getContentPathList, normalizeUrl, - parseMarkdownString, + parseMarkdownFile, posixPath, Globby, normalizeFrontMatterTags, @@ -140,13 +140,23 @@ async function doProcessDocMetadata({ env: DocEnv; }): Promise { const {source, content, contentPath, filePath} = docFile; - const {siteDir, i18n} = context; + const { + siteDir, + i18n, + siteConfig: { + markdown: {parseFrontMatter}, + }, + } = context; const { frontMatter: unsafeFrontMatter, contentTitle, excerpt, - } = parseMarkdownString(content); + } = await parseMarkdownFile({ + filePath, + fileContent: content, + parseFrontMatter, + }); const frontMatter = validateDocFrontMatter(unsafeFrontMatter); const { diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index e42e4e36cd46..956473b074ce 100644 --- a/packages/docusaurus-plugin-content-pages/package.json +++ b/packages/docusaurus-plugin-content-pages/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-content-pages", - "version": "3.0.1", + "version": "3.1.0", "description": "Pages plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-pages.d.ts", @@ -18,11 +18,11 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/docusaurus.config.js b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/docusaurus.config.js index ae48be19a450..d048d2caf5a1 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/docusaurus.config.js +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/docusaurus.config.js @@ -11,4 +11,11 @@ module.exports = { url: 'https://your-docusaurus-site.example.com', baseUrl: '/', favicon: 'img/favicon.ico', + markdown: { + parseFrontMatter: async (params) => { + const result = await params.defaultParseFrontMatter(params); + result.frontMatter.custom_frontMatter = 'added by parseFrontMatter'; + return result; + }, + }, }; diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap index 56028498771e..fc5fa2196778 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap @@ -14,7 +14,9 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = ` }, { "description": "Markdown index page", - "frontMatter": {}, + "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", + }, "permalink": "/hello/", "source": "@site/src/pages/hello/index.md", "title": "Index", @@ -24,6 +26,7 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = ` { "description": "my MDX page", "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", "description": "my MDX page", "title": "MDX page", }, @@ -40,7 +43,9 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = ` }, { "description": "translated Markdown page", - "frontMatter": {}, + "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", + }, "permalink": "/hello/translatedMd", "source": "@site/src/pages/hello/translatedMd.md", "title": undefined, @@ -69,7 +74,9 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat }, { "description": "Markdown index page", - "frontMatter": {}, + "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", + }, "permalink": "/fr/hello/", "source": "@site/src/pages/hello/index.md", "title": "Index", @@ -79,6 +86,7 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat { "description": "my MDX page", "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", "description": "my MDX page", "title": "MDX page", }, @@ -95,7 +103,9 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat }, { "description": "translated Markdown page (fr)", - "frontMatter": {}, + "frontMatter": { + "custom_frontMatter": "added by parseFrontMatter", + }, "permalink": "/fr/hello/translatedMd", "source": "@site/i18n/fr/docusaurus-plugin-content-pages/hello/translatedMd.md", "title": undefined, diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index e62d07c6cbaf..a4707110f2b4 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -19,7 +19,7 @@ import { createAbsoluteFilePathMatcher, normalizeUrl, DEFAULT_PLUGIN_ID, - parseMarkdownString, + parseMarkdownFile, isUnlisted, isDraft, } from '@docusaurus/utils'; @@ -113,7 +113,11 @@ export default function pluginContentPages( frontMatter: unsafeFrontMatter, contentTitle, excerpt, - } = parseMarkdownString(content); + } = await parseMarkdownFile({ + filePath: source, + fileContent: content, + parseFrontMatter: siteConfig.markdown.parseFrontMatter, + }); const frontMatter = validatePageFrontMatter(unsafeFrontMatter); if (isDraft({frontMatter})) { diff --git a/packages/docusaurus-plugin-debug/package.json b/packages/docusaurus-plugin-debug/package.json index 6f4fb668c64f..21abf9355108 100644 --- a/packages/docusaurus-plugin-debug/package.json +++ b/packages/docusaurus-plugin-debug/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-debug", - "version": "3.0.1", + "version": "3.1.0", "description": "Debug plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-debug.d.ts", @@ -20,9 +20,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", "fs-extra": "^11.1.1", "react-json-view-lite": "^1.2.0", "tslib": "^2.6.0" diff --git a/packages/docusaurus-plugin-google-analytics/package.json b/packages/docusaurus-plugin-google-analytics/package.json index f6430e069ea9..f580a915f77b 100644 --- a/packages/docusaurus-plugin-google-analytics/package.json +++ b/packages/docusaurus-plugin-google-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-analytics", - "version": "3.0.1", + "version": "3.1.0", "description": "Global analytics (analytics.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "tslib": "^2.6.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-google-gtag/package.json b/packages/docusaurus-plugin-google-gtag/package.json index 8826fdb1d963..979fb7097882 100644 --- a/packages/docusaurus-plugin-google-gtag/package.json +++ b/packages/docusaurus-plugin-google-gtag/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-gtag", - "version": "3.0.1", + "version": "3.1.0", "description": "Global Site Tag (gtag.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-plugin-google-tag-manager/package.json b/packages/docusaurus-plugin-google-tag-manager/package.json index 80dce95b3e59..bb86182bc11f 100644 --- a/packages/docusaurus-plugin-google-tag-manager/package.json +++ b/packages/docusaurus-plugin-google-tag-manager/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-google-tag-manager", - "version": "3.0.1", + "version": "3.1.0", "description": "Google Tag Manager (gtm.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "tslib": "^2.6.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-ideal-image/package.json b/packages/docusaurus-plugin-ideal-image/package.json index d2bcc8e8599d..196e3a0158e8 100644 --- a/packages/docusaurus-plugin-ideal-image/package.json +++ b/packages/docusaurus-plugin-ideal-image/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-ideal-image", - "version": "3.0.1", + "version": "3.1.0", "description": "Docusaurus Plugin to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder).", "main": "lib/index.js", "types": "src/plugin-ideal-image.d.ts", @@ -20,12 +20,12 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/lqip-loader": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/lqip-loader": "3.1.0", "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/theme-translations": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@slorber/react-ideal-image": "^0.0.12", "react-waypoint": "^10.3.0", "sharp": "^0.32.3", @@ -33,7 +33,7 @@ "webpack": "^5.88.1" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.0.1", + "@docusaurus/module-type-aliases": "3.1.0", "fs-extra": "^11.1.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-pwa/package.json b/packages/docusaurus-plugin-pwa/package.json index 7056dc3fdb1a..62309c14daaf 100644 --- a/packages/docusaurus-plugin-pwa/package.json +++ b/packages/docusaurus-plugin-pwa/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-pwa", - "version": "3.0.1", + "version": "3.1.0", "description": "Docusaurus Plugin to add PWA support.", "main": "lib/index.js", "types": "src/plugin-pwa.d.ts", @@ -22,12 +22,12 @@ "dependencies": { "@babel/core": "^7.23.3", "@babel/preset-env": "^7.23.3", - "@docusaurus/core": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-translations": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "babel-loader": "^9.1.3", "clsx": "^2.0.0", "core-js": "^3.31.1", @@ -36,12 +36,12 @@ "webpack": "^5.88.1", "webpack-merge": "^5.9.0", "webpackbar": "^5.0.2", - "workbox-build": "^6.6.1", - "workbox-precaching": "^6.6.1", - "workbox-window": "^6.6.1" + "workbox-build": "^7.0.0", + "workbox-precaching": "^7.0.0", + "workbox-window": "^7.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.0.1", + "@docusaurus/module-type-aliases": "3.1.0", "fs-extra": "^11.1.0" }, "peerDependencies": { diff --git a/packages/docusaurus-plugin-sitemap/package.json b/packages/docusaurus-plugin-sitemap/package.json index 33e1f1d6d091..76ef51d10d05 100644 --- a/packages/docusaurus-plugin-sitemap/package.json +++ b/packages/docusaurus-plugin-sitemap/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-sitemap", - "version": "3.0.1", + "version": "3.1.0", "description": "Simple sitemap generation plugin for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,12 +18,12 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" diff --git a/packages/docusaurus-preset-classic/package.json b/packages/docusaurus-preset-classic/package.json index 5703a380fd87..ea304bf47e14 100644 --- a/packages/docusaurus-preset-classic/package.json +++ b/packages/docusaurus-preset-classic/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/preset-classic", - "version": "3.0.1", + "version": "3.1.0", "description": "Classic preset for Docusaurus.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -18,19 +18,19 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/plugin-debug": "3.0.1", - "@docusaurus/plugin-google-analytics": "3.0.1", - "@docusaurus/plugin-google-gtag": "3.0.1", - "@docusaurus/plugin-google-tag-manager": "3.0.1", - "@docusaurus/plugin-sitemap": "3.0.1", - "@docusaurus/theme-classic": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-search-algolia": "3.0.1", - "@docusaurus/types": "3.0.1" + "@docusaurus/core": "3.1.0", + "@docusaurus/plugin-content-blog": "3.1.0", + "@docusaurus/plugin-content-docs": "3.1.0", + "@docusaurus/plugin-content-pages": "3.1.0", + "@docusaurus/plugin-debug": "3.1.0", + "@docusaurus/plugin-google-analytics": "3.1.0", + "@docusaurus/plugin-google-gtag": "3.1.0", + "@docusaurus/plugin-google-tag-manager": "3.1.0", + "@docusaurus/plugin-sitemap": "3.1.0", + "@docusaurus/theme-classic": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-search-algolia": "3.1.0", + "@docusaurus/types": "3.1.0" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/docusaurus-remark-plugin-npm2yarn/package.json b/packages/docusaurus-remark-plugin-npm2yarn/package.json index 7d988513238c..95381be9a92a 100644 --- a/packages/docusaurus-remark-plugin-npm2yarn/package.json +++ b/packages/docusaurus-remark-plugin-npm2yarn/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/remark-plugin-npm2yarn", - "version": "3.0.1", + "version": "3.1.0", "description": "Remark plugin for converting npm commands to Yarn commands as tabs.", "main": "lib/index.js", "publishConfig": { diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index e06540531392..d334a8ed9c5f 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-classic", - "version": "3.0.1", + "version": "3.1.0", "description": "Classic theme for Docusaurus", "main": "lib/index.js", "types": "src/theme-classic.d.ts", @@ -20,18 +20,18 @@ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch" }, "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/plugin-content-blog": "3.1.0", + "@docusaurus/plugin-content-docs": "3.1.0", + "@docusaurus/plugin-content-pages": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-translations": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 053e036dc5eb..b894974807d8 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -363,6 +363,14 @@ declare module '@theme/CodeBlock' { export default function CodeBlock(props: Props): JSX.Element; } +declare module '@theme/CodeInline' { + import type {ComponentProps} from 'react'; + + export interface Props extends ComponentProps<'code'> {} + + export default function CodeInline(props: Props): JSX.Element; +} + declare module '@theme/CodeBlock/CopyButton' { export interface Props { readonly code: string; diff --git a/packages/docusaurus-theme-classic/src/theme/CodeInline/index.tsx b/packages/docusaurus-theme-classic/src/theme/CodeInline/index.tsx new file mode 100644 index 000000000000..066ab2e61c5d --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/CodeInline/index.tsx @@ -0,0 +1,16 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import type {Props} from '@theme/CodeInline'; + +// Simple component used to render inline code blocks +// its purpose is to be swizzled and customized +// MDX 1 used to have a inlineCode comp, see https://mdxjs.com/migrating/v2/ +export default function CodeInline(props: Props): JSX.Element { + return ; +} diff --git a/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx b/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx index 9ca1bc3f0db9..b17cd12ec3b1 100644 --- a/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx @@ -10,11 +10,13 @@ import clsx from 'clsx'; import {translate} from '@docusaurus/Translate'; import {useThemeConfig} from '@docusaurus/theme-common'; import Link from '@docusaurus/Link'; +import useBrokenLinks from '@docusaurus/useBrokenLinks'; import type {Props} from '@theme/Heading'; import styles from './styles.module.css'; export default function Heading({as: As, id, ...props}: Props): JSX.Element { + const brokenLinks = useBrokenLinks(); const { navbar: {hideOnScroll}, } = useThemeConfig(); @@ -23,6 +25,8 @@ export default function Heading({as: As, id, ...props}: Props): JSX.Element { return ; } + brokenLinks.collectAnchor(id); + const anchorTitle = translate( { id: 'theme.common.headingLinkTitle', diff --git a/packages/docusaurus-theme-classic/src/theme/MDXComponents/Code.tsx b/packages/docusaurus-theme-classic/src/theme/MDXComponents/Code.tsx index 97e1ac4d8dd7..c666174b9cef 100644 --- a/packages/docusaurus-theme-classic/src/theme/MDXComponents/Code.tsx +++ b/packages/docusaurus-theme-classic/src/theme/MDXComponents/Code.tsx @@ -8,15 +8,23 @@ import type {ComponentProps} from 'react'; import React from 'react'; import CodeBlock from '@theme/CodeBlock'; +import CodeInline from '@theme/CodeInline'; import type {Props} from '@theme/MDXComponents/Code'; -export default function MDXCode(props: Props): JSX.Element { - const shouldBeInline = React.Children.toArray(props.children).every( - (el) => typeof el === 'string' && !el.includes('\n'), +function shouldBeInline(props: Props) { + return ( + // empty code blocks have no props.children, + // see https://github.com/facebook/docusaurus/pull/9704 + typeof props.children !== 'undefined' && + React.Children.toArray(props.children).every( + (el) => typeof el === 'string' && !el.includes('\n'), + ) ); +} - return shouldBeInline ? ( - +export default function MDXCode(props: Props): JSX.Element { + return shouldBeInline(props) ? ( + ) : ( )} /> ); diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json index fe8a61ed3f89..8e4af2c8494d 100644 --- a/packages/docusaurus-theme-common/package.json +++ b/packages/docusaurus-theme-common/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-common", - "version": "3.0.1", + "version": "3.1.0", "description": "Common code for Docusaurus themes.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -30,13 +30,13 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", + "@docusaurus/mdx-loader": "3.1.0", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/plugin-content-blog": "3.1.0", + "@docusaurus/plugin-content-docs": "3.1.0", + "@docusaurus/plugin-content-pages": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -47,8 +47,8 @@ "utility-types": "^3.10.0" }, "devDependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/types": "3.1.0", "fs-extra": "^11.1.1", "lodash": "^4.17.21" }, diff --git a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts index 06eaef6b3a41..ba92ca4a1f3a 100644 --- a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts +++ b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts @@ -17,15 +17,20 @@ const windowSizes = { type WindowSize = keyof typeof windowSizes; -const DesktopThresholdWidth = 996; +// Note: this value is also hardcoded in Infima +// Both JS and CSS must have the same value +// Updating this JS value alone is not enough +// See https://github.com/facebook/docusaurus/issues/9603 +const DesktopBreakpoint = 996; -function getWindowSize() { +function getWindowSize(desktopBreakpoint: number): WindowSize { if (!ExecutionEnvironment.canUseDOM) { throw new Error( 'getWindowSize() should only be called after React hydration', ); } - return window.innerWidth > DesktopThresholdWidth + + return window.innerWidth > desktopBreakpoint ? windowSizes.desktop : windowSizes.mobile; } @@ -40,7 +45,11 @@ function getWindowSize() { * with mediaquery). We don't return `undefined` on purpose, to make it more * explicit. */ -export function useWindowSize(): WindowSize { +export function useWindowSize({ + desktopBreakpoint = DesktopBreakpoint, +}: { + desktopBreakpoint?: number; +} = {}): WindowSize { const [windowSize, setWindowSize] = useState( () => // super important to return a constant value to avoid hydration mismatch @@ -50,7 +59,7 @@ export function useWindowSize(): WindowSize { useEffect(() => { function updateWindowSize() { - setWindowSize(getWindowSize()); + setWindowSize(getWindowSize(desktopBreakpoint)); } updateWindowSize(); @@ -60,7 +69,7 @@ export function useWindowSize(): WindowSize { return () => { window.removeEventListener('resize', updateWindowSize); }; - }, []); + }, [desktopBreakpoint]); return windowSize; } diff --git a/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts b/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts index 17a85878dcb5..16a45f856d84 100644 --- a/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts @@ -13,18 +13,31 @@ const codeBlockTitleRegex = /title=(?["'])(?.*?)\1/; const metastringLinesRangeRegex = /\{(?<range>[\d,-]+)\}/; // Supported types of highlight comments -const commentPatterns = { +const popularCommentPatterns = { js: {start: '\\/\\/', end: ''}, jsBlock: {start: '\\/\\*', end: '\\*\\/'}, jsx: {start: '\\{\\s*\\/\\*', end: '\\*\\/\\s*\\}'}, bash: {start: '#', end: ''}, html: {start: '<!--', end: '-->'}, +} as const; + +const commentPatterns = { + ...popularCommentPatterns, // shallow copy is sufficient + // minor comment styles lua: {start: '--', end: ''}, wasm: {start: '\\;\\;', end: ''}, tex: {start: '%', end: ''}, -}; + vb: {start: "['‘’]", end: ''}, + rem: {start: '[Rr][Ee][Mm]\\b', end: ''}, + f90: {start: '!', end: ''}, // Free format only + ml: {start: '\\(\\*', end: '\\*\\)'}, + cobol: {start: '\\*>', end: ''}, // Free format only +} as const; type CommentType = keyof typeof commentPatterns; +const popularCommentTypes = Object.keys( + popularCommentPatterns, +) as CommentType[]; export type MagicCommentConfig = { className: string; @@ -99,15 +112,34 @@ function getAllMagicCommentDirectiveStyles( case 'wasm': return getCommentPattern(['wasm'], magicCommentDirectives); + case 'vb': + case 'vbnet': + case 'vba': + case 'visual-basic': + return getCommentPattern(['vb', 'rem'], magicCommentDirectives); + + case 'batch': + return getCommentPattern(['rem'], magicCommentDirectives); + + case 'basic': // https://github.com/PrismJS/prism/blob/master/components/prism-basic.js#L3 + return getCommentPattern(['rem', 'f90'], magicCommentDirectives); + + case 'fsharp': + return getCommentPattern(['js', 'ml'], magicCommentDirectives); + + case 'ocaml': + case 'sml': + return getCommentPattern(['ml'], magicCommentDirectives); + + case 'fortran': + return getCommentPattern(['f90'], magicCommentDirectives); + + case 'cobol': + return getCommentPattern(['cobol'], magicCommentDirectives); + default: - // All comment types except lua, wasm and matlab - return getCommentPattern( - Object.keys(commentPatterns).filter( - (pattern) => - !['lua', 'wasm', 'tex', 'latex', 'matlab'].includes(pattern), - ) as CommentType[], - magicCommentDirectives, - ); + // All popular comment types + return getCommentPattern(popularCommentTypes, magicCommentDirectives); } } diff --git a/packages/docusaurus-theme-live-codeblock/package.json b/packages/docusaurus-theme-live-codeblock/package.json index 07c0736bc34c..98f02045ef8e 100644 --- a/packages/docusaurus-theme-live-codeblock/package.json +++ b/packages/docusaurus-theme-live-codeblock/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-live-codeblock", - "version": "3.0.1", + "version": "3.1.0", "description": "Docusaurus live code block component.", "main": "lib/index.js", "types": "src/theme-live-codeblock.d.ts", @@ -23,10 +23,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-translations": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@philpl/buble": "^0.19.7", "clsx": "^2.0.0", "fs-extra": "^11.1.1", @@ -34,7 +34,7 @@ "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/types": "3.0.1", + "@docusaurus/types": "3.1.0", "@types/buble": "^0.20.1" }, "peerDependencies": { diff --git a/packages/docusaurus-theme-live-codeblock/src/theme-live-codeblock.d.ts b/packages/docusaurus-theme-live-codeblock/src/theme-live-codeblock.d.ts index b3670f476ddf..12bd27e8c786 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme-live-codeblock.d.ts +++ b/packages/docusaurus-theme-live-codeblock/src/theme-live-codeblock.d.ts @@ -24,7 +24,8 @@ declare module '@theme/Playground' { type LiveProviderProps = React.ComponentProps<typeof LiveProvider>; export interface Props extends CodeBlockProps, LiveProviderProps { - children: string; + // Allow empty live playgrounds + children?: string; } export default function Playground(props: LiveProviderProps): JSX.Element; } diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx index ae0b2c40233e..1f36e69f570c 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx @@ -98,6 +98,10 @@ function EditorWithHeader() { ); } +// this should rather be a stable function +// see https://github.com/facebook/docusaurus/issues/9630#issuecomment-1855682643 +const DEFAULT_TRANSFORM_CODE = (code: string) => `${code};`; + export default function Playground({ children, transformCode, @@ -116,9 +120,9 @@ export default function Playground({ return ( <div className={styles.playgroundContainer}> <LiveProvider - code={children.replace(/\n$/, '')} + code={children?.replace(/\n$/, '')} noInline={noInline} - transformCode={transformCode ?? ((code) => `${code};`)} + transformCode={transformCode ?? DEFAULT_TRANSFORM_CODE} theme={prismTheme} {...props}> {playgroundPosition === 'top' ? ( diff --git a/packages/docusaurus-theme-mermaid/package.json b/packages/docusaurus-theme-mermaid/package.json index fe3aa5ddd0e4..d817de8ec417 100644 --- a/packages/docusaurus-theme-mermaid/package.json +++ b/packages/docusaurus-theme-mermaid/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-mermaid", - "version": "3.0.1", + "version": "3.1.0", "description": "Mermaid components for Docusaurus.", "main": "lib/index.js", "types": "src/theme-mermaid.d.ts", @@ -33,11 +33,11 @@ "copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch" }, "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/types": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "mermaid": "^10.4.0", "tslib": "^2.6.0" }, diff --git a/packages/docusaurus-theme-search-algolia/package.json b/packages/docusaurus-theme-search-algolia/package.json index 59773fc351df..94e83143892e 100644 --- a/packages/docusaurus-theme-search-algolia/package.json +++ b/packages/docusaurus-theme-search-algolia/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-search-algolia", - "version": "3.0.1", + "version": "3.1.0", "description": "Algolia search component for Docusaurus.", "main": "lib/index.js", "sideEffects": [ @@ -34,13 +34,13 @@ }, "dependencies": { "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/plugin-content-docs": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-translations": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "algoliasearch": "^4.18.0", "algoliasearch-helper": "^3.13.3", "clsx": "^2.0.0", @@ -51,7 +51,7 @@ "utility-types": "^3.10.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.0.1" + "@docusaurus/module-type-aliases": "3.1.0" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx index 0f4d7ee00099..9a3a4ae3bc9a 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx @@ -6,6 +6,7 @@ */ import React, {useCallback, useMemo, useRef, useState} from 'react'; +import {createPortal} from 'react-dom'; import {DocSearchButton, useDocSearchKeyboardEvents} from '@docsearch/react'; import Head from '@docusaurus/Head'; import Link from '@docusaurus/Link'; @@ -20,7 +21,6 @@ import { } from '@docusaurus/theme-search-algolia/client'; import Translate from '@docusaurus/Translate'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import {createPortal} from 'react-dom'; import translations from '@theme/SearchTranslations'; import type {AutocompleteState} from '@algolia/autocomplete-core'; diff --git a/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json b/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json index edf86395d97b..3c930a6ee184 100644 --- a/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json +++ b/packages/docusaurus-theme-translations/locales/pt-BR/theme-common.json @@ -4,22 +4,22 @@ "theme.CodeBlock.copied": "Copiado", "theme.CodeBlock.copy": "Copiar", "theme.CodeBlock.copyButtonAriaLabel": "Copiar código para a área de transferência", - "theme.CodeBlock.wordWrapToggle": "Toggle word wrap", - "theme.DocSidebarItem.collapseCategoryAriaLabel": "Collapse sidebar category '{label}'", - "theme.DocSidebarItem.expandCategoryAriaLabel": "Expand sidebar category '{label}'", - "theme.ErrorPageContent.title": "This page crashed.", - "theme.ErrorPageContent.tryAgain": "Try again", + "theme.CodeBlock.wordWrapToggle": "Alternar quebra de linha", + "theme.DocSidebarItem.collapseCategoryAriaLabel": "Fechar a categoria lateral '{label}'", + "theme.DocSidebarItem.expandCategoryAriaLabel": "Expandir a categoria lateral '{label}'", + "theme.ErrorPageContent.title": "Esta página deu erro.", + "theme.ErrorPageContent.tryAgain": "Tente novamente", "theme.NavBar.navAriaLabel": "Main", "theme.NotFound.p1": "Não foi possível encontrar o que você está procurando.", "theme.NotFound.p2": "Entre em contato com o proprietário do site que lhe trouxe para cá e lhe informe que o link está quebrado.", "theme.NotFound.title": "Página não encontrada", "theme.TOCCollapsible.toggleButtonLabel": "Nessa página", - "theme.admonition.caution": "caution", - "theme.admonition.danger": "danger", + "theme.admonition.caution": "cuidado", + "theme.admonition.danger": "perigo", "theme.admonition.info": "info", - "theme.admonition.note": "note", - "theme.admonition.tip": "tip", - "theme.admonition.warning": "warning", + "theme.admonition.note": "nota", + "theme.admonition.tip": "dica", + "theme.admonition.warning": "atenção", "theme.blog.archive.description": "Arquivo", "theme.blog.archive.title": "Arquivo", "theme.blog.paginator.navAriaLabel": "Navegação da página de listagem do blog", @@ -30,32 +30,32 @@ "theme.blog.post.paginator.olderPost": "Postagem mais antiga", "theme.blog.post.plurals": "Uma postagem|{count} postagens", "theme.blog.post.readMore": "Leia Mais", - "theme.blog.post.readMoreLabel": "Read more about {title}", + "theme.blog.post.readMoreLabel": "Ler mais sobre {title}", "theme.blog.post.readingTime.plurals": "Leitura de um minuto|Leitura de {readingTime} minutos", "theme.blog.sidebar.navAriaLabel": "Blog recent posts navigation", "theme.blog.tagTitle": "{nPosts} marcadas com \"{tagName}\"", - "theme.colorToggle.ariaLabel": "Switch between dark and light mode (currently {mode})", - "theme.colorToggle.ariaLabel.mode.dark": "dark mode", - "theme.colorToggle.ariaLabel.mode.light": "light mode", + "theme.colorToggle.ariaLabel": "Alterar entre os modos claro e escuro (modo {mode} ativado)", + "theme.colorToggle.ariaLabel.mode.dark": "modo escuro", + "theme.colorToggle.ariaLabel.mode.light": "modo claro", "theme.common.editThisPage": "Editar essa página", "theme.common.headingLinkTitle": "Link direto para {heading}", "theme.common.skipToMainContent": "Pular para o conteúdo principal", "theme.docs.DocCard.categoryDescription": "{count} items", - "theme.docs.breadcrumbs.home": "Home page", + "theme.docs.breadcrumbs.home": "Página Inicial", "theme.docs.breadcrumbs.navAriaLabel": "Breadcrumbs", "theme.docs.paginator.navAriaLabel": "Páginas de documentação", "theme.docs.paginator.next": "Próxima", "theme.docs.paginator.previous": "Anterior", - "theme.docs.sidebar.closeSidebarButtonAriaLabel": "Close navigation bar", + "theme.docs.sidebar.closeSidebarButtonAriaLabel": "Fechar barra de navegação", "theme.docs.sidebar.collapseButtonAriaLabel": "Fechar painel lateral", "theme.docs.sidebar.collapseButtonTitle": "Fechar painel lateral", "theme.docs.sidebar.expandButtonAriaLabel": "Expandir painel lateral", "theme.docs.sidebar.expandButtonTitle": "Expandir painel lateral", "theme.docs.sidebar.navAriaLabel": "Docs sidebar", - "theme.docs.sidebar.toggleSidebarButtonAriaLabel": "Toggle navigation bar", + "theme.docs.sidebar.toggleSidebarButtonAriaLabel": "Alternar a barra de navegação", "theme.docs.tagDocListPageTitle": "{nDocsTagged} com \"{tagName}\"", "theme.docs.tagDocListPageTitle.nDocsTagged": "Um documento selecionado|{count} documentos selecionados", - "theme.docs.versionBadge.label": "Version: {versionLabel}", + "theme.docs.versionBadge.label": "Versão: {versionLabel}", "theme.docs.versions.latestVersionLinkLabel": "última versão", "theme.docs.versions.latestVersionSuggestionLabel": "Para a documentação atualizada, veja: {latestVersionLink} ({versionLabel}).", "theme.docs.versions.unmaintainedVersionLabel": "Esta é a documentação para {siteTitle} {versionLabel}, que não é mais mantida ativamente.", @@ -63,12 +63,12 @@ "theme.lastUpdated.atDate": " em {date}", "theme.lastUpdated.byUser": " por {user}", "theme.lastUpdated.lastUpdatedAtBy": "Última atualização {atDate}{byUser}", - "theme.navbar.mobileLanguageDropdown.label": "Languages", + "theme.navbar.mobileLanguageDropdown.label": "Linguagens", "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← Voltar para o menu principal", - "theme.navbar.mobileVersionsDropdown.label": "Versions", + "theme.navbar.mobileVersionsDropdown.label": "Versões", "theme.tags.tagsListLabel": "Marcadores:", "theme.tags.tagsPageLink": "Ver todas os Marcadores", "theme.tags.tagsPageTitle": "Marcadores", "theme.unlistedContent.message": "This page is unlisted. Search engines will not index it, and only users having a direct link can access it.", - "theme.unlistedContent.title": "Unlisted page" + "theme.unlistedContent.title": "Página não listada" } diff --git a/packages/docusaurus-theme-translations/package.json b/packages/docusaurus-theme-translations/package.json index 795bd3e964a4..14d099b24ed6 100644 --- a/packages/docusaurus-theme-translations/package.json +++ b/packages/docusaurus-theme-translations/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-translations", - "version": "3.0.1", + "version": "3.1.0", "description": "Docusaurus theme translations.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -23,8 +23,8 @@ "tslib": "^2.6.0" }, "devDependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", "lodash": "^4.17.21" }, "engines": { diff --git a/packages/docusaurus-tsconfig/package.json b/packages/docusaurus-tsconfig/package.json index 3a716a9302a8..ae0132a236d7 100644 --- a/packages/docusaurus-tsconfig/package.json +++ b/packages/docusaurus-tsconfig/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/tsconfig", - "version": "3.0.1", + "version": "3.1.0", "description": "Docusaurus base TypeScript configuration.", "main": "tsconfig.json", "publishConfig": { diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index 9de288df6920..4c4e6944ea49 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/types", - "version": "3.0.1", + "version": "3.1.0", "description": "Common types for Docusaurus packages.", "types": "./src/index.d.ts", "publishConfig": { @@ -13,6 +13,7 @@ }, "license": "MIT", "dependencies": { + "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", "@types/react": "*", "commander": "^5.1.0", diff --git a/packages/docusaurus-types/src/config.d.ts b/packages/docusaurus-types/src/config.d.ts index 3a7bb99ae743..47bfde898d44 100644 --- a/packages/docusaurus-types/src/config.d.ts +++ b/packages/docusaurus-types/src/config.d.ts @@ -10,6 +10,10 @@ import type {Required as RequireKeys, DeepPartial} from 'utility-types'; import type {I18nConfig} from './i18n'; import type {PluginConfig, PresetConfig, HtmlTagObject} from './plugin'; +import type {ProcessorOptions} from '@mdx-js/mdx'; + +export type RemarkRehypeOptions = ProcessorOptions['remarkRehypeOptions']; + export type ReportingSeverity = 'ignore' | 'log' | 'warn' | 'throw'; export type ThemeConfig = { @@ -27,6 +31,20 @@ export type MDX1CompatOptions = { headingIds: boolean; }; +export type ParseFrontMatterParams = {filePath: string; fileContent: string}; +export type ParseFrontMatterResult = { + frontMatter: {[key: string]: unknown}; + content: string; +}; +export type DefaultParseFrontMatter = ( + params: ParseFrontMatterParams, +) => Promise<ParseFrontMatterResult>; +export type ParseFrontMatter = ( + params: ParseFrontMatterParams & { + defaultParseFrontMatter: DefaultParseFrontMatter; + }, +) => Promise<ParseFrontMatterResult>; + export type MarkdownConfig = { /** * The Markdown format to use by default. @@ -44,6 +62,14 @@ export type MarkdownConfig = { */ format: 'mdx' | 'md' | 'detect'; + /** + * A function callback that lets users parse the front matter themselves. + * Gives the opportunity to read it from a different source, or process it. + * + * @see https://github.com/facebook/docusaurus/issues/5568 + */ + parseFrontMatter: ParseFrontMatter; + /** * Allow mermaid language code blocks to be rendered into Mermaid diagrams: * @@ -69,6 +95,12 @@ export type MarkdownConfig = { * See also https://github.com/facebook/docusaurus/issues/4029 */ mdx1Compat: MDX1CompatOptions; + + /** + * Ability to provide custom remark-rehype options + * See also https://github.com/remarkjs/remark-rehype#options + */ + remarkRehypeOptions: RemarkRehypeOptions; }; /** @@ -143,6 +175,13 @@ export type DocusaurusConfig = { * @default "throw" */ onBrokenLinks: ReportingSeverity; + /** + * The behavior of Docusaurus when it detects any broken link. + * + * @see https://docusaurus.io/docs/api/docusaurus-config#onBrokenAnchors + * @default "warn" + */ + onBrokenAnchors: ReportingSeverity; /** * The behavior of Docusaurus when it detects any broken markdown link. * diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 53e83ce96345..257ec57811de 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -9,6 +9,8 @@ export { ReportingSeverity, ThemeConfig, MarkdownConfig, + DefaultParseFrontMatter, + ParseFrontMatter, DocusaurusConfig, Config, } from './config'; diff --git a/packages/docusaurus-utils-common/package.json b/packages/docusaurus-utils-common/package.json index 73c75cd2499a..4b453ad41093 100644 --- a/packages/docusaurus-utils-common/package.json +++ b/packages/docusaurus-utils-common/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils-common", - "version": "3.0.1", + "version": "3.1.0", "description": "Common (Node/Browser) utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", diff --git a/packages/docusaurus-utils-validation/package.json b/packages/docusaurus-utils-validation/package.json index 8b2c4966b5fa..d60487f6d78a 100644 --- a/packages/docusaurus-utils-validation/package.json +++ b/packages/docusaurus-utils-validation/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils-validation", - "version": "3.0.1", + "version": "3.1.0", "description": "Node validation utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,8 +18,8 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.0.1", - "@docusaurus/utils": "3.0.1", + "@docusaurus/logger": "3.1.0", + "@docusaurus/utils": "3.1.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", "tslib": "^2.6.0" diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index 5d716f418fa4..c1c49b4a6184 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils", - "version": "3.0.1", + "version": "3.1.0", "description": "Node utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,7 +18,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.0.1", + "@docusaurus/logger": "3.1.0", "@svgr/webpack": "^6.5.1", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", @@ -40,7 +40,7 @@ "node": ">=18.0" }, "devDependencies": { - "@docusaurus/types": "3.0.1", + "@docusaurus/types": "3.1.0", "@types/dedent": "^0.7.0", "@types/github-slugger": "^1.3.0", "@types/micromatch": "^4.0.2", diff --git a/packages/docusaurus-utils/src/__tests__/__snapshots__/markdownLinks.test.ts.snap b/packages/docusaurus-utils/src/__tests__/__snapshots__/markdownLinks.test.ts.snap index 7c5fc874287c..3c4f732a82fd 100644 --- a/packages/docusaurus-utils/src/__tests__/__snapshots__/markdownLinks.test.ts.snap +++ b/packages/docusaurus-utils/src/__tests__/__snapshots__/markdownLinks.test.ts.snap @@ -176,6 +176,7 @@ exports[`replaceMarkdownLinks replaces links with same title as URL 1`] = ` "brokenMarkdownLinks": [], "newContent": " [foo.md](/docs/foo) +[./foo.md](</docs/foo>) [./foo.md](/docs/foo) [foo.md](/docs/foo) [./foo.md](/docs/foo) diff --git a/packages/docusaurus-utils/src/__tests__/__snapshots__/markdownUtils.test.ts.snap b/packages/docusaurus-utils/src/__tests__/__snapshots__/markdownUtils.test.ts.snap index 5a65f0bb828f..8fb7a03dfa2f 100644 --- a/packages/docusaurus-utils/src/__tests__/__snapshots__/markdownUtils.test.ts.snap +++ b/packages/docusaurus-utils/src/__tests__/__snapshots__/markdownUtils.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`parseMarkdownString deletes only first heading 1`] = ` +exports[`parseMarkdownFile deletes only first heading 1`] = ` { "content": "# Markdown Title @@ -15,7 +15,7 @@ test test test # test bar } `; -exports[`parseMarkdownString deletes only first heading 2 1`] = ` +exports[`parseMarkdownFile deletes only first heading 2 1`] = ` { "content": "# test @@ -30,7 +30,7 @@ test3", } `; -exports[`parseMarkdownString does not warn for duplicate title if markdown title is not at the top 1`] = ` +exports[`parseMarkdownFile does not warn for duplicate title if markdown title is not at the top 1`] = ` { "content": "foo @@ -43,7 +43,7 @@ exports[`parseMarkdownString does not warn for duplicate title if markdown title } `; -exports[`parseMarkdownString handles code blocks 1`] = ` +exports[`parseMarkdownFile handles code blocks 1`] = ` { "content": "\`\`\`js code @@ -56,7 +56,7 @@ Content", } `; -exports[`parseMarkdownString handles code blocks 2`] = ` +exports[`parseMarkdownFile handles code blocks 2`] = ` { "content": "\`\`\`\`js Foo @@ -73,7 +73,7 @@ Content", } `; -exports[`parseMarkdownString handles code blocks 3`] = ` +exports[`parseMarkdownFile handles code blocks 3`] = ` { "content": "\`\`\`\`js Foo @@ -88,7 +88,7 @@ Content", } `; -exports[`parseMarkdownString ignores markdown title if its not a first text 1`] = ` +exports[`parseMarkdownFile ignores markdown title if its not a first text 1`] = ` { "content": "foo # test", @@ -98,18 +98,32 @@ exports[`parseMarkdownString ignores markdown title if its not a first text 1`] } `; -exports[`parseMarkdownString parse markdown with front matter 1`] = ` +exports[`parseMarkdownFile parse markdown with custom front matter parser 1`] = ` { "content": "Some text", "contentTitle": undefined, "excerpt": "Some text", "frontMatter": { + "age": 84, + "extra": "value", + "great": true, "title": "Frontmatter title", }, } `; -exports[`parseMarkdownString parses first heading as contentTitle 1`] = ` +exports[`parseMarkdownFile parse markdown with front matter 1`] = ` +{ + "content": "Some text", + "contentTitle": undefined, + "excerpt": "Some text", + "frontMatter": { + "title": "Frontmatter title", + }, +} +`; + +exports[`parseMarkdownFile parses first heading as contentTitle 1`] = ` { "content": "# Markdown Title @@ -120,7 +134,7 @@ Some text", } `; -exports[`parseMarkdownString parses front-matter and ignore h2 1`] = ` +exports[`parseMarkdownFile parses front-matter and ignore h2 1`] = ` { "content": "## test", "contentTitle": undefined, @@ -131,7 +145,7 @@ exports[`parseMarkdownString parses front-matter and ignore h2 1`] = ` } `; -exports[`parseMarkdownString parses title only 1`] = ` +exports[`parseMarkdownFile parses title only 1`] = ` { "content": "# test", "contentTitle": "test", @@ -140,7 +154,7 @@ exports[`parseMarkdownString parses title only 1`] = ` } `; -exports[`parseMarkdownString parses title only alternate 1`] = ` +exports[`parseMarkdownFile parses title only alternate 1`] = ` { "content": "test ===", @@ -150,7 +164,7 @@ exports[`parseMarkdownString parses title only alternate 1`] = ` } `; -exports[`parseMarkdownString reads front matter only 1`] = ` +exports[`parseMarkdownFile reads front matter only 1`] = ` { "content": "", "contentTitle": undefined, @@ -161,7 +175,7 @@ exports[`parseMarkdownString reads front matter only 1`] = ` } `; -exports[`parseMarkdownString warns about duplicate titles (front matter + markdown alternate) 1`] = ` +exports[`parseMarkdownFile warns about duplicate titles (front matter + markdown alternate) 1`] = ` { "content": "Markdown Title alternate ================ @@ -175,7 +189,7 @@ Some text", } `; -exports[`parseMarkdownString warns about duplicate titles (front matter + markdown) 1`] = ` +exports[`parseMarkdownFile warns about duplicate titles (front matter + markdown) 1`] = ` { "content": "# Markdown Title @@ -188,7 +202,7 @@ Some text", } `; -exports[`parseMarkdownString warns about duplicate titles 1`] = ` +exports[`parseMarkdownFile warns about duplicate titles 1`] = ` { "content": "# test", "contentTitle": "test", diff --git a/packages/docusaurus-utils/src/__tests__/markdownLinks.test.ts b/packages/docusaurus-utils/src/__tests__/markdownLinks.test.ts index b7d7abd556b5..ce0acfb3a99b 100644 --- a/packages/docusaurus-utils/src/__tests__/markdownLinks.test.ts +++ b/packages/docusaurus-utils/src/__tests__/markdownLinks.test.ts @@ -231,6 +231,7 @@ The following operations are defined for [URI]s: }, fileString: ` [foo.md](foo.md) +[./foo.md](<./foo.md>) [./foo.md](./foo.md) [foo.md](./foo.md) [./foo.md](foo.md) diff --git a/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts b/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts index 182c95b05ffe..0e04dbf5c280 100644 --- a/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/markdownUtils.test.ts @@ -9,12 +9,14 @@ import dedent from 'dedent'; import { createExcerpt, parseMarkdownContentTitle, - parseMarkdownString, parseMarkdownHeadingId, writeMarkdownHeadingId, escapeMarkdownHeadingIds, unwrapMdxCodeBlocks, admonitionTitleToDirectiveLabel, + parseMarkdownFile, + DEFAULT_PARSE_FRONT_MATTER, + parseFileContentFrontMatter, } from '../markdownUtils'; describe('createExcerpt', () => { @@ -623,32 +625,110 @@ Lorem Ipsum }); }); -describe('parseMarkdownString', () => { - it('parse markdown with front matter', () => { - expect( - parseMarkdownString(dedent` +describe('parseFileContentFrontMatter', () => { + function test(fileContent: string) { + return parseFileContentFrontMatter(fileContent); + } + + it('can parse front matter', () => { + const input = dedent` + --- + title: Frontmatter title + author: + age: 42 + birth: 2000-07-23 + --- + + Some text + `; + + const expectedResult = { + content: 'Some text', + frontMatter: { + title: 'Frontmatter title', + author: {age: 42, birth: new Date('2000-07-23')}, + }, + }; + + const result = test(input) as typeof expectedResult; + expect(result).toEqual(expectedResult); + expect(result.frontMatter.author.birth).toBeInstanceOf(Date); + + // A regression test, ensure we don't return gray-matter cached objects + result.frontMatter.title = 'modified'; + // @ts-expect-error: ok + result.frontMatter.author.age = 53; + expect(test(input)).toEqual(expectedResult); + }); +}); + +describe('parseMarkdownFile', () => { + async function test( + fileContent: string, + options?: Partial<Parameters<typeof parseMarkdownFile>>[0], + ) { + return parseMarkdownFile({ + fileContent, + filePath: 'some-file-path.mdx', + parseFrontMatter: DEFAULT_PARSE_FRONT_MATTER, + ...options, + }); + } + + it('parse markdown with front matter', async () => { + await expect( + test(dedent` --- title: Frontmatter title --- Some text `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('parses first heading as contentTitle', () => { - expect( - parseMarkdownString(dedent` + it('parse markdown with custom front matter parser', async () => { + await expect( + test( + dedent` + --- + title: Frontmatter title + age: 42 + --- + + Some text + `, + { + parseFrontMatter: async (params) => { + const result = await params.defaultParseFrontMatter(params); + return { + ...result, + frontMatter: { + ...result.frontMatter, + age: result.frontMatter.age * 2, + extra: 'value', + great: true, + }, + }; + }, + }, + ), + ).resolves.toMatchSnapshot(); + }); + + it('parses first heading as contentTitle', async () => { + await expect( + test(dedent` # Markdown Title Some text `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('warns about duplicate titles (front matter + markdown)', () => { - expect( - parseMarkdownString(dedent` + it('warns about duplicate titles (front matter + markdown)', async () => { + await expect( + test(dedent` --- title: Frontmatter title --- @@ -657,12 +737,12 @@ describe('parseMarkdownString', () => { Some text `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('warns about duplicate titles (front matter + markdown alternate)', () => { - expect( - parseMarkdownString(dedent` + it('warns about duplicate titles (front matter + markdown alternate)', async () => { + await expect( + test(dedent` --- title: Frontmatter title --- @@ -672,12 +752,12 @@ describe('parseMarkdownString', () => { Some text `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('does not warn for duplicate title if markdown title is not at the top', () => { - expect( - parseMarkdownString(dedent` + it('does not warn for duplicate title if markdown title is not at the top', async () => { + await expect( + test(dedent` --- title: Frontmatter title --- @@ -686,12 +766,12 @@ describe('parseMarkdownString', () => { # Markdown Title `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('deletes only first heading', () => { - expect( - parseMarkdownString(dedent` + it('deletes only first heading', async () => { + await expect( + test(dedent` # Markdown Title test test test # test bar @@ -700,12 +780,12 @@ describe('parseMarkdownString', () => { ### Markdown Title h3 `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('parses front-matter and ignore h2', () => { - expect( - parseMarkdownString( + it('parses front-matter and ignore h2', async () => { + await expect( + test( dedent` --- title: Frontmatter title @@ -713,55 +793,55 @@ describe('parseMarkdownString', () => { ## test `, ), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('reads front matter only', () => { - expect( - parseMarkdownString(dedent` + it('reads front matter only', async () => { + await expect( + test(dedent` --- title: test --- `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('parses title only', () => { - expect(parseMarkdownString('# test')).toMatchSnapshot(); + it('parses title only', async () => { + await expect(test('# test')).resolves.toMatchSnapshot(); }); - it('parses title only alternate', () => { - expect( - parseMarkdownString(dedent` + it('parses title only alternate', async () => { + await expect( + test(dedent` test === `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('warns about duplicate titles', () => { - expect( - parseMarkdownString(dedent` + it('warns about duplicate titles', async () => { + await expect( + test(dedent` --- title: Frontmatter title --- # test `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('ignores markdown title if its not a first text', () => { - expect( - parseMarkdownString(dedent` + it('ignores markdown title if its not a first text', async () => { + await expect( + test(dedent` foo # test `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('deletes only first heading 2', () => { - expect( - parseMarkdownString(dedent` + it('deletes only first heading 2', async () => { + await expect( + test(dedent` # test test test test test test test @@ -770,21 +850,21 @@ describe('parseMarkdownString', () => { ### test test3 `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('handles code blocks', () => { - expect( - parseMarkdownString(dedent` + it('handles code blocks', async () => { + await expect( + test(dedent` \`\`\`js code \`\`\` Content `), - ).toMatchSnapshot(); - expect( - parseMarkdownString(dedent` + ).resolves.toMatchSnapshot(); + await expect( + test(dedent` \`\`\`\`js Foo \`\`\`diff @@ -795,9 +875,9 @@ describe('parseMarkdownString', () => { Content `), - ).toMatchSnapshot(); - expect( - parseMarkdownString(dedent` + ).resolves.toMatchSnapshot(); + await expect( + test(dedent` \`\`\`\`js Foo \`\`\`diff @@ -806,17 +886,17 @@ describe('parseMarkdownString', () => { Content `), - ).toMatchSnapshot(); + ).resolves.toMatchSnapshot(); }); - it('throws for invalid front matter', () => { - expect(() => - parseMarkdownString(dedent` + it('throws for invalid front matter', async () => { + await expect( + test(dedent` --- foo: f: a --- `), - ).toThrowErrorMatchingInlineSnapshot(` + ).rejects.toThrowErrorMatchingInlineSnapshot(` "incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line at line 2, column 7: foo: f: a ^" diff --git a/packages/docusaurus-utils/src/__tests__/urlUtils.test.ts b/packages/docusaurus-utils/src/__tests__/urlUtils.test.ts index 30625e400554..301a91ae3224 100644 --- a/packages/docusaurus-utils/src/__tests__/urlUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/urlUtils.test.ts @@ -18,6 +18,8 @@ import { buildSshUrl, buildHttpsUrl, hasSSHProtocol, + parseURLPath, + serializeURLPath, } from '../urlUtils'; describe('normalizeUrl', () => { @@ -232,6 +234,137 @@ describe('removeTrailingSlash', () => { }); }); +describe('parseURLPath', () => { + it('parse and resolve pathname', () => { + expect(parseURLPath('')).toEqual({ + pathname: '/', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('/')).toEqual({ + pathname: '/', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('/page')).toEqual({ + pathname: '/page', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('/dir1/page')).toEqual({ + pathname: '/dir1/page', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('/dir1/dir2/./../page')).toEqual({ + pathname: '/dir1/page', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('/dir1/dir2/../..')).toEqual({ + pathname: '/', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('/dir1/dir2/../../..')).toEqual({ + pathname: '/', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('./dir1/dir2./../page', '/dir3/dir4/page2')).toEqual({ + pathname: '/dir3/dir4/dir1/page', + search: undefined, + hash: undefined, + }); + }); + + it('parse query string', () => { + expect(parseURLPath('/page')).toEqual({ + pathname: '/page', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('/page?')).toEqual({ + pathname: '/page', + search: '', + hash: undefined, + }); + expect(parseURLPath('/page?test')).toEqual({ + pathname: '/page', + search: 'test', + hash: undefined, + }); + expect(parseURLPath('/page?age=42&great=true')).toEqual({ + pathname: '/page', + search: 'age=42&great=true', + hash: undefined, + }); + }); + + it('parse hash', () => { + expect(parseURLPath('/page')).toEqual({ + pathname: '/page', + search: undefined, + hash: undefined, + }); + expect(parseURLPath('/page#')).toEqual({ + pathname: '/page', + search: undefined, + hash: '', + }); + expect(parseURLPath('/page#anchor')).toEqual({ + pathname: '/page', + search: undefined, + hash: 'anchor', + }); + }); + + it('parse fancy real-world edge cases', () => { + expect(parseURLPath('/page?#')).toEqual({ + pathname: '/page', + search: '', + hash: '', + }); + expect( + parseURLPath('dir1/dir2/../page?age=42#anchor', '/dir3/page2'), + ).toEqual({ + pathname: '/dir3/dir1/page', + search: 'age=42', + hash: 'anchor', + }); + }); +}); + +describe('serializeURLPath', () => { + function test(input: string, base?: string, expectedOutput?: string) { + expect(serializeURLPath(parseURLPath(input, base))).toEqual( + expectedOutput ?? input, + ); + } + + it('works for already resolved paths', () => { + test('/'); + test('/dir1/page'); + test('/dir1/page?'); + test('/dir1/page#'); + test('/dir1/page?#'); + test('/dir1/page?age=42#anchor'); + }); + + it('works for relative paths', () => { + test('', undefined, '/'); + test('', '/dir1/dir2/page2', '/dir1/dir2/page2'); + test('page', '/dir1/dir2/page2', '/dir1/dir2/page'); + test('../page', '/dir1/dir2/page2', '/dir1/page'); + test('/dir1/dir2/../page', undefined, '/dir1/page'); + test( + '/dir1/dir2/../page?age=42#anchor', + undefined, + '/dir1/page?age=42#anchor', + ); + }); +}); + describe('resolvePathname', () => { it('works', () => { // These tests are directly copied from https://github.com/mjackson/resolve-pathname/blob/master/modules/__tests__/resolvePathname-test.js diff --git a/packages/docusaurus-utils/src/constants.ts b/packages/docusaurus-utils/src/constants.ts index 6ecba7aea0f5..5039d6989b00 100644 --- a/packages/docusaurus-utils/src/constants.ts +++ b/packages/docusaurus-utils/src/constants.ts @@ -83,7 +83,9 @@ export const DEFAULT_I18N_DIR_NAME = 'i18n'; export const CODE_TRANSLATIONS_FILE_NAME = 'code.json'; /** Dev server opens on this port by default. */ -export const DEFAULT_PORT = 3000; +export const DEFAULT_PORT = process.env.PORT + ? parseInt(process.env.PORT, 10) + : 3000; /** Default plugin ID. */ export const DEFAULT_PLUGIN_ID = 'default'; diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index 5bb77a0c054f..6db01244d006 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -48,6 +48,8 @@ export { encodePath, isValidPathname, resolvePathname, + parseURLPath, + serializeURLPath, addLeadingSlash, addTrailingSlash, removeTrailingSlash, @@ -55,6 +57,7 @@ export { buildHttpsUrl, buildSshUrl, } from './urlUtils'; +export type {URLPath} from './urlUtils'; export { type Tag, type TagsListItem, @@ -70,9 +73,9 @@ export { unwrapMdxCodeBlocks, admonitionTitleToDirectiveLabel, createExcerpt, - parseFrontMatter, + DEFAULT_PARSE_FRONT_MATTER, parseMarkdownContentTitle, - parseMarkdownString, + parseMarkdownFile, writeMarkdownHeadingId, type WriteHeadingIDOptions, } from './markdownUtils'; diff --git a/packages/docusaurus-utils/src/markdownLinks.ts b/packages/docusaurus-utils/src/markdownLinks.ts index 88825e502f14..13afca33905e 100644 --- a/packages/docusaurus-utils/src/markdownLinks.ts +++ b/packages/docusaurus-utils/src/markdownLinks.ts @@ -128,7 +128,7 @@ export function replaceMarkdownLinks<T extends ContentPaths>({ const linkSuffixPattern = '(?:\\?[^#>\\s]+)?(?:#[^>\\s]+)?'; const linkCapture = (forbidden: string) => `((?!https?://|@site/)[^${forbidden}#?]+)`; - const linkURLPattern = `(?:${linkCapture( + const linkURLPattern = `(?:(?!<)${linkCapture( '()\\s', )}${linkSuffixPattern}|<${linkCapture('>')}${linkSuffixPattern}>)`; const linkPattern = new RegExp( diff --git a/packages/docusaurus-utils/src/markdownUtils.ts b/packages/docusaurus-utils/src/markdownUtils.ts index a2ca3db101e9..87aac88f09b1 100644 --- a/packages/docusaurus-utils/src/markdownUtils.ts +++ b/packages/docusaurus-utils/src/markdownUtils.ts @@ -8,6 +8,10 @@ import logger from '@docusaurus/logger'; import matter from 'gray-matter'; import {createSlugger, type Slugger, type SluggerOptions} from './slugger'; +import type { + ParseFrontMatter, + DefaultParseFrontMatter, +} from '@docusaurus/types'; // Some utilities for parsing Markdown content. These things are only used on // server-side when we infer metadata like `title` and `description` from the @@ -214,19 +218,40 @@ export function createExcerpt(fileString: string): string | undefined { * --- * ``` */ -export function parseFrontMatter(markdownFileContent: string): { +export function parseFileContentFrontMatter(fileContent: string): { /** Front matter as parsed by gray-matter. */ frontMatter: {[key: string]: unknown}; /** The remaining content, trimmed. */ content: string; } { - const {data, content} = matter(markdownFileContent); + // TODO Docusaurus v4: replace gray-matter by a better lib + // gray-matter is unmaintained, not flexible, and the code doesn't look good + const {data, content} = matter(fileContent); + + // gray-matter has an undocumented front matter caching behavior + // https://github.com/jonschlinkert/gray-matter/blob/ce67a86dba419381db0dd01cc84e2d30a1d1e6a5/index.js#L39 + // Unfortunately, this becomes a problem when we mutate returned front matter + // We want to make it possible as part of the parseFrontMatter API + // So we make it safe to mutate by always providing a deep copy + const frontMatter = + // And of course structuredClone() doesn't work well with Date in Jest... + // See https://github.com/jestjs/jest/issues/2549 + // So we parse again for tests with a {} option object + // This undocumented empty option object disables gray-matter caching.. + process.env.JEST_WORKER_ID + ? matter(fileContent, {}).data + : structuredClone(data); + return { - frontMatter: data, + frontMatter, content: content.trim(), }; } +export const DEFAULT_PARSE_FRONT_MATTER: DefaultParseFrontMatter = async ( + params, +) => parseFileContentFrontMatter(params.fileContent); + function toTextContentTitle(contentTitle: string): string { return contentTitle.replace(/`(?<text>[^`]*)`/g, '$<text>'); } @@ -309,10 +334,16 @@ export function parseMarkdownContentTitle( * @throws Throws when `parseFrontMatter` throws, usually because of invalid * syntax. */ -export function parseMarkdownString( - markdownFileContent: string, - options?: ParseMarkdownContentTitleOptions, -): { +export async function parseMarkdownFile({ + filePath, + fileContent, + parseFrontMatter, + removeContentTitle, +}: { + filePath: string; + fileContent: string; + parseFrontMatter: ParseFrontMatter; +} & ParseMarkdownContentTitleOptions): Promise<{ /** @see {@link parseFrontMatter} */ frontMatter: {[key: string]: unknown}; /** @see {@link parseMarkdownContentTitle} */ @@ -324,14 +355,18 @@ export function parseMarkdownString( * the `removeContentTitle` option. */ content: string; -} { +}> { try { const {frontMatter, content: contentWithoutFrontMatter} = - parseFrontMatter(markdownFileContent); + await parseFrontMatter({ + filePath, + fileContent, + defaultParseFrontMatter: DEFAULT_PARSE_FRONT_MATTER, + }); const {content, contentTitle} = parseMarkdownContentTitle( contentWithoutFrontMatter, - options, + {removeContentTitle}, ); const excerpt = createExcerpt(content); diff --git a/packages/docusaurus-utils/src/urlUtils.ts b/packages/docusaurus-utils/src/urlUtils.ts index bb901a291d06..8a7af4aa4b6d 100644 --- a/packages/docusaurus-utils/src/urlUtils.ts +++ b/packages/docusaurus-utils/src/urlUtils.ts @@ -165,14 +165,73 @@ export function isValidPathname(str: string): boolean { } } +export type URLPath = {pathname: string; search?: string; hash?: string}; + +// Let's name the concept of (pathname + search + hash) as URLPath +// See also https://twitter.com/kettanaito/status/1741768992866308120 +// Note: this function also resolves relative pathnames while parsing! +export function parseURLPath(urlPath: string, fromPath?: string): URLPath { + function parseURL(url: string, base?: string | URL): URL { + try { + // A possible alternative? https://github.com/unjs/ufo#url + return new URL(url, base ?? 'https://example.com'); + } catch (e) { + throw new Error( + `Can't parse URL ${url}${base ? ` with base ${base}` : ''}`, + {cause: e}, + ); + } + } + + const base = fromPath ? parseURL(fromPath) : undefined; + const url = parseURL(urlPath, base); + + const {pathname} = url; + + // Fixes annoying url.search behavior + // "" => undefined + // "?" => "" + // "?param => "param" + const search = url.search + ? url.search.slice(1) + : urlPath.includes('?') + ? '' + : undefined; + + // Fixes annoying url.hash behavior + // "" => undefined + // "#" => "" + // "?param => "param" + const hash = url.hash + ? url.hash.slice(1) + : urlPath.includes('#') + ? '' + : undefined; + + return { + pathname, + search, + hash, + }; +} + +export function serializeURLPath(urlPath: URLPath): string { + const search = urlPath.search === undefined ? '' : `?${urlPath.search}`; + const hash = urlPath.hash === undefined ? '' : `#${urlPath.hash}`; + return `${urlPath.pathname}${search}${hash}`; +} + /** * Resolve pathnames and fail-fast if resolution fails. Uses standard URL * semantics (provided by `resolve-pathname` which is used internally by React * router) */ export function resolvePathname(to: string, from?: string): string { + // TODO do we really need resolve-pathname lib anymore? + // possible alternative: decodeURI(parseURLPath(to, from).pathname); return resolvePathnameUnsafe(to, from); } + /** Appends a leading slash to `str`, if one doesn't exist. */ export function addLeadingSlash(str: string): string { return addPrefix(str, '/'); diff --git a/packages/docusaurus/bin/docusaurus.mjs b/packages/docusaurus/bin/docusaurus.mjs index a2738c3866b6..b65915bcd6bd 100755 --- a/packages/docusaurus/bin/docusaurus.mjs +++ b/packages/docusaurus/bin/docusaurus.mjs @@ -218,6 +218,9 @@ cli.arguments('<command>').action((cmd) => { logger.error` Unknown command name=${cmd}.`; }); +// === The above is the commander configuration === +// They don't start any code execution yet until cli.parse() is called below + /** * @param {string | undefined} command */ @@ -237,12 +240,29 @@ function isInternalCommand(command) { ); } -if (!isInternalCommand(process.argv.slice(2)[0])) { - await externalCommand(cli); -} +// process.argv always looks like this: +// [ +// '/path/to/node', +// '/path/to/docusaurus.mjs', +// '<subcommand>', +// ...subcommandArgs +// ] -if (!process.argv.slice(2).length) { +// There is no subcommand +// TODO: can we use commander to handle this case? +if (process.argv.length < 3 || process.argv[2]?.startsWith('--')) { cli.outputHelp(); + process.exit(1); +} + +// There is an unrecognized subcommand +// Let plugins extend the CLI before parsing +if (!isInternalCommand(process.argv[2])) { + // TODO: in this step, we must assume default site structure because there's + // no way to know the siteDir/config yet. Maybe the root cli should be + // responsible for parsing these arguments? + // https://github.com/facebook/docusaurus/issues/8903 + await externalCommand(cli); } cli.parse(process.argv); diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index 503faa340056..1edbc79b9e25 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -1,7 +1,7 @@ { "name": "@docusaurus/core", "description": "Easy to Maintain Open Source Documentation Websites", - "version": "3.0.1", + "version": "3.1.0", "license": "MIT", "publishConfig": { "access": "public" @@ -43,13 +43,13 @@ "@babel/runtime": "^7.22.6", "@babel/runtime-corejs3": "^7.22.6", "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", + "@docusaurus/cssnano-preset": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/mdx-loader": "3.1.0", "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", + "@docusaurus/utils-validation": "3.1.0", "@slorber/static-site-generator-webpack-plugin": "^4.0.7", "@svgr/webpack": "^6.5.1", "autoprefixer": "^10.4.14", @@ -104,8 +104,8 @@ "webpackbar": "^5.0.2" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/types": "3.0.1", + "@docusaurus/module-type-aliases": "3.1.0", + "@docusaurus/types": "3.1.0", "@types/detect-port": "^1.3.3", "@types/react-dom": "^18.2.7", "@types/react-router-config": "^5.0.7", diff --git a/packages/docusaurus/src/client/BrokenLinksContext.tsx b/packages/docusaurus/src/client/BrokenLinksContext.tsx new file mode 100644 index 000000000000..e04e8ab14731 --- /dev/null +++ b/packages/docusaurus/src/client/BrokenLinksContext.tsx @@ -0,0 +1,51 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, {type ReactNode, useContext} from 'react'; +import type {BrokenLinks} from '@docusaurus/useBrokenLinks'; + +export type StatefulBrokenLinks = BrokenLinks & { + getCollectedLinks: () => string[]; + getCollectedAnchors: () => string[]; +}; + +export const createStatefulBrokenLinks = (): StatefulBrokenLinks => { + // Set to dedup, as it's not useful to collect multiple times the same value + const allAnchors = new Set<string>(); + const allLinks = new Set<string>(); + return { + collectAnchor: (anchor: string): void => { + allAnchors.add(anchor); + }, + collectLink: (link: string): void => { + allLinks.add(link); + }, + getCollectedAnchors: (): string[] => [...allAnchors], + getCollectedLinks: (): string[] => [...allLinks], + }; +}; + +const Context = React.createContext<BrokenLinks>({ + collectAnchor: () => { + // No-op for client + }, + collectLink: () => { + // No-op for client + }, +}); + +export const useBrokenLinksContext = (): BrokenLinks => useContext(Context); + +export function BrokenLinksProvider({ + children, + brokenLinks, +}: { + children: ReactNode; + brokenLinks: BrokenLinks; +}): JSX.Element { + return <Context.Provider value={brokenLinks}>{children}</Context.Provider>; +} diff --git a/packages/docusaurus/src/client/LinksCollector.tsx b/packages/docusaurus/src/client/LinksCollector.tsx deleted file mode 100644 index d0fb33b9ec03..000000000000 --- a/packages/docusaurus/src/client/LinksCollector.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import React, {type ReactNode, useContext} from 'react'; - -type LinksCollector = { - collectLink: (link: string) => void; -}; - -type StatefulLinksCollector = LinksCollector & { - getCollectedLinks: () => string[]; -}; - -export const createStatefulLinksCollector = (): StatefulLinksCollector => { - // Set to dedup, as it's not useful to collect multiple times the same link - const allLinks = new Set<string>(); - return { - collectLink: (link: string): void => { - allLinks.add(link); - }, - getCollectedLinks: (): string[] => [...allLinks], - }; -}; - -const Context = React.createContext<LinksCollector>({ - collectLink: () => { - // No-op for client. We only use the broken links checker server-side. - }, -}); - -export const useLinksCollector = (): LinksCollector => useContext(Context); - -export function LinksCollectorProvider({ - children, - linksCollector, -}: { - children: ReactNode; - linksCollector: LinksCollector; -}): JSX.Element { - return <Context.Provider value={linksCollector}>{children}</Context.Provider>; -} diff --git a/packages/docusaurus/src/client/exports/Link.tsx b/packages/docusaurus/src/client/exports/Link.tsx index 4a7453dfef8f..8b886c8e7073 100644 --- a/packages/docusaurus/src/client/exports/Link.tsx +++ b/packages/docusaurus/src/client/exports/Link.tsx @@ -16,7 +16,7 @@ import {applyTrailingSlash} from '@docusaurus/utils-common'; import useDocusaurusContext from './useDocusaurusContext'; import isInternalUrl from './isInternalUrl'; import ExecutionEnvironment from './ExecutionEnvironment'; -import {useLinksCollector} from '../LinksCollector'; +import useBrokenLinks from './useBrokenLinks'; import {useBaseUrlUtils} from './useBaseUrl'; import type {Props} from '@docusaurus/Link'; @@ -44,7 +44,7 @@ function Link( siteConfig: {trailingSlash, baseUrl}, } = useDocusaurusContext(); const {withBaseUrl} = useBaseUrlUtils(); - const linksCollector = useLinksCollector(); + const brokenLinks = useBrokenLinks(); const innerRef = useRef<HTMLAnchorElement | null>(null); useImperativeHandle(forwardedRef, () => innerRef.current!); @@ -144,7 +144,7 @@ function Link( const isRegularHtmlLink = !targetLink || !isInternal || isAnchorLink; if (!isRegularHtmlLink && !noBrokenLinkCheck) { - linksCollector.collectLink(targetLink!); + brokenLinks.collectLink(targetLink!); } return isRegularHtmlLink ? ( diff --git a/packages/docusaurus/src/client/exports/useBrokenLinks.ts b/packages/docusaurus/src/client/exports/useBrokenLinks.ts new file mode 100644 index 000000000000..979aa399cdb8 --- /dev/null +++ b/packages/docusaurus/src/client/exports/useBrokenLinks.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {useBrokenLinksContext} from '../BrokenLinksContext'; +import type {BrokenLinks} from '@docusaurus/useBrokenLinks'; + +export default function useBrokenLinks(): BrokenLinks { + return useBrokenLinksContext(); +} diff --git a/packages/docusaurus/src/client/serverEntry.tsx b/packages/docusaurus/src/client/serverEntry.tsx index 2d67558926e7..c01c4779e904 100644 --- a/packages/docusaurus/src/client/serverEntry.tsx +++ b/packages/docusaurus/src/client/serverEntry.tsx @@ -20,9 +20,9 @@ import {renderStaticApp} from './serverRenderer'; import preload from './preload'; import App from './App'; import { - createStatefulLinksCollector, - LinksCollectorProvider, -} from './LinksCollector'; + createStatefulBrokenLinks, + BrokenLinksProvider, +} from './BrokenLinksContext'; import type {Locals} from '@slorber/static-site-generator-webpack-plugin'; const getCompiledSSRTemplate = _.memoize((template: string) => @@ -96,23 +96,27 @@ async function doRender(locals: Locals & {path: string}) { const routerContext = {}; const helmetContext = {}; - const linksCollector = createStatefulLinksCollector(); + const statefulBrokenLinks = createStatefulBrokenLinks(); const app = ( // @ts-expect-error: we are migrating away from react-loadable anyways <Loadable.Capture report={(moduleName) => modules.add(moduleName)}> <HelmetProvider context={helmetContext}> <StaticRouter location={location} context={routerContext}> - <LinksCollectorProvider linksCollector={linksCollector}> + <BrokenLinksProvider brokenLinks={statefulBrokenLinks}> <App /> - </LinksCollectorProvider> + </BrokenLinksProvider> </StaticRouter> </HelmetProvider> </Loadable.Capture> ); const appHtml = await renderStaticApp(app); - onLinksCollected(location, linksCollector.getCollectedLinks()); + onLinksCollected({ + staticPagePath: location, + anchors: statefulBrokenLinks.getCollectedAnchors(), + links: statefulBrokenLinks.getCollectedLinks(), + }); const {helmet} = helmetContext as FilledContext; const htmlAttributes = helmet.htmlAttributes.toString(); diff --git a/packages/docusaurus/src/commands/build.ts b/packages/docusaurus/src/commands/build.ts index 3b20912150ec..c0a38164092a 100644 --- a/packages/docusaurus/src/commands/build.ts +++ b/packages/docusaurus/src/commands/build.ts @@ -152,8 +152,8 @@ async function buildLocale({ generatedFilesDir, plugins, siteConfig: { - baseUrl, onBrokenLinks, + onBrokenAnchors, staticDirectories: staticDirectoriesOption, }, routes, @@ -180,13 +180,15 @@ async function buildLocale({ }, ); - const allCollectedLinks: {[location: string]: string[]} = {}; + const collectedLinks: { + [pathname: string]: {links: string[]; anchors: string[]}; + } = {}; const headTags: {[location: string]: HelmetServerState} = {}; let serverConfig: Configuration = await createServerConfig({ props, - onLinksCollected: (staticPagePath, links) => { - allCollectedLinks[staticPagePath] = links; + onLinksCollected: ({staticPagePath, links, anchors}) => { + collectedLinks[staticPagePath] = {links, anchors}; }, onHeadTagsCollected: (staticPagePath, tags) => { headTags[staticPagePath] = tags; @@ -288,11 +290,10 @@ async function buildLocale({ ); await handleBrokenLinks({ - allCollectedLinks, + collectedLinks, routes, onBrokenLinks, - outDir, - baseUrl, + onBrokenAnchors, }); logger.success`Generated static files in path=${path.relative( diff --git a/packages/docusaurus/src/deps.d.ts b/packages/docusaurus/src/deps.d.ts index 49bca18d06f9..199f39900970 100644 --- a/packages/docusaurus/src/deps.d.ts +++ b/packages/docusaurus/src/deps.d.ts @@ -42,7 +42,11 @@ declare module '@slorber/static-site-generator-webpack-plugin' { headTags: string; preBodyTags: string; postBodyTags: string; - onLinksCollected: (staticPagePath: string, links: string[]) => void; + onLinksCollected: (params: { + staticPagePath: string; + links: string[]; + anchors: string[]; + }) => void; onHeadTagsCollected: ( staticPagePath: string, tags: HelmetServerState, diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/brokenLinks.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/brokenLinks.test.ts.snap deleted file mode 100644 index 8aa3a3e837dc..000000000000 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/brokenLinks.test.ts.snap +++ /dev/null @@ -1,86 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`handleBrokenLinks reports all broken links 1`] = ` -"Docusaurus found broken links! - -Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. -Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. - -Exhaustive list of all broken links found: - -- On source page path = /docs/good doc with space: - -> linking to ./some%20other%20non-existent%20doc1 (resolved as: /docs/some%20other%20non-existent%20doc1) - -> linking to ./break%2F..%2F..%2Fout2 (resolved as: /docs/break%2F..%2F..%2Fout2) - -- On source page path = /docs/goodDoc: - -> linking to ../anotherGoodDoc#reported-because-of-bad-relative-path1 (resolved as: /anotherGoodDoc) - -> linking to ./docThatDoesNotExist2 (resolved as: /docs/docThatDoesNotExist2) - -> linking to ./badRelativeLink3 (resolved as: /docs/badRelativeLink3) - -> linking to ../badRelativeLink4 (resolved as: /badRelativeLink4) - -- On source page path = /community: - -> linking to /someNonExistentDoc1 - -> linking to /badLink2 - -> linking to ./badLink3 (resolved as: /badLink3) - -- On source page path = /page1: - -> linking to /link1 - -> linking to /emptyFolder - -- On source page path = /page2: - -> linking to /docs/link2 - -> linking to /emptyFolder/ - -> linking to /hey/link3 -" -`; - -exports[`handleBrokenLinks reports frequent broken links 1`] = ` -"Docusaurus found broken links! - -Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. -Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. - -It looks like some of the broken links we found appear in many pages of your site. -Maybe those broken links appear on all pages through your site layout? -We recommend that you check your theme configuration for such links (particularly, theme navbar and footer). -Frequent broken links are linking to: -- /frequent -- ./maybe-not - -Exhaustive list of all broken links found: - -- On source page path = /docs/good doc with space: - -> linking to ./some%20other%20non-existent%20doc1 (resolved as: /docs/some%20other%20non-existent%20doc1) - -> linking to ./break%2F..%2F..%2Fout2 (resolved as: /docs/break%2F..%2F..%2Fout2) - -> linking to /frequent - -> linking to ./maybe-not (resolved as: /docs/maybe-not) - -- On source page path = /docs/goodDoc: - -> linking to ../anotherGoodDoc#reported-because-of-bad-relative-path1 (resolved as: /anotherGoodDoc) - -> linking to ./docThatDoesNotExist2 (resolved as: /docs/docThatDoesNotExist2) - -> linking to ./badRelativeLink3 (resolved as: /docs/badRelativeLink3) - -> linking to ../badRelativeLink4 (resolved as: /badRelativeLink4) - -> linking to /frequent - -> linking to ./maybe-not (resolved as: /docs/maybe-not) - -- On source page path = /community: - -> linking to /someNonExistentDoc1 - -> linking to /badLink2 - -> linking to ./badLink3 (resolved as: /badLink3) - -> linking to /frequent - -> linking to ./maybe-not (resolved as: /maybe-not) - -- On source page path = /page1: - -> linking to /link1 - -> linking to /emptyFolder - -> linking to /frequent - -> linking to ./maybe-not (resolved as: /maybe-not) - -- On source page path = /page2: - -> linking to /docs/link2 - -> linking to /emptyFolder/ - -> linking to /hey/link3 - -> linking to /frequent - -> linking to ./maybe-not (resolved as: /maybe-not) -" -`; diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap index 2ed2b796fd01..c10c4833901e 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/config.test.ts.snap @@ -24,9 +24,12 @@ exports[`loadSiteConfig website with .cjs siteConfig 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -72,9 +75,12 @@ exports[`loadSiteConfig website with ts + js config 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -120,9 +126,12 @@ exports[`loadSiteConfig website with valid JS CJS config 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -168,9 +177,12 @@ exports[`loadSiteConfig website with valid JS ESM config 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -216,9 +228,12 @@ exports[`loadSiteConfig website with valid TypeScript CJS config 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -264,9 +279,12 @@ exports[`loadSiteConfig website with valid TypeScript ESM config 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -312,9 +330,12 @@ exports[`loadSiteConfig website with valid async config 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -362,9 +383,12 @@ exports[`loadSiteConfig website with valid async config creator function 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -412,9 +436,12 @@ exports[`loadSiteConfig website with valid config creator function 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", @@ -465,9 +492,12 @@ exports[`loadSiteConfig website with valid siteConfig 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", diff --git a/packages/docusaurus/src/server/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus/src/server/__tests__/__snapshots__/index.test.ts.snap index 45b94b869406..cba9622267ad 100644 --- a/packages/docusaurus/src/server/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus/src/server/__tests__/__snapshots__/index.test.ts.snap @@ -98,9 +98,12 @@ exports[`load loads props for site with custom i18n path 1`] = ` "headingIds": true, }, "mermaid": false, + "parseFrontMatter": [Function], "preprocessor": undefined, + "remarkRehypeOptions": undefined, }, "noIndex": false, + "onBrokenAnchors": "warn", "onBrokenLinks": "throw", "onBrokenMarkdownLinks": "warn", "onDuplicateRoutes": "warn", diff --git a/packages/docusaurus/src/server/__tests__/brokenLinks.test.ts b/packages/docusaurus/src/server/__tests__/brokenLinks.test.ts index 40e76ed45b7a..158af9165af7 100644 --- a/packages/docusaurus/src/server/__tests__/brokenLinks.test.ts +++ b/packages/docusaurus/src/server/__tests__/brokenLinks.test.ts @@ -6,190 +6,608 @@ */ import {jest} from '@jest/globals'; -import path from 'path'; -import _ from 'lodash'; import {handleBrokenLinks} from '../brokenLinks'; import type {RouteConfig} from '@docusaurus/types'; +type Params = Parameters<typeof handleBrokenLinks>[0]; + +// We don't need all the routes attributes for our tests +type SimpleRoute = {path: string; routes?: SimpleRoute[]}; + +// Conveniently apply defaults to function under test +async function testBrokenLinks(params: { + collectedLinks?: Params['collectedLinks']; + onBrokenLinks?: Params['onBrokenLinks']; + onBrokenAnchors?: Params['onBrokenAnchors']; + routes?: SimpleRoute[]; +}) { + await handleBrokenLinks({ + collectedLinks: {}, + onBrokenLinks: 'throw', + onBrokenAnchors: 'throw', + ...params, + // Unsafe but convenient for tests + routes: (params.routes ?? []) as RouteConfig[], + }); +} + describe('handleBrokenLinks', () => { - const routes: RouteConfig[] = [ - { - path: '/community', - component: '', - }, - { - path: '/docs', - component: '', + it('accepts valid link', async () => { + await testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/page2'], anchors: []}, + '/page2': {links: [], anchors: []}, + }, + }); + }); + + it('accepts valid link to uncollected page', async () => { + await testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/page2'], anchors: []}, + // /page2 is absent on purpose: it doesn't contain any link/anchor + }, + }); + }); + + it('accepts valid link to nested route', async () => { + await testBrokenLinks({ routes: [ - {path: '/docs/goodDoc', component: ''}, - {path: '/docs/anotherGoodDoc', component: ''}, - {path: '/docs/good doc with space', component: ''}, - {path: '/docs/another good doc with space', component: ''}, - {path: '/docs/weird%20but%20good', component: ''}, - ], - }, - { - path: '*', - component: '', - }, - ]; - - const link1 = '/link1'; - const link2 = '/docs/link2'; - const link3 = '/hey/link3'; - - const linkToJavadoc1 = '/javadoc'; - const linkToJavadoc2 = '/javadoc/'; - const linkToJavadoc3 = '/javadoc/index.html'; - const linkToJavadoc4 = '/javadoc/index.html#foo'; - - const linkToZipFile = '/files/file.zip'; - const linkToHtmlFile1 = '/files/hey.html'; - const linkToHtmlFile2 = '/files/hey'; - - const linkToEmptyFolder1 = '/emptyFolder'; - const linkToEmptyFolder2 = '/emptyFolder/'; - const allCollectedLinks = { - '/docs/good doc with space': [ - // Good - valid file with spaces in name - './another%20good%20doc%20with%20space', - // Good - valid file with percent-20 in its name - './weird%20but%20good', - // Bad - non-existent file with spaces in name - './some%20other%20non-existent%20doc1', - // Evil - trying to use ../../ but '/' won't get decoded - // cSpell:ignore Fout - './break%2F..%2F..%2Fout2', - ], - '/docs/goodDoc': [ - // Good links - './anotherGoodDoc#someHash', - '/docs/anotherGoodDoc?someQueryString=true#someHash', - '../docs/anotherGoodDoc?someQueryString=true', - '../docs/anotherGoodDoc#someHash', - // Bad links - '../anotherGoodDoc#reported-because-of-bad-relative-path1', - './docThatDoesNotExist2', - './badRelativeLink3', - '../badRelativeLink4', - ], - '/community': [ - // Good links - '/docs/goodDoc', - '/docs/anotherGoodDoc#someHash', - './docs/goodDoc#someHash', - './docs/anotherGoodDoc', - // Bad links - '/someNonExistentDoc1', - '/badLink2', - './badLink3', - ], - '/page1': [ - link1, - linkToHtmlFile1, - linkToJavadoc1, - linkToHtmlFile2, - linkToJavadoc3, - linkToJavadoc4, - linkToEmptyFolder1, // Not filtered! - ], - '/page2': [ - link2, - linkToEmptyFolder2, // Not filtered! - linkToJavadoc2, - link3, - linkToJavadoc3, - linkToZipFile, - ], - }; - - const outDir = path.resolve(__dirname, '__fixtures__/brokenLinks/outDir'); - - it('do not report anything for correct paths', async () => { - const consoleMock = jest - .spyOn(console, 'warn') - .mockImplementation(() => {}); - const allCollectedCorrectLinks = { - '/docs/good doc with space': [ - './another%20good%20doc%20with%20space', - './weird%20but%20good', - ], - '/docs/goodDoc': [ - './anotherGoodDoc#someHash', - '/docs/anotherGoodDoc?someQueryString=true#someHash', - '../docs/anotherGoodDoc?someQueryString=true', - '../docs/anotherGoodDoc#someHash', - ], - '/community': [ - '/docs/goodDoc', - '/docs/anotherGoodDoc#someHash', - './docs/goodDoc#someHash', - './docs/anotherGoodDoc', + {path: '/page1'}, + {path: '/nested/', routes: [{path: '/nested/page2'}]}, ], - '/page1': [ - linkToHtmlFile1, - linkToJavadoc1, - linkToHtmlFile2, - linkToJavadoc3, - linkToJavadoc4, - ], - }; - await handleBrokenLinks({ - allCollectedLinks: allCollectedCorrectLinks, - onBrokenLinks: 'warn', - routes, - baseUrl: '/', - outDir, + collectedLinks: { + '/page1': {links: ['/nested/page2'], anchors: []}, + }, }); - expect(consoleMock).toHaveBeenCalledTimes(0); }); - it('reports all broken links', async () => { + it('accepts valid relative link', async () => { + await testBrokenLinks({ + routes: [{path: '/dir/page1'}, {path: '/dir/page2'}], + collectedLinks: { + '/dir/page1': { + links: ['./page2', '../dir/page2', '/dir/page2'], + anchors: [], + }, + }, + }); + }); + + it('accepts valid link with anchor', async () => { + await testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/page2#page2anchor'], anchors: []}, + '/page2': {links: [], anchors: ['page2anchor']}, + }, + }); + }); + + it('accepts valid link with querystring + anchor', async () => { + await testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': { + links: ['/page2?age=42&theme=dark#page2anchor'], + anchors: [], + }, + '/page2': {links: [], anchors: ['page2anchor']}, + }, + }); + }); + + it('accepts valid link to self', async () => { + await testBrokenLinks({ + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: [ + '/page1', + './page1', + '', + '/page1#anchor1', + '#anchor1', + '/page1?age=42#anchor1', + '?age=42#anchor1', + ], + anchors: ['anchor1'], + }, + }, + }); + }); + + it('accepts valid link with spaces and encoding', async () => { + await testBrokenLinks({ + routes: [{path: '/page 1'}, {path: '/page 2'}], + collectedLinks: { + '/page 1': { + links: [ + '/page 1', + '/page%201', + '/page%201?age=42', + '/page 2', + '/page%202', + '/page%202?age=42', + '/page%202?age=42#page2anchor', + ], + anchors: [], + }, + '/page 2': {links: [], anchors: ['page2anchor']}, + }, + }); + }); + + it('rejects broken link', async () => { await expect(() => - handleBrokenLinks({ - allCollectedLinks, - onBrokenLinks: 'throw', - routes, - baseUrl: '/', - outDir, + testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/brokenLink'], anchors: []}, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken links! + + Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. + Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken links found: + - Broken link on source page path = /page1: + -> linking to /brokenLink + " + `); + }); + + it('rejects broken link with anchor', async () => { + await expect(() => + testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/brokenLink#anchor'], anchors: []}, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken links! + + Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. + Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken links found: + - Broken link on source page path = /page1: + -> linking to /brokenLink#anchor + " + `); + }); + + it('rejects broken link with querystring + anchor', async () => { + await expect(() => + testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/brokenLink?age=42#anchor'], anchors: []}, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken links! + + Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. + Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken links found: + - Broken link on source page path = /page1: + -> linking to /brokenLink?age=42#anchor + " + `); + }); + + it('rejects valid link with broken anchor', async () => { + await expect(() => + testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/page2#brokenAnchor'], anchors: []}, + '/page2': {links: [], anchors: []}, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to /page2#brokenAnchor + " + `); + }); + + it('rejects valid link with empty broken anchor', async () => { + await expect(() => + testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/page2#'], anchors: []}, + '/page2': {links: [], anchors: []}, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to /page2# + " + `); + }); + + it('rejects valid link with broken anchor + query-string', async () => { + await expect(() => + testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': { + links: ['/page2?age=42&theme=dark#brokenAnchor'], + anchors: [], + }, + '/page2': {links: [], anchors: []}, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to /page2?age=42&theme=dark#brokenAnchor + " + `); + }); + + it('rejects valid link with broken anchor to self', async () => { + await expect(() => + testBrokenLinks({ + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: [ + '/page1', + '', + '#goodAnchor', + '/page1#goodAnchor', + '/page1?age=42#goodAnchor', + '#badAnchor1', + '/page1#badAnchor2', + '/page1?age=42#badAnchor3', + ], + + anchors: ['goodAnchor'], + }, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to #badAnchor1 (resolved as: /page1#badAnchor1) + -> linking to /page1#badAnchor2 + -> linking to /page1?age=42#badAnchor3 + " + `); + }); + + it('rejects valid link with broken anchor to uncollected page', async () => { + await expect(() => + testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': {links: ['/page2#brokenAnchor'], anchors: []}, + // /page2 is absent on purpose: it doesn't contain any link/anchor + }, }), - ).rejects.toThrowErrorMatchingSnapshot(); + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to /page2#brokenAnchor + " + `); + }); + + it('rejects broken anchor with query-string to uncollected page', async () => { + await expect(() => + testBrokenLinks({ + routes: [{path: '/page1'}, {path: '/page2'}], + collectedLinks: { + '/page1': { + links: ['/page2?age=42&theme=dark#brokenAnchor'], + anchors: [], + }, + // /page2 is absent on purpose: it doesn't contain any link/anchor + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to /page2?age=42&theme=dark#brokenAnchor + " + `); }); - it('no-op for ignore', async () => { - // In any case, _.mapValues will always be called, unless handleBrokenLinks - // has already bailed - const lodashMock = jest.spyOn(_, 'mapValues'); - await handleBrokenLinks({ - allCollectedLinks, + it('can ignore broken links', async () => { + await testBrokenLinks({ onBrokenLinks: 'ignore', - routes, - baseUrl: '/', - outDir, + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: ['/page2'], + anchors: [], + }, + }, }); - expect(lodashMock).toHaveBeenCalledTimes(0); - lodashMock.mockRestore(); - }); - - it('reports frequent broken links', async () => { - Object.values(allCollectedLinks).forEach((links) => - links.push( - '/frequent', - // This is in the gray area of what should be reported. Relative paths - // may be resolved to different slugs on different locations. But if - // this comes from a layout link, it should be reported anyways - './maybe-not', - ), + }); + + it('can ignore broken anchors', async () => { + await testBrokenLinks({ + onBrokenAnchors: 'ignore', + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: ['/page1#brokenAnchor'], + anchors: [], + }, + }, + }); + }); + + it('can ignore broken anchors but report broken link', async () => { + await expect(() => + testBrokenLinks({ + onBrokenAnchors: 'ignore', + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: ['/page1#brokenAnchor', '/page2'], + anchors: [], + }, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken links! + + Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. + Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken links found: + - Broken link on source page path = /page1: + -> linking to /page2 + " + `); + }); + + it('can ignore broken link but report broken anchors', async () => { + await expect(() => + testBrokenLinks({ + onBrokenLinks: 'ignore', + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: [ + '/page2', + '/page1#brokenAnchor1', + '/page1#brokenAnchor2', + '#brokenAnchor3', + ], + + anchors: [], + }, + }, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to /page1#brokenAnchor1 + -> linking to /page1#brokenAnchor2 + -> linking to #brokenAnchor3 (resolved as: /page1#brokenAnchor3) + " + `); + }); + + it('can warn for broken links', async () => { + const warnMock = jest.spyOn(console, 'warn'); + + await testBrokenLinks({ + onBrokenLinks: 'warn', + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: ['/page2'], + anchors: [], + }, + }, + }); + + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Docusaurus found broken links! + + Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. + Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken links found: + - Broken link on source page path = /page1: + -> linking to /page2 + ", + ], + ] + `); + warnMock.mockRestore(); + }); + + it('can warn for broken anchors', async () => { + const warnMock = jest.spyOn(console, 'warn'); + + await testBrokenLinks({ + onBrokenAnchors: 'warn', + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: ['/page1#brokenAnchor'], + anchors: [], + }, + }, + }); + + expect(warnMock).toHaveBeenCalledTimes(1); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to /page1#brokenAnchor + ", + ], + ] + `); + warnMock.mockRestore(); + }); + + it('can warn for both broken links and anchors', async () => { + const warnMock = jest.spyOn(console, 'warn'); + + await testBrokenLinks({ + onBrokenLinks: 'warn', + onBrokenAnchors: 'warn', + routes: [{path: '/page1'}], + collectedLinks: { + '/page1': { + links: ['/page1#brokenAnchor', '/page2'], + anchors: [], + }, + }, + }); + + expect(warnMock).toHaveBeenCalledTimes(2); + expect(warnMock.mock.calls).toMatchInlineSnapshot(` + [ + [ + "[WARNING] Docusaurus found broken links! + + Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. + Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken links found: + - Broken link on source page path = /page1: + -> linking to /page2 + ", + ], + [ + "[WARNING] Docusaurus found broken anchors! + + Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. + Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + + Exhaustive list of all broken anchors found: + - Broken anchor on source page path = /page1: + -> linking to /page1#brokenAnchor + ", + ], + ] + `); + warnMock.mockRestore(); + }); + + it('reports frequent broken links differently', async () => { + const pagePaths = [ + '/page1', + '/page2', + '/dir/page3', + '/dir/page4', + '/dir/page5', + ]; + + const routes: SimpleRoute[] = pagePaths.map((pagePath) => ({ + path: pagePath, + })); + + const collectedLinks: Params['collectedLinks'] = Object.fromEntries( + pagePaths.map((pagePath) => [ + pagePath, + { + links: ['/frequentBrokenLink', './relativeFrequentBrokenLink'], + anchors: [], + }, + ]), ); await expect(() => - handleBrokenLinks({ - allCollectedLinks, - onBrokenLinks: 'throw', + testBrokenLinks({ routes, - baseUrl: '/', - outDir, + collectedLinks, }), - ).rejects.toThrowErrorMatchingSnapshot(); + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Docusaurus found broken links! + + Please check the pages of your site in the list below, and make sure you don't reference any path that does not exist. + Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass. + + It looks like some of the broken links we found appear in many pages of your site. + Maybe those broken links appear on all pages through your site layout? + We recommend that you check your theme configuration for such links (particularly, theme navbar and footer). + Frequent broken links are linking to: + - /frequentBrokenLink + - ./relativeFrequentBrokenLink + + Exhaustive list of all broken links found: + - Broken link on source page path = /page1: + -> linking to /frequentBrokenLink + -> linking to ./relativeFrequentBrokenLink (resolved as: /relativeFrequentBrokenLink) + - Broken link on source page path = /page2: + -> linking to /frequentBrokenLink + -> linking to ./relativeFrequentBrokenLink (resolved as: /relativeFrequentBrokenLink) + - Broken link on source page path = /dir/page3: + -> linking to /frequentBrokenLink + -> linking to ./relativeFrequentBrokenLink (resolved as: /dir/relativeFrequentBrokenLink) + - Broken link on source page path = /dir/page4: + -> linking to /frequentBrokenLink + -> linking to ./relativeFrequentBrokenLink (resolved as: /dir/relativeFrequentBrokenLink) + - Broken link on source page path = /dir/page5: + -> linking to /frequentBrokenLink + -> linking to ./relativeFrequentBrokenLink (resolved as: /dir/relativeFrequentBrokenLink) + " + `); }); }); diff --git a/packages/docusaurus/src/server/__tests__/configValidation.test.ts b/packages/docusaurus/src/server/__tests__/configValidation.test.ts index b3bc7b2611ef..ea76af81408b 100644 --- a/packages/docusaurus/src/server/__tests__/configValidation.test.ts +++ b/packages/docusaurus/src/server/__tests__/configValidation.test.ts @@ -61,12 +61,17 @@ describe('normalizeConfig', () => { markdown: { format: 'md', mermaid: true, + parseFrontMatter: async (params) => + params.defaultParseFrontMatter(params), preprocessor: ({fileContent}) => fileContent, mdx1Compat: { comments: true, admonitions: false, headingIds: true, }, + remarkRehypeOptions: { + footnoteLabel: 'Pied de page', + }, }, }; const normalizedConfig = normalizeConfig(userConfig); @@ -504,12 +509,19 @@ describe('markdown', () => { const markdown: DocusaurusConfig['markdown'] = { format: 'md', mermaid: true, + parseFrontMatter: async (params) => + params.defaultParseFrontMatter(params), preprocessor: ({fileContent}) => fileContent, mdx1Compat: { comments: false, admonitions: true, headingIds: false, }, + remarkRehypeOptions: { + footnoteLabel: 'Notes de bas de page', + // @ts-expect-error: we don't validate it on purpose + anyKey: 'heck we accept it on purpose', + }, }; expect( normalizeConfig({ diff --git a/packages/docusaurus/src/server/brokenLinks.ts b/packages/docusaurus/src/server/brokenLinks.ts index f443a4659cf9..ccbaadcd3ffb 100644 --- a/packages/docusaurus/src/server/brokenLinks.ts +++ b/packages/docusaurus/src/server/brokenLinks.ts @@ -5,45 +5,42 @@ * LICENSE file in the root directory of this source tree. */ -import fs from 'fs-extra'; -import path from 'path'; import _ from 'lodash'; import logger from '@docusaurus/logger'; -import combinePromises from 'combine-promises'; import {matchRoutes} from 'react-router-config'; -import {removePrefix, removeSuffix, resolvePathname} from '@docusaurus/utils'; +import {parseURLPath, serializeURLPath, type URLPath} from '@docusaurus/utils'; import {getAllFinalRoutes} from './utils'; import type {RouteConfig, ReportingSeverity} from '@docusaurus/types'; type BrokenLink = { link: string; resolvedLink: string; + anchor: boolean; }; -// matchRoutes does not support qs/anchors, so we remove it! -function onlyPathname(link: string) { - return link.split('#')[0]!.split('?')[0]!; -} +type BrokenLinksMap = {[pathname: string]: BrokenLink[]}; + +// The linking data that has been collected on Docusaurus pages during SSG +// {rendered page pathname => links and anchors collected on that page} +type CollectedLinks = { + [pathname: string]: {links: string[]; anchors: string[]}; +}; -function getPageBrokenLinks({ +function getBrokenLinksForPage({ + collectedLinks, pagePath, pageLinks, routes, }: { + collectedLinks: CollectedLinks; pagePath: string; pageLinks: string[]; + pageAnchors: string[]; routes: RouteConfig[]; }): BrokenLink[] { - // ReactRouter is able to support links like ./../somePath but `matchRoutes` - // does not do this resolution internally. We must resolve the links before - // using `matchRoutes`. `resolvePathname` is used internally by React Router - function resolveLink(link: string) { - const resolvedLink = resolvePathname(onlyPathname(link), pagePath); - return {link, resolvedLink}; - } - - function isBrokenLink(link: string) { - const matchedRoutes = [link, decodeURI(link)] + // console.log('routes:', routes); + function isPathBrokenLink(linkPath: URLPath) { + const matchedRoutes = [linkPath.pathname, decodeURI(linkPath.pathname)] // @ts-expect-error: React router types RouteConfig with an actual React // component, but we load route components with string paths. // We don't actually access component here, so it's fine. @@ -52,7 +49,52 @@ function getPageBrokenLinks({ return matchedRoutes.length === 0; } - return pageLinks.map(resolveLink).filter((l) => isBrokenLink(l.resolvedLink)); + function isAnchorBrokenLink(linkPath: URLPath) { + const {pathname, hash} = linkPath; + + // Link has no hash: it can't be a broken anchor link + if (hash === undefined) { + return false; + } + + const targetPage = + collectedLinks[pathname] || collectedLinks[decodeURI(pathname)]; + + // link with anchor to a page that does not exist (or did not collect any + // link/anchor) is considered as a broken anchor + if (!targetPage) { + return true; + } + + // it's a broken anchor if the target page exists + // but the anchor does not exist on that page + return !targetPage.anchors.includes(hash); + } + + const brokenLinks = pageLinks.flatMap((link) => { + const linkPath = parseURLPath(link, pagePath); + if (isPathBrokenLink(linkPath)) { + return [ + { + link, + resolvedLink: serializeURLPath(linkPath), + anchor: false, + }, + ]; + } + if (isAnchorBrokenLink(linkPath)) { + return [ + { + link, + resolvedLink: serializeURLPath(linkPath), + anchor: true, + }, + ]; + } + return []; + }); + + return brokenLinks; } /** @@ -66,45 +108,76 @@ function filterIntermediateRoutes(routesInput: RouteConfig[]): RouteConfig[] { return getAllFinalRoutes(routesWithout404); } -function getAllBrokenLinks({ - allCollectedLinks, +function getBrokenLinks({ + collectedLinks, routes, }: { - allCollectedLinks: {[location: string]: string[]}; + collectedLinks: CollectedLinks; routes: RouteConfig[]; -}): {[location: string]: BrokenLink[]} { +}): BrokenLinksMap { const filteredRoutes = filterIntermediateRoutes(routes); - const allBrokenLinks = _.mapValues(allCollectedLinks, (pageLinks, pagePath) => - getPageBrokenLinks({pageLinks, pagePath, routes: filteredRoutes}), + return _.mapValues(collectedLinks, (pageCollectedData, pagePath) => + getBrokenLinksForPage({ + collectedLinks, + pageLinks: pageCollectedData.links, + pageAnchors: pageCollectedData.anchors, + pagePath, + routes: filteredRoutes, + }), ); +} + +function brokenLinkMessage(brokenLink: BrokenLink): string { + const showResolvedLink = brokenLink.link !== brokenLink.resolvedLink; + return `${brokenLink.link}${ + showResolvedLink ? ` (resolved as: ${brokenLink.resolvedLink})` : '' + }`; +} + +function createBrokenLinksMessage( + pagePath: string, + brokenLinks: BrokenLink[], +): string { + const type = brokenLinks[0]?.anchor === true ? 'anchor' : 'link'; - return _.pickBy(allBrokenLinks, (brokenLinks) => brokenLinks.length > 0); + const anchorMessage = + brokenLinks.length > 0 + ? `- Broken ${type} on source page path = ${pagePath}: + -> linking to ${brokenLinks + .map(brokenLinkMessage) + .join('\n -> linking to ')}` + : ''; + + return `${anchorMessage}`; } -function getBrokenLinksErrorMessage(allBrokenLinks: { - [location: string]: BrokenLink[]; -}): string | undefined { - if (Object.keys(allBrokenLinks).length === 0) { +function createBrokenAnchorsMessage( + brokenAnchors: BrokenLinksMap, +): string | undefined { + if (Object.keys(brokenAnchors).length === 0) { return undefined; } - function brokenLinkMessage(brokenLink: BrokenLink): string { - const showResolvedLink = brokenLink.link !== brokenLink.resolvedLink; - return `${brokenLink.link}${ - showResolvedLink ? ` (resolved as: ${brokenLink.resolvedLink})` : '' - }`; - } + return `Docusaurus found broken anchors! - function pageBrokenLinksMessage( - pagePath: string, - brokenLinks: BrokenLink[], - ): string { - return ` -- On source page path = ${pagePath}: - -> linking to ${brokenLinks - .map(brokenLinkMessage) - .join('\n -> linking to ')}`; +Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist. +Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass. + +Exhaustive list of all broken anchors found: +${Object.entries(brokenAnchors) + .map(([pagePath, brokenLinks]) => + createBrokenLinksMessage(pagePath, brokenLinks), + ) + .join('\n')} +`; +} + +function createBrokenPathsMessage( + brokenPathsMap: BrokenLinksMap, +): string | undefined { + if (Object.keys(brokenPathsMap).length === 0) { + return undefined; } /** @@ -113,7 +186,7 @@ function getBrokenLinksErrorMessage(allBrokenLinks: { * this out. See https://github.com/facebook/docusaurus/issues/3567#issuecomment-706973805 */ function getLayoutBrokenLinksHelpMessage() { - const flatList = Object.entries(allBrokenLinks).flatMap( + const flatList = Object.entries(brokenPathsMap).flatMap( ([pagePage, brokenLinks]) => brokenLinks.map((brokenLink) => ({pagePage, brokenLink})), ); @@ -146,102 +219,78 @@ Please check the pages of your site in the list below, and make sure you don't r Note: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration, and let the build pass.${getLayoutBrokenLinksHelpMessage()} Exhaustive list of all broken links found: -${Object.entries(allBrokenLinks) - .map(([pagePath, brokenLinks]) => - pageBrokenLinksMessage(pagePath, brokenLinks), +${Object.entries(brokenPathsMap) + .map(([pagePath, brokenPaths]) => + createBrokenLinksMessage(pagePath, brokenPaths), ) .join('\n')} `; } -async function isExistingFile(filePath: string) { - try { - return (await fs.stat(filePath)).isFile(); - } catch { - return false; - } -} +function splitBrokenLinks(brokenLinks: BrokenLinksMap): { + brokenPaths: BrokenLinksMap; + brokenAnchors: BrokenLinksMap; +} { + const brokenPaths: BrokenLinksMap = {}; + const brokenAnchors: BrokenLinksMap = {}; -// If a file actually exist on the file system, we know the link is valid -// even if docusaurus does not know about this file, so we don't report it -async function filterExistingFileLinks({ - baseUrl, - outDir, - allCollectedLinks, -}: { - baseUrl: string; - outDir: string; - allCollectedLinks: {[location: string]: string[]}; -}): Promise<{[location: string]: string[]}> { - async function linkFileExists(link: string) { - // /baseUrl/javadoc/ -> /outDir/javadoc - const baseFilePath = onlyPathname( - removeSuffix(`${outDir}/${removePrefix(link, baseUrl)}`, '/'), + Object.entries(brokenLinks).forEach(([pathname, pageBrokenLinks]) => { + const [anchorBrokenLinks, pathBrokenLinks] = _.partition( + pageBrokenLinks, + (link) => link.anchor, ); - // -> /outDir/javadoc - // -> /outDir/javadoc.html - // -> /outDir/javadoc/index.html - const filePathsToTry: string[] = [baseFilePath]; - if (!path.extname(baseFilePath)) { - filePathsToTry.push( - `${baseFilePath}.html`, - path.join(baseFilePath, 'index.html'), - ); + if (pathBrokenLinks.length > 0) { + brokenPaths[pathname] = pathBrokenLinks; } - - for (const file of filePathsToTry) { - if (await isExistingFile(file)) { - return true; - } + if (anchorBrokenLinks.length > 0) { + brokenAnchors[pathname] = anchorBrokenLinks; } - return false; + }); + + return {brokenPaths, brokenAnchors}; +} + +function reportBrokenLinks({ + brokenLinks, + onBrokenLinks, + onBrokenAnchors, +}: { + brokenLinks: BrokenLinksMap; + onBrokenLinks: ReportingSeverity; + onBrokenAnchors: ReportingSeverity; +}) { + // We need to split the broken links reporting in 2 for better granularity + // This is because we need to report broken path/anchors independently + // For v3.x retro-compatibility, we can't throw by default for broken anchors + // TODO Docusaurus v4: make onBrokenAnchors throw by default? + const {brokenPaths, brokenAnchors} = splitBrokenLinks(brokenLinks); + + const pathErrorMessage = createBrokenPathsMessage(brokenPaths); + if (pathErrorMessage) { + logger.report(onBrokenLinks)(pathErrorMessage); } - return combinePromises( - _.mapValues(allCollectedLinks, async (links) => - ( - await Promise.all( - links.map(async (link) => ((await linkFileExists(link)) ? '' : link)), - ) - ).filter(Boolean), - ), - ); + const anchorErrorMessage = createBrokenAnchorsMessage(brokenAnchors); + if (anchorErrorMessage) { + logger.report(onBrokenAnchors)(anchorErrorMessage); + } } export async function handleBrokenLinks({ - allCollectedLinks, + collectedLinks, onBrokenLinks, + onBrokenAnchors, routes, - baseUrl, - outDir, }: { - allCollectedLinks: {[location: string]: string[]}; + collectedLinks: CollectedLinks; onBrokenLinks: ReportingSeverity; + onBrokenAnchors: ReportingSeverity; routes: RouteConfig[]; - baseUrl: string; - outDir: string; }): Promise<void> { - if (onBrokenLinks === 'ignore') { + if (onBrokenLinks === 'ignore' && onBrokenAnchors === 'ignore') { return; } - - // If we link to a file like /myFile.zip, and the file actually exist for the - // file system. It is not a broken link, it may simply be a link to an - // existing static file... - const allCollectedLinksFiltered = await filterExistingFileLinks({ - allCollectedLinks, - baseUrl, - outDir, - }); - - const allBrokenLinks = getAllBrokenLinks({ - allCollectedLinks: allCollectedLinksFiltered, - routes, - }); - - const errorMessage = getBrokenLinksErrorMessage(allBrokenLinks); - if (errorMessage) { - logger.report(onBrokenLinks)(errorMessage); - } + const brokenLinks = getBrokenLinks({routes, collectedLinks}); + reportBrokenLinks({brokenLinks, onBrokenLinks, onBrokenAnchors}); } diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index 3f9de2ce6807..13f554512c0a 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -6,6 +6,7 @@ */ import { + DEFAULT_PARSE_FRONT_MATTER, DEFAULT_STATIC_DIR_NAME, DEFAULT_I18N_DIR_NAME, addLeadingSlash, @@ -13,7 +14,11 @@ import { removeTrailingSlash, } from '@docusaurus/utils'; import {Joi, printWarning} from '@docusaurus/utils-validation'; -import type {DocusaurusConfig, I18nConfig} from '@docusaurus/types'; +import type { + DocusaurusConfig, + I18nConfig, + MarkdownConfig, +} from '@docusaurus/types'; const DEFAULT_I18N_LOCALE = 'en'; @@ -24,10 +29,24 @@ export const DEFAULT_I18N_CONFIG: I18nConfig = { localeConfigs: {}, }; +export const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = { + format: 'mdx', // TODO change this to "detect" in Docusaurus v4? + mermaid: false, + preprocessor: undefined, + parseFrontMatter: DEFAULT_PARSE_FRONT_MATTER, + mdx1Compat: { + comments: true, + admonitions: true, + headingIds: true, + }, + remarkRehypeOptions: undefined, +}; + export const DEFAULT_CONFIG: Pick< DocusaurusConfig, | 'i18n' | 'onBrokenLinks' + | 'onBrokenAnchors' | 'onBrokenMarkdownLinks' | 'onDuplicateRoutes' | 'plugins' @@ -48,6 +67,7 @@ export const DEFAULT_CONFIG: Pick< > = { i18n: DEFAULT_I18N_CONFIG, onBrokenLinks: 'throw', + onBrokenAnchors: 'warn', // TODO Docusaurus v4: change to throw onBrokenMarkdownLinks: 'warn', onDuplicateRoutes: 'warn', plugins: [], @@ -64,37 +84,26 @@ export const DEFAULT_CONFIG: Pick< tagline: '', baseUrlIssueBanner: true, staticDirectories: [DEFAULT_STATIC_DIR_NAME], - markdown: { - format: 'mdx', // TODO change this to "detect" in Docusaurus v4? - mermaid: false, - preprocessor: undefined, - mdx1Compat: { - comments: true, - admonitions: true, - headingIds: true, - }, - }, + markdown: DEFAULT_MARKDOWN_CONFIG, }; function createPluginSchema(theme: boolean) { - return ( - Joi.alternatives() - .try( - Joi.function(), - Joi.array() - .ordered(Joi.function().required(), Joi.object().required()) - .length(2), - Joi.string(), - Joi.array() - .ordered(Joi.string().required(), Joi.object().required()) - .length(2), - Joi.any().valid(false, null), - ) - // @ts-expect-error: bad lib def, doesn't recognize an array of reports - .error((errors) => { - errors.forEach((error) => { - const validConfigExample = theme - ? `Example valid theme config: + return Joi.alternatives() + .try( + Joi.function(), + Joi.array() + .ordered(Joi.function().required(), Joi.object().required()) + .length(2), + Joi.string(), + Joi.array() + .ordered(Joi.string().required(), Joi.object().required()) + .length(2), + Joi.any().valid(false, null), + ) + .error((errors) => { + errors.forEach((error) => { + const validConfigExample = theme + ? `Example valid theme config: { themes: [ ["@docusaurus/theme-classic",options], @@ -104,7 +113,7 @@ function createPluginSchema(theme: boolean) { [function myTheme() { },options] ], };` - : `Example valid plugin config: + : `Example valid plugin config: { plugins: [ ["@docusaurus/plugin-content-docs",options], @@ -115,17 +124,16 @@ function createPluginSchema(theme: boolean) { ], };`; - error.message = ` => Bad Docusaurus ${ - theme ? 'theme' : 'plugin' - } value ${error.path.reduce((acc, cur) => - typeof cur === 'string' ? `${acc}.${cur}` : `${acc}[${cur}]`, - )}. + error.message = ` => Bad Docusaurus ${ + theme ? 'theme' : 'plugin' + } value ${error.path.reduce((acc, cur) => + typeof cur === 'string' ? `${acc}.${cur}` : `${acc}[${cur}]`, + )}. ${validConfigExample} `; - }); - return errors; - }) - ); + }); + return errors; + }); } const PluginSchema = createPluginSchema(false); @@ -202,6 +210,9 @@ export const ConfigSchema = Joi.object<DocusaurusConfig>({ onBrokenLinks: Joi.string() .equal('ignore', 'log', 'warn', 'throw') .default(DEFAULT_CONFIG.onBrokenLinks), + onBrokenAnchors: Joi.string() + .equal('ignore', 'log', 'warn', 'throw') + .default(DEFAULT_CONFIG.onBrokenAnchors), onBrokenMarkdownLinks: Joi.string() .equal('ignore', 'log', 'warn', 'throw') .default(DEFAULT_CONFIG.onBrokenMarkdownLinks), @@ -280,6 +291,9 @@ export const ConfigSchema = Joi.object<DocusaurusConfig>({ format: Joi.string() .equal('mdx', 'md', 'detect') .default(DEFAULT_CONFIG.markdown.format), + parseFrontMatter: Joi.function().default( + () => DEFAULT_CONFIG.markdown.parseFrontMatter, + ), mermaid: Joi.boolean().default(DEFAULT_CONFIG.markdown.mermaid), preprocessor: Joi.function() .arity(1) @@ -296,6 +310,11 @@ export const ConfigSchema = Joi.object<DocusaurusConfig>({ DEFAULT_CONFIG.markdown.mdx1Compat.headingIds, ), }).default(DEFAULT_CONFIG.markdown.mdx1Compat), + remarkRehypeOptions: + // add proper external options validation? + // Not sure if it's a good idea, validation is likely to become stale + // See https://github.com/remarkjs/remark-rehype#options + Joi.object().unknown(), }).default(DEFAULT_CONFIG.markdown), }).messages({ 'docusaurus.configValidationWarning': diff --git a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap index 9567720d587f..7299deaf977a 100644 --- a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap +++ b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap @@ -16,6 +16,7 @@ exports[`base webpack config creates webpack aliases 1`] = ` "@docusaurus/renderRoutes": "../../../../client/exports/renderRoutes.ts", "@docusaurus/router": "../../../../client/exports/router.ts", "@docusaurus/useBaseUrl": "../../../../client/exports/useBaseUrl.ts", + "@docusaurus/useBrokenLinks": "../../../../client/exports/useBrokenLinks.ts", "@docusaurus/useDocusaurusContext": "../../../../client/exports/useDocusaurusContext.ts", "@docusaurus/useGlobalData": "../../../../client/exports/useGlobalData.ts", "@docusaurus/useIsBrowser": "../../../../client/exports/useIsBrowser.ts", diff --git a/packages/docusaurus/src/webpack/aliases/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus/src/webpack/aliases/__tests__/__snapshots__/index.test.ts.snap index c9738c847d56..46390d21c92d 100644 --- a/packages/docusaurus/src/webpack/aliases/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus/src/webpack/aliases/__tests__/__snapshots__/index.test.ts.snap @@ -16,6 +16,7 @@ exports[`getDocusaurusAliases returns appropriate webpack aliases 1`] = ` "@docusaurus/renderRoutes": "<PROJECT_ROOT>/packages/docusaurus/src/client/exports/renderRoutes.ts", "@docusaurus/router": "<PROJECT_ROOT>/packages/docusaurus/src/client/exports/router.ts", "@docusaurus/useBaseUrl": "<PROJECT_ROOT>/packages/docusaurus/src/client/exports/useBaseUrl.ts", + "@docusaurus/useBrokenLinks": "<PROJECT_ROOT>/packages/docusaurus/src/client/exports/useBrokenLinks.ts", "@docusaurus/useDocusaurusContext": "<PROJECT_ROOT>/packages/docusaurus/src/client/exports/useDocusaurusContext.ts", "@docusaurus/useGlobalData": "<PROJECT_ROOT>/packages/docusaurus/src/client/exports/useGlobalData.ts", "@docusaurus/useIsBrowser": "<PROJECT_ROOT>/packages/docusaurus/src/client/exports/useIsBrowser.ts", diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index e783475161c4..1d1c73d42188 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/eslint-plugin", - "version": "3.0.1", + "version": "3.1.0", "description": "ESLint plugin to enforce best Docusaurus practices.", "main": "lib/index.js", "keywords": [ diff --git a/packages/lqip-loader/package.json b/packages/lqip-loader/package.json index 1972966052df..c7f6a59c2255 100644 --- a/packages/lqip-loader/package.json +++ b/packages/lqip-loader/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/lqip-loader", - "version": "3.0.1", + "version": "3.1.0", "description": "Low Quality Image Placeholders (LQIP) loader for webpack.", "main": "lib/index.js", "publishConfig": { @@ -17,7 +17,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.0.1", + "@docusaurus/logger": "3.1.0", "file-loader": "^6.2.0", "lodash": "^4.17.21", "sharp": "^0.32.3", diff --git a/packages/stylelint-copyright/package.json b/packages/stylelint-copyright/package.json index d6db8b806758..3113e41560c3 100644 --- a/packages/stylelint-copyright/package.json +++ b/packages/stylelint-copyright/package.json @@ -1,6 +1,6 @@ { "name": "stylelint-copyright", - "version": "3.0.1", + "version": "3.1.0", "description": "Stylelint plugin to check CSS files for a copyright header.", "main": "lib/index.js", "license": "MIT", diff --git a/project-words.txt b/project-words.txt index 203bcb7c0f29..51136e928328 100644 --- a/project-words.txt +++ b/project-words.txt @@ -1,346 +1,323 @@ +# Project Words - DO NOT TOUCH - This is updated through CI abernathyca -adriaan -agan +Adriaan +Agan alexbdebrie -alexey +Alexey algoliasearch -anonymized +Anshul anshul août +APFS apfs -apos appinstalled -applanga +Applanga architecting -astro +Astro atrule -autoconverted +Autoconverted +Autogen autogen autogenerating autohide -autolinks -backport -backticks -bartosz +Autolinks +Bartosz beforeinstallprompt -bhatt -blocklist +Bhatt +Blockquotes blockquotes Bokmål -browserslist browserstack +Buble buble -builtins +Buble's bunx caabernathy cacheable callouts -callstack +Callstack camelcase -candillon +Candillon cdabcdab cdpath +Cena cena +Changefreq changefreq +Chedeau chedeau -cheng -clément -clsx -codegen -codeql +Clément codesandbox -codespaces +Codespaces commonmark contravariance corejs -crawlable creativecommons -csapo -cssnano -csvg +Csapo +Csvg +Customizability customizability +Dabit dabit -daishi +Daishi +Datagit datagit -datamap -datas -dbaeumer -décembre +Datagit's dedup -deduplicated -déja -deps -devcontainers -devs -devspace devto -dmitry -docgen +Dmitry docsearch -docsify +Docsify +Docu docu docusuarus -docz -doesn +Docz +Dogfood dogfood +Dogfooding dogfooding -dojocat +Dojocat +Dyte dyte +Déja easyops +Endi endi +Endi's +Endilie endilie endiliey -entrypoints -errnametoolong -esbenp -esbuild -eslintcache -estree +ERRNAMETOOLONG evaluable +Execa execa externalwaiting failfast Fargate -fbid -février -fienny +FBID +Fienny flac -flightcontrol -formik -fouc +Flightcontrol +Flightcontrol's +Formik +FOUC froms funboxteam +février gabrielcsapo -gantt -getopts -gifs -gitgraph -gitpod -globbing -globby -goss -goyal -gruntfuggly +Gifs +Goss +Goyal +Gtag gtag hahaha -hamel -hardcoding -hastscript +Hamel +Hasura hasura -heavener -héctor -héllô -heuristical +Heavener +Hideable hideable hola -horiz -hostman +Hostman hoverable -husain -ianad +Husain +Héctor +héllô +IANAD idempotency Iframes -immer +Immer +Infima infima +Infima's inlines -intelli +Intelli intellij interactiveness +Interpolatable interpolatable -investec -jakepartusch -jamstack +Investec janvier javadoc jiti jmarcey jodyheavener joshcena -jscodeshift jssdk juillet -kaszubowski +Kaszubowski +Katex katex -kato -keyscan +Kato +Keytar keytar -kinsta -knapen -koyeb -kubernetes -lamana +Kinsta +Knapen +Koyeb +Koyeb's +Lamana +Lifecycles lifecycles -lighthouserc +Linkify linkify -localizable +Localizable lockb -longpaths -lorber -lowercased +Lorber +Lorber's +LQIP lqip lunrjs -mapbox -marcey +Marcey +Marcey's +Markprompt markprompt -marocchino -massoud +Massoud mathjax maxlynch maxresdefault +MDAST mdast mdwn -mdxa -mdxast -mdxhast +MDXA +MDXAST +MDXHAST +Mdxjs mdxjs metadatum metastring metrica -metrika +Metrika +Microdata microdata -microlink -middlewares +Mindmap mindmap -minifier -mkcert -mkdir -mkdirs mkdn mkdocs mkdown +Moesif moesif msapplication -nabors -nakagawa +Nabors +Nakagawa nand +Navigations navigations navlink netrc -nextra +Nextra ngryman -nisarag +Nisarag noflash noicon -noindex nojekyll noninteractive -noreply npmjs -npmrc nprogress -ntfs -nuxt -o’shannessy -onboarded -openapi +Nuxt opensearch opensearchdescription opensource optimizt -optind +Orta orta +Outerbounds outerbounds overrideable +O’Shannessy pageview +Palenight palenight -paletton -palo +Paletton +Palo +Paraiso paraiso pathinfo -pathnames paularmstrong -pbcopy -pcss peaceiris philpl +Photoshop photoshop -picocolors picomatch Pipeable playbtn +Pluggable pluggable +Plushie plushie plushies -pnpm posthog -preactjs +Precache precache precached precaching preconfigured -preconnect -prefetch -prefetching -preloads -prepended -preprocess -preprocessors prerendered prerendering +printfn println prismjs producthunt +Profilo profilo -protobuf +Protobuf protobuffet -prpl -pyltsyn -qjpuv -qovery +PRPL +Pyltsyn +QJPUV +Qovery quasis -quddus -quddús +Quddus +Quddús +Quickwit quickwit -quotify rachelnabors -ramón +Ramón reactjs rearchitecture recrawl redirections -redoc +Redoc redocusaurus redwoodjs refactorings -regexes +Rehype rehype renderable -reponame -reqs -requireindex +REPONAME +Retrocompatibility retrocompatibility +Retrocompatible retrocompatible rmiz -roadmap -rocketvalidator rtcts rtlcss saurus -scaleway +Scaleway searchbar +Sebastien sebastien -sébastien sebastienlorber sensical -serializers setaf setext +setlocal +Shiki shiki shortcodes showinfo -sida -simen +Sida +Simen slorber sluggified sluggifies sluggify +Solana solana spâce stackblitz stackblitzrc -strikethrough +Strikethrough strikethroughs -styl stylelint stylelintrc subdir @@ -354,71 +331,68 @@ subsetting subsubcategory subsubfolder subsubsection +Subsubsubfolder subsubsubfolder -sucipto +Sucipto sunsetting +Supabase supabase +SVGR svgr swizzlable -teik +Sébastien +Teik templating -thanos -therox +Thanos +Therox toolset toplevel -transifex +Transifex transpiles +Treeified treeified treeifies treeify -treosh +Triaging triaging -tses +TSES twoslash typecheck -typechecks -typedoc +Typesense typesense -unavatar -unflat -unist +Unavatar unlinkable +Unlisteds unlisteds +Unlocalized unlocalized -unmatch unnormalized -unoptimized -unprefixed unswizzle -unversioned upvotes urlset -userland -vannicatte -vercel -verifymethod +Vannicatte +vbnet +Vetter vetter vfile -vicenti -vieira -viet -viewports -vinnik +Vicenti +Vieira +Viet +Vinnik vjeux waivable +WCAG wcag webfactory -webp webpackbar webstorm -wolcott -writeups -xclip -xplorer -xsoar -yacop +Wolcott +Xplorer +XSOAR +Yacop +Yangshun yangshun yangshunz -zhou +Zhou zoomable zpao diff --git a/website/_dogfooding/_docs tests/tests/visibility/force-unlisted.mdx b/website/_dogfooding/_docs tests/tests/visibility/force-unlisted.mdx new file mode 100644 index 000000000000..08018984425a --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/visibility/force-unlisted.mdx @@ -0,0 +1,10 @@ +--- +unlisted: false +force_unlisted_parseFrontMatter_test: true +--- + +# force_unlisted_parseFrontMatter_test + +This doc is hidden despite `unlisted: false` + +We use `parseFrontMatter` to force it to true thanks to `force_unlisted_parseFrontMatter_test: true` diff --git a/website/_dogfooding/_docs tests/tests/visibility/index.mdx b/website/_dogfooding/_docs tests/tests/visibility/index.mdx index 88a78b5d6b2c..71c3712f2d12 100644 --- a/website/_dogfooding/_docs tests/tests/visibility/index.mdx +++ b/website/_dogfooding/_docs tests/tests/visibility/index.mdx @@ -24,6 +24,7 @@ In production, unlisted items should remain accessible, but be hidden in the sid - [./some-unlisteds/unlisted1.md](./some-unlisteds/unlisted1.mdx) - [./some-unlisteds/unlisted2.md](./some-unlisteds/unlisted2.mdx) - [./some-unlisteds/unlisted-subcategory/unlisted3.md](./some-unlisteds/unlisted-subcategory/unlisted3.mdx) +- [./force-unlisted.mdx](./force-unlisted.mdx) --- diff --git a/website/_dogfooding/_pages tests/code-block-tests.mdx b/website/_dogfooding/_pages tests/code-block-tests.mdx index 3b778e7cea56..27e751cfa6cc 100644 --- a/website/_dogfooding/_pages tests/code-block-tests.mdx +++ b/website/_dogfooding/_pages tests/code-block-tests.mdx @@ -384,6 +384,61 @@ y = times2(x); \end{document} ``` +```vbnet title="vbnet.vb" +Dim languages As New Set(Of String) From { + ' highlight-start + "C#", + "Visual Basic", + "F#", + ' highlight-end + "PowerShell", + ' highlight-next-line + "TypeScript" +} +``` + +```batch title="cmd.bat" +rem highlight-start +@echo off +setlocal +Rem highlight-end +ipconfig +REM highlight-next-line +echo Docusaurus is awesome +netstat +``` + +```fortran title="fortran.f90" +! highlight-start +program hello +! highlight-end + implicit none + ! highlight-next-line + print *, "Hello, World!" +end program hello +``` + +```cobol title="cobol.cob" +*> highlight-start +IDENTIFICATION DIVISION. +PROGRAM-ID. HELLO. +*> highlight-end +PROCEDURE DIVISION. + *> highlight-next-line + DISPLAY "Hello, World!". +END PROGRAM HELLO. +``` + +```fsharp title="fsharp.fsx" +(* highlight-start *) +[<EntryPoint>] +(* highlight-end *) +let main _ = + // highlight-next-line + printfn "Hello, World!" + 0 +``` + ## HTML - script + style highlighting See https://github.com/facebook/docusaurus/issues/9517 @@ -403,3 +458,33 @@ See https://github.com/facebook/docusaurus/issues/9517 </head> </html> ``` + +## Empty code blocks edge cases + +Empty inline code block: `` + +Single space inline code block: ` ` + +Empty code block + +{/* prettier-ignore */} +``` +``` + +Empty 1 line code block + +``` + +``` + +Empty 2 line code block + +``` + +``` + +Empty live code block + +```js live + +``` diff --git a/website/_dogfooding/dogfooding.config.ts b/website/_dogfooding/dogfooding.config.ts index 10f70d71fb95..3e57c13c36ad 100644 --- a/website/_dogfooding/dogfooding.config.ts +++ b/website/_dogfooding/dogfooding.config.ts @@ -10,6 +10,15 @@ import type {Options as DocsOptions} from '@docusaurus/plugin-content-docs'; import type {Options as BlogOptions} from '@docusaurus/plugin-content-blog'; import type {Options as PageOptions} from '@docusaurus/plugin-content-pages'; +export function dogfoodingTransformFrontMatter(frontMatter: { + [key: string]: unknown; +}): {[key: string]: unknown} { + if (frontMatter.force_unlisted_parseFrontMatter_test === true) { + return {...frontMatter, unlisted: true}; + } + return frontMatter; +} + export const dogfoodingThemeInstances: PluginConfig[] = [ function swizzleThemeTests(): Plugin { return { diff --git a/website/blog/releases/3.0/index.mdx b/website/blog/releases/3.0/index.mdx index 13db01db308b..98184cedaf47 100644 --- a/website/blog/releases/3.0/index.mdx +++ b/website/blog/releases/3.0/index.mdx @@ -291,7 +291,7 @@ function Hello() { } ``` -In [#8982](https://github.com/facebook/docusaurus/pull/8982) and [#8870](https://github.com/facebook/docusaurus/pull/8870), we also added [magic comments](docs/markdown-features/code-blocks#custom-magic-comments) support for TeX-like, Haskell-like, and WebAssembly comment syntax. +In [#8982](https://github.com/facebook/docusaurus/pull/8982) and [#8870](https://github.com/facebook/docusaurus/pull/8870), we also added [magic comments](/docs/markdown-features/code-blocks#custom-magic-comments) support for TeX-like, Haskell-like, and WebAssembly comment syntax. ```haskell title="haskell.hs" stringLength :: String -> Int diff --git a/website/docs/advanced/routing.mdx b/website/docs/advanced/routing.mdx index 5bf943072ba6..e9e96d4892c7 100644 --- a/website/docs/advanced/routing.mdx +++ b/website/docs/advanced/routing.mdx @@ -265,26 +265,18 @@ export function PageRoute() { Docusaurus builds a [single-page application](https://developer.mozilla.org/en-US/docs/Glossary/SPA), where route transitions are done through the `history.push()` method of React router. This operation is done on the client side. However, the prerequisite for a route transition to happen this way is that the target URL is known to our router. Otherwise, the router catches this path and displays a 404 page instead. -If you put some HTML pages under the `static` folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a `pathname://` protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link. Try the following two links: +If you put some HTML pages under the `static` folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a `pathname://` protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link. ```md -- [/pure-html](/pure-html) - [pathname:///pure-html](pathname:///pure-html) ``` <BrowserWindow> -- [`/pure-html`](/pure-html) - [`pathname:///pure-html`](pathname:///pure-html) </BrowserWindow> -:::tip - -The first link will **not** trigger a "broken links detected" check during the production build, because the respective file actually exists. Nevertheless, when you click on the link, a "page not found" will be displayed until you refresh. - -::: - The `pathname://` protocol is useful for referencing any content in the static folder. For example, Docusaurus would convert [all Markdown static assets to require() calls](../guides/markdown-features/markdown-features-assets.mdx#static-assets). You can use `pathname://` to keep it a regular link instead of being hashed by Webpack. ```md title="my-doc.md" diff --git a/website/docs/api/docusaurus.config.js.mdx b/website/docs/api/docusaurus.config.js.mdx index ddb4e02bf965..ee481288f706 100644 --- a/website/docs/api/docusaurus.config.js.mdx +++ b/website/docs/api/docusaurus.config.js.mdx @@ -190,7 +190,7 @@ export default { The behavior of Docusaurus when it detects any broken link. -By default, it throws an error, to ensure you never ship any broken link, but you can lower this security if needed. +By default, it throws an error, to ensure you never ship any broken link. :::note @@ -198,13 +198,21 @@ The broken links detection is only available for a production build (`docusaurus ::: +### `onBrokenAnchors` {#onBrokenAnchors} + +- Type: `'ignore' | 'log' | 'warn' | 'throw'` + +The behavior of Docusaurus when it detects any broken anchor declared with the `Heading` component of Docusaurus. + +By default, it prints a warning, to let you know about your broken anchors. + ### `onBrokenMarkdownLinks` {#onBrokenMarkdownLinks} - Type: `'ignore' | 'log' | 'warn' | 'throw'` The behavior of Docusaurus when it detects any broken Markdown link. -By default, it prints a warning, to let you know about your broken Markdown link, but you can change this security if needed. +By default, it prints a warning, to let you know about your broken Markdown link. ### `onDuplicateRoutes` {#onDuplicateRoutes} @@ -423,11 +431,22 @@ type MDX1CompatOptions = headingIds: boolean; }; +export type ParseFrontMatter = (params: { + filePath: string; + fileContent: string; + defaultParseFrontMatter: ParseFrontMatter; +}) => Promise<{ + frontMatter: {[key: string]: unknown}; + content: string; +}>; + type MarkdownConfig = { format: 'mdx' | 'md' | 'detect'; mermaid: boolean; preprocessor?: MarkdownPreprocessor; + parseFrontMatter?: ParseFrontMatter; mdx1Compat: MDX1CompatOptions; + remarkRehypeOptions: object; // see https://github.com/remarkjs/remark-rehype#options }; ``` @@ -441,6 +460,12 @@ export default { preprocessor: ({filePath, fileContent}) => { return fileContent.replaceAll('{{MY_VAR}}', 'MY_VALUE'); }, + parseFrontMatter: async (params) => { + const result = await params.defaultParseFrontMatter(params); + result.frontMatter.description = + result.frontMatter.description?.replaceAll('{{MY_VAR}}', 'MY_VALUE'); + return result; + }, mdx1Compat: { comments: true, admonitions: true, @@ -459,7 +484,9 @@ export default { | `format` | `'mdx' \| 'md' \| 'detect'` | `'mdx'` | The default parser format to use for Markdown content. Using 'detect' will select the appropriate format automatically based on file extensions: `.md` vs `.mdx`. | | `mermaid` | `boolean` | `false` | When `true`, allows Docusaurus to render Markdown code blocks with `mermaid` language as Mermaid diagrams. | | `preprocessor` | `MarkdownPreprocessor` | `undefined` | Gives you the ability to alter the Markdown content string before parsing. Use it as a last-resort escape hatch or workaround: it is almost always better to implement a Remark/Rehype plugin. | +| `parseFrontMatter` | `ParseFrontMatter` | `undefined` | Gives you the ability to provide your own front matter parser, or to enhance the default parser. Read our [front matter guide](../guides/markdown-features/markdown-features-intro.mdx#front-matter) for details. | | `mdx1Compat` | `MDX1CompatOptions` | `{comments: true, admonitions: true, headingIds: true}` | Compatibility options to make it easier to upgrade to Docusaurus v3+. | +| `remarkRehypeOptions` | `object` | `undefined` | Makes it possible to pass custom [`remark-rehype` options](https://github.com/remarkjs/remark-rehype#options). | ```mdx-code-block </APITable> diff --git a/website/docs/api/plugins/plugin-content-docs.mdx b/website/docs/api/plugins/plugin-content-docs.mdx index d9238f65bb36..754a56d293d9 100644 --- a/website/docs/api/plugins/plugin-content-docs.mdx +++ b/website/docs/api/plugins/plugin-content-docs.mdx @@ -42,10 +42,10 @@ Accepted fields: | `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. | | `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. | | `sidebarPath` | <code>false \| string</code> | `undefined` | Path to sidebar configuration. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. | -| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar#collapsible-categories) | -| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar#expanded-categories-by-default) | -| `sidebarItemsGenerator` | <a href="#SidebarGenerator"><code>SidebarGenerator</code></a> | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) | -| `numberPrefixParser` | <code>boolean \|</code> <a href="#PrefixParser"><code>PrefixParser</code></a> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar#using-number-prefixes) | +| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar/items#collapsible-categories) | +| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar/items#expanded-categories-by-default) | +| `sidebarItemsGenerator` | <a href="#SidebarGenerator"><code>SidebarGenerator</code></a> | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar/autogenerated#customize-the-sidebar-items-generator) | +| `numberPrefixParser` | <code>boolean \|</code> <a href="#PrefixParser"><code>PrefixParser</code></a> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes) | | `docsRootComponent` | `string` | `'@theme/DocsRoot'` | Parent component of all the docs plugin pages (including all versions). Stays mounted when navigation between docs pages and versions. | | `docVersionRootComponent` | `string` | `'@theme/DocVersionLayout'` | Parent component of all docs pages of an individual version (doc pages with sidebars, tags pages). Stays mounted when navigation between pages of that specific version. | | `docRootComponent` | `string` | `'@theme/DocPage'` | Parent component of all doc pages with sidebars (regular docs pages, category generated index pages). Stays mounted when navigation between such pages. | @@ -275,7 +275,7 @@ Accepted fields: | `title` | `string` | Markdown title or `id` | The text title of your document. Used for the page metadata and as a fallback value in multiple places (sidebar, next/previous buttons...). Automatically added at the top of your doc if it does not contain any Markdown title. | | `pagination_label` | `string` | `sidebar_label` or `title` | The text used in the document next/previous buttons for this document. | | `sidebar_label` | `string` | `title` | The text shown in the document sidebar for this document. | -| `sidebar_position` | `number` | Default ordering | Controls the position of a doc inside the generated sidebar slice when using `autogenerated` sidebar items. See also [Autogenerated sidebar metadata](/docs/sidebar#autogenerated-sidebar-metadata). | +| `sidebar_position` | `number` | Default ordering | Controls the position of a doc inside the generated sidebar slice when using `autogenerated` sidebar items. See also [Autogenerated sidebar metadata](/docs/sidebar/autogenerated#autogenerated-sidebar-metadata). | | `sidebar_class_name` | `string` | `undefined` | Gives the corresponding sidebar label a special class name when using autogenerated sidebars. | | `sidebar_custom_props` | `object` | `undefined` | Assign [custom props](../../guides/docs/sidebar/index.mdx#passing-custom-props) to the sidebar item referencing this doc | | `displayed_sidebar` | `string` | `undefined` | Force the display of a given sidebar when browsing the current document. Read the [multiple sidebars guide](../../guides/docs/sidebar/multiple-sidebars.mdx) for details. | @@ -285,7 +285,7 @@ Accepted fields: | `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | | `pagination_next` | <code>string \| null</code> | Next doc in the sidebar | The ID of the documentation you want the "Next" pagination to link to. Use `null` to disable showing "Next" for this page. | | `pagination_prev` | <code>string \| null</code> | Previous doc in the sidebar | The ID of the documentation you want the "Previous" pagination to link to. Use `null` to disable showing "Previous" for this page. | -| `parse_number_prefixes` | `boolean` | `numberPrefixParser` plugin option | Whether number prefix parsing is disabled on this doc. See also [Using number prefixes](/docs/sidebar#using-number-prefixes). | +| `parse_number_prefixes` | `boolean` | `numberPrefixParser` plugin option | Whether number prefix parsing is disabled on this doc. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes). | | `custom_edit_url` | <code>string \| null</code> | Computed using the `editUrl` plugin option | The URL for editing this document. Use `null` to disable showing "Edit this page" for this page. | | `keywords` | `string[]` | `undefined` | Keywords meta tag for the document page, for search engines. | | `description` | `string` | The first line of Markdown content | The description of your document, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. | diff --git a/website/docs/cli.mdx b/website/docs/cli.mdx index 0b38c01776f7..bb1f32c91d68 100644 --- a/website/docs/cli.mdx +++ b/website/docs/cli.mdx @@ -177,7 +177,7 @@ By default, the files are written in `website/i18n/<defaultLocale>/...`. ### `docusaurus write-heading-ids [siteDir] [files]` {#docusaurus-write-heading-ids-sitedir} -Add [explicit heading IDs](./guides/markdown-features/markdown-features-toc.mdx#explicit-ids) to the Markdown documents of your site. +Add [explicit heading IDs](./guides/markdown-features/markdown-features-toc.mdx#heading-ids) to the Markdown documents of your site. | Name | Default | Description | | --- | --- | --- | diff --git a/website/docs/docusaurus-core.mdx b/website/docs/docusaurus-core.mdx index e96d9ccf5068..4249f47bec24 100644 --- a/website/docs/docusaurus-core.mdx +++ b/website/docs/docusaurus-core.mdx @@ -605,6 +605,49 @@ const MyComponent = () => { }; ``` +### `useBrokenLinks` {#useBrokenLinks} + +React hook to access the Docusaurus broken link checker APIs, exposing a way for a Docusaurus pages to report and collect their links and anchors. + +:::warning + +This is an **advanced** API that **most Docusaurus users don't need to use directly**. + +It is already **built-in** in existing high-level components: + +- the [`<Link>`](#link) component will collect links for you +- the `@theme/Heading` (used for Markdown headings) will collect anchors + +Use `useBrokenLinks()` if you implement your own `<Heading>` or `<Link>` component. + +::: + +Usage example: + +```js title="MyHeading.js" +import useBrokenLinks from '@docusaurus/useBrokenLinks'; + +export default function MyHeading({id, ...props}): JSX.Element { + const brokenLinks = useBrokenLinks(); + + brokenLinks.collectAnchor(id); + + return <h2 id={id}>Heading</h2>; +} +``` + +```js title="MyLink.js" +import useBrokenLinks from '@docusaurus/useBrokenLinks'; + +export default function MyLink({targetLink, ...props}): JSX.Element { + const brokenLinks = useBrokenLinks(); + + brokenLinks.collectLink(targetLink); + + return <a href={targetLink}>Link</a>; +} +``` + ## Functions {#functions} ### `interpolate` {#interpolate-1} diff --git a/website/docs/guides/docs/sidebar/autogenerated.mdx b/website/docs/guides/docs/sidebar/autogenerated.mdx index 000e1e4cbdcf..7e3bfcf0a005 100644 --- a/website/docs/guides/docs/sidebar/autogenerated.mdx +++ b/website/docs/guides/docs/sidebar/autogenerated.mdx @@ -371,7 +371,7 @@ customProps: :::info -If the `link` is explicitly specified, Docusaurus will not apply any [default conventions](items.mdx#category-index-convention). +If the `link` is explicitly specified, Docusaurus will not apply any [default conventions](#category-index-convention). The doc links can be specified relatively, e.g. if the category is generated with the `guides` directory, `"link": {"type": "doc", "id": "intro"}` will be resolved to the ID `guides/intro`, only falling back to `intro` if a doc with the former ID doesn't exist. diff --git a/website/docs/guides/docs/versioning.mdx b/website/docs/guides/docs/versioning.mdx index b473d69a1268..1fa34fb1c5f4 100644 --- a/website/docs/guides/docs/versioning.mdx +++ b/website/docs/guides/docs/versioning.mdx @@ -106,7 +106,7 @@ npm run docusaurus docs:version 1.1.0 When tagging a new version, the document versioning mechanism will: - Copy the full `docs/` folder contents into a new `versioned_docs/version-[versionName]/` folder. -- Create a versioned sidebars file based from your current [sidebar](docs-introduction.mdx#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-[versionName]-sidebars.json`. +- Create a versioned sidebars file based from your current [sidebar](./sidebar/index.mdx) configuration (if it exists) - saved as `versioned_sidebars/version-[versionName]-sidebars.json`. - Append the new version number to `versions.json`. ### Creating new docs {#creating-new-docs} diff --git a/website/docs/guides/markdown-features/markdown-features-intro.mdx b/website/docs/guides/markdown-features/markdown-features-intro.mdx index b3116e29983c..b6bcd756beff 100644 --- a/website/docs/guides/markdown-features/markdown-features-intro.mdx +++ b/website/docs/guides/markdown-features/markdown-features-intro.mdx @@ -120,6 +120,45 @@ The API documentation of each official plugin lists the supported attributes: ::: +:::tip enhance your front matter + +Use the [Markdown config `parseFrontMatter` function](../../api/docusaurus.config.js.mdx#markdown) to provide your own front matter parser, or to enhance the default parser. + +It is possible to reuse the default parser to wrap it with your own custom proprietary logic. This makes it possible to implement convenient front matter transformations, shortcuts, or to integrate with external systems using front matter that Docusaurus plugins do not support. + +```js title="docusaurus.config.js" +export default { + markdown: { + // highlight-start + parseFrontMatter: async (params) => { + // Reuse the default parser + const result = await params.defaultParseFrontMatter(params); + + // Process front matter description placeholders + result.frontMatter.description = + result.frontMatter.description?.replaceAll('{{MY_VAR}}', 'MY_VALUE'); + + // Create your own front matter shortcut + if (result.frontMatter.i_do_not_want_docs_pagination) { + result.frontMatter.pagination_prev = null; + result.frontMatter.pagination_next = null; + } + + // Rename an unsupported front matter coming from another system + if (result.frontMatter.cms_seo_summary) { + result.frontMatter.description = result.frontMatter.cms_seo_summary; + delete result.frontMatter.cms_seo_summary; + } + + return result; + }, + // highlight-end + }, +}; +``` + +::: + ## Quotes {#quotes} Markdown quotes are beautifully styled: diff --git a/website/docs/i18n/i18n-tutorial.mdx b/website/docs/i18n/i18n-tutorial.mdx index b74896547cd7..a88e2f0a388b 100644 --- a/website/docs/i18n/i18n-tutorial.mdx +++ b/website/docs/i18n/i18n-tutorial.mdx @@ -445,7 +445,7 @@ Generated IDs are not always a good fit for localized sites, as it requires you + [link](#bonjour-le-monde) ``` -For localized sites, it is recommended to use **[explicit heading IDs](../guides/markdown-features/markdown-features-toc.mdx#explicit-ids)**. +For localized sites, it is recommended to use **[explicit heading IDs](../guides/markdown-features/markdown-features-toc.mdx#heading-ids)**. ::: diff --git a/website/docs/seo.mdx b/website/docs/seo.mdx index 147bf99657c0..031ab1ddf340 100644 --- a/website/docs/seo.mdx +++ b/website/docs/seo.mdx @@ -211,7 +211,7 @@ For example, [`/examples/noIndex`](/examples/noIndex) is not included in the [Do ## Human readable links {#human-readable-links} -Docusaurus uses your file names as links, but you can always change that using slugs, see this [tutorial](./guides/docs/docs-introduction.mdx#document-id) for more details. +Docusaurus uses your file names as links, but you can always change that using slugs, see this [tutorial](./guides/docs/docs-create-doc.mdx#document-id) for more details. ## Structured content {#structured-content} diff --git a/website/docs/styling-layout.mdx b/website/docs/styling-layout.mdx index 369c688ea51a..b4b296dc6281 100644 --- a/website/docs/styling-layout.mdx +++ b/website/docs/styling-layout.mdx @@ -180,6 +180,12 @@ Docusaurus uses `996px` as the cutoff between mobile screen width and desktop. I } ``` +:::tip Customizing the breakpoint + +Some React components, such as the header and the sidebar, implement different JavaScript logic when in mobile view. If you change the breakpoint value in your custom CSS, you probably also want to update the invocations of the `useWindowSize` hook by [swizzling](./swizzling.mdx) the components it's used in and passing an explicit option argument. + +::: + ## CSS modules {#css-modules} To style your components using [CSS Modules](https://github.com/css-modules/css-modules), name your stylesheet files with the `.module.css` suffix (e.g. `welcome.module.css`). Webpack will load such CSS files as CSS modules and you have to reference the class names as properties of the imported CSS module (as opposed to using plain strings). This is similar to the convention used in [Create React App](https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet). diff --git a/website/docs/using-plugins.mdx b/website/docs/using-plugins.mdx index 28e25e491541..92d86097d717 100644 --- a/website/docs/using-plugins.mdx +++ b/website/docs/using-plugins.mdx @@ -114,7 +114,7 @@ At most one plugin instance can be the "default plugin instance", by omitting th ## Using themes {#using-themes} -Themes are loaded in the exact same way as plugins. From the consumer perspective, the `themes` and `plugins` entries are interchangeable when installing and configuring a plugin. The only nuance is that themes are loaded after plugins, and it's possible for [a theme to override a plugin's default theme components](./swizzling.mdx#theme-aliases). +Themes are loaded in the exact same way as plugins. From the consumer perspective, the `themes` and `plugins` entries are interchangeable when installing and configuring a plugin. The only nuance is that themes are loaded after plugins, and it's possible for [a theme to override a plugin's default theme components](./advanced/client.mdx#theme-aliases). :::tip diff --git a/website/docusaurus.config.localized.json b/website/docusaurus.config.localized.json index 1c90178b80c2..4e8553a8d59e 100644 --- a/website/docusaurus.config.localized.json +++ b/website/docusaurus.config.localized.json @@ -2,5 +2,9 @@ "tagline": { "en": "Build optimized websites quickly, focus on your content", "fr": "Construisez rapidement des sites web optimisés, concentrez-vous sur votre contenu" + }, + "remarkRehypeOptions_footnotes": { + "en": "Footnotes", + "fr": "Notes de bas de page" } } diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 9bd7288a4f7f..dbdc49dd2675 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -17,6 +17,7 @@ import { dogfoodingPluginInstances, dogfoodingThemeInstances, dogfoodingRedirects, + dogfoodingTransformFrontMatter, } from './_dogfooding/dogfooding.config'; import ConfigLocalized from './docusaurus.config.localized.json'; @@ -101,7 +102,7 @@ const TwitterSvg = const defaultLocale = 'en'; -function getLocalizedConfigValue(key: string) { +function getLocalizedConfigValue(key: keyof typeof ConfigLocalized) { const currentLocale = process.env.DOCUSAURUS_CURRENT_LOCALE ?? defaultLocale; const values = ConfigLocalized[key]; if (!values) { @@ -176,6 +177,16 @@ export default async function createConfigAsync() { mdx1Compat: { // comments: false, }, + remarkRehypeOptions: { + footnoteLabel: getLocalizedConfigValue('remarkRehypeOptions_footnotes'), + }, + parseFrontMatter: async (params) => { + const result = await params.defaultParseFrontMatter(params); + return { + ...result, + frontMatter: dogfoodingTransformFrontMatter(result.frontMatter), + }; + }, preprocessor: ({filePath, fileContent}) => { let result = fileContent; @@ -195,7 +206,11 @@ export default async function createConfigAsync() { }, }, onBrokenLinks: - isBuildFast || + isVersioningDisabled || + process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale + ? 'warn' + : 'throw', + onBrokenAnchors: isVersioningDisabled || process.env.DOCUSAURUS_CURRENT_LOCALE !== defaultLocale ? 'warn' diff --git a/website/package.json b/website/package.json index 73ce9a835bfb..5a6535804c1d 100644 --- a/website/package.json +++ b/website/package.json @@ -1,6 +1,6 @@ { "name": "website", - "version": "3.0.1", + "version": "3.1.0", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -36,19 +36,19 @@ "dependencies": { "@crowdin/cli": "^3.13.0", "@crowdin/crowdin-api-client": "^1.23.3", - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/plugin-client-redirects": "3.0.1", - "@docusaurus/plugin-ideal-image": "3.0.1", - "@docusaurus/plugin-pwa": "3.0.1", - "@docusaurus/preset-classic": "3.0.1", - "@docusaurus/remark-plugin-npm2yarn": "3.0.1", - "@docusaurus/theme-classic": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-live-codeblock": "3.0.1", - "@docusaurus/theme-mermaid": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", + "@docusaurus/core": "3.1.0", + "@docusaurus/logger": "3.1.0", + "@docusaurus/plugin-client-redirects": "3.1.0", + "@docusaurus/plugin-ideal-image": "3.1.0", + "@docusaurus/plugin-pwa": "3.1.0", + "@docusaurus/preset-classic": "3.1.0", + "@docusaurus/remark-plugin-npm2yarn": "3.1.0", + "@docusaurus/theme-classic": "3.1.0", + "@docusaurus/theme-common": "3.1.0", + "@docusaurus/theme-live-codeblock": "3.1.0", + "@docusaurus/theme-mermaid": "3.1.0", + "@docusaurus/utils": "3.1.0", + "@docusaurus/utils-common": "3.1.0", "@popperjs/core": "^2.11.8", "@swc/core": "1.2.197", "clsx": "^2.0.0", @@ -67,8 +67,8 @@ "swc-loader": "^0.2.3", "unist-util-visit": "^5.0.0", "webpack": "^5.88.1", - "workbox-routing": "^6.6.1", - "workbox-strategies": "^6.6.1" + "workbox-routing": "^7.0.0", + "workbox-strategies": "^7.0.0" }, "browserslist": { "production": [ @@ -83,8 +83,8 @@ ] }, "devDependencies": { - "@docusaurus/eslint-plugin": "3.0.1", - "@docusaurus/tsconfig": "3.0.1", + "@docusaurus/eslint-plugin": "3.1.0", + "@docusaurus/tsconfig": "3.1.0", "@types/color": "^3.0.4", "@types/jest": "^29.5.3", "cross-env": "^7.0.3", diff --git a/website/versioned_docs/version-2.x/advanced/routing.mdx b/website/versioned_docs/version-2.x/advanced/routing.mdx index e6513637e379..9e3551fdd37e 100644 --- a/website/versioned_docs/version-2.x/advanced/routing.mdx +++ b/website/versioned_docs/version-2.x/advanced/routing.mdx @@ -265,26 +265,18 @@ export function PageRoute() { Docusaurus builds a [single-page application](https://developer.mozilla.org/en-US/docs/Glossary/SPA), where route transitions are done through the `history.push()` method of React router. This operation is done on the client side. However, the prerequisite for a route transition to happen this way is that the target URL is known to our router. Otherwise, the router catches this path and displays a 404 page instead. -If you put some HTML pages under the `static` folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a `pathname://` protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link. Try the following two links: +If you put some HTML pages under the `static` folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a `pathname://` protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link. ```md -- [/pure-html](/pure-html) - [pathname:///pure-html](pathname:///pure-html) ``` <BrowserWindow> -- [`/pure-html`](/pure-html) - [`pathname:///pure-html`](pathname:///pure-html) </BrowserWindow> -:::tip - -The first link will **not** trigger a "broken links detected" check during the production build, because the respective file actually exists. Nevertheless, when you click on the link, a "page not found" will be displayed until you refresh. - -::: - The `pathname://` protocol is useful for referencing any content in the static folder. For example, Docusaurus would convert [all Markdown static assets to require() calls](../guides/markdown-features/markdown-features-assets.mdx#static-assets). You can use `pathname://` to keep it a regular link instead of being hashed by Webpack. ```md title="my-doc.md" diff --git a/website/versioned_docs/version-2.x/api/plugins/plugin-content-docs.mdx b/website/versioned_docs/version-2.x/api/plugins/plugin-content-docs.mdx index e8343d9742cc..cd98d4e99e1c 100644 --- a/website/versioned_docs/version-2.x/api/plugins/plugin-content-docs.mdx +++ b/website/versioned_docs/version-2.x/api/plugins/plugin-content-docs.mdx @@ -42,10 +42,10 @@ Accepted fields: | `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. | | `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. | | `sidebarPath` | <code>false \| string</code> | `undefined` | Path to sidebar configuration. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. | -| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar#collapsible-categories) | -| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar#expanded-categories-by-default) | -| `sidebarItemsGenerator` | <a href="#SidebarGenerator"><code>SidebarGenerator</code></a> | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) | -| `numberPrefixParser` | <code>boolean \|</code> <a href="#PrefixParser"><code>PrefixParser</code></a> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar#using-number-prefixes) | +| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar/items#collapsible-categories) | +| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar/items#expanded-categories-by-default) | +| `sidebarItemsGenerator` | <a href="#SidebarGenerator"><code>SidebarGenerator</code></a> | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar/autogenerated#customize-the-sidebar-items-generator) | +| `numberPrefixParser` | <code>boolean \|</code> <a href="#PrefixParser"><code>PrefixParser</code></a> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes) | | `docLayoutComponent` | `string` | `'@theme/DocPage'` | Root layout component of each doc page. Provides the version data context, and is not unmounted when switching docs. | | `docItemComponent` | `string` | `'@theme/DocItem'` | Main doc container, with TOC, pagination, etc. | | `docTagsListComponent` | `string` | `'@theme/DocTagsListPage'` | Root component of the tags list page | @@ -273,7 +273,7 @@ Accepted fields: | `title` | `string` | Markdown title or `id` | The text title of your document. Used for the page metadata and as a fallback value in multiple places (sidebar, next/previous buttons...). Automatically added at the top of your doc if it does not contain any Markdown title. | | `pagination_label` | `string` | `sidebar_label` or `title` | The text used in the document next/previous buttons for this document. | | `sidebar_label` | `string` | `title` | The text shown in the document sidebar for this document. | -| `sidebar_position` | `number` | Default ordering | Controls the position of a doc inside the generated sidebar slice when using `autogenerated` sidebar items. See also [Autogenerated sidebar metadata](/docs/sidebar#autogenerated-sidebar-metadata). | +| `sidebar_position` | `number` | Default ordering | Controls the position of a doc inside the generated sidebar slice when using `autogenerated` sidebar items. See also [Autogenerated sidebar metadata](/docs/sidebar/autogenerated#autogenerated-sidebar-metadata). | | `sidebar_class_name` | `string` | `undefined` | Gives the corresponding sidebar label a special class name when using autogenerated sidebars. | | `sidebar_custom_props` | `object` | `undefined` | Assign [custom props](../../guides/docs/sidebar/index.mdx#passing-custom-props) to the sidebar item referencing this doc | | `displayed_sidebar` | `string` | `undefined` | Force the display of a given sidebar when browsing the current document. Read the [multiple sidebars guide](../../guides/docs/sidebar/multiple-sidebars.mdx) for details. | @@ -283,7 +283,7 @@ Accepted fields: | `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | | `pagination_next` | <code>string \| null</code> | Next doc in the sidebar | The ID of the documentation you want the "Next" pagination to link to. Use `null` to disable showing "Next" for this page. | | `pagination_prev` | <code>string \| null</code> | Previous doc in the sidebar | The ID of the documentation you want the "Previous" pagination to link to. Use `null` to disable showing "Previous" for this page. | -| `parse_number_prefixes` | `boolean` | `numberPrefixParser` plugin option | Whether number prefix parsing is disabled on this doc. See also [Using number prefixes](/docs/sidebar#using-number-prefixes). | +| `parse_number_prefixes` | `boolean` | `numberPrefixParser` plugin option | Whether number prefix parsing is disabled on this doc. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes). | | `custom_edit_url` | `string` | Computed using the `editUrl` plugin option | The URL for editing this document. | | `keywords` | `string[]` | `undefined` | Keywords meta tag for the document page, for search engines. | | `description` | `string` | The first line of Markdown content | The description of your document, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. | diff --git a/website/versioned_docs/version-2.x/cli.mdx b/website/versioned_docs/version-2.x/cli.mdx index aaa652a48d5a..551b560aef84 100644 --- a/website/versioned_docs/version-2.x/cli.mdx +++ b/website/versioned_docs/version-2.x/cli.mdx @@ -176,7 +176,7 @@ By default, the files are written in `website/i18n/<defaultLocale>/...`. ### `docusaurus write-heading-ids [siteDir] [files]` {#docusaurus-write-heading-ids-sitedir} -Add [explicit heading IDs](./guides/markdown-features/markdown-features-toc.mdx#explicit-ids) to the Markdown documents of your site. +Add [explicit heading IDs](./guides/markdown-features/markdown-features-toc.mdx#heading-ids) to the Markdown documents of your site. | Name | Default | Description | | --- | --- | --- | diff --git a/website/versioned_docs/version-2.x/deployment.mdx b/website/versioned_docs/version-2.x/deployment.mdx index 0c49003366ba..c45e7fc6c10d 100644 --- a/website/versioned_docs/version-2.x/deployment.mdx +++ b/website/versioned_docs/version-2.x/deployment.mdx @@ -57,7 +57,7 @@ Use [slorber/trailing-slash-guide](https://github.com/slorber/trailing-slash-gui ## Using environment variables {#using-environment-variables} -Putting potentially sensitive information in the environment is common practice. However, in a typical Docusaurus website, the `docusaurus.config.js` file is the only interface to the Node.js environment (see [our architecture overview](advanced/architecture.mdx)), while everything else—MDX pages, React components... are client side and do not have direct access to the `process` global. In this case, you can consider using [`customFields`](api/docusaurus.config.js.mdx#customFields) to pass environment variables to the client side. +Putting potentially sensitive information in the environment is common practice. However, in a typical Docusaurus website, the `docusaurus.config.js` file is the only interface to the Node.js environment (see [our architecture overview](advanced/architecture.mdx)), while everything else—MDX pages, React components... are client side and do not have direct access to the `process` global. In this case, you can consider using [`customFields`](api/docusaurus.config.js.mdx#customfields) to pass environment variables to the client side. ```js title="docusaurus.config.js" // If you are using dotenv (https://www.npmjs.com/package/dotenv) diff --git a/website/versioned_docs/version-2.x/guides/docs/sidebar/autogenerated.mdx b/website/versioned_docs/version-2.x/guides/docs/sidebar/autogenerated.mdx index 4ac6fa6e620f..6d9a074f19d6 100644 --- a/website/versioned_docs/version-2.x/guides/docs/sidebar/autogenerated.mdx +++ b/website/versioned_docs/version-2.x/guides/docs/sidebar/autogenerated.mdx @@ -371,7 +371,7 @@ customProps: :::info -If the `link` is explicitly specified, Docusaurus will not apply any [default conventions](items.mdx#category-index-convention). +If the `link` is explicitly specified, Docusaurus will not apply any [default conventions](#category-index-convention). The doc links can be specified relatively, e.g. if the category is generated with the `guides` directory, `"link": {"type": "doc", "id": "intro"}` will be resolved to the ID `guides/intro`, only falling back to `intro` if a doc with the former ID doesn't exist. diff --git a/website/versioned_docs/version-2.x/guides/docs/versioning.mdx b/website/versioned_docs/version-2.x/guides/docs/versioning.mdx index 2b5657f48d81..60e41494d745 100644 --- a/website/versioned_docs/version-2.x/guides/docs/versioning.mdx +++ b/website/versioned_docs/version-2.x/guides/docs/versioning.mdx @@ -106,7 +106,7 @@ npm run docusaurus docs:version 1.1.0 When tagging a new version, the document versioning mechanism will: - Copy the full `docs/` folder contents into a new `versioned_docs/version-[versionName]/` folder. -- Create a versioned sidebars file based from your current [sidebar](docs-introduction.mdx#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-[versionName]-sidebars.json`. +- Create a versioned sidebars file based from your current [sidebar](./sidebar/index.mdx) configuration (if it exists) - saved as `versioned_sidebars/version-[versionName]-sidebars.json`. - Append the new version number to `versions.json`. ### Creating new docs {#creating-new-docs} diff --git a/website/versioned_docs/version-2.x/guides/markdown-features/markdown-features-react.mdx b/website/versioned_docs/version-2.x/guides/markdown-features/markdown-features-react.mdx index ac2c4a2ebc94..606ddf5e2451 100644 --- a/website/versioned_docs/version-2.x/guides/markdown-features/markdown-features-react.mdx +++ b/website/versioned_docs/version-2.x/guides/markdown-features/markdown-features-react.mdx @@ -84,7 +84,7 @@ Since all doc files are parsed using MDX, anything that looks like HTML is actua <span style={{backgroundColor: 'red'}}>Foo</span> ``` -This behavior is different from Docusaurus 1. See also [Migrating from v1 to v2](../../migration/migration-manual.mdx#convert-style-attributes-to-style-objects-in-mdx). +This behavior is different from Docusaurus 1. See also [Migrating from v1 to v2](../../migration/migration-manual.mdx). In addition, MDX is not [100% compatible with CommonMark](https://github.com/facebook/docusaurus/issues/3018). Use the **[MDX playground](https://mdx-git-renovate-babel-monorepo-mdx.vercel.app/playground)** to ensure that your syntax is valid MDX. diff --git a/website/versioned_docs/version-2.x/i18n/i18n-tutorial.mdx b/website/versioned_docs/version-2.x/i18n/i18n-tutorial.mdx index de7c22845af1..6c80b02dcc00 100644 --- a/website/versioned_docs/version-2.x/i18n/i18n-tutorial.mdx +++ b/website/versioned_docs/version-2.x/i18n/i18n-tutorial.mdx @@ -437,7 +437,7 @@ Generated IDs are not always a good fit for localized sites, as it requires you + [link](#bonjour-le-monde) ``` -For localized sites, it is recommended to use **[explicit heading IDs](../guides/markdown-features/markdown-features-toc.mdx#explicit-ids)**. +For localized sites, it is recommended to use **[explicit heading IDs](../guides/markdown-features/markdown-features-toc.mdx#heading-ids)**. ::: diff --git a/website/versioned_docs/version-2.x/seo.mdx b/website/versioned_docs/version-2.x/seo.mdx index ea09f87d4ae8..a8af9c30c75a 100644 --- a/website/versioned_docs/version-2.x/seo.mdx +++ b/website/versioned_docs/version-2.x/seo.mdx @@ -152,7 +152,7 @@ For example, [`/examples/noIndex`](/examples/noIndex) is not included in the [Do ## Human readable links {#human-readable-links} -Docusaurus uses your file names as links, but you can always change that using slugs, see this [tutorial](./guides/docs/docs-introduction.mdx#document-id) for more details. +Docusaurus uses your file names as links, but you can always change that using slugs, see this [tutorial](./guides/docs/docs-create-doc.mdx#document-id) for more details. ## Structured content {#structured-content} diff --git a/website/versioned_docs/version-2.x/using-plugins.mdx b/website/versioned_docs/version-2.x/using-plugins.mdx index c40672830ee6..8d7accf505b5 100644 --- a/website/versioned_docs/version-2.x/using-plugins.mdx +++ b/website/versioned_docs/version-2.x/using-plugins.mdx @@ -114,7 +114,7 @@ At most one plugin instance can be the "default plugin instance", by omitting th ## Using themes {#using-themes} -Themes are loaded in the exact same way as plugins. From the consumer perspective, the `themes` and `plugins` entries are interchangeable when installing and configuring a plugin. The only nuance is that themes are loaded after plugins, and it's possible for [a theme to override a plugin's default theme components](./swizzling.mdx#theme-aliases). +Themes are loaded in the exact same way as plugins. From the consumer perspective, the `themes` and `plugins` entries are interchangeable when installing and configuring a plugin. The only nuance is that themes are loaded after plugins, and it's possible for [a theme to override a plugin's default theme components](./advanced/client.mdx#theme-aliases). :::tip diff --git a/website/versioned_docs/version-3.0.0/advanced/routing.mdx b/website/versioned_docs/version-3.0.0/advanced/routing.mdx index 5bf943072ba6..e9e96d4892c7 100644 --- a/website/versioned_docs/version-3.0.0/advanced/routing.mdx +++ b/website/versioned_docs/version-3.0.0/advanced/routing.mdx @@ -265,26 +265,18 @@ export function PageRoute() { Docusaurus builds a [single-page application](https://developer.mozilla.org/en-US/docs/Glossary/SPA), where route transitions are done through the `history.push()` method of React router. This operation is done on the client side. However, the prerequisite for a route transition to happen this way is that the target URL is known to our router. Otherwise, the router catches this path and displays a 404 page instead. -If you put some HTML pages under the `static` folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a `pathname://` protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link. Try the following two links: +If you put some HTML pages under the `static` folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a `pathname://` protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link. ```md -- [/pure-html](/pure-html) - [pathname:///pure-html](pathname:///pure-html) ``` <BrowserWindow> -- [`/pure-html`](/pure-html) - [`pathname:///pure-html`](pathname:///pure-html) </BrowserWindow> -:::tip - -The first link will **not** trigger a "broken links detected" check during the production build, because the respective file actually exists. Nevertheless, when you click on the link, a "page not found" will be displayed until you refresh. - -::: - The `pathname://` protocol is useful for referencing any content in the static folder. For example, Docusaurus would convert [all Markdown static assets to require() calls](../guides/markdown-features/markdown-features-assets.mdx#static-assets). You can use `pathname://` to keep it a regular link instead of being hashed by Webpack. ```md title="my-doc.md" diff --git a/website/versioned_docs/version-3.0.0/api/plugins/plugin-content-docs.mdx b/website/versioned_docs/version-3.0.0/api/plugins/plugin-content-docs.mdx index d9238f65bb36..754a56d293d9 100644 --- a/website/versioned_docs/version-3.0.0/api/plugins/plugin-content-docs.mdx +++ b/website/versioned_docs/version-3.0.0/api/plugins/plugin-content-docs.mdx @@ -42,10 +42,10 @@ Accepted fields: | `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. | | `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. | | `sidebarPath` | <code>false \| string</code> | `undefined` | Path to sidebar configuration. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. | -| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar#collapsible-categories) | -| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar#expanded-categories-by-default) | -| `sidebarItemsGenerator` | <a href="#SidebarGenerator"><code>SidebarGenerator</code></a> | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) | -| `numberPrefixParser` | <code>boolean \|</code> <a href="#PrefixParser"><code>PrefixParser</code></a> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar#using-number-prefixes) | +| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar/items#collapsible-categories) | +| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar/items#expanded-categories-by-default) | +| `sidebarItemsGenerator` | <a href="#SidebarGenerator"><code>SidebarGenerator</code></a> | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar/autogenerated#customize-the-sidebar-items-generator) | +| `numberPrefixParser` | <code>boolean \|</code> <a href="#PrefixParser"><code>PrefixParser</code></a> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes) | | `docsRootComponent` | `string` | `'@theme/DocsRoot'` | Parent component of all the docs plugin pages (including all versions). Stays mounted when navigation between docs pages and versions. | | `docVersionRootComponent` | `string` | `'@theme/DocVersionLayout'` | Parent component of all docs pages of an individual version (doc pages with sidebars, tags pages). Stays mounted when navigation between pages of that specific version. | | `docRootComponent` | `string` | `'@theme/DocPage'` | Parent component of all doc pages with sidebars (regular docs pages, category generated index pages). Stays mounted when navigation between such pages. | @@ -275,7 +275,7 @@ Accepted fields: | `title` | `string` | Markdown title or `id` | The text title of your document. Used for the page metadata and as a fallback value in multiple places (sidebar, next/previous buttons...). Automatically added at the top of your doc if it does not contain any Markdown title. | | `pagination_label` | `string` | `sidebar_label` or `title` | The text used in the document next/previous buttons for this document. | | `sidebar_label` | `string` | `title` | The text shown in the document sidebar for this document. | -| `sidebar_position` | `number` | Default ordering | Controls the position of a doc inside the generated sidebar slice when using `autogenerated` sidebar items. See also [Autogenerated sidebar metadata](/docs/sidebar#autogenerated-sidebar-metadata). | +| `sidebar_position` | `number` | Default ordering | Controls the position of a doc inside the generated sidebar slice when using `autogenerated` sidebar items. See also [Autogenerated sidebar metadata](/docs/sidebar/autogenerated#autogenerated-sidebar-metadata). | | `sidebar_class_name` | `string` | `undefined` | Gives the corresponding sidebar label a special class name when using autogenerated sidebars. | | `sidebar_custom_props` | `object` | `undefined` | Assign [custom props](../../guides/docs/sidebar/index.mdx#passing-custom-props) to the sidebar item referencing this doc | | `displayed_sidebar` | `string` | `undefined` | Force the display of a given sidebar when browsing the current document. Read the [multiple sidebars guide](../../guides/docs/sidebar/multiple-sidebars.mdx) for details. | @@ -285,7 +285,7 @@ Accepted fields: | `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | | `pagination_next` | <code>string \| null</code> | Next doc in the sidebar | The ID of the documentation you want the "Next" pagination to link to. Use `null` to disable showing "Next" for this page. | | `pagination_prev` | <code>string \| null</code> | Previous doc in the sidebar | The ID of the documentation you want the "Previous" pagination to link to. Use `null` to disable showing "Previous" for this page. | -| `parse_number_prefixes` | `boolean` | `numberPrefixParser` plugin option | Whether number prefix parsing is disabled on this doc. See also [Using number prefixes](/docs/sidebar#using-number-prefixes). | +| `parse_number_prefixes` | `boolean` | `numberPrefixParser` plugin option | Whether number prefix parsing is disabled on this doc. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes). | | `custom_edit_url` | <code>string \| null</code> | Computed using the `editUrl` plugin option | The URL for editing this document. Use `null` to disable showing "Edit this page" for this page. | | `keywords` | `string[]` | `undefined` | Keywords meta tag for the document page, for search engines. | | `description` | `string` | The first line of Markdown content | The description of your document, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. | diff --git a/website/versioned_docs/version-3.0.0/cli.mdx b/website/versioned_docs/version-3.0.0/cli.mdx index 0b38c01776f7..bb1f32c91d68 100644 --- a/website/versioned_docs/version-3.0.0/cli.mdx +++ b/website/versioned_docs/version-3.0.0/cli.mdx @@ -177,7 +177,7 @@ By default, the files are written in `website/i18n/<defaultLocale>/...`. ### `docusaurus write-heading-ids [siteDir] [files]` {#docusaurus-write-heading-ids-sitedir} -Add [explicit heading IDs](./guides/markdown-features/markdown-features-toc.mdx#explicit-ids) to the Markdown documents of your site. +Add [explicit heading IDs](./guides/markdown-features/markdown-features-toc.mdx#heading-ids) to the Markdown documents of your site. | Name | Default | Description | | --- | --- | --- | diff --git a/website/versioned_docs/version-3.0.0/guides/docs/sidebar/autogenerated.mdx b/website/versioned_docs/version-3.0.0/guides/docs/sidebar/autogenerated.mdx index 000e1e4cbdcf..7e3bfcf0a005 100644 --- a/website/versioned_docs/version-3.0.0/guides/docs/sidebar/autogenerated.mdx +++ b/website/versioned_docs/version-3.0.0/guides/docs/sidebar/autogenerated.mdx @@ -371,7 +371,7 @@ customProps: :::info -If the `link` is explicitly specified, Docusaurus will not apply any [default conventions](items.mdx#category-index-convention). +If the `link` is explicitly specified, Docusaurus will not apply any [default conventions](#category-index-convention). The doc links can be specified relatively, e.g. if the category is generated with the `guides` directory, `"link": {"type": "doc", "id": "intro"}` will be resolved to the ID `guides/intro`, only falling back to `intro` if a doc with the former ID doesn't exist. diff --git a/website/versioned_docs/version-3.0.0/guides/docs/versioning.mdx b/website/versioned_docs/version-3.0.0/guides/docs/versioning.mdx index b473d69a1268..1fa34fb1c5f4 100644 --- a/website/versioned_docs/version-3.0.0/guides/docs/versioning.mdx +++ b/website/versioned_docs/version-3.0.0/guides/docs/versioning.mdx @@ -106,7 +106,7 @@ npm run docusaurus docs:version 1.1.0 When tagging a new version, the document versioning mechanism will: - Copy the full `docs/` folder contents into a new `versioned_docs/version-[versionName]/` folder. -- Create a versioned sidebars file based from your current [sidebar](docs-introduction.mdx#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-[versionName]-sidebars.json`. +- Create a versioned sidebars file based from your current [sidebar](./sidebar/index.mdx) configuration (if it exists) - saved as `versioned_sidebars/version-[versionName]-sidebars.json`. - Append the new version number to `versions.json`. ### Creating new docs {#creating-new-docs} diff --git a/website/versioned_docs/version-3.0.0/i18n/i18n-tutorial.mdx b/website/versioned_docs/version-3.0.0/i18n/i18n-tutorial.mdx index b74896547cd7..a88e2f0a388b 100644 --- a/website/versioned_docs/version-3.0.0/i18n/i18n-tutorial.mdx +++ b/website/versioned_docs/version-3.0.0/i18n/i18n-tutorial.mdx @@ -445,7 +445,7 @@ Generated IDs are not always a good fit for localized sites, as it requires you + [link](#bonjour-le-monde) ``` -For localized sites, it is recommended to use **[explicit heading IDs](../guides/markdown-features/markdown-features-toc.mdx#explicit-ids)**. +For localized sites, it is recommended to use **[explicit heading IDs](../guides/markdown-features/markdown-features-toc.mdx#heading-ids)**. ::: diff --git a/website/versioned_docs/version-3.0.0/seo.mdx b/website/versioned_docs/version-3.0.0/seo.mdx index 147bf99657c0..031ab1ddf340 100644 --- a/website/versioned_docs/version-3.0.0/seo.mdx +++ b/website/versioned_docs/version-3.0.0/seo.mdx @@ -211,7 +211,7 @@ For example, [`/examples/noIndex`](/examples/noIndex) is not included in the [Do ## Human readable links {#human-readable-links} -Docusaurus uses your file names as links, but you can always change that using slugs, see this [tutorial](./guides/docs/docs-introduction.mdx#document-id) for more details. +Docusaurus uses your file names as links, but you can always change that using slugs, see this [tutorial](./guides/docs/docs-create-doc.mdx#document-id) for more details. ## Structured content {#structured-content} diff --git a/website/versioned_docs/version-3.0.0/using-plugins.mdx b/website/versioned_docs/version-3.0.0/using-plugins.mdx index 28e25e491541..92d86097d717 100644 --- a/website/versioned_docs/version-3.0.0/using-plugins.mdx +++ b/website/versioned_docs/version-3.0.0/using-plugins.mdx @@ -114,7 +114,7 @@ At most one plugin instance can be the "default plugin instance", by omitting th ## Using themes {#using-themes} -Themes are loaded in the exact same way as plugins. From the consumer perspective, the `themes` and `plugins` entries are interchangeable when installing and configuring a plugin. The only nuance is that themes are loaded after plugins, and it's possible for [a theme to override a plugin's default theme components](./swizzling.mdx#theme-aliases). +Themes are loaded in the exact same way as plugins. From the consumer perspective, the `themes` and `plugins` entries are interchangeable when installing and configuring a plugin. The only nuance is that themes are loaded after plugins, and it's possible for [a theme to override a plugin's default theme components](./advanced/client.mdx#theme-aliases). :::tip diff --git a/yarn.lock b/yarn.lock index 734a9c96ac4d..b7eb7ddca010 100644 --- a/yarn.lock +++ b/yarn.lock @@ -192,46 +192,46 @@ resolved "https://registry.yarnpkg.com/@argos-ci/util/-/util-1.0.0.tgz#52f5270f5377e25f471951d0620c8a6b82e5aee6" integrity sha512-aljQTWre/WoLY88WlXyK72cxxI391bQYoSVDFfcZ17dKw/BKnzVSfL7yB/oD9XrsZahzEwGZmooFPs8c27hNaQ== -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.8.3": - version "7.22.13" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" - integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.8.3": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== dependencies: - "@babel/highlight" "^7.22.13" + "@babel/highlight" "^7.23.4" chalk "^2.4.2" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9", "@babel/compat-data@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.3.tgz#3febd552541e62b5e883a25eb3effd7c7379db11" - integrity sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.3", "@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== "@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.19.6", "@babel/core@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.3.tgz#5ec09c8803b91f51cc887dedc2654a35852849c9" - integrity sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew== + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f" + integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.13" - "@babel/generator" "^7.23.3" - "@babel/helper-compilation-targets" "^7.22.15" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.2" - "@babel/parser" "^7.23.3" + "@babel/helpers" "^7.23.7" + "@babel/parser" "^7.23.6" "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.3" - "@babel/types" "^7.23.3" + "@babel/traverse" "^7.23.7" + "@babel/types" "^7.23.6" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.23.3", "@babel/generator@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.3.tgz#86e6e83d95903fbe7613f448613b8b319f330a8e" - integrity sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg== +"@babel/generator@^7.23.3", "@babel/generator@^7.23.6", "@babel/generator@^7.7.2": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== dependencies: - "@babel/types" "^7.23.3" + "@babel/types" "^7.23.6" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" @@ -250,14 +250,14 @@ dependencies: "@babel/types" "^7.22.15" -"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" - integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== +"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== dependencies: - "@babel/compat-data" "^7.22.9" - "@babel/helper-validator-option" "^7.22.15" - browserslist "^4.21.9" + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" lru-cache "^5.1.1" semver "^6.3.1" @@ -392,20 +392,20 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-string-parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" - integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== -"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.22.5": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" - integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== +"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.22.5", "@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== "@babel/helper-wrap-function@^7.22.20": version "7.22.20" @@ -416,28 +416,28 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.22.19" -"@babel/helpers@^7.23.2": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767" - integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ== +"@babel/helpers@^7.23.7": + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.7.tgz#eb543c36f81da2873e47b76ee032343ac83bba60" + integrity sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ== dependencies: "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.2" - "@babel/types" "^7.23.0" + "@babel/traverse" "^7.23.7" + "@babel/types" "^7.23.6" -"@babel/highlight@^7.22.13": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" - integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== dependencies: "@babel/helper-validator-identifier" "^7.22.20" chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.7", "@babel/parser@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.3.tgz#0ce0be31a4ca4f1884b5786057cadcb6c3be58f9" - integrity sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.7", "@babel/parser@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" + integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3": version "7.23.3" @@ -1198,11 +1198,11 @@ regenerator-runtime "^0.13.11" "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.20.7", "@babel/runtime@^7.22.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" - integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.7.tgz#dd7c88deeb218a0f8bd34d5db1aa242e0f203193" + integrity sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA== dependencies: - regenerator-runtime "^0.13.11" + regenerator-runtime "^0.14.0" "@babel/template@^7.22.15", "@babel/template@^7.3.3": version "7.22.15" @@ -1213,28 +1213,28 @@ "@babel/parser" "^7.22.15" "@babel/types" "^7.22.15" -"@babel/traverse@^7.22.8", "@babel/traverse@^7.23.2", "@babel/traverse@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.3.tgz#26ee5f252e725aa7aca3474aa5b324eaf7908b5b" - integrity sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ== +"@babel/traverse@^7.22.8", "@babel/traverse@^7.23.7": + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305" + integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg== dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/generator" "^7.23.3" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.3" - "@babel/types" "^7.23.3" - debug "^4.1.0" + "@babel/parser" "^7.23.6" + "@babel/types" "^7.23.6" + debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.3", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.3.tgz#d5ea892c07f2ec371ac704420f4dcdb07b5f9598" - integrity sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw== +"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" + integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== dependencies: - "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-string-parser" "^7.23.4" "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" @@ -1271,139 +1271,155 @@ dependencies: axios "^1" -"@cspell/cspell-bundled-dicts@6.31.2": - version "6.31.2" - resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-6.31.2.tgz#42865a6c025b0ce5550efa24c9a78d7094b206dc" - integrity sha512-rQ5y/U1Ah5AaduIh3NU2z371hRrOr1cmNdhhP8oiuz2E4VqmcoVHflXIct9DgY8uIJpwsSCdR6ypOQWZYXYnwA== - dependencies: - "@cspell/dict-ada" "^4.0.1" - "@cspell/dict-aws" "^3.0.0" - "@cspell/dict-bash" "^4.1.1" - "@cspell/dict-companies" "^3.0.9" - "@cspell/dict-cpp" "^5.0.2" - "@cspell/dict-cryptocurrencies" "^3.0.1" +"@cspell/cspell-bundled-dicts@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.1.0.tgz#7103d6087a4d26c6d34fadf04fbde78bb5b71348" + integrity sha512-o/R/kR1QO9SQV2hUroaguTlHD6MDDtrVY6Xj5eG0loM7T0Pm3TEdlGYQ0LP6O9/CfUiHTntIFUM+PJ999+LuHQ== + dependencies: + "@cspell/dict-ada" "^4.0.2" + "@cspell/dict-aws" "^4.0.0" + "@cspell/dict-bash" "^4.1.2" + "@cspell/dict-companies" "^3.0.28" + "@cspell/dict-cpp" "^5.0.10" + "@cspell/dict-cryptocurrencies" "^4.0.0" "@cspell/dict-csharp" "^4.0.2" - "@cspell/dict-css" "^4.0.5" - "@cspell/dict-dart" "^2.0.2" - "@cspell/dict-django" "^4.0.2" - "@cspell/dict-docker" "^1.1.6" + "@cspell/dict-css" "^4.0.12" + "@cspell/dict-dart" "^2.0.3" + "@cspell/dict-django" "^4.1.0" + "@cspell/dict-docker" "^1.1.7" "@cspell/dict-dotnet" "^5.0.0" - "@cspell/dict-elixir" "^4.0.2" + "@cspell/dict-elixir" "^4.0.3" "@cspell/dict-en-common-misspellings" "^1.0.2" "@cspell/dict-en-gb" "1.1.33" - "@cspell/dict-en_us" "^4.3.2" - "@cspell/dict-filetypes" "^3.0.0" - "@cspell/dict-fonts" "^3.0.2" + "@cspell/dict-en_us" "^4.3.12" + "@cspell/dict-filetypes" "^3.0.3" + "@cspell/dict-fonts" "^4.0.0" + "@cspell/dict-fsharp" "^1.0.1" "@cspell/dict-fullstack" "^3.1.5" "@cspell/dict-gaming-terms" "^1.0.4" "@cspell/dict-git" "^2.0.0" - "@cspell/dict-golang" "^6.0.1" + "@cspell/dict-golang" "^6.0.5" "@cspell/dict-haskell" "^4.0.1" - "@cspell/dict-html" "^4.0.3" + "@cspell/dict-html" "^4.0.5" "@cspell/dict-html-symbol-entities" "^4.0.0" - "@cspell/dict-java" "^5.0.5" - "@cspell/dict-k8s" "^1.0.1" + "@cspell/dict-java" "^5.0.6" + "@cspell/dict-k8s" "^1.0.2" "@cspell/dict-latex" "^4.0.0" - "@cspell/dict-lorem-ipsum" "^3.0.0" - "@cspell/dict-lua" "^4.0.1" - "@cspell/dict-node" "^4.0.2" - "@cspell/dict-npm" "^5.0.5" - "@cspell/dict-php" "^4.0.1" - "@cspell/dict-powershell" "^5.0.1" - "@cspell/dict-public-licenses" "^2.0.2" - "@cspell/dict-python" "^4.0.2" + "@cspell/dict-lorem-ipsum" "^4.0.0" + "@cspell/dict-lua" "^4.0.2" + "@cspell/dict-makefile" "^1.0.0" + "@cspell/dict-node" "^4.0.3" + "@cspell/dict-npm" "^5.0.13" + "@cspell/dict-php" "^4.0.4" + "@cspell/dict-powershell" "^5.0.2" + "@cspell/dict-public-licenses" "^2.0.5" + "@cspell/dict-python" "^4.1.10" "@cspell/dict-r" "^2.0.1" - "@cspell/dict-ruby" "^5.0.0" + "@cspell/dict-ruby" "^5.0.1" "@cspell/dict-rust" "^4.0.1" "@cspell/dict-scala" "^5.0.0" - "@cspell/dict-software-terms" "^3.1.6" - "@cspell/dict-sql" "^2.1.0" + "@cspell/dict-software-terms" "^3.3.11" + "@cspell/dict-sql" "^2.1.2" "@cspell/dict-svelte" "^1.0.2" "@cspell/dict-swift" "^2.0.1" - "@cspell/dict-typescript" "^3.1.1" + "@cspell/dict-typescript" "^3.1.2" "@cspell/dict-vue" "^3.0.0" -"@cspell/cspell-pipe@6.31.1": - version "6.31.1" - resolved "https://registry.yarnpkg.com/@cspell/cspell-pipe/-/cspell-pipe-6.31.1.tgz#6c8edc92039125695a894186a899290d56d0f2c7" - integrity sha512-zk1olZi4dr6GLm5PAjvsiZ01HURNSruUYFl1qSicGnTwYN8GaN4RhAwannAytcJ7zJPIcyXlid0YsB58nJf3wQ== +"@cspell/cspell-json-reporter@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.1.0.tgz#96eb098580e6962afba2efdc65b18df50555aba4" + integrity sha512-Iss9dq5XBc5wYADv/Z59W4DgRQYs8BSHNVD6+LbQctuqmeJAte426/oi4x0Y76AJtEe0N6BZouj8HXykovwP5w== + dependencies: + "@cspell/cspell-types" "8.1.0" -"@cspell/cspell-service-bus@6.31.1": - version "6.31.1" - resolved "https://registry.yarnpkg.com/@cspell/cspell-service-bus/-/cspell-service-bus-6.31.1.tgz#ede5859e180f8d9be760df500e02164dae0084fe" - integrity sha512-YyBicmJyZ1uwKVxujXw7sgs9x+Eps43OkWmCtDZmZlnq489HdTSuhF1kTbVi2yeFSeaXIS87+uHo12z97KkQpg== +"@cspell/cspell-pipe@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@cspell/cspell-pipe/-/cspell-pipe-8.1.0.tgz#871d88a0e5c50ccbbe423738da9a07fef8831d3b" + integrity sha512-HDNX7MFAPAJ9acyYBa1bG+P4WiHHMFNYeywYBf3h6ScVhHobAqnhqS6b8R7MVhVRivwnKIQPG3zK7UpcwfyRcw== -"@cspell/cspell-types@6.31.1": - version "6.31.1" - resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-6.31.1.tgz#b3737ef7743c0e5803d57e667f816418ac8da1cf" - integrity sha512-1KeTQFiHMssW1eRoF2NZIEg4gPVIfXLsL2+VSD/AV6YN7lBcuf6gRRgV5KWYarhxtEfjxhDdDTmu26l/iJEUtw== +"@cspell/cspell-resolver@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@cspell/cspell-resolver/-/cspell-resolver-8.1.0.tgz#5028978abd31d80ce5dfa4b844a7deefa716ab88" + integrity sha512-nlppKh2o6g0zz+oIQ/dZB+oFQFf8lvn3mJKBpDwoeQY7/o9ZORPibXjtqXM83OhhdpoUVuk+3RFMsnFBBffa2Q== + dependencies: + global-directory "^4.0.1" -"@cspell/dict-ada@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-ada/-/dict-ada-4.0.1.tgz#214c91445eab16bd3fe10da5517f95bf2c90fe5f" - integrity sha512-/E9o3nHrXOhYmQE43deKbxZcR3MIJAsa+66IzP9TXGHheKEx8b9dVMVVqydDDH8oom1H0U20NRPtu6KRVbT9xw== +"@cspell/cspell-service-bus@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@cspell/cspell-service-bus/-/cspell-service-bus-8.1.0.tgz#38e61e8b47c05eebe9a4b9ba43241d5cb9909a63" + integrity sha512-9Enayhkef732f15kHgiUe4QKyJgKk1dcZ4EFq4eyzUUDFF/eBv6qTQo5k2juUhPIjaKosqqMBHg4ffXcpkhr+Q== -"@cspell/dict-aws@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@cspell/dict-aws/-/dict-aws-3.0.0.tgz#7b2db82bb632c664c3d72b83267b93b9b0cafe60" - integrity sha512-O1W6nd5y3Z00AMXQMzfiYrIJ1sTd9fB1oLr+xf/UD7b3xeHeMeYE2OtcWbt9uyeHim4tk+vkSTcmYEBKJgS5bQ== +"@cspell/cspell-types@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-8.1.0.tgz#1a1f4df435a62a7ea2c56a075bdff935e3a799cd" + integrity sha512-1SxBjQdZtVjrTs3Ftw5I3nNpuDjdpsFMvfbbt6EnxqMpmZiUwkqxLCKla0pEy5R9CZcFFlntlOTMTmNsIkgmWg== -"@cspell/dict-bash@^4.1.1": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-bash/-/dict-bash-4.1.1.tgz#fe28016096f44d4a09fe4c5bcaf6fa40f33d98c6" - integrity sha512-8czAa/Mh96wu2xr0RXQEGMTBUGkTvYn/Pb0o+gqOO1YW+poXGQc3gx0YPqILDryP/KCERrNvkWUJz3iGbvwC2A== +"@cspell/dict-ada@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-ada/-/dict-ada-4.0.2.tgz#8da2216660aeb831a0d9055399a364a01db5805a" + integrity sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA== -"@cspell/dict-companies@^3.0.9": - version "3.0.17" - resolved "https://registry.yarnpkg.com/@cspell/dict-companies/-/dict-companies-3.0.17.tgz#98c8bed74892a415f9471f77d11d2aa8f727b103" - integrity sha512-vo1jbozgZWSzz2evIL26kLd35tVb+5kW/UTvTzAwaWutSWRloRyKx38nj2CaLJ2IFxBdiATteCFGTzKCvJJl6A== +"@cspell/dict-aws@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-aws/-/dict-aws-4.0.0.tgz#ab71fe0c05d9ad662d27495e74361bdcb5b470eb" + integrity sha512-1YkCMWuna/EGIDN/zKkW+j98/55mxigftrSFgsehXhPld+ZMJM5J9UuBA88YfL7+/ETvBdd7mwW6IwWsC+/ltQ== -"@cspell/dict-cpp@^5.0.2": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@cspell/dict-cpp/-/dict-cpp-5.0.3.tgz#231c03019dba4db59bcfee0fda5a710d70569052" - integrity sha512-7sx/RFsf0hB3q8chx8OHYl9Kd+g0pqA1laphwaAQ+/jPwoAreYT3kNQWbJ3bIt/rMoORetFSQxckSbaJXwwqpw== +"@cspell/dict-bash@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-bash/-/dict-bash-4.1.2.tgz#47696a13f6294c310801b811e75fc62e6151d28c" + integrity sha512-AEBWjbaMaJEyAjOHW0F15P2izBjli2cNerG3NjuVH7xX/HUUeNoTj8FF1nwpMufKwGQCvuyO2hCmkVxhJ0y55Q== -"@cspell/dict-cryptocurrencies@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-3.0.1.tgz#de1c235d6427946b679d23aacff12fea94e6385b" - integrity sha512-Tdlr0Ahpp5yxtwM0ukC13V6+uYCI0p9fCRGMGZt36rWv8JQZHIuHfehNl7FB/Qc09NCF7p5ep0GXbL+sVTd/+w== +"@cspell/dict-companies@^3.0.28": + version "3.0.28" + resolved "https://registry.yarnpkg.com/@cspell/dict-companies/-/dict-companies-3.0.28.tgz#d617be3e036955d2f656d568f0cc6d1bdf198819" + integrity sha512-UinHkMYB/1pUkLKm1PGIm9PBFYxeAa6YvbB1Rq/RAAlrs0WDwiDBr3BAYdxydukG1IqqwT5z9WtU+8D/yV/5lw== + +"@cspell/dict-cpp@^5.0.10": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@cspell/dict-cpp/-/dict-cpp-5.0.10.tgz#08c3eb438b631dd3f0fc04f5a6d4b6cab87c8d9b" + integrity sha512-WCRuDrkFdpmeIR6uXQYKU9loMQKNFS4bUhtHdv5fu4qVyJSh3k/kgmtTm1h1BDTj8EwPRc/RGxS+9Z3b2mnabA== + +"@cspell/dict-cryptocurrencies@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-4.0.0.tgz#6517a7e1b0ed184cf3fc18f03230c82508369dec" + integrity sha512-EiZp91ATyRxTmauIQfOX9adLYCunKjHEh092rrM7o2eMXP9n7zpXAL9BK7LviL+LbB8VDOm21q+s83cKrrRrsg== "@cspell/dict-csharp@^4.0.2": version "4.0.2" resolved "https://registry.yarnpkg.com/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz#e55659dbe594e744d86b1baf0f3397fe57b1e283" integrity sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g== -"@cspell/dict-css@^4.0.5": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@cspell/dict-css/-/dict-css-4.0.6.tgz#39cf199e68d6e17b9518938fa64368cec2f7f9ca" - integrity sha512-2Lo8W2ezHmGgY8cWFr4RUwnjbndna5mokpCK/DuxGILQnuajR0J31ANQOXj/8iZM2phFB93ZzMNk/0c04TDfSQ== +"@cspell/dict-css@^4.0.12": + version "4.0.12" + resolved "https://registry.yarnpkg.com/@cspell/dict-css/-/dict-css-4.0.12.tgz#59abf3512ae729835c933c38f64a3d8a5f09ce3d" + integrity sha512-vGBgPM92MkHQF5/2jsWcnaahOZ+C6OE/fPvd5ScBP72oFY9tn5GLuomcyO0z8vWCr2e0nUSX1OGimPtcQAlvSw== -"@cspell/dict-dart@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-dart/-/dict-dart-2.0.2.tgz#714285f4f8bd304c1c477779ccbbfae5949819d7" - integrity sha512-jigcODm7Z4IFZ4vParwwP3IT0fIgRq/9VoxkXfrxBMsLBGGM2QltHBj7pl+joX+c4cOHxfyZktGJK1B1wFtR4Q== +"@cspell/dict-dart@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-dart/-/dict-dart-2.0.3.tgz#75e7ffe47d5889c2c831af35acdd92ebdbd4cf12" + integrity sha512-cLkwo1KT5CJY5N5RJVHks2genFkNCl/WLfj+0fFjqNR+tk3tBI1LY7ldr9piCtSFSm4x9pO1x6IV3kRUY1lLiw== -"@cspell/dict-data-science@^1.0.0": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@cspell/dict-data-science/-/dict-data-science-1.0.7.tgz#4f4fe831c10b97336d7ceff3a4278006f79e77ed" - integrity sha512-Q9VUFaarUpqM6CAmR8peP4o9alk0XQ4rgVoE2R2XalpC2cqPI8Hmg6QwMU2UPioSUcWMJCqLc/KzJti0gBMuxA== +"@cspell/dict-data-science@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@cspell/dict-data-science/-/dict-data-science-1.0.11.tgz#4eabba75c21d27253c1114b4fbbade0ead739ffc" + integrity sha512-TaHAZRVe0Zlcc3C23StZqqbzC0NrodRwoSAc8dis+5qLeLLnOCtagYQeROQvDlcDg3X/VVEO9Whh4W/z4PAmYQ== -"@cspell/dict-django@^4.0.2": +"@cspell/dict-django@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@cspell/dict-django/-/dict-django-4.1.0.tgz#2d4b765daf3c83e733ef3e06887ea34403a4de7a" integrity sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w== -"@cspell/dict-docker@^1.1.6": - version "1.1.6" - resolved "https://registry.yarnpkg.com/@cspell/dict-docker/-/dict-docker-1.1.6.tgz#f84faed121e2093e3b212d19542fd27eda751c80" - integrity sha512-zCCiRTZ6EOQpBnSOm0/3rnKW1kCcAUDUA7SxJG3SuH6iZvKi3I8FEg8+O83WQUeXg0SyPNerD9F40JLnnJjJig== +"@cspell/dict-docker@^1.1.7": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@cspell/dict-docker/-/dict-docker-1.1.7.tgz#bcf933283fbdfef19c71a642e7e8c38baf9014f2" + integrity sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A== "@cspell/dict-dotnet@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-5.0.0.tgz#13690aafe14b240ad17a30225ac1ec29a5a6a510" integrity sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw== -"@cspell/dict-elixir@^4.0.2": +"@cspell/dict-elixir@^4.0.3": version "4.0.3" resolved "https://registry.yarnpkg.com/@cspell/dict-elixir/-/dict-elixir-4.0.3.tgz#57c25843e46cf3463f97da72d9ef8e37c818296f" integrity sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q== @@ -1418,20 +1434,25 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz#7f1fd90fc364a5cb77111b5438fc9fcf9cc6da0e" integrity sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g== -"@cspell/dict-en_us@^4.3.2": - version "4.3.4" - resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-4.3.4.tgz#176fbbcd546538787776007fa38a58c1424243a7" - integrity sha512-mR2yqWmFip1zTKja2SqyVMbzuqEThqkEJk9M32bMDziPJpEyOIPvLA0UPmj3cyRKJkRuVF0bhDCE33O+at38hw== +"@cspell/dict-en_us@^4.3.12": + version "4.3.12" + resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-4.3.12.tgz#3b0ceaf5ed3cf30b225834ca7d528e4dc96e9605" + integrity sha512-1bsUxFjgxF30FTzcU5uvmCvH3lyqVKR9dbwsJhomBlUM97f0edrd6590SiYBXDm7ruE68m3lJd4vs0Ev2D6FtQ== -"@cspell/dict-filetypes@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-filetypes/-/dict-filetypes-3.0.1.tgz#61642b14af90894e6acf4c00f20ab2d097c1ed12" - integrity sha512-8z8mY1IbrTyTRumx2vvD9yzRhNMk9SajM/GtI5hdMM2pPpNSp25bnuauzjRf300eqlqPY2MNb5MmhBFO014DJw== +"@cspell/dict-filetypes@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-filetypes/-/dict-filetypes-3.0.3.tgz#ab0723ca2f4d3d5674e9c9745efc9f144e49c905" + integrity sha512-J9UP+qwwBLfOQ8Qg9tAsKtSY/WWmjj21uj6zXTI9hRLD1eG1uUOLcfVovAmtmVqUWziPSKMr87F6SXI3xmJXgw== -"@cspell/dict-fonts@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-fonts/-/dict-fonts-3.0.2.tgz#657d871cf627466765166cf18c448743c19317e2" - integrity sha512-Z5QdbgEI7DV+KPXrAeDA6dDm/vTzyaW53SGlKqz6PI5VhkOjgkBXv3YtZjnxMZ4dY2ZIqq+RUK6qa9Pi8rQdGQ== +"@cspell/dict-fonts@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-fonts/-/dict-fonts-4.0.0.tgz#9bc8beb2a7b068b4fdb45cb994b36fd184316327" + integrity sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q== + +"@cspell/dict-fsharp@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-fsharp/-/dict-fsharp-1.0.1.tgz#d62c699550a39174f182f23c8c1330a795ab5f53" + integrity sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ== "@cspell/dict-fullstack@^3.1.5": version "3.1.5" @@ -1448,10 +1469,10 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-git/-/dict-git-2.0.0.tgz#fa5cb298845da9c69efc01c6af07a99097718dc9" integrity sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w== -"@cspell/dict-golang@^6.0.1": - version "6.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-golang/-/dict-golang-6.0.2.tgz#dcba58b9e658c1cc713c19965a358185d15d1987" - integrity sha512-5pyZn4AAiYukAW+gVMIMVmUSkIERFrDX2vtPDjg8PLQUhAHWiVeQSDjuOhq9/C5GCCEZU/zWSONkGiwLBBvV9A== +"@cspell/dict-golang@^6.0.5": + version "6.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-golang/-/dict-golang-6.0.5.tgz#4dd2e2fda419730a21fb77ade3b90241ad4a5bcc" + integrity sha512-w4mEqGz4/wV+BBljLxduFNkMrd3rstBNDXmoX5kD4UTzIb4Sy0QybWCtg2iVT+R0KWiRRA56QKOvBsgXiddksA== "@cspell/dict-haskell@^4.0.1": version "4.0.1" @@ -1463,77 +1484,82 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.0.tgz#4d86ac18a4a11fdb61dfb6f5929acd768a52564f" integrity sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw== -"@cspell/dict-html@^4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@cspell/dict-html/-/dict-html-4.0.3.tgz#155450cb57750774583fce463d01d6323ab41701" - integrity sha512-Gae8i8rrArT0UyG1I6DHDK62b7Be6QEcBSIeWOm4VIIW1CASkN9B0qFgSVnkmfvnu1Y3H7SSaaEynKjdj3cs8w== +"@cspell/dict-html@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-html/-/dict-html-4.0.5.tgz#03a5182148d80e6c25f71339dbb2b7c5b9894ef8" + integrity sha512-p0brEnRybzSSWi8sGbuVEf7jSTDmXPx7XhQUb5bgG6b54uj+Z0Qf0V2n8b/LWwIPJNd1GygaO9l8k3HTCy1h4w== -"@cspell/dict-java@^5.0.5": - version "5.0.5" - resolved "https://registry.yarnpkg.com/@cspell/dict-java/-/dict-java-5.0.5.tgz#c673f27ce7a5d96e205f42e8be540aeda0beef11" - integrity sha512-X19AoJgWIBwJBSWGFqSgHaBR/FEykBHTMjL6EqOnhIGEyE9nvuo32tsSHjXNJ230fQxQptEvRZoaldNLtKxsRg== +"@cspell/dict-java@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@cspell/dict-java/-/dict-java-5.0.6.tgz#2462d6fc15f79ec15eb88ecf875b6ad2a7bf7a6a" + integrity sha512-kdE4AHHHrixyZ5p6zyms1SLoYpaJarPxrz8Tveo6gddszBVVwIUZ+JkQE1bWNLK740GWzIXdkznpUfw1hP9nXw== -"@cspell/dict-k8s@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-k8s/-/dict-k8s-1.0.1.tgz#6c0cc521dd42fee2c807368ebfef77137686f3a1" - integrity sha512-gc5y4Nm3hVdMZNBZfU2M1AsAmObZsRWjCUk01NFPfGhFBXyVne41T7E62rpnzu5330FV/6b/TnFcPgRmak9lLw== +"@cspell/dict-k8s@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-k8s/-/dict-k8s-1.0.2.tgz#b19e66f4ac8a4264c0f3981ac6e23e88a60f1c91" + integrity sha512-tLT7gZpNPnGa+IIFvK9SP1LrSpPpJ94a/DulzAPOb1Q2UBFwdpFd82UWhio0RNShduvKG/WiMZf/wGl98pn+VQ== "@cspell/dict-latex@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@cspell/dict-latex/-/dict-latex-4.0.0.tgz#85054903db834ea867174795d162e2a8f0e9c51e" integrity sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ== -"@cspell/dict-lorem-ipsum@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-3.0.0.tgz#c6347660fcab480b47bdcaec3b57e8c3abc4af68" - integrity sha512-msEV24qEpzWZs2kcEicqYlhyBpR0amfDkJOs+iffC07si9ftqtQ+yP3lf1VFLpgqw3SQh1M1vtU7RD4sPrNlcQ== - -"@cspell/dict-lua@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-lua/-/dict-lua-4.0.1.tgz#4c31975646cb2d71f1216c7aeaa0c5ab6994ea25" - integrity sha512-j0MFmeCouSoC6EdZTbvGe1sJ9V+ruwKSeF+zRkNNNload7R72Co5kX1haW2xLHGdlq0kqSy1ODRZKdVl0e+7hg== +"@cspell/dict-lorem-ipsum@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.0.tgz#2793a5dbfde474a546b0caecc40c38fdf076306e" + integrity sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw== -"@cspell/dict-node@^4.0.2": +"@cspell/dict-lua@^4.0.2": version "4.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-node/-/dict-node-4.0.2.tgz#9e5f64d882568fdd2a2243542d1263dbbb87c53a" - integrity sha512-FEQJ4TnMcXEFslqBQkXa5HposMoCGsiBv2ux4IZuIXgadXeHKHUHk60iarWpjhzNzQLyN2GD7NoRMd12bK3Llw== + resolved "https://registry.yarnpkg.com/@cspell/dict-lua/-/dict-lua-4.0.2.tgz#74f080296f94eda4e65f79d14be00cb0f8fdcb22" + integrity sha512-eeC20Q+UnHcTVBK6pgwhSjGIVugO2XqU7hv4ZfXp2F9DxGx1RME0+1sKX4qAGhdFGwOBsEzb2fwUsAEP6Mibpg== -"@cspell/dict-npm@^5.0.5": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@cspell/dict-npm/-/dict-npm-5.0.7.tgz#f2977579413a09d53fb385ed48f93184aad55aea" - integrity sha512-6SegF0HsVaBTl6PlHjeErG8Av+tRYkUG1yaXUQIGWXU0A8oxhI0o4PuL65UWH5lkCKhJyGai69Cd0iytL0oVFg== +"@cspell/dict-makefile@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-makefile/-/dict-makefile-1.0.0.tgz#5afb2910873ebbc01ab8d9c38661c4c93d0e5a40" + integrity sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ== -"@cspell/dict-php@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-php/-/dict-php-4.0.1.tgz#f3c5cd241f43a32b09355370fc6ce7bd50e6402c" - integrity sha512-XaQ/JkSyq2c07MfRG54DjLi2CV+HHwS99DDCAao9Fq2JfkWroTQsUeek7wYZXJATrJVOULoV3HKih12x905AtQ== +"@cspell/dict-node@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-node/-/dict-node-4.0.3.tgz#5ae0222d72871e82978049f8e11ea627ca42fca3" + integrity sha512-sFlUNI5kOogy49KtPg8SMQYirDGIAoKBO3+cDLIwD4MLdsWy1q0upc7pzGht3mrjuyMiPRUV14Bb0rkVLrxOhg== + +"@cspell/dict-npm@^5.0.13": + version "5.0.13" + resolved "https://registry.yarnpkg.com/@cspell/dict-npm/-/dict-npm-5.0.13.tgz#81051f791ee29563430145b360947f711316ccd1" + integrity sha512-uPb3DlQA/FvlmzT5RjZoy7fy91mxMRZW1B+K3atVM5A/cmP1QlDaSW/iCtde5kHET1MOV7uxz+vy0Yha2OI5pQ== + +"@cspell/dict-php@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@cspell/dict-php/-/dict-php-4.0.4.tgz#7510c0fe4bdbb049c143eb3c471820d1e681bbb9" + integrity sha512-fRlLV730fJbulDsLIouZxXoxHt3KIH6hcLFwxaupHL+iTXDg0lo7neRpbqD5MScr/J3idEr7i9G8XWzIikKFug== -"@cspell/dict-powershell@^5.0.1": +"@cspell/dict-powershell@^5.0.2": version "5.0.2" resolved "https://registry.yarnpkg.com/@cspell/dict-powershell/-/dict-powershell-5.0.2.tgz#2b1d7d514354b6d7de405d5faaef30f8eca0ef09" integrity sha512-IHfWLme3FXE7vnOmMncSBxOsMTdNWd1Vcyhag03WS8oANSgX8IZ+4lMI00mF0ptlgchf16/OU8WsV4pZfikEFw== -"@cspell/dict-public-licenses@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.2.tgz#81f0fde2e78bf8160ce988ae6961003a3cde3d56" - integrity sha512-baKkbs/WGEV2lCWZoL0KBPh3uiPcul5GSDwmXEBAsR5McEW52LF94/b7xWM0EmSAc/y8ODc5LnPYC7RDRLi6LQ== +"@cspell/dict-public-licenses@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.5.tgz#86948b29bd36184943955eaa80bf594488c4dd8a" + integrity sha512-91HK4dSRri/HqzAypHgduRMarJAleOX5NugoI8SjDLPzWYkwZ1ftuCXSk+fy8DLc3wK7iOaFcZAvbjmnLhVs4A== -"@cspell/dict-python@^4.0.2": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-python/-/dict-python-4.1.2.tgz#64a050faf6ecba1e5fdee2ab7c31b2267247eb45" - integrity sha512-Whcn4K8R0Ux/hcx/P9Fbx6i29GwTaXgT3LTt95AuCnV5RRLrzsqoyZkz851hcg5z4kjUQVMduDl3HECGgW/FNw== +"@cspell/dict-python@^4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@cspell/dict-python/-/dict-python-4.1.10.tgz#bae6557e7b828a1701d3733b7766c4d95f279175" + integrity sha512-ErF/Ohcu6Xk4QVNzFgo8p7CxkxvAKAmFszvso41qOOhu8CVpB35ikBRpGVDw9gsCUtZzi15Yl0izi4do6WcLkA== dependencies: - "@cspell/dict-data-science" "^1.0.0" + "@cspell/dict-data-science" "^1.0.11" "@cspell/dict-r@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@cspell/dict-r/-/dict-r-2.0.1.tgz#73474fb7cce45deb9094ebf61083fbf5913f440a" integrity sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA== -"@cspell/dict-ruby@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@cspell/dict-ruby/-/dict-ruby-5.0.0.tgz#ca22ddf0842f29b485e3ef585c666c6be5227e6d" - integrity sha512-ssb96QxLZ76yPqFrikWxItnCbUKhYXJ2owkoIYzUGNFl2CHSoHCb5a6Zetum9mQ/oUA3gNeUhd28ZUlXs0la2A== +"@cspell/dict-ruby@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-ruby/-/dict-ruby-5.0.1.tgz#a59df952d66781d811e7aac9208c145680e8cdf9" + integrity sha512-rruTm7Emhty/BSYavSm8ZxRuVw0OBqzJkwIFXcV0cX7To8D1qbmS9HFHRuRg8IL11+/nJvtdDz+lMFBSmPUagQ== "@cspell/dict-rust@^4.0.1": version "4.0.1" @@ -1545,15 +1571,15 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-scala/-/dict-scala-5.0.0.tgz#b64365ad559110a36d44ccd90edf7151ea648022" integrity sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ== -"@cspell/dict-software-terms@^3.1.6": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-3.2.0.tgz#41f5a7ff187298f04c9d564d45423afaddf637e0" - integrity sha512-RI6sv4Bc4i42YH/ofVelv8lXpJRhCyS9IhI2BtejUoMXKhKA9gC01ATXOylx+oaQmj3t5ark4R50xKFRvC7ENA== +"@cspell/dict-software-terms@^3.3.11": + version "3.3.11" + resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-3.3.11.tgz#caa173f5489a426c495b73eaf57654f692d55c05" + integrity sha512-a2Zml4G47dbQ6GDdN7+YlIWs3nFnIcJkZOLT88m/LzxjApiF7AOZLqQiKwow03hyvGSuZy8itgQZmQHoPlw2vQ== -"@cspell/dict-sql@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@cspell/dict-sql/-/dict-sql-2.1.0.tgz#4210e83b9fc05ef91f577ae44fd264825ccfbf71" - integrity sha512-Bb+TNWUrTNNABO0bmfcYXiTlSt0RD6sB2MIY+rNlaMyIwug43jUjeYmkLz2tPkn3+2uvySeFEOMVYhMVfcuDKg== +"@cspell/dict-sql@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-sql/-/dict-sql-2.1.2.tgz#80492b887e7986dd8bc39a9c5ea513ede2b17cb1" + integrity sha512-Pi0hAcvsSGtZZeyyAN1VfGtQJbrXos5x2QjJU0niAQKhmITSOrXU/1II1Gogk+FYDjWyV9wP2De0U2f7EWs6oQ== "@cspell/dict-svelte@^1.0.2": version "1.0.2" @@ -1565,27 +1591,27 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-swift/-/dict-swift-2.0.1.tgz#06ec86e52e9630c441d3c19605657457e33d7bb6" integrity sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw== -"@cspell/dict-typescript@^3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-typescript/-/dict-typescript-3.1.1.tgz#25a9c241fa79c032f907db21b0aaf7c7baee6cc3" - integrity sha512-N9vNJZoOXmmrFPR4ir3rGvnqqwmQGgOYoL1+y6D4oIhyr7FhaYiyF/d7QT61RmjZQcATMa6PSL+ZisCeRLx9+A== +"@cspell/dict-typescript@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-typescript/-/dict-typescript-3.1.2.tgz#14d05f54db2984feaa24ea133b583d19c04cc104" + integrity sha512-lcNOYWjLUvDZdLa0UMNd/LwfVdxhE9rKA+agZBGjL3lTA3uNvH7IUqSJM/IXhJoBpLLMVEOk8v1N9xi+vDuCdA== "@cspell/dict-vue@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@cspell/dict-vue/-/dict-vue-3.0.0.tgz#68ccb432ad93fcb0fd665352d075ae9a64ea9250" integrity sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A== -"@cspell/dynamic-import@6.31.1": - version "6.31.1" - resolved "https://registry.yarnpkg.com/@cspell/dynamic-import/-/dynamic-import-6.31.1.tgz#26e218362e98158be5c88f970ce774458e53dd60" - integrity sha512-uliIUv9uZlnyYmjUlcw/Dm3p0xJOEnWJNczHAfqAl4Ytg6QZktw0GtUA9b1umbRXLv0KRTPtSC6nMq3cR7rRmQ== +"@cspell/dynamic-import@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@cspell/dynamic-import/-/dynamic-import-8.1.0.tgz#b14a1ef4b90d5c802cf36c51acb57d564aaa9512" + integrity sha512-TJ1OnP0ubdVr5YTMU15rVs8R6ROuPvP/Z5lY2gtHscEsf9tZxvIt3924uMc9fTJXgNsITNWSoCzgwJYcDvGM6A== dependencies: - import-meta-resolve "^2.2.2" + import-meta-resolve "^4.0.0" -"@cspell/strong-weak-map@6.31.1": - version "6.31.1" - resolved "https://registry.yarnpkg.com/@cspell/strong-weak-map/-/strong-weak-map-6.31.1.tgz#370faeae5ecb0c9a55344a34cd70f1690c62de01" - integrity sha512-z8AuWvUuSnugFKJOA9Ke0aiFuehcqLFqia9bk8XaQNEWr44ahPVn3sEWnAncTxPbpWuUw5UajoJa0egRAE1CCg== +"@cspell/strong-weak-map@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@cspell/strong-weak-map/-/strong-weak-map-8.1.0.tgz#3952e8a1ce6de45a38a99ec3064a3ac6642cabae" + integrity sha512-yBc3ejGpx3QLbfS+Sec8ycS+lKuou5rnnpfz3aVBCnNHUPozosFuNYPFB6Iah2CBY6v6rkDCkIp5vnp1IwQzdA== "@csstools/selector-specificity@^2.0.2": version "2.2.0" @@ -4440,11 +4466,11 @@ axe-core@^4.6.2: integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g== axios@^1, axios@^1.0.0, axios@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.1.tgz#11fbaa11fc35f431193a9564109c88c1f27b585f" - integrity sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A== + version "1.6.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.4.tgz#184ee1f63d412caffcf30d2c50982253c3ee86e0" + integrity sha512-heJnIs6N4aa1eSthhN9M5ioILu8Wi8vmQW9iHQ9NUvfkJb0lEEDUiIdQNAuBtfUt3FxReaKdpQA5DbmMOqzF/A== dependencies: - follow-redirects "^1.15.0" + follow-redirects "^1.15.4" form-data "^4.0.0" proxy-from-env "^1.1.0" @@ -4719,14 +4745,14 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.18.1, browserslist@^4.21.4, browserslist@^4.21.5, browserslist@^4.21.9, browserslist@^4.22.1: - version "4.22.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619" - integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.18.1, browserslist@^4.21.4, browserslist@^4.21.5, browserslist@^4.22.1, browserslist@^4.22.2: + version "4.22.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" + integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== dependencies: - caniuse-lite "^1.0.30001541" - electron-to-chromium "^1.4.535" - node-releases "^2.0.13" + caniuse-lite "^1.0.30001565" + electron-to-chromium "^1.4.601" + node-releases "^2.0.14" update-browserslist-db "^1.0.13" bser@2.1.1: @@ -4943,10 +4969,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001541: - version "1.0.30001561" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz#752f21f56f96f1b1a52e97aae98c57c562d5d9da" - integrity sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001565: + version "1.0.30001574" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz#fb4f1359c77f6af942510493672e1ec7ec80230c" + integrity sha512-BtYEK4r/iHt/txm81KBudCUcTy7t+s9emrIaHqjYurQ10x71zJ5VQ9x1dYPcz/b+pKSp4y/v1xSI67A+LzpNyg== ccount@^2.0.0: version "2.0.1" @@ -4960,6 +4986,13 @@ chainsaw@~0.1.0: dependencies: traverse ">=0.3.0 <0.4" +chalk-template@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-1.1.0.tgz#ffc55db6dd745e9394b85327c8ac8466edb7a7b1" + integrity sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg== + dependencies: + chalk "^5.2.0" + chalk@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" @@ -4990,7 +5023,7 @@ chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^5.0.1, chalk@^5.2.0: +chalk@^5.0.1, chalk@^5.2.0, chalk@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== @@ -5338,6 +5371,11 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +commander@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" + integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -5448,18 +5486,6 @@ config-chain@^1.1.11: ini "^1.3.4" proto-list "~1.2.1" -configstore@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - dependencies: - dot-prop "^5.2.0" - graceful-fs "^4.1.2" - make-dir "^3.0.0" - unique-string "^2.0.0" - write-file-atomic "^3.0.0" - xdg-basedir "^4.0.0" - configstore@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/configstore/-/configstore-6.0.0.tgz#49eca2ebc80983f77e09394a1a56e0aca8235566" @@ -5687,16 +5713,6 @@ cosmiconfig@7.0.0: path-type "^4.0.0" yaml "^1.10.0" -cosmiconfig@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.0.0.tgz#e9feae014eab580f858f8a0288f38997a7bebe97" - integrity sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ== - dependencies: - import-fresh "^3.2.1" - js-yaml "^4.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -5768,106 +5784,115 @@ crypto-random-string@^4.0.0: dependencies: type-fest "^1.0.1" -cspell-dictionary@6.31.1: - version "6.31.1" - resolved "https://registry.yarnpkg.com/cspell-dictionary/-/cspell-dictionary-6.31.1.tgz#a5c52da365aa03d7b6454f017d97b0d4b3da8859" - integrity sha512-7+K7aQGarqbpucky26wled7QSCJeg6VkLUWS+hLjyf0Cqc9Zew5xsLa4QjReExWUJx+a97jbiflITZNuWxgMrg== +cspell-config-lib@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell-config-lib/-/cspell-config-lib-8.1.0.tgz#3fbccef07271bdaa99122c902cdafdbe9d284c7a" + integrity sha512-mIv8etMAp05OapdxJQt0nkfzclMti8AfACPryWnVePrwB89A2KjErHYBa7hX6gn20B4K+KgD7ckPcOi6L8vLYA== dependencies: - "@cspell/cspell-pipe" "6.31.1" - "@cspell/cspell-types" "6.31.1" - cspell-trie-lib "6.31.1" - fast-equals "^4.0.3" - gensequence "^5.0.2" + "@cspell/cspell-types" "8.1.0" + comment-json "^4.2.3" + yaml "^2.3.4" -cspell-gitignore@6.31.2: - version "6.31.2" - resolved "https://registry.yarnpkg.com/cspell-gitignore/-/cspell-gitignore-6.31.2.tgz#c297f0c094a96ea1ba8849fd17fb1a7feb274318" - integrity sha512-B1i8aiXCIbb/08u0K3xnDyXtg0qD+lb5B2itOOXi7KXlPkKvIuN4hWyXxhVDweWyYWEzyXD5wBpPrqICVrStHQ== +cspell-dictionary@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell-dictionary/-/cspell-dictionary-8.1.0.tgz#c2f140aa75209a62cf48b32333c0839a31a33a23" + integrity sha512-nwvlPiM7jsZThZ2bUS2CYzqwAbxWC4OL5GozQfbGEwW/8unNhifBpJzlOZuzLyX4Vu94ETExeIc625wBqPWjVA== dependencies: - cspell-glob "6.31.2" - find-up "^5.0.0" + "@cspell/cspell-pipe" "8.1.0" + "@cspell/cspell-types" "8.1.0" + cspell-trie-lib "8.1.0" + fast-equals "^5.0.1" + gensequence "^6.0.0" -cspell-glob@6.31.2: - version "6.31.2" - resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-6.31.2.tgz#877d914420e38aa3b375066f425e5a33514cc5e2" - integrity sha512-ceTjHM4HaBgvG5S3oiB+PTPYq58EQYG6MmYpycDHzpR5I2H1NurK9lxWHfANmLbi0DsHn58tIZNDMUnnQj19Jw== +cspell-gitignore@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell-gitignore/-/cspell-gitignore-8.1.0.tgz#feef4e31e212d4c2b09d014a1deada225f8d65e3" + integrity sha512-upMIEjbBz1g92Vt80h2hMMRZ9057iAmCWxi05l0WrwGrtc3CGsA8gQQIFIbVZ0x86Sbmv1cBZms1Y/hKWPWuvg== dependencies: - micromatch "^4.0.5" + cspell-glob "8.1.0" + find-up-simple "^1.0.0" -cspell-grammar@6.31.1: - version "6.31.1" - resolved "https://registry.yarnpkg.com/cspell-grammar/-/cspell-grammar-6.31.1.tgz#f766df3d5f1ec95a1e472fc339716757d2acfa56" - integrity sha512-AsRVP0idcNFVSb9+p9XjMumFj3BUV67WIPWApaAzJl/dYyiIygQObRE+si0/QtFWGNw873b7hNhWZiKjqIdoaQ== +cspell-glob@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-8.1.0.tgz#735582370a7bb0b19cf8022fe9342317b71ffea2" + integrity sha512-onPRqJqPZaaUQ1CKeuh2fJJ9UjIBicRq6Ffd6bqWCu7IdwfEBPtjWa/nlEjCVp1CMRwhS3Y0zG3jHkKLydsR4Q== dependencies: - "@cspell/cspell-pipe" "6.31.1" - "@cspell/cspell-types" "6.31.1" + micromatch "^4.0.5" -cspell-io@6.31.2: - version "6.31.2" - resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-6.31.2.tgz#5b1059779b8417510df077781a82cbe2b5c7463b" - integrity sha512-Lp7LsF/f35LaOneROb/9mWiprShz2ONxjYFAt3bYP7gIxq41lWi8QhO+SN6spoqPp/wQXjSqJ7MuTZsemxPRnA== +cspell-grammar@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell-grammar/-/cspell-grammar-8.1.0.tgz#7530cc8ba0c56ab85fbbb94ff533857938fdbc8f" + integrity sha512-E28SDJYOOuHk8eBtMSIGyCu8qiKb/H4LX1J/kw8+eV0RLvnllmq2FAYFBk8jtu4uW49TW5n/eLg7J2TvPONYAA== dependencies: - "@cspell/cspell-service-bus" "6.31.1" - node-fetch "^2.6.9" + "@cspell/cspell-pipe" "8.1.0" + "@cspell/cspell-types" "8.1.0" -cspell-lib@6.31.2: - version "6.31.2" - resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-6.31.2.tgz#46e1f89876e5a5c055bc2493562c2c6d7ebff8fb" - integrity sha512-LqaB2ZfVfQHKL5aZzYoKU6/UxxAtWeXAYwpC9l+satXmajYyXtAh4kWmuW+y7kKRH2jA79rJQS3QE6ToeSqgQQ== +cspell-io@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-8.1.0.tgz#68677da77171339d513c7aa89f8cc187af38bc2d" + integrity sha512-oPRMS/XUWcdZXMj6Zhs65mgOVyRZajAhHLm18o6cPLOGUD0770oMqi8ZNKj7LuvubkyP/NL0m4AEcWwvmz/Cbw== dependencies: - "@cspell/cspell-bundled-dicts" "6.31.2" - "@cspell/cspell-pipe" "6.31.1" - "@cspell/cspell-types" "6.31.1" - "@cspell/strong-weak-map" "6.31.1" + "@cspell/cspell-service-bus" "8.1.0" + +cspell-lib@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-8.1.0.tgz#eeb88222b90b3c3ecfea3ad032b700e7221f67bf" + integrity sha512-tatdY9teElqqPtKHAY1osOhV68h/f3x+4Niw7rV12OXmJ9El1lPka59bVTV401fODWRoF3WWJXUpTg012zhdrQ== + dependencies: + "@cspell/cspell-bundled-dicts" "8.1.0" + "@cspell/cspell-pipe" "8.1.0" + "@cspell/cspell-resolver" "8.1.0" + "@cspell/cspell-types" "8.1.0" + "@cspell/dynamic-import" "8.1.0" + "@cspell/strong-weak-map" "8.1.0" clear-module "^4.1.2" comment-json "^4.2.3" - configstore "^5.0.1" - cosmiconfig "8.0.0" - cspell-dictionary "6.31.1" - cspell-glob "6.31.2" - cspell-grammar "6.31.1" - cspell-io "6.31.2" - cspell-trie-lib "6.31.1" - fast-equals "^4.0.3" - find-up "^5.0.0" - gensequence "^5.0.2" + configstore "^6.0.0" + cspell-config-lib "8.1.0" + cspell-dictionary "8.1.0" + cspell-glob "8.1.0" + cspell-grammar "8.1.0" + cspell-io "8.1.0" + cspell-trie-lib "8.1.0" + fast-equals "^5.0.1" + gensequence "^6.0.0" import-fresh "^3.3.0" resolve-from "^5.0.0" - resolve-global "^1.0.0" - vscode-languageserver-textdocument "^1.0.8" - vscode-uri "^3.0.7" - -cspell-trie-lib@6.31.1: - version "6.31.1" - resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-6.31.1.tgz#72b272e16d53c15de5a1ef3178dd2519670daca7" - integrity sha512-MtYh7s4Sbr1rKT31P2BK6KY+YfOy3dWsuusq9HnqCXmq6aZ1HyFgjH/9p9uvqGi/TboMqn1KOV8nifhXK3l3jg== - dependencies: - "@cspell/cspell-pipe" "6.31.1" - "@cspell/cspell-types" "6.31.1" - gensequence "^5.0.2" - -cspell@^6.31.2: - version "6.31.2" - resolved "https://registry.yarnpkg.com/cspell/-/cspell-6.31.2.tgz#c334ac34353fe446d82c27fe348bb17b4b3e9f7f" - integrity sha512-HJcQ8jqL/1N3Mj5dufFnIZCX3ACuRoFTSVY6h3Bo5wBqd2iiJTyeQ1SY9Zymlxtb2KyJ6jQRiFmkWeFx2HVs7w== - dependencies: - "@cspell/cspell-pipe" "6.31.1" - "@cspell/cspell-types" "6.31.1" - "@cspell/dynamic-import" "6.31.1" - chalk "^4.1.2" - commander "^10.0.0" - cspell-gitignore "6.31.2" - cspell-glob "6.31.2" - cspell-io "6.31.2" - cspell-lib "6.31.2" - fast-glob "^3.2.12" + vscode-languageserver-textdocument "^1.0.11" + vscode-uri "^3.0.8" + +cspell-trie-lib@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-8.1.0.tgz#d322c80faa10bbabe6b10526b4f8a47612a211d2" + integrity sha512-OF5ZNuGPIGg2CCMdMeAgd1I2iVDjoelpMjVDyqpuNu+RVpAkmNRqMFDBlsnJPWCCeOLn7blWPMBZW2KXctsm3Q== + dependencies: + "@cspell/cspell-pipe" "8.1.0" + "@cspell/cspell-types" "8.1.0" + gensequence "^6.0.0" + +cspell@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cspell/-/cspell-8.1.0.tgz#73c9e7e3c1bcac80915bc14aadb0d5ac60b5bc2c" + integrity sha512-oxQLyhW3yIAfvDdtoobvriWqfWVqOBo1o+WWRxlDyJdKDBH6my++p6KU3ZjxcJb7VG+CRLGfU7zASWwTPxMXRA== + dependencies: + "@cspell/cspell-json-reporter" "8.1.0" + "@cspell/cspell-pipe" "8.1.0" + "@cspell/cspell-types" "8.1.0" + "@cspell/dynamic-import" "8.1.0" + chalk "^5.3.0" + chalk-template "^1.1.0" + commander "^11.1.0" + cspell-gitignore "8.1.0" + cspell-glob "8.1.0" + cspell-io "8.1.0" + cspell-lib "8.1.0" + fast-glob "^3.3.2" fast-json-stable-stringify "^2.1.0" - file-entry-cache "^6.0.1" - get-stdin "^8.0.0" - imurmurhash "^0.1.4" - semver "^7.3.8" - strip-ansi "^6.0.1" - vscode-uri "^3.0.7" + file-entry-cache "^7.0.2" + get-stdin "^9.0.0" + semver "^7.5.4" + strip-ansi "^7.1.0" + vscode-uri "^3.0.8" css-declaration-sorter@^6.3.1: version "6.4.1" @@ -6372,7 +6397,7 @@ debug@2.6.9, debug@^2.6.0: dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -6711,7 +6736,7 @@ dot-prop@6.0.1, dot-prop@^6.0.1: dependencies: is-obj "^2.0.0" -dot-prop@^5.1.0, dot-prop@^5.2.0: +dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== @@ -6752,10 +6777,10 @@ ejs@^3.1.6, ejs@^3.1.7: dependencies: jake "^10.8.5" -electron-to-chromium@^1.4.535: - version "1.4.580" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.580.tgz#2f8f70f70733a6be1fb6f31de1224e6dc4bb196d" - integrity sha512-T5q3pjQon853xxxHUq3ZP68ZpvJHuSMY2+BZaW3QzjS4HvNuvsMmZ/+lU+nCrftre1jFZ+OSlExynXWBihnXzw== +electron-to-chromium@^1.4.601: + version "1.4.622" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.622.tgz#925d8b2264abbcbe264a9a6290d97b9e5a1af205" + integrity sha512-GZ47DEy0Gm2Z8RVG092CkFvX7SdotG57c4YZOe8W8qD4rOmk3plgeNmiLVRHP/Liqj1wRiY3uUUod9vb9hnxZA== elkjs@^0.8.2: version "0.8.2" @@ -7475,10 +7500,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-equals@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-4.0.3.tgz#72884cc805ec3c6679b99875f6b7654f39f0e8c7" - integrity sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg== +fast-equals@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-5.0.1.tgz#a4eefe3c5d1c0d021aeed0bc10ba5e0c12ee405d" + integrity sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ== fast-fifo@^1.1.0, fast-fifo@^1.2.0: version "1.3.0" @@ -7503,10 +7528,10 @@ fast-glob@3.2.7: merge2 "^1.3.0" micromatch "^4.0.4" -fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== +fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1, fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -7592,6 +7617,13 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-entry-cache@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-7.0.2.tgz#2d61bb70ba89b9548e3035b7c9173fe91deafff0" + integrity sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g== + dependencies: + flat-cache "^3.2.0" + file-loader@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" @@ -7645,6 +7677,11 @@ find-cache-dir@^4.0.0: common-path-prefix "^3.0.0" pkg-dir "^7.0.0" +find-up-simple@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/find-up-simple/-/find-up-simple-1.0.0.tgz#21d035fde9fdbd56c8f4d2f63f32fd93a1cfc368" + integrity sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw== + find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -7683,12 +7720,13 @@ find-up@^6.3.0: locate-path "^7.1.0" path-exists "^5.0.0" -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== +flat-cache@^3.0.4, flat-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: - flatted "^3.1.0" + flatted "^3.2.9" + keyv "^4.5.3" rimraf "^3.0.2" flat@^5.0.2: @@ -7696,15 +7734,15 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +flatted@^3.2.9: + version "3.2.9" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" + integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== -follow-redirects@^1.0.0, follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.0.0, follow-redirects@^1.15.4: + version "1.15.4" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" + integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== for-each@^0.3.3: version "0.3.3" @@ -7892,10 +7930,10 @@ gauge@^5.0.0: strip-ansi "^6.0.1" wide-align "^1.1.5" -gensequence@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/gensequence/-/gensequence-5.0.2.tgz#f065be2f9a5b2967b9cad7f33b2d79ce1f22dc82" - integrity sha512-JlKEZnFc6neaeSVlkzBGGgkIoIaSxMgvdamRoPN8r3ozm2r9dusqxeKqYQ7lhzmj2UhFQP8nkyfCaiLQxiLrDA== +gensequence@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gensequence/-/gensequence-6.0.0.tgz#ae46a0f89ebd7cc334e45cfb8f1c99a65248694e" + integrity sha512-8WwuywE9pokJRAcg2QFR/plk3cVPebSUqRPzpGQh3WQ0wIiHAw+HyOQj5IuHyUTQBHpBKFoB2JUMu9zT3vJ16Q== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" @@ -7942,10 +7980,10 @@ get-port@5.1.1: resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== -get-stdin@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" - integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== +get-stdin@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575" + integrity sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA== get-stream@6.0.0: version "6.0.0" @@ -8111,12 +8149,12 @@ glob@^9.2.0: minipass "^4.2.4" path-scurry "^1.6.1" -global-dirs@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg== +global-directory@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-4.0.1.tgz#4d7ac7cfd2cb73f304c53b8810891748df5e361e" + integrity sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q== dependencies: - ini "^1.3.4" + ini "4.1.1" global-dirs@^3.0.0: version "3.0.1" @@ -8871,10 +8909,10 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" -import-meta-resolve@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-2.2.2.tgz#75237301e72d1f0fbd74dbc6cca9324b164c2cc9" - integrity sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA== +import-meta-resolve@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz#0b1195915689f60ab00f830af0f15cc841e8919e" + integrity sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA== imurmurhash@^0.1.4: version "0.1.4" @@ -8919,6 +8957,11 @@ ini@2.0.0: resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== +ini@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" + integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== + ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" @@ -9884,9 +9927,9 @@ jkroso-type@1: integrity sha512-zZgay+fPG6PgMUrpyFADmQmvLo39+AZa7Gc5pZhev2RhDxwANEq2etwD8d0e6rTg5NkwOIlQmaEmns3draC6Ng== joi@^17.9.2: - version "17.9.2" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.9.2.tgz#8b2e4724188369f55451aebd1d0b1d9482470690" - integrity sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw== + version "17.11.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.11.0.tgz#aa9da753578ec7720e6f0ca2c7046996ed04fc1a" + integrity sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ== dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" @@ -10074,10 +10117,10 @@ katex@^0.16.0: dependencies: commander "^8.3.0" -keyv@^4.5.2: - version "4.5.2" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" - integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== +keyv@^4.5.2, keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: json-buffer "3.0.1" @@ -12009,10 +12052,10 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.7, node-fetch@^2.6.9: - version "2.6.12" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" - integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== +node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -12048,10 +12091,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" - integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== non-layered-tidy-tree-layout@^2.0.2: version "2.0.2" @@ -13398,9 +13441,9 @@ pretty-time@^1.1.0: integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== prism-react-renderer@^2.0.6, prism-react-renderer@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-2.3.0.tgz#5f8f615af6af8201a0b734bd8c946df3d818ea54" - integrity sha512-UYRg2TkVIaI6tRVHC5OJ4/BxqPUxJkJvq/odLT/ykpt1zGYXooNperUxQcCvi87LyRnR4nCh81ceOA+e7nrydg== + version "2.3.1" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-2.3.1.tgz#e59e5450052ede17488f6bc85de1553f584ff8d5" + integrity sha512-Rdf+HzBLR7KYjzpJ1rSoxT9ioO85nZngQEoFIhL07XhtJHlCU3SOz0GJ6+qvMyQe0Se+BV3qpe6Yd/NmQF5Juw== dependencies: "@types/prismjs" "^1.26.0" clsx "^2.0.0" @@ -14026,6 +14069,11 @@ regenerator-runtime@^0.13.11: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + regenerator-transform@^0.15.2: version "0.15.2" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" @@ -14300,13 +14348,6 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-global@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-global/-/resolve-global-1.0.0.tgz#a2a79df4af2ca3f49bf77ef9ddacd322dad19255" - integrity sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw== - dependencies: - global-dirs "^0.1.1" - resolve-pathname@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" @@ -15230,7 +15271,7 @@ stringify-object@^3.3.0: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -16419,15 +16460,15 @@ vfile@^6.0.0, vfile@^6.0.1: unist-util-stringify-position "^4.0.0" vfile-message "^4.0.0" -vscode-languageserver-textdocument@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz#9eae94509cbd945ea44bca8dcfe4bb0c15bb3ac0" - integrity sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q== +vscode-languageserver-textdocument@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz#0822a000e7d4dc083312580d7575fe9e3ba2e2bf" + integrity sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA== -vscode-uri@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.7.tgz#6d19fef387ee6b46c479e5fb00870e15e58c1eb8" - integrity sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA== +vscode-uri@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f" + integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== w3c-xmlserializer@^4.0.0: version "4.0.0" @@ -16737,25 +16778,25 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -workbox-background-sync@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.6.1.tgz#08d603a33717ce663e718c30cc336f74909aff2f" - integrity sha512-trJd3ovpWCvzu4sW0E8rV3FUyIcC0W8G+AZ+VcqzzA890AsWZlUGOTSxIMmIHVusUw/FDq1HFWfy/kC/WTRqSg== +workbox-background-sync@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-7.0.0.tgz#2b84b96ca35fec976e3bd2794b70e4acec46b3a5" + integrity sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA== dependencies: idb "^7.0.1" - workbox-core "6.6.1" + workbox-core "7.0.0" -workbox-broadcast-update@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.6.1.tgz#0fad9454cf8e4ace0c293e5617c64c75d8a8c61e" - integrity sha512-fBhffRdaANdeQ1V8s692R9l/gzvjjRtydBOvR6WCSB0BNE2BacA29Z4r9/RHd9KaXCPl6JTdI9q0bR25YKP8TQ== +workbox-broadcast-update@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-7.0.0.tgz#7f611ca1a94ba8ac0aa40fa171c9713e0f937d22" + integrity sha512-oUuh4jzZrLySOo0tC0WoKiSg90bVAcnE98uW7F8GFiSOXnhogfNDGZelPJa+6KpGBO5+Qelv04Hqx2UD+BJqNQ== dependencies: - workbox-core "6.6.1" + workbox-core "7.0.0" -workbox-build@^6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.6.1.tgz#6010e9ce550910156761448f2dbea8cfcf759cb0" - integrity sha512-INPgDx6aRycAugUixbKgiEQBWD0MPZqU5r0jyr24CehvNuLPSXp/wGOpdRJmts656lNiXwqV7dC2nzyrzWEDnw== +workbox-build@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-7.0.0.tgz#02ab5ef2991b3369b8b9395703f08912212769b4" + integrity sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg== dependencies: "@apideck/better-ajv-errors" "^0.3.1" "@babel/core" "^7.11.1" @@ -16779,121 +16820,121 @@ workbox-build@^6.6.1: strip-comments "^2.0.1" tempy "^0.6.0" upath "^1.2.0" - workbox-background-sync "6.6.1" - workbox-broadcast-update "6.6.1" - workbox-cacheable-response "6.6.1" - workbox-core "6.6.1" - workbox-expiration "6.6.1" - workbox-google-analytics "6.6.1" - workbox-navigation-preload "6.6.1" - workbox-precaching "6.6.1" - workbox-range-requests "6.6.1" - workbox-recipes "6.6.1" - workbox-routing "6.6.1" - workbox-strategies "6.6.1" - workbox-streams "6.6.1" - workbox-sw "6.6.1" - workbox-window "6.6.1" - -workbox-cacheable-response@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.6.1.tgz#284c2b86be3f4fd191970ace8c8e99797bcf58e9" - integrity sha512-85LY4veT2CnTCDxaVG7ft3NKaFbH6i4urZXgLiU4AiwvKqS2ChL6/eILiGRYXfZ6gAwDnh5RkuDbr/GMS4KSag== - dependencies: - workbox-core "6.6.1" - -workbox-core@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.6.1.tgz#7184776d4134c5ed2f086878c882728fc9084265" - integrity sha512-ZrGBXjjaJLqzVothoE12qTbVnOAjFrHDXpZe7coCb6q65qI/59rDLwuFMO4PcZ7jcbxY+0+NhUVztzR/CbjEFw== - -workbox-expiration@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.6.1.tgz#a841fa36676104426dbfb9da1ef6a630b4f93739" - integrity sha512-qFiNeeINndiOxaCrd2DeL1Xh1RFug3JonzjxUHc5WkvkD2u5abY3gZL1xSUNt3vZKsFFGGORItSjVTVnWAZO4A== + workbox-background-sync "7.0.0" + workbox-broadcast-update "7.0.0" + workbox-cacheable-response "7.0.0" + workbox-core "7.0.0" + workbox-expiration "7.0.0" + workbox-google-analytics "7.0.0" + workbox-navigation-preload "7.0.0" + workbox-precaching "7.0.0" + workbox-range-requests "7.0.0" + workbox-recipes "7.0.0" + workbox-routing "7.0.0" + workbox-strategies "7.0.0" + workbox-streams "7.0.0" + workbox-sw "7.0.0" + workbox-window "7.0.0" + +workbox-cacheable-response@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-7.0.0.tgz#ee27c036728189eed69d25a135013053277482d2" + integrity sha512-0lrtyGHn/LH8kKAJVOQfSu3/80WDc9Ma8ng0p2i/5HuUndGttH+mGMSvOskjOdFImLs2XZIimErp7tSOPmu/6g== + dependencies: + workbox-core "7.0.0" + +workbox-core@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-7.0.0.tgz#dec114ec923cc2adc967dd9be1b8a0bed50a3545" + integrity sha512-81JkAAZtfVP8darBpfRTovHg8DGAVrKFgHpOArZbdFd78VqHr5Iw65f2guwjE2NlCFbPFDoez3D3/6ZvhI/rwQ== + +workbox-expiration@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-7.0.0.tgz#3d90bcf2a7577241de950f89784f6546b66c2baa" + integrity sha512-MLK+fogW+pC3IWU9SFE+FRStvDVutwJMR5if1g7oBJx3qwmO69BNoJQVaMXq41R0gg3MzxVfwOGKx3i9P6sOLQ== dependencies: idb "^7.0.1" - workbox-core "6.6.1" + workbox-core "7.0.0" -workbox-google-analytics@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.6.1.tgz#a07a6655ab33d89d1b0b0a935ffa5dea88618c5d" - integrity sha512-1TjSvbFSLmkpqLcBsF7FuGqqeDsf+uAXO/pjiINQKg3b1GN0nBngnxLcXDYo1n/XxK4N7RaRrpRlkwjY/3ocuA== +workbox-google-analytics@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-7.0.0.tgz#603b2c4244af1e85de0fb26287d4e17d3293452a" + integrity sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg== dependencies: - workbox-background-sync "6.6.1" - workbox-core "6.6.1" - workbox-routing "6.6.1" - workbox-strategies "6.6.1" + workbox-background-sync "7.0.0" + workbox-core "7.0.0" + workbox-routing "7.0.0" + workbox-strategies "7.0.0" -workbox-navigation-preload@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.6.1.tgz#61a34fe125558dd88cf09237f11bd966504ea059" - integrity sha512-DQCZowCecO+wRoIxJI2V6bXWK6/53ff+hEXLGlQL4Rp9ZaPDLrgV/32nxwWIP7QpWDkVEtllTAK5h6cnhxNxDA== +workbox-navigation-preload@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-7.0.0.tgz#4913878dbbd97057181d57baa18d2bbdde085c6c" + integrity sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA== dependencies: - workbox-core "6.6.1" + workbox-core "7.0.0" -workbox-precaching@6.6.1, workbox-precaching@^6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.6.1.tgz#dedeeba10a2d163d990bf99f1c2066ac0d1a19e2" - integrity sha512-K4znSJ7IKxCnCYEdhNkMr7X1kNh8cz+mFgx9v5jFdz1MfI84pq8C2zG+oAoeE5kFrUf7YkT5x4uLWBNg0DVZ5A== +workbox-precaching@7.0.0, workbox-precaching@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-7.0.0.tgz#3979ba8033aadf3144b70e9fe631d870d5fbaa03" + integrity sha512-EC0vol623LJqTJo1mkhD9DZmMP604vHqni3EohhQVwhJlTgyKyOkMrZNy5/QHfOby+39xqC01gv4LjOm4HSfnA== dependencies: - workbox-core "6.6.1" - workbox-routing "6.6.1" - workbox-strategies "6.6.1" + workbox-core "7.0.0" + workbox-routing "7.0.0" + workbox-strategies "7.0.0" -workbox-range-requests@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.6.1.tgz#ddaf7e73af11d362fbb2f136a9063a4c7f507a39" - integrity sha512-4BDzk28govqzg2ZpX0IFkthdRmCKgAKreontYRC5YsAPB2jDtPNxqx3WtTXgHw1NZalXpcH/E4LqUa9+2xbv1g== +workbox-range-requests@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-7.0.0.tgz#97511901e043df27c1aa422adcc999a7751f52ed" + integrity sha512-SxAzoVl9j/zRU9OT5+IQs7pbJBOUOlriB8Gn9YMvi38BNZRbM+RvkujHMo8FOe9IWrqqwYgDFBfv6sk76I1yaQ== dependencies: - workbox-core "6.6.1" + workbox-core "7.0.0" -workbox-recipes@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.6.1.tgz#ea70d2b2b0b0bce8de0a9d94f274d4a688e69fae" - integrity sha512-/oy8vCSzromXokDA+X+VgpeZJvtuf8SkQ8KL0xmRivMgJZrjwM3c2tpKTJn6PZA6TsbxGs3Sc7KwMoZVamcV2g== +workbox-recipes@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-7.0.0.tgz#1a6a01c8c2dfe5a41eef0fed3fe517e8a45c6514" + integrity sha512-DntcK9wuG3rYQOONWC0PejxYYIDHyWWZB/ueTbOUDQgefaeIj1kJ7pdP3LZV2lfrj8XXXBWt+JDRSw1lLLOnww== dependencies: - workbox-cacheable-response "6.6.1" - workbox-core "6.6.1" - workbox-expiration "6.6.1" - workbox-precaching "6.6.1" - workbox-routing "6.6.1" - workbox-strategies "6.6.1" + workbox-cacheable-response "7.0.0" + workbox-core "7.0.0" + workbox-expiration "7.0.0" + workbox-precaching "7.0.0" + workbox-routing "7.0.0" + workbox-strategies "7.0.0" -workbox-routing@6.6.1, workbox-routing@^6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.6.1.tgz#cba9a1c7e0d1ea11e24b6f8c518840efdc94f581" - integrity sha512-j4ohlQvfpVdoR8vDYxTY9rA9VvxTHogkIDwGdJ+rb2VRZQ5vt1CWwUUZBeD/WGFAni12jD1HlMXvJ8JS7aBWTg== +workbox-routing@7.0.0, workbox-routing@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-7.0.0.tgz#6668438a06554f60645aedc77244a4fe3a91e302" + integrity sha512-8YxLr3xvqidnbVeGyRGkaV4YdlKkn5qZ1LfEePW3dq+ydE73hUUJJuLmGEykW3fMX8x8mNdL0XrWgotcuZjIvA== dependencies: - workbox-core "6.6.1" + workbox-core "7.0.0" -workbox-strategies@6.6.1, workbox-strategies@^6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.6.1.tgz#38d0f0fbdddba97bd92e0c6418d0b1a2ccd5b8bf" - integrity sha512-WQLXkRnsk4L81fVPkkgon1rZNxnpdO5LsO+ws7tYBC6QQQFJVI6v98klrJEjFtZwzw/mB/HT5yVp7CcX0O+mrw== +workbox-strategies@7.0.0, workbox-strategies@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-7.0.0.tgz#dcba32b3f3074476019049cc490fe1a60ea73382" + integrity sha512-dg3qJU7tR/Gcd/XXOOo7x9QoCI9nk74JopaJaYAQ+ugLi57gPsXycVdBnYbayVj34m6Y8ppPwIuecrzkpBVwbA== dependencies: - workbox-core "6.6.1" + workbox-core "7.0.0" -workbox-streams@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.6.1.tgz#b2f7ba7b315c27a6e3a96a476593f99c5d227d26" - integrity sha512-maKG65FUq9e4BLotSKWSTzeF0sgctQdYyTMq529piEN24Dlu9b6WhrAfRpHdCncRS89Zi2QVpW5V33NX8PgH3Q== +workbox-streams@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-7.0.0.tgz#36722aecd04785f88b6f709e541c094fc658c0f9" + integrity sha512-moVsh+5to//l6IERWceYKGiftc+prNnqOp2sgALJJFbnNVpTXzKISlTIsrWY+ogMqt+x1oMazIdHj25kBSq/HQ== dependencies: - workbox-core "6.6.1" - workbox-routing "6.6.1" + workbox-core "7.0.0" + workbox-routing "7.0.0" -workbox-sw@6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.6.1.tgz#d4c4ca3125088e8b9fd7a748ed537fa0247bd72c" - integrity sha512-R7whwjvU2abHH/lR6kQTTXLHDFU2izht9kJOvBRYK65FbwutT4VvnUAJIgHvfWZ/fokrOPhfoWYoPCMpSgUKHQ== +workbox-sw@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-7.0.0.tgz#7350126411e3de1409f7ec243df8d06bb5b08b86" + integrity sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA== -workbox-window@6.6.1, workbox-window@^6.6.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.6.1.tgz#f22a394cbac36240d0dadcbdebc35f711bb7b89e" - integrity sha512-wil4nwOY58nTdCvif/KEZjQ2NP8uk3gGeRNy2jPBbzypU4BT4D9L8xiwbmDBpZlSgJd2xsT9FvSNU0gsxV51JQ== +workbox-window@7.0.0, workbox-window@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-7.0.0.tgz#a683ab33c896e4f16786794eac7978fc98a25d08" + integrity sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA== dependencies: "@types/trusted-types" "^2.0.2" - workbox-core "6.6.1" + workbox-core "7.0.0" "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" @@ -16944,7 +16985,7 @@ write-file-atomic@^2.4.2: imurmurhash "^0.1.4" signal-exit "^3.0.2" -write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: +write-file-atomic@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== @@ -17001,11 +17042,6 @@ ws@^8.11.0, ws@^8.13.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== - xdg-basedir@^5.0.1, xdg-basedir@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-5.1.0.tgz#1efba19425e73be1bc6f2a6ceb52a3d2c884c0c9" @@ -17053,10 +17089,10 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.2.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" - integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== +yaml@^2.2.2, yaml@^2.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" + integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== yargs-parser@20.2.4: version "20.2.4"