diff --git a/.eslintrc.js b/.eslintrc.js index 886bd74c917a..66d72dd28313 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,6 +28,7 @@ module.exports = { 'eslint:recommended', 'plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', 'airbnb', 'prettier', 'prettier/react', @@ -41,6 +42,8 @@ module.exports = { }, plugins: ['react-hooks', 'header'], rules: { + 'react-hooks/rules-of-hooks': ERROR, + 'react-hooks/exhaustive-deps': ERROR, 'class-methods-use-this': OFF, // It's a way of allowing private variables. 'func-names': OFF, // Ignore certain webpack alias because it can't be resolved @@ -77,7 +80,6 @@ module.exports = { 'react/destructuring-assignment': OFF, // Too many lines. 'react/prefer-stateless-function': WARNING, 'react/jsx-props-no-spreading': OFF, - 'react-hooks/rules-of-hooks': ERROR, 'react/require-default-props': [ERROR, {ignoreFunctionalComponents: true}], '@typescript-eslint/no-inferrable-types': OFF, 'import/first': OFF, diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 97b691569831..b02d363b105f 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,7 +2,7 @@ blank_issues_enabled: false contact_links: - name: πŸš€ Feature request url: https://docusaurus.io/feature-requests - about: The Canny board to send us feature requests, vote and measure the interest of users. Useful to submit a featurre request when you have an idea but no concrete api design proposal. + about: The Canny board to send us feature requests, vote and measure the interest of users. Useful to submit a feature request when you have an idea but no concrete API design proposal. - name: ❓ Simple question - Discord chat url: https://discord.gg/docusaurus about: This issue tracker is not for technical support. Please use our Discord chat, and ask the community for help. diff --git a/CHANGELOG.md b/CHANGELOG.md index b7612b54a2a7..34c46bc8d7a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,85 @@ # Docusaurus 2 Changelog +## 2.0.0-beta.8 (2021-10-21) + +#### :rocket: New Feature + +- `docusaurus-plugin-content-blog` + - [#5702](https://github.com/facebook/docusaurus/pull/5702) feat(content-blog): new readingTime plugin option ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus` + - [#5740](https://github.com/facebook/docusaurus/pull/5740) feat(core): write-heading-ids options maintainCasing, overwrite ([@Josh-Cena](https://github.com/Josh-Cena)) +- `docusaurus-plugin-content-docs` + - [#5705](https://github.com/facebook/docusaurus/pull/5705) feat(content-docs): new front matter options to customize pagination ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :boom: Breaking Change + +- `docusaurus-theme-search-algolia` + - [#5751](https://github.com/facebook/docusaurus/pull/5751) fix: stable callbacks in useSearchQuery + refactor ([@slorber](https://github.com/slorber)) + +#### :bug: Bug Fix + +- `docusaurus-plugin-ideal-image` + - [#5760](https://github.com/facebook/docusaurus/pull/5760) fix(ideal-image): fix IdealImage in dev not handling ES import images properly ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic` + - [#5732](https://github.com/facebook/docusaurus/pull/5732) fix(theme-classic): allow tabs with number as value ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5721](https://github.com/facebook/docusaurus/pull/5721) fix: handle rubber band scrolling in hideable navbar ([@lex111](https://github.com/lex111)) +- `docusaurus-theme-search-algolia` + - [#5751](https://github.com/facebook/docusaurus/pull/5751) fix: stable callbacks in useSearchQuery + refactor ([@slorber](https://github.com/slorber)) + +#### :nail_care: Polish + +- `docusaurus-theme-classic` + - [#5717](https://github.com/facebook/docusaurus/pull/5717) refactor: Polish de translation ([@philipp985](https://github.com/philipp985)) + - [#5725](https://github.com/facebook/docusaurus/pull/5725) refactor: add missing Turkish translations to theme-classic ([@canercanbaz](https://github.com/canercanbaz)) + - [#5723](https://github.com/facebook/docusaurus/pull/5723) refactor(v2): update Vietnamese translations ([@datlechin](https://github.com/datlechin)) +- `docusaurus-module-type-aliases`, `docusaurus-plugin-ideal-image`, `docusaurus-theme-classic`, `docusaurus` + - [#5726](https://github.com/facebook/docusaurus/pull/5726) refactor(module-type-aliases): remove fallback aliases ([@Josh-Cena](https://github.com/Josh-Cena)) + +#### :memo: Documentation + +- Other + - [#5755](https://github.com/facebook/docusaurus/pull/5755) docs: rename docusaurus.config.js route + redirects cleanup ([@slorber](https://github.com/slorber)) + - [#5750](https://github.com/facebook/docusaurus/pull/5750) docs(v2): Fix typo in using-plugins.md ([@thanasis00](https://github.com/thanasis00)) + - [#5727](https://github.com/facebook/docusaurus/pull/5727) docs(v2): Add Fenghua Frontend Developer site to showcase page ([@zxuqian](https://github.com/zxuqian)) + - [#5746](https://github.com/facebook/docusaurus/pull/5746) docs: Add plugin-image-zoom ([@ataft](https://github.com/ataft)) + - [#5728](https://github.com/facebook/docusaurus/pull/5728) docs: add h4 into toc on certain pages ([@Josh-Cena](https://github.com/Josh-Cena)) + - [#5737](https://github.com/facebook/docusaurus/pull/5737) docs: Add Apex FP to showcase ([@ipavlic](https://github.com/ipavlic)) +- `docusaurus-plugin-content-blog` + - [#5753](https://github.com/facebook/docusaurus/pull/5753) fix(content-blog): temporarily swallow feed mdxToHtml errors + feed refactor ([@slorber](https://github.com/slorber)) + +#### :house: Internal + +- `docusaurus` + - [#5761](https://github.com/facebook/docusaurus/pull/5761) chore: upgrade html-webpack-plugin, remove terser 4 ([@slorber](https://github.com/slorber)) +- `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-search-algolia`, `docusaurus` + - [#5714](https://github.com/facebook/docusaurus/pull/5714) chore: Enable ESLint rules of hooks + fix new lint errors ([@slorber](https://github.com/slorber)) +- Other + - [#5722](https://github.com/facebook/docusaurus/pull/5722) chore: fix gen script to support TS template ([@lex111](https://github.com/lex111)) + - [#5730](https://github.com/facebook/docusaurus/pull/5730) chore: fix typos / casing in issue template ([@johnnyreilly](https://github.com/johnnyreilly)) + - [#5720](https://github.com/facebook/docusaurus/pull/5720) chore: regenerate beta.7 examples ([@lex111](https://github.com/lex111)) + - [#5719](https://github.com/facebook/docusaurus/pull/5719) chore: remove beta.5 docs ([@lex111](https://github.com/lex111)) + +#### :running_woman: Performance + +- `docusaurus` + - [#5748](https://github.com/facebook/docusaurus/pull/5748) refactor: perform shallow clone during deploy ([@nlfurniss](https://github.com/nlfurniss)) + +#### Committers: 13 + +- Alexey Pyltsyn ([@lex111](https://github.com/lex111)) +- Andrew Taft ([@ataft](https://github.com/ataft)) +- Caner Canbaz ([@canercanbaz](https://github.com/canercanbaz)) +- Dimi Mikadze ([@DimiMikadze](https://github.com/DimiMikadze)) +- Ilija Pavlic ([@ipavlic](https://github.com/ipavlic)) +- John Reilly ([@johnnyreilly](https://github.com/johnnyreilly)) +- Joshua Chen ([@Josh-Cena](https://github.com/Josh-Cena)) +- Nathaniel Furniss ([@nlfurniss](https://github.com/nlfurniss)) +- NgΓ΄ Quα»‘c Đẑt ([@datlechin](https://github.com/datlechin)) +- SΓ©bastien Lorber ([@slorber](https://github.com/slorber)) +- Thanasis Katsadas ([@thanasis00](https://github.com/thanasis00)) +- Xuqian ([@zxuqian](https://github.com/zxuqian)) +- [@philipp985](https://github.com/philipp985) + ## 2.0.0-beta.7 (2021-10-15) #### :rocket: New Feature diff --git a/admin/new.docusaurus.io/package.json b/admin/new.docusaurus.io/package.json index 4ca5b66c70d5..df4980850d23 100644 --- a/admin/new.docusaurus.io/package.json +++ b/admin/new.docusaurus.io/package.json @@ -1,6 +1,6 @@ { "name": "new.docusaurus.io", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "private": true, "scripts": { "start": "netlify dev" diff --git a/examples/classic-typescript/package.json b/examples/classic-typescript/package.json index 0b6516338c12..240047ecd66d 100644 --- a/examples/classic-typescript/package.json +++ b/examples/classic-typescript/package.json @@ -12,11 +12,12 @@ "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", + "typecheck": "tsc", "dev": "docusaurus start" }, "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/preset-classic": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/preset-classic": "2.0.0-beta.8", "@mdx-js/react": "^1.6.21", "@svgr/webpack": "^5.5.0", "clsx": "^1.1.1", @@ -26,6 +27,11 @@ "react-dom": "^17.0.1", "url-loader": "^4.1.1" }, + "devDependencies": { + "@docusaurus/module-type-aliases": "2.0.0-beta.8", + "@tsconfig/docusaurus": "^1.0.4", + "typescript": "^4.3.5" + }, "browserslist": { "production": [ ">0.5%", diff --git a/examples/classic-typescript/src/components/HomepageFeatures.js b/examples/classic-typescript/src/components/HomepageFeatures.tsx similarity index 66% rename from examples/classic-typescript/src/components/HomepageFeatures.js rename to examples/classic-typescript/src/components/HomepageFeatures.tsx index 16f820b10355..3897078da114 100644 --- a/examples/classic-typescript/src/components/HomepageFeatures.js +++ b/examples/classic-typescript/src/components/HomepageFeatures.tsx @@ -1,11 +1,23 @@ +/** + * 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 clsx from 'clsx'; import styles from './HomepageFeatures.module.css'; -const FeatureList = [ +type FeatureItem = { + title: string; + image: string; + description: JSX.Element; +}; + +const FeatureList: FeatureItem[] = [ { title: 'Easy to Use', - Svg: require('../../static/img/undraw_docusaurus_mountain.svg').default, + image: '/img/undraw_docusaurus_mountain.svg', description: ( <> Docusaurus was designed from the ground up to be easily installed and @@ -15,7 +27,7 @@ const FeatureList = [ }, { title: 'Focus on What Matters', - Svg: require('../../static/img/undraw_docusaurus_tree.svg').default, + image: '/img/undraw_docusaurus_tree.svg', description: ( <> Docusaurus lets you focus on your docs, and we'll do the chores. Go @@ -25,7 +37,7 @@ const FeatureList = [ }, { title: 'Powered by React', - Svg: require('../../static/img/undraw_docusaurus_react.svg').default, + image: '/img/undraw_docusaurus_react.svg', description: ( <> Extend or customize your website layout by reusing React. Docusaurus can @@ -35,11 +47,11 @@ const FeatureList = [ }, ]; -function Feature({Svg, title, description}) { +function Feature({title, image, description}: FeatureItem) { return (
- + {title}

{title}

@@ -49,7 +61,7 @@ function Feature({Svg, title, description}) { ); } -export default function HomepageFeatures() { +export default function HomepageFeatures(): JSX.Element { return (
diff --git a/examples/classic-typescript/src/pages/index.js b/examples/classic-typescript/src/pages/index.tsx similarity index 96% rename from examples/classic-typescript/src/pages/index.js rename to examples/classic-typescript/src/pages/index.tsx index 27c21e8f99c4..cc4f72112724 100644 --- a/examples/classic-typescript/src/pages/index.js +++ b/examples/classic-typescript/src/pages/index.tsx @@ -25,7 +25,7 @@ function HomepageHeader() { ); } -export default function Home() { +export default function Home(): JSX.Element { const {siteConfig} = useDocusaurusContext(); return ( /jest/emptyModule.js', // TODO maybe use "projects" + multiple configs if we plan to add tests to another theme? - '@theme/(.*)': '@docusaurus/theme-classic/lib-next/theme/$1', + '@theme/(.*)': '@docusaurus/theme-classic/src/theme/$1', }, }; diff --git a/lerna.json b/lerna.json index 0f2cae777f16..c59848a18698 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "npmClient": "yarn", "useWorkspaces": true, "changelog": { diff --git a/package.json b/package.json index fa46ef270357..cf4ce7e0902a 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "build:website:baseUrl": "yarn workspace website build:baseUrl", "build:website:blogOnly": "yarn workspace website build:blogOnly", "build:website:deployPreview": "cross-env NETLIFY=true CONTEXT='deploy-preview' yarn workspace website build", + "build:website:fast": "yarn workspace website build:fast", "build:website:en": "yarn workspace website build --locale en", "clear:website": "yarn workspace website clear", "serve:website": "yarn workspace website serve", diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json index 507737cb5335..5b62bf280350 100755 --- a/packages/create-docusaurus/package.json +++ b/packages/create-docusaurus/package.json @@ -1,6 +1,6 @@ { "name": "create-docusaurus", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Create Docusaurus apps easily.", "repository": { "type": "git", diff --git a/packages/create-docusaurus/templates/classic-typescript/package.json b/packages/create-docusaurus/templates/classic-typescript/package.json index 3089140f82d4..0df788d22526 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -15,8 +15,8 @@ "typecheck": "tsc" }, "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/preset-classic": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/preset-classic": "2.0.0-beta.8", "@mdx-js/react": "^1.6.21", "@svgr/webpack": "^5.5.0", "clsx": "^1.1.1", @@ -27,7 +27,7 @@ "url-loader": "^4.1.1" }, "devDependencies": { - "@docusaurus/module-type-aliases": "2.0.0-beta.7", + "@docusaurus/module-type-aliases": "2.0.0-beta.8", "@tsconfig/docusaurus": "^1.0.4", "typescript": "^4.3.5" }, diff --git a/packages/create-docusaurus/templates/classic/package.json b/packages/create-docusaurus/templates/classic/package.json index 1edb6021f8ea..257f2672bed1 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -14,8 +14,8 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/preset-classic": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/preset-classic": "2.0.0-beta.8", "@mdx-js/react": "^1.6.21", "@svgr/webpack": "^5.5.0", "clsx": "^1.1.1", diff --git a/packages/create-docusaurus/templates/facebook/package.json b/packages/create-docusaurus/templates/facebook/package.json index e35f27e4a9dd..0ac930a90771 100644 --- a/packages/create-docusaurus/templates/facebook/package.json +++ b/packages/create-docusaurus/templates/facebook/package.json @@ -1,6 +1,6 @@ { "name": "docusaurus-2-facebook-template", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -18,8 +18,8 @@ "prettier:diff": "prettier --config .prettierrc --list-different \"**/*.{js,jsx,ts,tsx,md,mdx}\"" }, "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/preset-classic": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/preset-classic": "2.0.0-beta.8", "@mdx-js/react": "^1.6.21", "@svgr/webpack": "^5.5.0", "clsx": "^1.1.1", diff --git a/packages/docusaurus-cssnano-preset/package.json b/packages/docusaurus-cssnano-preset/package.json index e94b31c56fd4..44965c05a309 100644 --- a/packages/docusaurus-cssnano-preset/package.json +++ b/packages/docusaurus-cssnano-preset/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/cssnano-preset", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Advanced cssnano preset for maximum optimization.", "main": "index.js", "license": "MIT", diff --git a/packages/docusaurus-mdx-loader/package.json b/packages/docusaurus-mdx-loader/package.json index debde5f8be40..8662df2cb49d 100644 --- a/packages/docusaurus-mdx-loader/package.json +++ b/packages/docusaurus-mdx-loader/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/mdx-loader", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Docusaurus Loader for MDX", "main": "lib/index.js", "types": "src/types.d.ts", @@ -20,8 +20,8 @@ "dependencies": { "@babel/parser": "^7.12.16", "@babel/traverse": "^7.12.13", - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", "@mdx-js/mdx": "^1.6.21", "@mdx-js/react": "^1.6.21", "chalk": "^4.1.2", @@ -38,7 +38,7 @@ "webpack": "^5.40.0" }, "devDependencies": { - "@docusaurus/types": "2.0.0-beta.7", + "@docusaurus/types": "2.0.0-beta.8", "@types/escape-html": "^1.0.1", "@types/mdast": "^3.0.7", "@types/stringify-object": "^3.3.1", diff --git a/packages/docusaurus-migrate/package.json b/packages/docusaurus-migrate/package.json index 1bfb454a7e1c..d5c215f70da1 100644 --- a/packages/docusaurus-migrate/package.json +++ b/packages/docusaurus-migrate/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/migrate", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "A CLI tool to migrate from older versions of Docusaurus.", "main": "lib/index.js", "license": "MIT", diff --git a/packages/docusaurus-module-type-aliases/package.json b/packages/docusaurus-module-type-aliases/package.json index 1e261a2de8b4..bbc02b928a30 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Docusaurus module type aliases.", "types": "./src/index.d.ts", "publishConfig": { diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 9714e568736d..d61de8b4dae2 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -69,11 +69,41 @@ declare module '@generated/codeTranslations' { export default codeTranslations; } -declare module '@theme/*'; - declare module '@theme-original/*'; -declare module '@docusaurus/*'; +declare module '@theme/Layout' { + import type {ReactNode} from 'react'; + + export interface Props { + readonly children: ReactNode; + readonly title?: string; + readonly description?: string; + } + export default function Layout(props: Props): JSX.Element; +} + +declare module '@theme/Loading' { + import type {LoadingComponentProps} from 'react-loadable'; + + export default function Loading(props: LoadingComponentProps): JSX.Element; +} + +declare module '@theme/NotFound' { + export default function NotFound(props: any): JSX.Element; +} + +declare module '@theme/Root' { + import type {ReactNode} from 'react'; + + export interface Props { + readonly children: ReactNode; + } + export default function Root({children}: Props): JSX.Element; +} + +declare module '@docusaurus/constants' { + export const DEFAULT_PLUGIN_ID: 'default'; +} declare module '@docusaurus/Head' { import type {HelmetProps} from 'react-helmet'; diff --git a/packages/docusaurus-plugin-client-redirects/package.json b/packages/docusaurus-plugin-client-redirects/package.json index 10312d004c75..fe4f2b2c29d2 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Client redirects plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-client-redirects.d.ts", @@ -18,11 +18,11 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/types": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-common": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/types": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-common": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "chalk": "^4.1.2", "eta": "^1.12.3", "fs-extra": "^10.0.0", diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index 791f13e89657..d75f9df3de6c 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Blog plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-blog.d.ts", @@ -18,11 +18,11 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/mdx-loader": "2.0.0-beta.7", - "@docusaurus/types": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/mdx-loader": "2.0.0-beta.8", + "@docusaurus/types": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "chalk": "^4.1.2", "escape-string-regexp": "^4.0.0", "feed": "^4.2.2", diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/mdx-require-blog-post.mdx b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/mdx-require-blog-post.mdx new file mode 100644 index 000000000000..5ff703b4cb3d --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/mdx-require-blog-post.mdx @@ -0,0 +1,14 @@ +--- +title: MDX Blog Sample with require calls +date: 2021-03-06 +--- + +Test MDX with require calls + +import useBaseUrl from '@docusaurus/useBaseUrl'; + + + + + + diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/static/img/docusaurus.png b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/static/img/docusaurus.png new file mode 100644 index 000000000000..f458149e3c8f Binary files /dev/null and b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/static/img/docusaurus.png differ diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap similarity index 90% rename from packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap rename to packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap index 8914514cebaa..8e600fd89a0b 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap @@ -1,18 +1,23 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`blogFeed atom should not show feed without posts 1`] = `null`; - exports[`blogFeed atom shows feed item for each post 1`] = ` " https://docusaurus.io/myBaseUrl/blog Hello Blog - 2021-03-05T00:00:00.000Z + 2021-03-06T00:00:00.000Z https://github.com/jpmonette/feed Hello Blog https://docusaurus.io/myBaseUrl/image/favicon.ico Copyright + + <![CDATA[MDX Blog Sample with require calls]]> + MDX Blog Sample with require calls + + 2021-03-06T00:00:00.000Z + + <![CDATA[Full Blog Sample]]> Full Blog Sample @@ -81,8 +86,6 @@ exports[`blogFeed atom shows feed item for each post 1`] = ` " `; -exports[`blogFeed rss should not show feed without posts 1`] = `null`; - exports[`blogFeed rss shows feed item for each post 1`] = ` " @@ -90,10 +93,17 @@ exports[`blogFeed rss shows feed item for each post 1`] = ` Hello Blog https://docusaurus.io/myBaseUrl/blog Hello Blog - Fri, 05 Mar 2021 00:00:00 GMT + Sat, 06 Mar 2021 00:00:00 GMT https://validator.w3.org/feed/docs/rss2.html https://github.com/jpmonette/feed Copyright + + <![CDATA[MDX Blog Sample with require calls]]> + https://docusaurus.io/myBaseUrl/blog/mdx-require-blog-post + MDX Blog Sample with require calls + Sat, 06 Mar 2021 00:00:00 GMT + + <![CDATA[Full Blog Sample]]> https://docusaurus.io/myBaseUrl/blog/mdx-blog-post diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/generateBlogFeed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts similarity index 77% rename from packages/docusaurus-plugin-content-blog/src/__tests__/generateBlogFeed.test.ts rename to packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts index c9cc678e7bea..2c2d0337a46e 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/generateBlogFeed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts @@ -6,10 +6,12 @@ */ import path from 'path'; -import {generateBlogFeed} from '../blogUtils'; +import {generateBlogFeed} from '../feed'; import {LoadContext, I18n} from '@docusaurus/types'; import {PluginOptions, BlogContentPaths} from '../types'; import {DEFAULT_OPTIONS} from '../pluginOptionSchema'; +import {generateBlogPosts} from '../blogUtils'; +import {Feed} from 'feed'; const DefaultI18N: I18n = { currentLocale: 'en', @@ -30,6 +32,23 @@ function getBlogContentPaths(siteDir: string): BlogContentPaths { }; } +async function testGenerateFeeds( + context: LoadContext, + options: PluginOptions, +): Promise { + const blogPosts = await generateBlogPosts( + getBlogContentPaths(context.siteDir), + context, + options, + ); + + return generateBlogFeed({ + blogPosts, + options, + siteConfig: context.siteConfig, + }); +} + describe('blogFeed', () => { (['atom', 'rss'] as const).forEach((feedType) => { describe(`${feedType}`, () => { @@ -42,8 +61,7 @@ describe('blogFeed', () => { favicon: 'image/favicon.ico', }; - const feed = await generateBlogFeed( - getBlogContentPaths(siteDir), + const feed = await testGenerateFeeds( { siteDir, siteConfig, @@ -59,11 +77,12 @@ describe('blogFeed', () => { type: [feedType], copyright: 'Copyright', }, + readingTime: ({content, defaultReadingTime}) => + defaultReadingTime({content}), } as PluginOptions, ); - const feedContent = - feed && (feedType === 'rss' ? feed.rss2() : feed.atom1()); - expect(feedContent).toMatchSnapshot(); + + expect(feed).toEqual(null); }); test('shows feed item for each post', async () => { @@ -76,8 +95,7 @@ describe('blogFeed', () => { favicon: 'image/favicon.ico', }; - const feed = await generateBlogFeed( - getBlogContentPaths(siteDir), + const feed = await testGenerateFeeds( { siteDir, siteConfig, @@ -95,6 +113,8 @@ describe('blogFeed', () => { type: [feedType], copyright: 'Copyright', }, + readingTime: ({content, defaultReadingTime}) => + defaultReadingTime({content}), } as PluginOptions, ); const feedContent = 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 238b4f04fef7..0aa725b0bf94 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -246,26 +246,29 @@ describe('loadBlog', () => { test('simple website blog dates localized', async () => { const siteDir = path.join(__dirname, '__fixtures__', 'website'); const blogPostsFrench = await getBlogPosts(siteDir, {}, getI18n('fr')); - expect(blogPostsFrench).toHaveLength(7); + expect(blogPostsFrench).toHaveLength(8); expect(blogPostsFrench[0].metadata.formattedDate).toMatchInlineSnapshot( - `"5 mars 2021"`, + `"6 mars 2021"`, ); expect(blogPostsFrench[1].metadata.formattedDate).toMatchInlineSnapshot( - `"16 aoΓ»t 2020"`, + `"5 mars 2021"`, ); expect(blogPostsFrench[2].metadata.formattedDate).toMatchInlineSnapshot( - `"15 aoΓ»t 2020"`, + `"16 aoΓ»t 2020"`, ); expect(blogPostsFrench[3].metadata.formattedDate).toMatchInlineSnapshot( - `"27 fΓ©vrier 2020"`, + `"15 aoΓ»t 2020"`, ); expect(blogPostsFrench[4].metadata.formattedDate).toMatchInlineSnapshot( - `"2 janvier 2019"`, + `"27 fΓ©vrier 2020"`, ); expect(blogPostsFrench[5].metadata.formattedDate).toMatchInlineSnapshot( - `"1 janvier 2019"`, + `"2 janvier 2019"`, ); expect(blogPostsFrench[6].metadata.formattedDate).toMatchInlineSnapshot( + `"1 janvier 2019"`, + ); + expect(blogPostsFrench[7].metadata.formattedDate).toMatchInlineSnapshot( `"14 dΓ©cembre 2018"`, ); }); @@ -295,7 +298,8 @@ describe('loadBlog', () => { expect(blogPost.metadata.editUrl).toEqual(hardcodedEditUrl); }); - expect(editUrlFunction).toHaveBeenCalledTimes(7); + expect(editUrlFunction).toHaveBeenCalledTimes(8); + expect(editUrlFunction).toHaveBeenCalledWith({ blogDirPath: 'blog', blogPath: 'date-matter.md', @@ -314,6 +318,12 @@ describe('loadBlog', () => { permalink: '/blog/mdx-blog-post', locale: 'en', }); + expect(editUrlFunction).toHaveBeenCalledWith({ + blogDirPath: 'blog', + blogPath: 'mdx-require-blog-post.mdx', + permalink: '/blog/mdx-require-blog-post', + locale: 'en', + }); expect(editUrlFunction).toHaveBeenCalledWith({ blogDirPath: 'blog', blogPath: 'complex-slug.md', diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 9465103030a3..e50e4cadfcce 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -9,7 +9,6 @@ import fs from 'fs-extra'; import chalk from 'chalk'; import path from 'path'; import readingTime from 'reading-time'; -import {Feed, Author as FeedAuthor} from 'feed'; import {compact, keyBy, mapValues} from 'lodash'; import { PluginOptions, @@ -17,7 +16,7 @@ import { BlogContentPaths, BlogMarkdownLoaderOptions, BlogTags, - Author, + ReadingTimeFunction, } from './types'; import { parseMarkdownFile, @@ -26,7 +25,6 @@ import { getEditUrl, getFolderContainingFile, posixPath, - mdxToHtml, replaceMarkdownLinks, Globby, normalizeFrontMatterTags, @@ -104,66 +102,6 @@ function formatBlogPostDate(locale: string, date: Date): string { } } -export async function generateBlogFeed( - contentPaths: BlogContentPaths, - context: LoadContext, - options: PluginOptions, -): Promise { - if (!options.feedOptions) { - throw new Error( - 'Invalid options: "feedOptions" is not expected to be null.', - ); - } - const {siteConfig} = context; - const blogPosts = await generateBlogPosts(contentPaths, context, options); - if (!blogPosts.length) { - return null; - } - - const {feedOptions, routeBasePath} = options; - const {url: siteUrl, baseUrl, title, favicon} = siteConfig; - const blogBaseUrl = normalizeUrl([siteUrl, baseUrl, routeBasePath]); - - const updated = - (blogPosts[0] && blogPosts[0].metadata.date) || - new Date('2015-10-25T16:29:00.000-07:00'); - - const feed = new Feed({ - id: blogBaseUrl, - title: feedOptions.title || `${title} Blog`, - updated, - language: feedOptions.language, - link: blogBaseUrl, - description: feedOptions.description || `${siteConfig.title} Blog`, - favicon: favicon ? normalizeUrl([siteUrl, baseUrl, favicon]) : undefined, - copyright: feedOptions.copyright, - }); - - function toFeedAuthor(author: Author): FeedAuthor { - // TODO ask author emails? - // RSS feed requires email to render authors - return {name: author.name, link: author.url}; - } - - blogPosts.forEach((post) => { - const { - id, - metadata: {title: metadataTitle, permalink, date, description, authors}, - } = post; - feed.addItem({ - title: metadataTitle, - id, - link: normalizeUrl([siteUrl, permalink]), - date, - description, - content: mdxToHtml(post.content), - author: authors.map(toFeedAuthor), - }); - }); - - return feed; -} - async function parseBlogPostMarkdownFile(blogSourceAbsolute: string) { const result = await parseMarkdownFile(blogSourceAbsolute, { removeContentTitle: true, @@ -174,6 +112,10 @@ async function parseBlogPostMarkdownFile(blogSourceAbsolute: string) { }; } +const defaultReadingTime: ReadingTimeFunction = ({content, options}) => { + return readingTime(content, options).minutes; +}; + async function processBlogSourceFile( blogSourceRelative: string, contentPaths: BlogContentPaths, @@ -290,7 +232,13 @@ async function processBlogSourceFile( date, formattedDate, tags: normalizeFrontMatterTags(tagsBasePath, frontMatter.tags), - readingTime: showReadingTime ? readingTime(content).minutes : undefined, + readingTime: showReadingTime + ? options.readingTime({ + content, + frontMatter, + defaultReadingTime, + }) + : undefined, truncated: truncateMarker?.test(content) || false, authors, }, diff --git a/packages/docusaurus-plugin-content-blog/src/feed.ts b/packages/docusaurus-plugin-content-blog/src/feed.ts new file mode 100644 index 000000000000..7d0ce97add9a --- /dev/null +++ b/packages/docusaurus-plugin-content-blog/src/feed.ts @@ -0,0 +1,129 @@ +/** + * 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 {Feed, Author as FeedAuthor} from 'feed'; +import {PluginOptions, Author, BlogPost, FeedType} from './types'; +import {normalizeUrl, mdxToHtml} from '@docusaurus/utils'; +import {DocusaurusConfig} from '@docusaurus/types'; +import path from 'path'; +import fs from 'fs-extra'; + +// TODO this is temporary until we handle mdxToHtml better +// It's hard to convert reliably JSX/require calls to an html feed content +// See https://github.com/facebook/docusaurus/issues/5664 +function mdxToFeedContent(mdxContent: string): string | undefined { + try { + return mdxToHtml(mdxContent); + } catch (e) { + // TODO will we need a plugin option to configure how to handle such an error + // Swallow the error on purpose for now, until we understand better the problem space + return undefined; + } +} + +export async function generateBlogFeed({ + blogPosts, + options, + siteConfig, +}: { + blogPosts: BlogPost[]; + options: PluginOptions; + siteConfig: DocusaurusConfig; +}): Promise { + if (!blogPosts.length) { + return null; + } + + const {feedOptions, routeBasePath} = options; + const {url: siteUrl, baseUrl, title, favicon} = siteConfig; + const blogBaseUrl = normalizeUrl([siteUrl, baseUrl, routeBasePath]); + + const updated = + (blogPosts[0] && blogPosts[0].metadata.date) || + new Date('2015-10-25T16:29:00.000-07:00'); // weird legacy magic date + + const feed = new Feed({ + id: blogBaseUrl, + title: feedOptions.title || `${title} Blog`, + updated, + language: feedOptions.language, + link: blogBaseUrl, + description: feedOptions.description || `${siteConfig.title} Blog`, + favicon: favicon ? normalizeUrl([siteUrl, baseUrl, favicon]) : undefined, + copyright: feedOptions.copyright, + }); + + function toFeedAuthor(author: Author): FeedAuthor { + // TODO ask author emails? + // RSS feed requires email to render authors + return {name: author.name, link: author.url}; + } + + blogPosts.forEach((post) => { + const { + id, + metadata: {title: metadataTitle, permalink, date, description, authors}, + } = post; + feed.addItem({ + title: metadataTitle, + id, + link: normalizeUrl([siteUrl, permalink]), + date, + description, + content: mdxToFeedContent(post.content), + author: authors.map(toFeedAuthor), + }); + }); + + return feed; +} + +async function createBlogFeedFile({ + feed, + feedType, + filePath, +}: { + feed: Feed; + feedType: FeedType; + filePath: string; +}) { + const feedContent = feedType === 'rss' ? feed.rss2() : feed.atom1(); + try { + await fs.outputFile(filePath, feedContent); + } catch (err) { + throw new Error(`Generating ${feedType} feed failed: ${err}.`); + } +} + +export async function createBlogFeedFiles({ + blogPosts, + options, + siteConfig, + outDir, +}: { + blogPosts: BlogPost[]; + options: PluginOptions; + siteConfig: DocusaurusConfig; + outDir: string; +}): Promise { + const feed = await generateBlogFeed({blogPosts, options, siteConfig}); + + const feedTypes = options.feedOptions.type; + if (!feed || !feedTypes) { + return; + } + + await Promise.all( + feedTypes.map(async function (feedType) { + await createBlogFeedFile({ + feed, + feedType, + filePath: path.join(outDir, options.routeBasePath, `${feedType}.xml`), + }); + }), + ); +} diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 3cb75b946a6f..b7f2cf7ebd68 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import fs from 'fs-extra'; import path from 'path'; import admonitions from 'remark-admonitions'; import { @@ -49,13 +48,13 @@ import { } from '@docusaurus/types'; import {Configuration} from 'webpack'; import { - generateBlogFeed, generateBlogPosts, getContentPathList, getSourceToPermalink, getBlogTags, } from './blogUtils'; import {BlogPostFrontMatter} from './blogFrontMatter'; +import {createBlogFeedFiles} from './feed'; export default function pluginContentBlog( context: LoadContext, @@ -69,10 +68,11 @@ export default function pluginContentBlog( const { siteDir, - siteConfig: {onBrokenMarkdownLinks, baseUrl}, + siteConfig, generatedFilesDir, i18n: {currentLocale}, } = context; + const {onBrokenMarkdownLinks, baseUrl} = siteConfig; const contentPaths: BlogContentPaths = { contentPath: path.resolve(siteDir, options.path), @@ -519,29 +519,18 @@ export default function pluginContentBlog( return; } - const feed = await generateBlogFeed(contentPaths, context, options); - - if (!feed) { + // TODO: we shouldn't need to re-read the posts here! + // postBuild should receive loadedContent + const blogPosts = await generateBlogPosts(contentPaths, context, options); + if (blogPosts.length) { return; } - - const feedTypes = options.feedOptions.type; - - await Promise.all( - feedTypes.map(async (feedType) => { - const feedPath = path.join( - outDir, - options.routeBasePath, - `${feedType}.xml`, - ); - const feedContent = feedType === 'rss' ? feed.rss2() : feed.atom1(); - try { - await fs.outputFile(feedPath, feedContent); - } catch (err) { - throw new Error(`Generating ${feedType} feed failed: ${err}.`); - } - }), - ); + await createBlogFeedFiles({ + blogPosts, + options, + outDir, + siteConfig, + }); }, injectHtmlTags({content}) { diff --git a/packages/docusaurus-plugin-content-blog/src/pluginOptionSchema.ts b/packages/docusaurus-plugin-content-blog/src/pluginOptionSchema.ts index 0d0e4cb75569..00ede624e043 100644 --- a/packages/docusaurus-plugin-content-blog/src/pluginOptionSchema.ts +++ b/packages/docusaurus-plugin-content-blog/src/pluginOptionSchema.ts @@ -41,6 +41,7 @@ export const DEFAULT_OPTIONS: PluginOptions = { path: 'blog', editLocalizedFiles: false, authorsMapPath: 'authors.yml', + readingTime: ({content, defaultReadingTime}) => defaultReadingTime({content}), }; export const PluginOptionSchema = Joi.object({ @@ -113,4 +114,5 @@ export const PluginOptionSchema = Joi.object({ language: Joi.string(), }).default(DEFAULT_OPTIONS.feedOptions), authorsMapPath: Joi.string().default(DEFAULT_OPTIONS.authorsMapPath), + readingTime: Joi.function().default(() => DEFAULT_OPTIONS.readingTime), }); diff --git a/packages/docusaurus-plugin-content-blog/src/types.ts b/packages/docusaurus-plugin-content-blog/src/types.ts index 3d40724e5b0a..e8990d5437d7 100644 --- a/packages/docusaurus-plugin-content-blog/src/types.ts +++ b/packages/docusaurus-plugin-content-blog/src/types.ts @@ -12,6 +12,7 @@ import type { ContentPaths, } from '@docusaurus/utils/lib/markdownLinks'; import {Overwrite} from 'utility-types'; +import {BlogPostFrontMatter} from './blogFrontMatter'; export type BlogContentPaths = ContentPaths; @@ -46,6 +47,24 @@ export type EditUrlFunction = (editUrlParams: { locale: string; }) => string | undefined; +// Duplicate from ngryman/reading-time to keep stability of API +type ReadingTimeOptions = { + wordsPerMinute?: number; + wordBound?: (char: string) => boolean; +}; + +export type ReadingTimeFunction = (params: { + content: string; + frontMatter?: BlogPostFrontMatter & Record; + options?: ReadingTimeOptions; +}) => number; + +export type ReadingTimeFunctionOption = ( + params: Required[0], 'options'>> & { + defaultReadingTime: ReadingTimeFunction; + }, +) => number | undefined; + export type PluginOptions = RemarkAndRehypePluginOptions & { id?: string; path: string; @@ -76,6 +95,7 @@ export type PluginOptions = RemarkAndRehypePluginOptions & { editLocalizedFiles?: boolean; admonitions: Record; authorsMapPath: string; + readingTime: ReadingTimeFunctionOption; }; // Options, as provided in the user config (before normalization) diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index f1d89e62ca79..3196262b2ac1 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Docs plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-content-docs.d.ts", @@ -18,7 +18,7 @@ }, "license": "MIT", "devDependencies": { - "@docusaurus/module-type-aliases": "2.0.0-beta.7", + "@docusaurus/module-type-aliases": "2.0.0-beta.8", "@types/js-yaml": "^4.0.0", "@types/picomatch": "^2.2.1", "commander": "^5.1.0", @@ -26,11 +26,11 @@ "utility-types": "^3.10.0" }, "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/mdx-loader": "2.0.0-beta.7", - "@docusaurus/types": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/mdx-loader": "2.0.0-beta.8", + "@docusaurus/types": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "chalk": "^4.1.2", "combine-promises": "^1.1.0", "escape-string-regexp": "^4.0.0", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md index a9f7e1d353df..3aa6ccb0ff30 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md @@ -1,5 +1,7 @@ --- slug: /rootAbsoluteSlug +pagination_next: headingAsTitle +pagination_prev: foo/baz --- Lorem \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md index 660f01f0dfae..4b795e81f300 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md @@ -1,5 +1,7 @@ --- slug: rootRelativeSlug +pagination_next: headingAsTitle +pagination_prev: foo/baz --- Lorem \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md index e0119375626d..0581995f86e0 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md @@ -1,5 +1,7 @@ --- slug: ./hey/ho/../rootResolvedSlug +pagination_next: headingAsTitle +pagination_prev: foo/baz --- Lorem \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md index d736a1881c6b..b6f0a49aab8f 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md @@ -1,5 +1,7 @@ --- slug: ../../../../../../../../rootTryToEscapeSlug +pagination_next: headingAsTitle +pagination_prev: foo/baz --- Lorem \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/sidebars.json b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/sidebars.json index 7892de099a43..65c87bc85975 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/sidebars.json +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/sidebars.json @@ -4,7 +4,21 @@ { "type": "category", "label": "foo", - "items": ["foo/bar", "foo/baz"] + "items": ["foo/bar", "foo/baz"] + }, + { + "type": "category", + "label": "Slugs", + "items": [ + "rootAbsoluteSlug", + "rootRelativeSlug", + "rootResolvedSlug", + "rootTryToEscapeSlug" + ] + }, + { + "type": "doc", + "id": "headingAsTitle" }, { "type": "link", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/cli.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/cli.test.ts.snap index 9ed12034a2ae..2d4f355595c6 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/cli.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/cli.test.ts.snap @@ -23,6 +23,34 @@ Object { "label": "foo", "type": "category", }, + Object { + "collapsed": true, + "collapsible": true, + "items": Array [ + Object { + "id": "version-1.0.0/rootAbsoluteSlug", + "type": "doc", + }, + Object { + "id": "version-1.0.0/rootRelativeSlug", + "type": "doc", + }, + Object { + "id": "version-1.0.0/rootResolvedSlug", + "type": "doc", + }, + Object { + "id": "version-1.0.0/rootTryToEscapeSlug", + "type": "doc", + }, + ], + "label": "Slugs", + "type": "category", + }, + Object { + "id": "version-1.0.0/headingAsTitle", + "type": "doc", + }, Object { "href": "https://github.com", "label": "Github", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/docs.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/docs.test.ts.snap new file mode 100644 index 000000000000..97a9e725b268 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/docs.test.ts.snap @@ -0,0 +1,140 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`simple site custom pagination 1`] = ` +Array [ + Array [ + Object { + "permalink": "/docs/rootTryToEscapeSlug", + "title": "rootTryToEscapeSlug", + }, + Object { + "permalink": "/docs/foo/bazSlug.html", + "title": "baz pagination_label", + }, + ], + Array [ + Object { + "permalink": "/docs/foo/bar", + "title": "Bar", + }, + Object { + "permalink": "/docs/absoluteSlug", + "title": "absoluteSlug", + }, + ], + Array [ + undefined, + Object { + "permalink": "/docs/hello", + "title": "Hello sidebar_label", + }, + ], + Array [ + Object { + "permalink": "/docs/headingAsTitle", + "title": "My heading as title", + }, + Object { + "permalink": "/docs/ipsum", + "title": "ipsum", + }, + ], + Array [ + Object { + "permalink": "/docs/hello", + "title": "Hello sidebar_label", + }, + Object { + "permalink": "/docs/lorem", + "title": "lorem", + }, + ], + Array [ + Object { + "permalink": "/docs/ipsum", + "title": "ipsum", + }, + Object { + "permalink": "/docs/rootAbsoluteSlug", + "title": "rootAbsoluteSlug", + }, + ], + Array [ + Object { + "permalink": "/docs/foo/bazSlug.html", + "title": "baz pagination_label", + }, + Object { + "permalink": "/docs/headingAsTitle", + "title": "My heading as title", + }, + ], + Array [ + Object { + "permalink": "/docs/foo/bazSlug.html", + "title": "baz pagination_label", + }, + Object { + "permalink": "/docs/headingAsTitle", + "title": "My heading as title", + }, + ], + Array [ + Object { + "permalink": "/docs/foo/bazSlug.html", + "title": "baz pagination_label", + }, + Object { + "permalink": "/docs/headingAsTitle", + "title": "My heading as title", + }, + ], + Array [ + Object { + "permalink": "/docs/foo/bazSlug.html", + "title": "baz pagination_label", + }, + Object { + "permalink": "/docs/headingAsTitle", + "title": "My heading as title", + }, + ], + Array [ + Object { + "permalink": "/docs/foo/bazSlug.html", + "title": "baz pagination_label", + }, + Object { + "permalink": "/docs/slugs/relativeSlug", + "title": "relativeSlug", + }, + ], + Array [ + Object { + "permalink": "/docs/absoluteSlug", + "title": "absoluteSlug", + }, + Object { + "permalink": "/docs/slugs/hey/resolvedSlug", + "title": "resolvedSlug", + }, + ], + Array [ + Object { + "permalink": "/docs/slugs/relativeSlug", + "title": "relativeSlug", + }, + Object { + "permalink": "/docs/tryToEscapeSlug", + "title": "tryToEscapeSlug", + }, + ], + Array [ + Object { + "permalink": "/docs/slugs/hey/resolvedSlug", + "title": "resolvedSlug", + }, + undefined, + ], +] +`; 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 8cd395b58b2f..368c1c146870 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 @@ -45,6 +45,34 @@ Object { "label": "foo", "type": "category", }, + Object { + "collapsed": true, + "collapsible": true, + "items": Array [ + Object { + "id": "rootAbsoluteSlug", + "type": "doc", + }, + Object { + "id": "rootRelativeSlug", + "type": "doc", + }, + Object { + "id": "rootResolvedSlug", + "type": "doc", + }, + Object { + "id": "rootTryToEscapeSlug", + "type": "doc", + }, + ], + "label": "Slugs", + "type": "category", + }, + Object { + "id": "headingAsTitle", + "type": "doc", + }, Object { "href": "https://github.com", "label": "Github", @@ -95,7 +123,7 @@ Object { Object { "id": "headingAsTitle", "path": "/docs/headingAsTitle", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "hello", @@ -115,22 +143,22 @@ Object { Object { "id": "rootAbsoluteSlug", "path": "/docs/rootAbsoluteSlug", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "rootRelativeSlug", "path": "/docs/rootRelativeSlug", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "rootResolvedSlug", "path": "/docs/hey/rootResolvedSlug", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "rootTryToEscapeSlug", "path": "/docs/rootTryToEscapeSlug", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "slugs/absoluteSlug", @@ -231,8 +259,8 @@ Object { \\"permalink\\": \\"/docs/foo/bar\\" }, \\"next\\": { - \\"title\\": \\"Hello sidebar_label\\", - \\"permalink\\": \\"/docs/\\" + \\"title\\": \\"rootAbsoluteSlug\\", + \\"permalink\\": \\"/docs/rootAbsoluteSlug\\" } }", "site-docs-heading-as-title-md-c6d.json": "{ @@ -247,7 +275,16 @@ Object { \\"permalink\\": \\"/docs/headingAsTitle\\", \\"tags\\": [], \\"version\\": \\"current\\", - \\"frontMatter\\": {} + \\"frontMatter\\": {}, + \\"sidebar\\": \\"docs\\", + \\"previous\\": { + \\"title\\": \\"rootTryToEscapeSlug\\", + \\"permalink\\": \\"/docs/rootTryToEscapeSlug\\" + }, + \\"next\\": { + \\"title\\": \\"Hello sidebar_label\\", + \\"permalink\\": \\"/docs/\\" + } }", "site-docs-hello-md-9df.json": "{ \\"unversionedId\\": \\"hello\\", @@ -281,8 +318,8 @@ Object { }, \\"sidebar\\": \\"docs\\", \\"previous\\": { - \\"title\\": \\"baz pagination_label\\", - \\"permalink\\": \\"/docs/foo/bazSlug.html\\" + \\"title\\": \\"My heading as title\\", + \\"permalink\\": \\"/docs/headingAsTitle\\" } }", "site-docs-ipsum-md-c61.json": "{ @@ -333,7 +370,18 @@ Object { \\"tags\\": [], \\"version\\": \\"current\\", \\"frontMatter\\": { - \\"slug\\": \\"/rootAbsoluteSlug\\" + \\"slug\\": \\"/rootAbsoluteSlug\\", + \\"pagination_next\\": \\"headingAsTitle\\", + \\"pagination_prev\\": \\"foo/baz\\" + }, + \\"sidebar\\": \\"docs\\", + \\"previous\\": { + \\"title\\": \\"baz pagination_label\\", + \\"permalink\\": \\"/docs/foo/bazSlug.html\\" + }, + \\"next\\": { + \\"title\\": \\"My heading as title\\", + \\"permalink\\": \\"/docs/headingAsTitle\\" } }", "site-docs-root-relative-slug-md-3dd.json": "{ @@ -349,7 +397,18 @@ Object { \\"tags\\": [], \\"version\\": \\"current\\", \\"frontMatter\\": { - \\"slug\\": \\"rootRelativeSlug\\" + \\"slug\\": \\"rootRelativeSlug\\", + \\"pagination_next\\": \\"headingAsTitle\\", + \\"pagination_prev\\": \\"foo/baz\\" + }, + \\"sidebar\\": \\"docs\\", + \\"previous\\": { + \\"title\\": \\"baz pagination_label\\", + \\"permalink\\": \\"/docs/foo/bazSlug.html\\" + }, + \\"next\\": { + \\"title\\": \\"My heading as title\\", + \\"permalink\\": \\"/docs/headingAsTitle\\" } }", "site-docs-root-resolved-slug-md-4d1.json": "{ @@ -365,7 +424,18 @@ Object { \\"tags\\": [], \\"version\\": \\"current\\", \\"frontMatter\\": { - \\"slug\\": \\"./hey/ho/../rootResolvedSlug\\" + \\"slug\\": \\"./hey/ho/../rootResolvedSlug\\", + \\"pagination_next\\": \\"headingAsTitle\\", + \\"pagination_prev\\": \\"foo/baz\\" + }, + \\"sidebar\\": \\"docs\\", + \\"previous\\": { + \\"title\\": \\"baz pagination_label\\", + \\"permalink\\": \\"/docs/foo/bazSlug.html\\" + }, + \\"next\\": { + \\"title\\": \\"My heading as title\\", + \\"permalink\\": \\"/docs/headingAsTitle\\" } }", "site-docs-root-try-to-escape-slug-md-9ee.json": "{ @@ -381,7 +451,18 @@ Object { \\"tags\\": [], \\"version\\": \\"current\\", \\"frontMatter\\": { - \\"slug\\": \\"../../../../../../../../rootTryToEscapeSlug\\" + \\"slug\\": \\"../../../../../../../../rootTryToEscapeSlug\\", + \\"pagination_next\\": \\"headingAsTitle\\", + \\"pagination_prev\\": \\"foo/baz\\" + }, + \\"sidebar\\": \\"docs\\", + \\"previous\\": { + \\"title\\": \\"baz pagination_label\\", + \\"permalink\\": \\"/docs/foo/bazSlug.html\\" + }, + \\"next\\": { + \\"title\\": \\"My heading as title\\", + \\"permalink\\": \\"/docs/headingAsTitle\\" } }", "site-docs-slugs-absolute-slug-md-4e8.json": "{ @@ -544,6 +625,39 @@ Object { \\"collapsible\\": true, \\"collapsed\\": true }, + { + \\"type\\": \\"category\\", + \\"label\\": \\"Slugs\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"rootAbsoluteSlug\\", + \\"href\\": \\"/docs/rootAbsoluteSlug\\" + }, + { + \\"type\\": \\"link\\", + \\"label\\": \\"rootRelativeSlug\\", + \\"href\\": \\"/docs/rootRelativeSlug\\" + }, + { + \\"type\\": \\"link\\", + \\"label\\": \\"rootResolvedSlug\\", + \\"href\\": \\"/docs/hey/rootResolvedSlug\\" + }, + { + \\"type\\": \\"link\\", + \\"label\\": \\"rootTryToEscapeSlug\\", + \\"href\\": \\"/docs/rootTryToEscapeSlug\\" + } + ], + \\"collapsible\\": true, + \\"collapsed\\": true + }, + { + \\"type\\": \\"link\\", + \\"label\\": \\"My heading as title\\", + \\"href\\": \\"/docs/headingAsTitle\\" + }, { \\"type\\": \\"link\\", \\"label\\": \\"Github\\", @@ -596,7 +710,7 @@ Object { Object { "id": "headingAsTitle", "path": "/docs/headingAsTitle", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "hello", @@ -616,22 +730,22 @@ Object { Object { "id": "rootAbsoluteSlug", "path": "/docs/rootAbsoluteSlug", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "rootRelativeSlug", "path": "/docs/rootRelativeSlug", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "rootResolvedSlug", "path": "/docs/hey/rootResolvedSlug", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "rootTryToEscapeSlug", "path": "/docs/rootTryToEscapeSlug", - "sidebar": undefined, + "sidebar": "docs", }, Object { "id": "slugs/absoluteSlug", @@ -751,6 +865,7 @@ Array [ "content": "@site/docs/headingAsTitle.md", }, "path": "/docs/headingAsTitle", + "sidebar": "docs", }, Object { "component": "@theme/DocItem", @@ -759,6 +874,7 @@ Array [ "content": "@site/docs/rootResolvedSlug.md", }, "path": "/docs/hey/rootResolvedSlug", + "sidebar": "docs", }, Object { "component": "@theme/DocItem", @@ -783,6 +899,7 @@ Array [ "content": "@site/docs/rootAbsoluteSlug.md", }, "path": "/docs/rootAbsoluteSlug", + "sidebar": "docs", }, Object { "component": "@theme/DocItem", @@ -791,6 +908,7 @@ Array [ "content": "@site/docs/rootRelativeSlug.md", }, "path": "/docs/rootRelativeSlug", + "sidebar": "docs", }, Object { "component": "@theme/DocItem", @@ -799,6 +917,7 @@ Array [ "content": "@site/docs/rootTryToEscapeSlug.md", }, "path": "/docs/rootTryToEscapeSlug", + "sidebar": "docs", }, Object { "component": "@theme/DocItem", 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 0324112b3b1b..7f2574f101da 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts @@ -7,7 +7,13 @@ import path from 'path'; import {loadContext} from '@docusaurus/core/src/server/index'; -import {processDocMetadata, readVersionDocs, readDocFile} from '../docs'; +import { + processDocMetadata, + readVersionDocs, + readDocFile, + handleNavigation, +} from '../docs'; +import {loadSidebars} from '../sidebars'; import {readVersionsMetadata} from '../versions'; import { DocFile, @@ -16,6 +22,7 @@ import { VersionMetadata, PluginOptions, EditUrlFunction, + DocNavLink, } from '../types'; import {LoadContext} from '@docusaurus/types'; import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants'; @@ -110,7 +117,38 @@ function createTestUtils({ expect(metadata.permalink).toEqual(expectedPermalink); } - return {processDocFile, testMeta, testSlug}; + async function generateNavigation( + docFiles: DocFile[], + ): Promise<[DocNavLink, DocNavLink][]> { + const rawDocs = await Promise.all( + docFiles.map((docFile) => + processDocMetadata({ + docFile, + versionMetadata, + context, + options, + }), + ), + ); + const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, { + sidebarItemsGenerator: ({defaultSidebarItemsGenerator, ...args}) => + defaultSidebarItemsGenerator({...args}), + numberPrefixParser: options.numberPrefixParser, + docs: rawDocs, + version: versionMetadata, + options: { + sidebarCollapsed: false, + sidebarCollapsible: true, + }, + }); + return handleNavigation( + rawDocs, + sidebars, + versionMetadata.sidebarFilePath as string, + ).docs.map((doc) => [doc.previous, doc.next]); + } + + return {processDocFile, testMeta, testSlug, generateNavigation}; } describe('simple site', () => { @@ -541,6 +579,28 @@ describe('simple site', () => { `"The docs homepage (homePageId=homePageId) is not allowed to have a frontmatter slug=/x/y => you have to choose either homePageId or slug, not both"`, ); }); + + test('custom pagination', async () => { + const {defaultTestUtils, options, versionsMetadata} = await loadSite(); + const docs = await readVersionDocs(versionsMetadata[0], options); + expect(await defaultTestUtils.generateNavigation(docs)).toMatchSnapshot(); + }); + + test('bad pagination', async () => { + const {defaultTestUtils, options, versionsMetadata} = await loadSite(); + const docs = await readVersionDocs(versionsMetadata[0], options); + docs.push( + createFakeDocFile({ + source: 'hehe', + frontmatter: {pagination_prev: 'nonexistent'}, + }), + ); + await expect(async () => { + await defaultTestUtils.generateNavigation(docs); + }).rejects.toThrowErrorMatchingInlineSnapshot( + `"Error when loading hehe in .: the pagination_prev front matter points to a non-existent ID nonexistent."`, + ); + }); }); describe('versioned site', () => { diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index 98016bd9aed7..a17d351bcdc4 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -345,10 +345,11 @@ describe('simple website', () => { permalink: '/docs/foo/bar', }, next: { - title: 'Hello sidebar_label', - permalink: '/docs/', + title: 'rootAbsoluteSlug', + permalink: '/docs/rootAbsoluteSlug', }, sidebar: 'docs', + sidebarPosition: undefined, source: path.posix.join( '@site', posixPath(path.relative(siteDir, currentVersion.contentPath)), @@ -391,8 +392,8 @@ describe('simple website', () => { permalink: '/docs/', slug: '/', previous: { - title: 'baz pagination_label', - permalink: '/docs/foo/bazSlug.html', + title: 'My heading as title', + permalink: '/docs/headingAsTitle', }, sidebar: 'docs', source: path.posix.join( diff --git a/packages/docusaurus-plugin-content-docs/src/docFrontMatter.ts b/packages/docusaurus-plugin-content-docs/src/docFrontMatter.ts index cfb550ab9da7..1a20d1485ad2 100644 --- a/packages/docusaurus-plugin-content-docs/src/docFrontMatter.ts +++ b/packages/docusaurus-plugin-content-docs/src/docFrontMatter.ts @@ -34,6 +34,8 @@ const DocFrontMatterSchema = Joi.object({ pagination_label: Joi.string(), custom_edit_url: URISchema.allow('', null), parse_number_prefixes: Joi.boolean(), + pagination_next: Joi.string().allow(null), + pagination_prev: Joi.string().allow(null), ...FrontMatterTOCHeadingLevels, }).unknown(); diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index 8f92614e57a6..c2532d12ccc0 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -7,6 +7,8 @@ import path from 'path'; import fs from 'fs-extra'; +import chalk from 'chalk'; +import {keyBy} from 'lodash'; import { aliasedSitePath, getEditUrl, @@ -23,17 +25,21 @@ import {getFileLastUpdate} from './lastUpdate'; import { DocFile, DocMetadataBase, + DocMetadata, + DocNavLink, LastUpdateData, MetadataOptions, PluginOptions, VersionMetadata, + LoadedVersion, } from './types'; import getSlug from './slug'; import {CURRENT_VERSION_NAME} from './constants'; import {getDocsDirPaths} from './versions'; import {stripPathNumberPrefixes} from './numberPrefix'; import {validateDocFrontMatter} from './docFrontMatter'; -import chalk from 'chalk'; +import type {Sidebars} from './sidebars/types'; +import {createSidebarsUtils} from './sidebars/utils'; type LastUpdateOptions = Pick< PluginOptions, @@ -284,3 +290,77 @@ export function processDocMetadata(args: { throw e; } } + +export function handleNavigation( + docsBase: DocMetadataBase[], + sidebars: Sidebars, + sidebarFilePath: string, +): Pick { + const docsBaseById = keyBy(docsBase, (doc) => doc.id); + const {checkSidebarsDocIds, getDocNavigation, getFirstDocIdOfFirstSidebar} = + createSidebarsUtils(sidebars); + + const validDocIds = Object.keys(docsBaseById); + checkSidebarsDocIds(validDocIds, sidebarFilePath); + + // Add sidebar/next/previous to the docs + function addNavData(doc: DocMetadataBase): DocMetadata { + const {sidebarName, previousId, nextId} = getDocNavigation(doc.id); + const toDocNavLink = ( + docId: string | null | undefined, + type: 'prev' | 'next', + ): DocNavLink | undefined => { + if (!docId) { + return undefined; + } + if (!docsBaseById[docId]) { + // This could only happen if user provided the ID through front matter + throw new Error( + `Error when loading ${doc.id} in ${doc.sourceDirName}: the pagination_${type} front matter points to a non-existent ID ${docId}.`, + ); + } + const { + title, + permalink, + frontMatter: { + pagination_label: paginationLabel, + sidebar_label: sidebarLabel, + }, + } = docsBaseById[docId]; + return {title: paginationLabel ?? sidebarLabel ?? title, permalink}; + }; + const { + frontMatter: { + pagination_next: paginationNext = nextId, + pagination_prev: paginationPrev = previousId, + }, + } = doc; + const previous = toDocNavLink(paginationPrev, 'prev'); + const next = toDocNavLink(paginationNext, 'next'); + return {...doc, sidebar: sidebarName, previous, next}; + } + const docs = docsBase.map(addNavData); + // sort to ensure consistent output for tests + docs.sort((a, b) => a.id.localeCompare(b.id)); + + /** + * The "main doc" is the "version entry point" + * We browse this doc by clicking on a version: + * - the "home" doc (at '/docs/') + * - the first doc of the first sidebar + * - a random doc (if no docs are in any sidebar... edge case) + */ + function getMainDoc(): DocMetadata { + const versionHomeDoc = docs.find((doc) => doc.slug === '/'); + const firstDocIdOfFirstSidebar = getFirstDocIdOfFirstSidebar(); + if (versionHomeDoc) { + return versionHomeDoc; + } else if (firstDocIdOfFirstSidebar) { + return docs.find((doc) => doc.id === firstDocIdOfFirstSidebar)!; + } else { + return docs[0]; + } + } + + return {mainDocId: getMainDoc().unversionedId, docs}; +} diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 340ce400187e..4c2f5220466e 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -22,9 +22,8 @@ import { } from '@docusaurus/utils'; import {LoadContext, Plugin, RouteConfig} from '@docusaurus/types'; import {loadSidebars} from './sidebars'; -import {createSidebarsUtils} from './sidebars/utils'; import {CategoryMetadataFilenamePattern} from './sidebars/generator'; -import {readVersionDocs, processDocMetadata} from './docs'; +import {readVersionDocs, processDocMetadata, handleNavigation} from './docs'; import {getDocsDirPaths, readVersionsMetadata} from './versions'; import { @@ -35,7 +34,6 @@ import { DocMetadata, GlobalPluginData, VersionMetadata, - DocNavLink, LoadedVersion, DocFile, DocsMarkdownOption, @@ -165,10 +163,6 @@ export default function pluginContentDocs( const docsBase: DocMetadataBase[] = await loadVersionDocsBase( versionMetadata, ); - const docsBaseById: Record = keyBy( - docsBase, - (doc) => doc.id, - ); const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, { sidebarItemsGenerator: options.sidebarItemsGenerator, @@ -180,70 +174,14 @@ export default function pluginContentDocs( sidebarCollapsible: options.sidebarCollapsible, }, }); - - const { - checkSidebarsDocIds, - getDocNavigation, - getFirstDocIdOfFirstSidebar, - } = createSidebarsUtils(sidebars); - - const validDocIds = Object.keys(docsBaseById); - checkSidebarsDocIds( - validDocIds, - versionMetadata.sidebarFilePath as string, - ); - - // Add sidebar/next/previous to the docs - function addNavData(doc: DocMetadataBase): DocMetadata { - const {sidebarName, previousId, nextId} = getDocNavigation(doc.id); - const toDocNavLink = (navDocId: string): DocNavLink => { - const {title, permalink, frontMatter} = docsBaseById[navDocId]; - return { - title: - frontMatter.pagination_label ?? - frontMatter.sidebar_label ?? - title, - permalink, - }; - }; - return { - ...doc, - sidebar: sidebarName, - previous: previousId ? toDocNavLink(previousId) : undefined, - next: nextId ? toDocNavLink(nextId) : undefined, - }; - } - - const docs = docsBase.map(addNavData); - - // sort to ensure consistent output for tests - docs.sort((a, b) => a.id.localeCompare(b.id)); - - // The "main doc" is the "version entry point" - // We browse this doc by clicking on a version: - // - the "home" doc (at '/docs/') - // - the first doc of the first sidebar - // - a random doc (if no docs are in any sidebar... edge case) - function getMainDoc(): DocMetadata { - const versionHomeDoc = docs.find( - (doc) => - doc.unversionedId === options.homePageId || doc.slug === '/', - ); - const firstDocIdOfFirstSidebar = getFirstDocIdOfFirstSidebar(); - if (versionHomeDoc) { - return versionHomeDoc; - } else if (firstDocIdOfFirstSidebar) { - return docs.find((doc) => doc.id === firstDocIdOfFirstSidebar)!; - } else { - return docs[0]; - } - } - return { ...versionMetadata, - mainDocId: getMainDoc().unversionedId, + ...handleNavigation( + docsBase, + sidebars, + versionMetadata.sidebarFilePath as string, + ), sidebars, - docs: docs.map(addNavData), }; } diff --git a/packages/docusaurus-plugin-content-docs/src/types.ts b/packages/docusaurus-plugin-content-docs/src/types.ts index 0b75fe4700c2..eebe226722d0 100644 --- a/packages/docusaurus-plugin-content-docs/src/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/types.ts @@ -131,6 +131,8 @@ export type DocFrontMatter = { parse_number_prefixes?: boolean; toc_min_heading_level?: number; toc_max_heading_level?: number; + pagination_next?: string | null; + pagination_prev?: string | null; /* eslint-enable camelcase */ }; diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index ce4b703ebb5b..9115ae5d933a 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "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": "2.0.0-beta.7", - "@docusaurus/mdx-loader": "2.0.0-beta.7", - "@docusaurus/types": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/mdx-loader": "2.0.0-beta.8", + "@docusaurus/types": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "globby": "^11.0.2", "lodash": "^4.17.20", "remark-admonitions": "^1.2.1", diff --git a/packages/docusaurus-plugin-debug/package.json b/packages/docusaurus-plugin-debug/package.json index 9210d6812df1..69146690e143 100644 --- a/packages/docusaurus-plugin-debug/package.json +++ b/packages/docusaurus-plugin-debug/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-debug", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Debug plugin for Docusaurus.", "main": "lib/index.js", "types": "src/types.d.ts", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/types": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/types": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", "fs-extra": "^10.0.0", "react-json-view": "^1.21.3", "tslib": "^2.3.1" diff --git a/packages/docusaurus-plugin-google-analytics/package.json b/packages/docusaurus-plugin-google-analytics/package.json index 85711cafa213..9f7ab26e0efe 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Global analytics (analytics.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-google-analytics.d.ts", @@ -18,10 +18,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7" + "@docusaurus/core": "2.0.0-beta.8" }, "devDependencies": { - "@docusaurus/types": "2.0.0-beta.7" + "@docusaurus/types": "2.0.0-beta.8" }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", diff --git a/packages/docusaurus-plugin-google-gtag/package.json b/packages/docusaurus-plugin-google-gtag/package.json index 7b10cf5d4a09..13e8bd955a6a 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Global Site Tag (gtag.js) plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-google-gtag.d.ts", @@ -18,10 +18,10 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7" + "@docusaurus/core": "2.0.0-beta.8" }, "devDependencies": { - "@docusaurus/types": "2.0.0-beta.7" + "@docusaurus/types": "2.0.0-beta.8" }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", diff --git a/packages/docusaurus-plugin-ideal-image/.npmignore b/packages/docusaurus-plugin-ideal-image/.npmignore index 4978437c5d30..c59f11ebb5fa 100644 --- a/packages/docusaurus-plugin-ideal-image/.npmignore +++ b/packages/docusaurus-plugin-ideal-image/.npmignore @@ -1,2 +1 @@ -src -copyUntypedFiles.js \ No newline at end of file +copyUntypedFiles.js diff --git a/packages/docusaurus-plugin-ideal-image/package.json b/packages/docusaurus-plugin-ideal-image/package.json index d682f2f4b691..0c9c0fe99ce7 100644 --- a/packages/docusaurus-plugin-ideal-image/package.json +++ b/packages/docusaurus-plugin-ideal-image/package.json @@ -1,8 +1,9 @@ { "name": "@docusaurus/plugin-ideal-image", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "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", "scripts": { "build": "tsc && node copyUntypedFiles.js", "watch": "node copyUntypedFiles.js && tsc --watch" @@ -20,10 +21,10 @@ "fs-extra": "^10.0.0" }, "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/lqip-loader": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/lqip-loader": "2.0.0-beta.8", "@docusaurus/responsive-loader": "1.4.0", - "@docusaurus/types": "2.0.0-beta.7", + "@docusaurus/types": "2.0.0-beta.8", "@endiliey/react-ideal-image": "^0.0.11", "react-waypoint": "^10.1.0", "sharp": "^0.29.1", diff --git a/packages/docusaurus-plugin-ideal-image/src/index.ts b/packages/docusaurus-plugin-ideal-image/src/index.ts index 70d3a6631eff..d62ddcb9e875 100644 --- a/packages/docusaurus-plugin-ideal-image/src/index.ts +++ b/packages/docusaurus-plugin-ideal-image/src/index.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ import {LoadContext, Plugin} from '@docusaurus/types'; -import {PluginOptions} from './types'; +import type {PluginOptions} from '@docusaurus/plugin-ideal-image'; import {Configuration} from 'webpack'; import path from 'path'; diff --git a/packages/docusaurus-plugin-ideal-image/src/plugin-ideal-image.d.ts b/packages/docusaurus-plugin-ideal-image/src/plugin-ideal-image.d.ts new file mode 100644 index 000000000000..6e2a3eff2146 --- /dev/null +++ b/packages/docusaurus-plugin-ideal-image/src/plugin-ideal-image.d.ts @@ -0,0 +1,50 @@ +/** + * 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. + */ + +declare module '@docusaurus/plugin-ideal-image' { + export type PluginOptions = { + /** + * Filename template for output files. + */ + name?: string; + /** + * Specify all widths you want to use; if a specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up). You may also declare a default sizes array in the loader options in your webpack.config.js. + */ + sizes?: number[]; + /** + * Specify one width you want to use; if the specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up) + */ + size?: number; + /** + * As an alternative to manually specifying sizes, you can specify min, max and steps, and the sizes will be generated for you. + */ + min?: number; + /** + * See min above + */ + max?: number; + /** + * Configure the number of images generated between min and max (inclusive) + */ + steps?: number; + /** + * JPEG compression quality + */ + quality?: number; + }; +} + +declare module '@theme/IdealImage' { + import type {ComponentProps} from 'react'; + + export interface Props extends ComponentProps<'img'> { + img: any; + } + export default function IdealImage(props: Props): JSX.Element; +} + +declare module '@endiliey/react-ideal-image'; diff --git a/packages/docusaurus-plugin-ideal-image/src/theme/IdealImage.js b/packages/docusaurus-plugin-ideal-image/src/theme/IdealImage.js index 7679f53bb2ed..d5d0215f138d 100644 --- a/packages/docusaurus-plugin-ideal-image/src/theme/IdealImage.js +++ b/packages/docusaurus-plugin-ideal-image/src/theme/IdealImage.js @@ -12,8 +12,15 @@ function Image(props) { const {alt, className, img} = props; // In dev env just use regular img with original file - if (img.default) { - return {alt}; + if (typeof img === 'string' || typeof img.default === 'string') { + return ( + {alt} + ); } return ( diff --git a/packages/docusaurus-plugin-ideal-image/src/types.ts b/packages/docusaurus-plugin-ideal-image/src/types.ts deleted file mode 100644 index 2f034e2129b8..000000000000 --- a/packages/docusaurus-plugin-ideal-image/src/types.ts +++ /dev/null @@ -1,37 +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. - */ - -export interface PluginOptions { - /** - * Filename template for output files. - */ - name?: string; - /** - * Specify all widths you want to use; if a specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up). You may also declare a default sizes array in the loader options in your webpack.config.js. - */ - sizes?: number[]; - /** - * Specify one width you want to use; if the specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up) - */ - size?: number; - /** - * As an alternative to manually specifying sizes, you can specify min, max and steps, and the sizes will be generated for you. - */ - min?: number; - /** - * See min above - */ - max?: number; - /** - * Configure the number of images generated between min and max (inclusive) - */ - steps?: number; - /** - * JPEG compression quality - */ - quality?: number; -} diff --git a/packages/docusaurus-plugin-pwa/package.json b/packages/docusaurus-plugin-pwa/package.json index cacecbc6032e..9a9adfb0b334 100644 --- a/packages/docusaurus-plugin-pwa/package.json +++ b/packages/docusaurus-plugin-pwa/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-pwa", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Docusaurus Plugin to add PWA support.", "main": "src/index.js", "publishConfig": { @@ -16,10 +16,10 @@ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.13", "@babel/plugin-proposal-optional-chaining": "^7.12.16", "@babel/preset-env": "^7.15.6", - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/theme-common": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/theme-common": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "babel-loader": "^8.2.2", "clsx": "^1.1.1", "core-js": "^2.6.5", diff --git a/packages/docusaurus-plugin-sitemap/package.json b/packages/docusaurus-plugin-sitemap/package.json index a4e78129ffba..55294198b26b 100644 --- a/packages/docusaurus-plugin-sitemap/package.json +++ b/packages/docusaurus-plugin-sitemap/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/plugin-sitemap", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Simple sitemap generation plugin for Docusaurus.", "main": "lib/index.js", "types": "src/plugin-sitemap.d.ts", @@ -18,11 +18,11 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/types": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-common": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/types": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-common": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "fs-extra": "^10.0.0", "sitemap": "^7.0.0", "tslib": "^2.3.1" diff --git a/packages/docusaurus-preset-classic/package.json b/packages/docusaurus-preset-classic/package.json index 7e4dadc6acc3..7bf4969b65d4 100644 --- a/packages/docusaurus-preset-classic/package.json +++ b/packages/docusaurus-preset-classic/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/preset-classic", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Classic preset for Docusaurus.", "main": "lib/index.js", "types": "src/preset-classic.d.ts", @@ -18,16 +18,16 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/plugin-content-blog": "2.0.0-beta.7", - "@docusaurus/plugin-content-docs": "2.0.0-beta.7", - "@docusaurus/plugin-content-pages": "2.0.0-beta.7", - "@docusaurus/plugin-debug": "2.0.0-beta.7", - "@docusaurus/plugin-google-analytics": "2.0.0-beta.7", - "@docusaurus/plugin-google-gtag": "2.0.0-beta.7", - "@docusaurus/plugin-sitemap": "2.0.0-beta.7", - "@docusaurus/theme-classic": "2.0.0-beta.7", - "@docusaurus/theme-search-algolia": "2.0.0-beta.7" + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/plugin-content-blog": "2.0.0-beta.8", + "@docusaurus/plugin-content-docs": "2.0.0-beta.8", + "@docusaurus/plugin-content-pages": "2.0.0-beta.8", + "@docusaurus/plugin-debug": "2.0.0-beta.8", + "@docusaurus/plugin-google-analytics": "2.0.0-beta.8", + "@docusaurus/plugin-google-gtag": "2.0.0-beta.8", + "@docusaurus/plugin-sitemap": "2.0.0-beta.8", + "@docusaurus/theme-classic": "2.0.0-beta.8", + "@docusaurus/theme-search-algolia": "2.0.0-beta.8" }, "peerDependencies": { "react": "^16.8.4 || ^17.0.0", diff --git a/packages/docusaurus-remark-plugin-npm2yarn/package.json b/packages/docusaurus-remark-plugin-npm2yarn/package.json index b9003a92ee37..6ab516482abd 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Remark plugin for converting npm commands to Yarn commands as tabs.", "main": "src/index.js", "publishConfig": { diff --git a/packages/docusaurus-theme-classic/codeTranslations/de.json b/packages/docusaurus-theme-classic/codeTranslations/de.json index 219ba427859d..56c63138c65f 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/de.json +++ b/packages/docusaurus-theme-classic/codeTranslations/de.json @@ -1,6 +1,6 @@ { "theme.AnnouncementBar.closeButtonAriaLabel": "Schließen", - "theme.BackToTopButton.buttonAriaLabel": "Scroll back to top", + "theme.BackToTopButton.buttonAriaLabel": "ZurΓΌck nach oben scrollen", "theme.CodeBlock.copied": "Kopiert", "theme.CodeBlock.copy": "Kopieren", "theme.CodeBlock.copyButtonAriaLabel": "In die Zwischenablage kopieren", @@ -21,7 +21,7 @@ "theme.SearchPage.inputLabel": "Suche", "theme.SearchPage.inputPlaceholder": "Geben Sie hier Ihre Suche ein", "theme.SearchPage.noResultsText": "Es wurden keine Ergebnisse gefunden", - "theme.TOCCollapsible.toggleButtonLabel": "On this page", + "theme.TOCCollapsible.toggleButtonLabel": "Auf dieser Seite", "theme.blog.archive.description": "Archive", "theme.blog.archive.title": "Archive", "theme.blog.paginator.navAriaLabel": "Navigation der Blog-Listenseite", @@ -54,7 +54,7 @@ "theme.lastUpdated.atDate": " am {date}", "theme.lastUpdated.byUser": " von {user}", "theme.lastUpdated.lastUpdatedAtBy": "Letztes Update{atDate}{byUser}", - "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← Back to main menu", + "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← ZurΓΌck zum HauptmenΓΌ", "theme.navbar.mobileVersionsDropdown.label": "Versions", "theme.tags.tagsListLabel": "Tags:", "theme.tags.tagsPageLink": "Alle Tags anzeigen", diff --git a/packages/docusaurus-theme-classic/codeTranslations/tr.json b/packages/docusaurus-theme-classic/codeTranslations/tr.json index f3189d2fc085..e256de49ef15 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/tr.json +++ b/packages/docusaurus-theme-classic/codeTranslations/tr.json @@ -1,6 +1,6 @@ { "theme.AnnouncementBar.closeButtonAriaLabel": "Kapat", - "theme.BackToTopButton.buttonAriaLabel": "Scroll back to top", + "theme.BackToTopButton.buttonAriaLabel": "Sayfa başına dΓΆn", "theme.CodeBlock.copied": "KopyalandΔ±", "theme.CodeBlock.copy": "Kopyala", "theme.CodeBlock.copyButtonAriaLabel": "Kodu panoya kopyala", @@ -21,9 +21,9 @@ "theme.SearchPage.inputLabel": "Ara", "theme.SearchPage.inputPlaceholder": "AramanΔ±zΔ± buraya yazΔ±n", "theme.SearchPage.noResultsText": "HiΓ§bir sonuΓ§ bulunamadΔ±", - "theme.TOCCollapsible.toggleButtonLabel": "On this page", - "theme.blog.archive.description": "Archive", - "theme.blog.archive.title": "Archive", + "theme.TOCCollapsible.toggleButtonLabel": "Bu sayfada", + "theme.blog.archive.description": "Arşiv", + "theme.blog.archive.title": "Arşiv", "theme.blog.paginator.navAriaLabel": "Blog gΓΆnderi sayfasΔ± navigasyonu", "theme.blog.paginator.newerEntries": "Yeni Girdiler", "theme.blog.paginator.olderEntries": "Eski Girdiler", @@ -33,7 +33,7 @@ "theme.blog.post.plurals": "Bir gΓΆnderi|{count} gΓΆnderi", "theme.blog.post.readMore": "Daha Fazla", "theme.blog.post.readingTime.plurals": "{readingTime} dakikalΔ±k okuma|{readingTime} dakikalΔ±k okuma", - "theme.blog.sidebar.navAriaLabel": "Blog recent posts navigation", + "theme.blog.sidebar.navAriaLabel": "Blog son gΓΆnderiler navigasyonu", "theme.blog.tagTitle": "\"{tagName}\" ile etiketlenmiş {nPosts}", "theme.common.editThisPage": "Bu sayfayΔ± dΓΌzenle", "theme.common.headingLinkTitle": "Başlığa doğrudan bağlantΔ±", @@ -45,8 +45,8 @@ "theme.docs.sidebar.collapseButtonTitle": "Kenar Γ§ubuğunu daralt", "theme.docs.sidebar.expandButtonAriaLabel": "Kenar Γ§ubuğunu genişlet", "theme.docs.sidebar.expandButtonTitle": "Kenar Γ§ubuğunu genişlet", - "theme.docs.tagDocListPageTitle": "{nDocsTagged} with \"{tagName}\"", - "theme.docs.tagDocListPageTitle.nDocsTagged": "One doc tagged|{count} docs tagged", + "theme.docs.tagDocListPageTitle": "\"{tagName}\" ile etiketlenmiş {nDocsTagged}", + "theme.docs.tagDocListPageTitle.nDocsTagged": "Bir dokΓΌman etiketlendi|{count} dokΓΌman etiketlendi", "theme.docs.versions.latestVersionLinkLabel": "en son sΓΌrΓΌm", "theme.docs.versions.latestVersionSuggestionLabel": "GΓΌncel belgeler iΓ§in bkz. {latestVersionLink} ({versionLabel}).", "theme.docs.versions.unmaintainedVersionLabel": "Bu, {siteTitle} {versionLabel} dokΓΌmantasyonudur ve bakΔ±mΔ± sonlanmıştΔ±r.", @@ -54,8 +54,8 @@ "theme.lastUpdated.atDate": " {date} tarihinde", "theme.lastUpdated.byUser": " {user} tarafΔ±ndan", "theme.lastUpdated.lastUpdatedAtBy": "En son{atDate}{byUser} gΓΌncellendi", - "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← Back to main menu", - "theme.navbar.mobileVersionsDropdown.label": "Versions", + "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← Ana menΓΌye dΓΆn", + "theme.navbar.mobileVersionsDropdown.label": "Versiyonlar", "theme.tags.tagsListLabel": "Etiketler:", "theme.tags.tagsPageLink": "TΓΌm Etiketleri GΓΆrΓΌntΓΌle", "theme.tags.tagsPageTitle": "Etiketler" diff --git a/packages/docusaurus-theme-classic/codeTranslations/vi.json b/packages/docusaurus-theme-classic/codeTranslations/vi.json index cf007aa3425f..ff52d99012c0 100644 --- a/packages/docusaurus-theme-classic/codeTranslations/vi.json +++ b/packages/docusaurus-theme-classic/codeTranslations/vi.json @@ -32,7 +32,7 @@ "theme.blog.post.paginator.olderPost": "BΓ i cΕ© hΖ‘n", "theme.blog.post.plurals": "Mα»™t bΓ i viαΊΏt|{count} bΓ i viαΊΏt", "theme.blog.post.readMore": "Đọc TiαΊΏp", - "theme.blog.post.readingTime.plurals": "{readingTime} phΓΊt để đọc", + "theme.blog.post.readingTime.plurals": "Mα»™t phΓΊt để đọc|{readingTime} phΓΊt để đọc", "theme.blog.sidebar.navAriaLabel": "Điều hΖ°α»›ng cΓ‘c bΓ i viαΊΏt gαΊ§n Δ‘Γ’y trΓͺn blog", "theme.blog.tagTitle": "{nPosts} được gαΊ―n thαΊ» \"{tagName}\"", "theme.common.editThisPage": "Sα»­a trang nΓ y", diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 14bf990f2325..faf718bc8fd8 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-classic", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Classic theme for Docusaurus", "main": "lib/index.js", "types": "src/types.d.ts", @@ -23,15 +23,15 @@ "update-code-translations": "node -e 'require(\"./update-code-translations.js\").run()'" }, "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/plugin-content-blog": "2.0.0-beta.7", - "@docusaurus/plugin-content-docs": "2.0.0-beta.7", - "@docusaurus/plugin-content-pages": "2.0.0-beta.7", - "@docusaurus/theme-common": "2.0.0-beta.7", - "@docusaurus/types": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-common": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/plugin-content-blog": "2.0.0-beta.8", + "@docusaurus/plugin-content-docs": "2.0.0-beta.8", + "@docusaurus/plugin-content-pages": "2.0.0-beta.8", + "@docusaurus/theme-common": "2.0.0-beta.8", + "@docusaurus/types": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-common": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "@mdx-js/mdx": "^1.6.21", "@mdx-js/react": "^1.6.21", "chalk": "^4.1.2", @@ -50,7 +50,7 @@ "rtlcss": "^3.3.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "2.0.0-beta.7", + "@docusaurus/module-type-aliases": "2.0.0-beta.8", "@types/mdx-js__react": "^1.5.4", "@types/parse-numeric-range": "^0.0.1", "@types/rtlcss": "^3.1.1", diff --git a/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx b/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx index 1a0e7e2b861d..bd7d49ac24a9 100644 --- a/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx @@ -101,7 +101,7 @@ const highlightDirectiveRegex = (lang: string) => { export default function CodeBlock({ children, - className: languageClassName, + className: blockClassName, metastring, title, }: Props): JSX.Element { @@ -141,6 +141,9 @@ export default function CodeBlock({ highlightLines = rangeParser(highlightLinesRange).filter((n) => n > 0); } + const languageClassName = blockClassName + ?.split(' ') + .find((str) => str.startsWith('language-')); let language = languageClassName?.replace(/language-/, '') as Language; if (!language && prism.defaultLanguage) { @@ -209,7 +212,11 @@ export default function CodeBlock({ code={code} language={language}> {({className, style, tokens, getLineProps, getTokenProps}) => ( -
+
{codeBlockTitle && (
{codeBlockTitle} diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx index 25bc454dcddf..ebb2ff1abb51 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx @@ -51,7 +51,7 @@ function DocPageContent({ setHiddenSidebar(false); } - setHiddenSidebarContainer(!hiddenSidebarContainer); + setHiddenSidebarContainer((value) => !value); }, [hiddenSidebar]); return ( diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx index 8c769004fef5..59a2d2a330c4 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/index.tsx @@ -93,7 +93,7 @@ function useAutoExpandActiveCategory({ if (justBecameActive && collapsed) { setCollapsed(false); } - }, [isActive, wasActive, collapsed]); + }, [isActive, wasActive, collapsed, setCollapsed]); } function DocSidebarItemCategory({ diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx index a3d38a2c28c8..35459e2b556a 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx @@ -141,7 +141,7 @@ function DropdownNavbarItemMobile({ if (containsActive) { setCollapsed(!containsActive); } - }, [localPathname, containsActive]); + }, [localPathname, containsActive, setCollapsed]); return (
  • { test('Should reject bad Tabs child', () => { @@ -54,53 +56,74 @@ describe('Tabs', () => { test('Should accept valid Tabs config', () => { expect(() => { renderer.create( - <> - - Tab 1 - Tab 2 - - - Tab 1 - - Tab 2 - - - - - Tab 1 - - - Tab 2 - - - - Tab 1 - Tab 2 - - - Tab 1 - Tab 2 - - - - Tab 1 - - - Tab 2 - - - , + + + + Tab 1 + Tab 2 + + + Tab 1 + + Tab 2 + + + + + Tab 1 + + + Tab 2 + + + + Tab 1 + Tab 2 + + + Tab 1 + Tab 2 + + + + Tab 1 + + + Tab 2 + + + + , ); - }).toMatchInlineSnapshot(`[Function]`); // This is just a check that the function returns. We don't care about the actual DOM. + }).not.toThrow(); // TODO Better Jest infrastructure to mock the Layout + }); + // https://github.com/facebook/docusaurus/issues/5729 + test('Should accept dynamic Tabs with number values', () => { + expect(() => { + const tabs = ['Apple', 'Banana', 'Carrot']; + renderer.create( + + + ({label: t, value: idx}))} + defaultValue={0}> + {tabs.map((t, idx) => ( + {t} + ))} + + + , + ); + }).not.toThrow(); }); }); diff --git a/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx b/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx index 91871dae86e9..343874ac09a2 100644 --- a/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx @@ -25,7 +25,7 @@ import styles from './styles.module.css'; // A very rough duck type, but good enough to guard against mistakes while // allowing customization function isTabItem(comp: ReactElement): comp is ReactElement { - return typeof comp.props.value === 'string'; + return typeof comp.props.value !== 'undefined'; } function TabsComponent(props: Props): JSX.Element { @@ -51,10 +51,7 @@ function TabsComponent(props: Props): JSX.Element { ); }); const values = - valuesProp ?? - children.map(({props: {value, label}}) => { - return {value, label}; - }); + valuesProp ?? children.map(({props: {value, label}}) => ({value, label})); const dup = duplicates(values, (a, b) => a.value === b.value); if (dup.length > 0) { throw new Error( diff --git a/packages/docusaurus-theme-classic/src/theme/hooks/useHideableNavbar.ts b/packages/docusaurus-theme-classic/src/theme/hooks/useHideableNavbar.ts index f4ae24278158..40a9da1ae93d 100644 --- a/packages/docusaurus-theme-classic/src/theme/hooks/useHideableNavbar.ts +++ b/packages/docusaurus-theme-classic/src/theme/hooks/useHideableNavbar.ts @@ -24,12 +24,19 @@ const useHideableNavbar = (hideOnScroll: boolean): useHideableNavbarReturns => { return; } + const scrollTop = currentPosition.scrollY; + + // It needed for mostly to handle rubber band scrolling + if (scrollTop < navbarHeight.current) { + setIsNavbarVisible(true); + return; + } + if (isFocusedAnchor.current) { isFocusedAnchor.current = false; return; } - const scrollTop = currentPosition.scrollY; const lastScrollTop = lastPosition?.scrollY; const documentHeight = document.documentElement.scrollHeight - navbarHeight.current; diff --git a/packages/docusaurus-theme-classic/src/theme/hooks/useTheme.ts b/packages/docusaurus-theme-classic/src/theme/hooks/useTheme.ts index fd06deac55c6..931055917607 100644 --- a/packages/docusaurus-theme-classic/src/theme/hooks/useTheme.ts +++ b/packages/docusaurus-theme-classic/src/theme/hooks/useTheme.ts @@ -68,7 +68,7 @@ const useTheme = (): useThemeReturns => { } catch (err) { console.error(err); } - }, [setTheme]); + }, [disableSwitch, setTheme]); useEffect(() => { if (disableSwitch && !respectPrefersColorScheme) { @@ -80,7 +80,7 @@ const useTheme = (): useThemeReturns => { .addListener(({matches}) => { setTheme(matches ? themes.dark : themes.light); }); - }, []); + }, [disableSwitch, respectPrefersColorScheme]); return { isDarkTheme: theme === themes.dark, diff --git a/packages/docusaurus-theme-classic/src/types.d.ts b/packages/docusaurus-theme-classic/src/types.d.ts index d2c8d415c8c2..cabd03ed3e94 100644 --- a/packages/docusaurus-theme-classic/src/types.d.ts +++ b/packages/docusaurus-theme-classic/src/types.d.ts @@ -19,6 +19,10 @@ declare module '@theme/AnnouncementBar' { export default AnnouncementBar; } +declare module '@theme/BackToTopButton' { + export default function BackToTopButton(): JSX.Element; +} + declare module '@theme/BlogListPaginator' { import type {Metadata} from '@theme/BlogListPage'; @@ -505,6 +509,10 @@ declare module '@theme/NavbarItem' { export default NavbarItem; } +declare module '@theme/SearchBar' { + export default function SearchBar(): JSX.Element; +} + declare module '@theme/TabItem' { import type {ReactNode} from 'react'; diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json index 52157559ecda..2bc7a79733f9 100644 --- a/packages/docusaurus-theme-common/package.json +++ b/packages/docusaurus-theme-common/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/theme-common", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Common code for Docusaurus themes.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,18 +18,18 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/plugin-content-blog": "2.0.0-beta.7", - "@docusaurus/plugin-content-docs": "2.0.0-beta.7", - "@docusaurus/plugin-content-pages": "2.0.0-beta.7", - "@docusaurus/types": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/plugin-content-blog": "2.0.0-beta.8", + "@docusaurus/plugin-content-docs": "2.0.0-beta.8", + "@docusaurus/plugin-content-pages": "2.0.0-beta.8", + "@docusaurus/types": "2.0.0-beta.8", "clsx": "^1.1.1", "fs-extra": "^10.0.0", "tslib": "^2.3.1", "utility-types": "^3.10.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "2.0.0-beta.7", + "@docusaurus/module-type-aliases": "2.0.0-beta.8", "lodash": "^4.17.20" }, "peerDependencies": { diff --git a/packages/docusaurus-theme-common/src/index.ts b/packages/docusaurus-theme-common/src/index.ts index f5c9ab1cdd2a..48874061623f 100644 --- a/packages/docusaurus-theme-common/src/index.ts +++ b/packages/docusaurus-theme-common/src/index.ts @@ -88,3 +88,8 @@ export { useScrollPosition, useScrollPositionBlocker, } from './utils/scrollUtils'; + +export { + useIsomorphicLayoutEffect, + useDynamicCallback, +} from './utils/reactUtils'; diff --git a/packages/docusaurus-theme-common/src/utils/announcementBarUtils.tsx b/packages/docusaurus-theme-common/src/utils/announcementBarUtils.tsx index 8a4c7a376e5e..14f67e9d4476 100644 --- a/packages/docusaurus-theme-common/src/utils/announcementBarUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/announcementBarUtils.tsx @@ -83,14 +83,14 @@ const useAnnouncementBarContextValue = (): AnnouncementBarAPI => { if (isNewAnnouncement || !isDismissedInStorage()) { setClosed(false); } - }, []); + }, [announcementBar]); return useMemo(() => { return { isActive: !!announcementBar && !isClosed, close: handleClose, }; - }, [isClosed]); + }, [announcementBar, isClosed, handleClose]); }; const AnnouncementBarContext = createContext(null); diff --git a/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/DocsPreferredVersionProvider.tsx b/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/DocsPreferredVersionProvider.tsx index 2176c25e5f51..07911a858ed8 100644 --- a/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/DocsPreferredVersionProvider.tsx +++ b/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/DocsPreferredVersionProvider.tsx @@ -120,7 +120,7 @@ function useContextValue() { return { savePreferredVersion, }; - }, [setState]); + }, [versionPersistence]); return [state, api] as const; } diff --git a/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/useDocsPreferredVersion.ts b/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/useDocsPreferredVersion.ts index 5bfa49b3729d..ace170eafd40 100644 --- a/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/useDocsPreferredVersion.ts +++ b/packages/docusaurus-theme-common/src/utils/docsPreferredVersion/useDocsPreferredVersion.ts @@ -30,7 +30,7 @@ export function useDocsPreferredVersion( (versionName: string) => { api.savePreferredVersion(pluginId, versionName); }, - [api], + [api, pluginId], ); return {preferredVersion, savePreferredVersionName} as const; diff --git a/packages/docusaurus-theme-common/src/utils/mobileSecondaryMenu.tsx b/packages/docusaurus-theme-common/src/utils/mobileSecondaryMenu.tsx index f51c93795e64..b58b621a38c1 100644 --- a/packages/docusaurus-theme-common/src/utils/mobileSecondaryMenu.tsx +++ b/packages/docusaurus-theme-common/src/utils/mobileSecondaryMenu.tsx @@ -83,6 +83,7 @@ function useShallowMemoizedObject>(obj: O) { return useMemo( () => obj, // Is this safe? + // eslint-disable-next-line react-hooks/exhaustive-deps [...Object.keys(obj), ...Object.values(obj)], ); } diff --git a/packages/docusaurus-theme-common/src/utils/reactUtils.tsx b/packages/docusaurus-theme-common/src/utils/reactUtils.tsx new file mode 100644 index 000000000000..5a3ce9ec7064 --- /dev/null +++ b/packages/docusaurus-theme-common/src/utils/reactUtils.tsx @@ -0,0 +1,34 @@ +/** + * 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 {useCallback, useEffect, useLayoutEffect, useRef} from 'react'; + +// This hook is like useLayoutEffect, but without the SSR warning +// It seems hacky but it's used in many React libs (Redux, Formik...) +// Also mentioned here: https://github.com/facebook/react/issues/16956 +// It is useful when you need to update a ref as soon as possible after a React render (before useEffect) +export const useIsomorphicLayoutEffect = + typeof window !== 'undefined' ? useLayoutEffect : useEffect; + +// Permits to transform an unstable callback (like an arrow function provided as props) +// to a "stable" callback that is safe to use in a useEffect dependency array +// Useful to avoid React stale closure problems + avoid useless effect re-executions +// +// Workaround until the React team recommends a good solution, see https://github.com/facebook/react/issues/16956 +// This generally works has some potential drawbacks, such as https://github.com/facebook/react/issues/16956#issuecomment-536636418 +export function useDynamicCallback unknown>( + callback: T, +): T { + const ref = useRef(callback); + + useIsomorphicLayoutEffect(() => { + ref.current = callback; + }, [callback]); + + // @ts-expect-error: TODO, not sure how to fix this TS error + return useCallback((...args) => ref.current(...args), []); +} diff --git a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx index 9c54f405ae31..6bd3e4b766ef 100644 --- a/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/scrollUtils.tsx @@ -15,6 +15,7 @@ import React, { useMemo, useRef, } from 'react'; +import {useDynamicCallback} from './reactUtils'; import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; /** @@ -103,20 +104,22 @@ export function useScrollPosition( const {scrollEventsEnabledRef} = useScrollController(); const lastPositionRef = useRef(getScrollPosition()); - const handleScroll = () => { - if (!scrollEventsEnabledRef.current) { - return; - } - const currentPosition = getScrollPosition()!; + const dynamicEffect = useDynamicCallback(effect); - if (effect) { - effect(currentPosition, lastPositionRef.current); - } + useEffect(() => { + const handleScroll = () => { + if (!scrollEventsEnabledRef.current) { + return; + } + const currentPosition = getScrollPosition()!; - lastPositionRef.current = currentPosition; - }; + if (dynamicEffect) { + dynamicEffect(currentPosition, lastPositionRef.current); + } + + lastPositionRef.current = currentPosition; + }; - useEffect(() => { const opts: AddEventListenerOptions & EventListenerOptions = { passive: true, }; @@ -125,7 +128,12 @@ export function useScrollPosition( window.addEventListener('scroll', handleScroll, opts); return () => window.removeEventListener('scroll', handleScroll, opts); - }, deps); + }, [ + dynamicEffect, + scrollEventsEnabledRef, + // eslint-disable-next-line react-hooks/exhaustive-deps + ...deps, + ]); } type UseScrollPositionSaver = { @@ -170,7 +178,7 @@ function useScrollPositionSaver(): UseScrollPositionSaver { return {restored: heightDiff !== 0}; }, []); - return useMemo(() => ({save, restore}), []); + return useMemo(() => ({save, restore}), [restore, save]); } type UseScrollPositionBlockerReturn = { @@ -217,7 +225,7 @@ export function useScrollPositionBlocker(): UseScrollPositionBlockerReturn { } }; }, - [scrollController], + [scrollController, scrollPositionSaver], ); useLayoutEffect(() => { diff --git a/packages/docusaurus-theme-common/src/utils/useLocationChange.ts b/packages/docusaurus-theme-common/src/utils/useLocationChange.ts index 70120ca277c0..6be0d3000a7f 100644 --- a/packages/docusaurus-theme-common/src/utils/useLocationChange.ts +++ b/packages/docusaurus-theme-common/src/utils/useLocationChange.ts @@ -9,6 +9,7 @@ import {useEffect} from 'react'; import {useLocation} from '@docusaurus/router'; import {Location} from '@docusaurus/history'; import {usePrevious} from './usePrevious'; +import {useDynamicCallback} from './reactUtils'; type LocationChangeEvent = { location: Location; @@ -21,10 +22,12 @@ export function useLocationChange(onLocationChange: OnLocationChange): void { const location = useLocation(); const previousLocation = usePrevious(location); + const onLocationChangeDynamic = useDynamicCallback(onLocationChange); + useEffect(() => { - onLocationChange({ + onLocationChangeDynamic({ location, previousLocation, }); - }, [location]); + }, [onLocationChangeDynamic, location, previousLocation]); } diff --git a/packages/docusaurus-theme-common/src/utils/usePrevious.ts b/packages/docusaurus-theme-common/src/utils/usePrevious.ts index 2a27462ff374..22cb744e05bd 100644 --- a/packages/docusaurus-theme-common/src/utils/usePrevious.ts +++ b/packages/docusaurus-theme-common/src/utils/usePrevious.ts @@ -5,12 +5,13 @@ * LICENSE file in the root directory of this source tree. */ -import {useRef, useEffect} from 'react'; +import {useRef} from 'react'; +import {useIsomorphicLayoutEffect} from './reactUtils'; export function usePrevious(value: T): T | undefined { const ref = useRef(); - useEffect(() => { + useIsomorphicLayoutEffect(() => { ref.current = value; }); diff --git a/packages/docusaurus-theme-live-codeblock/package.json b/packages/docusaurus-theme-live-codeblock/package.json index 517460f58fa0..293046ab891b 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Docusaurus live code block component.", "main": "src/index.js", "publishConfig": { @@ -13,8 +13,8 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "@philpl/buble": "^0.19.7", "clsx": "^1.1.1", "parse-numeric-range": "^1.3.0", diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.js b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.js index 2b35c04b51a2..92ee17f67d9a 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.js +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.js @@ -10,14 +10,20 @@ import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live'; import clsx from 'clsx'; import Translate from '@docusaurus/Translate'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import useIsBrowser from '@docusaurus/useIsBrowser'; +import BrowserOnly from '@docusaurus/BrowserOnly'; import usePrismTheme from '@theme/hooks/usePrismTheme'; import styles from './styles.module.css'; +import useIsBrowser from '@docusaurus/core/lib/client/exports/useIsBrowser'; function Header({children}) { return
    {children}
    ; } +function LivePreviewLoader() { + // Is it worth improving/translating? + return
    Loading...
    ; +} + function ResultWithHeader() { return ( <> @@ -28,14 +34,33 @@ function ResultWithHeader() { Result + {/* https://github.com/facebook/docusaurus/issues/5747 */}
    - - + }> + {() => ( + <> + + + + )} +
    ); } +function ThemedLiveEditor() { + const isBrowser = useIsBrowser(); + return ( + + ); +} + function EditorWithHeader() { return ( <> @@ -46,13 +71,12 @@ function EditorWithHeader() { Live Editor - + ); } export default function Playground({children, transformCode, ...props}) { - const isBrowser = useIsBrowser(); const { siteConfig: { themeConfig: { @@ -65,8 +89,7 @@ export default function Playground({children, transformCode, ...props}) { return (
    `${code};`)} theme={prismTheme} {...props}> diff --git a/packages/docusaurus-theme-search-algolia/package.json b/packages/docusaurus-theme-search-algolia/package.json index c4681f522ecd..6dda70cec94b 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Algolia search component for Docusaurus.", "main": "src/index.js", "publishConfig": { @@ -14,10 +14,10 @@ "license": "MIT", "dependencies": { "@docsearch/react": "^3.0.0-alpha.39", - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/theme-common": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/theme-common": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "algoliasearch": "^4.10.5", "algoliasearch-helper": "^3.5.5", "clsx": "^1.1.1", diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.js b/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.js index 8e0fd9e973f0..8c3ac8b7d7a6 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.js +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.js @@ -16,7 +16,11 @@ import clsx from 'clsx'; import Head from '@docusaurus/Head'; import Link from '@docusaurus/Link'; import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; -import {useTitleFormatter, usePluralForm} from '@docusaurus/theme-common'; +import { + useTitleFormatter, + usePluralForm, + useDynamicCallback, +} from '@docusaurus/theme-common'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import {useAllDocsData} from '@theme/hooks/useDocs'; import useSearchQuery from '@theme/hooks/useSearchQuery'; @@ -125,8 +129,7 @@ function SearchPage() { const documentsFoundPlural = useDocumentsFoundPlural(); const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers(); - const {searchValue, updateSearchPath} = useSearchQuery(); - const [searchQuery, setSearchQuery] = useState(searchValue); + const {searchQuery, setSearchQuery} = useSearchQuery(); const initialSearchResultState = { items: [], query: null, @@ -173,6 +176,7 @@ function SearchPage() { }, initialSearchResultState, ); + const algoliaClient = algoliaSearch(appId, apiKey); const algoliaHelper = algoliaSearchHelper(algoliaClient, indexName, { hitsPerPage: 15, @@ -271,7 +275,7 @@ function SearchPage() { description: 'The search page title for empty query', }); - const makeSearch = (page = 0) => { + const makeSearch = useDynamicCallback((page = 0) => { algoliaHelper.addDisjunctiveFacetRefinement('docusaurus_tag', 'default'); algoliaHelper.addDisjunctiveFacetRefinement('language', currentLocale); @@ -285,23 +289,19 @@ function SearchPage() { ); algoliaHelper.setQuery(searchQuery).setPage(page).search(); - }; + }); useEffect(() => { if (!loaderRef) { return undefined; } + const currentObserver = observer.current; - observer.current.observe(loaderRef); - - return () => { - observer.current.unobserve(loaderRef); - }; + currentObserver.observe(loaderRef); + return () => currentObserver.unobserve(loaderRef); }, [loaderRef]); useEffect(() => { - updateSearchPath(searchQuery); - searchResultStateDispatcher({type: 'reset'}); if (searchQuery) { @@ -311,7 +311,7 @@ function SearchPage() { makeSearch(); }, 300); } - }, [searchQuery, docsSearchVersionsHelpers.searchVersions]); + }, [searchQuery, docsSearchVersionsHelpers.searchVersions, makeSearch]); useEffect(() => { if (!searchResultState.lastPage || searchResultState.lastPage === 0) { @@ -319,13 +319,7 @@ function SearchPage() { } makeSearch(searchResultState.lastPage); - }, [searchResultState.lastPage]); - - useEffect(() => { - if (searchValue && searchValue !== searchQuery) { - setSearchQuery(searchValue); - } - }, [searchValue]); + }, [makeSearch, searchResultState.lastPage]); return ( diff --git a/packages/docusaurus-theme-search-algolia/src/theme/hooks/useSearchQuery.js b/packages/docusaurus-theme-search-algolia/src/theme/hooks/useSearchQuery.js index 19e942c1dba2..5789251fa814 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/hooks/useSearchQuery.js +++ b/packages/docusaurus-theme-search-algolia/src/theme/hooks/useSearchQuery.js @@ -5,27 +5,34 @@ * LICENSE file in the root directory of this source tree. */ -import {useHistory, useLocation} from '@docusaurus/router'; -import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; +import {useHistory} from '@docusaurus/router'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import {useCallback, useEffect, useState} from 'react'; const SEARCH_PARAM_QUERY = 'q'; function useSearchQuery() { const history = useHistory(); - const location = useLocation(); - const {siteConfig: {baseUrl} = {}} = useDocusaurusContext(); + const { + siteConfig: {baseUrl}, + } = useDocusaurusContext(); - return { - searchValue: - (ExecutionEnvironment.canUseDOM && - new URLSearchParams(location.search).get(SEARCH_PARAM_QUERY)) || - '', - updateSearchPath: (searchValue) => { - const searchParams = new URLSearchParams(location.search); - - if (searchValue) { - searchParams.set(SEARCH_PARAM_QUERY, searchValue); + const [searchQuery, setSearchQueryState] = useState(''); + + // Init search query just after React hydration + useEffect(() => { + const searchQueryStringValue = + new URLSearchParams(window.location.search).get(SEARCH_PARAM_QUERY) ?? ''; + + setSearchQueryState(searchQueryStringValue); + }, []); + + const setSearchQuery = useCallback( + (newSearchQuery) => { + const searchParams = new URLSearchParams(window.location.search); + + if (newSearchQuery) { + searchParams.set(SEARCH_PARAM_QUERY, newSearchQuery); } else { searchParams.delete(SEARCH_PARAM_QUERY); } @@ -33,11 +40,23 @@ function useSearchQuery() { history.replace({ search: searchParams.toString(), }); + setSearchQueryState(newSearchQuery); }, - generateSearchPageLink: (searchValue) => { + [history], + ); + + const generateSearchPageLink = useCallback( + (targetSearchQuery) => { // Refer to https://github.com/facebook/docusaurus/pull/2838 - return `${baseUrl}search?q=${encodeURIComponent(searchValue)}`; + return `${baseUrl}search?q=${encodeURIComponent(targetSearchQuery)}`; }, + [baseUrl], + ); + + return { + searchQuery, + setSearchQuery, + generateSearchPageLink, }; } diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index 0b4203445764..24a00f2f4a8c 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/types", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Common types for Docusaurus packages.", "types": "./src/index.d.ts", "publishConfig": { diff --git a/packages/docusaurus-utils-common/package.json b/packages/docusaurus-utils-common/package.json index 5edf47a0b256..5a3cfba53587 100644 --- a/packages/docusaurus-utils-common/package.json +++ b/packages/docusaurus-utils-common/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils-common", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Common (Node/Browser) utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,7 +18,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/types": "2.0.0-beta.7", + "@docusaurus/types": "2.0.0-beta.8", "tslib": "^2.3.1" }, "engines": { diff --git a/packages/docusaurus-utils-validation/package.json b/packages/docusaurus-utils-validation/package.json index b75b1b77eecd..cfca0396407c 100644 --- a/packages/docusaurus-utils-validation/package.json +++ b/packages/docusaurus-utils-validation/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils-validation", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Node validation utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,7 +18,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/utils": "2.0.0-beta.7", + "@docusaurus/utils": "2.0.0-beta.8", "chalk": "^4.1.2", "joi": "^17.4.2", "tslib": "^2.3.1" diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index 94e45dfe70ab..f1d257417da9 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/utils", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Node utility functions for Docusaurus packages.", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -18,7 +18,7 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/types": "2.0.0-beta.7", + "@docusaurus/types": "2.0.0-beta.8", "@mdx-js/runtime": "^1.6.22", "@types/github-slugger": "^1.3.0", "chalk": "^4.1.2", diff --git a/packages/docusaurus/bin/docusaurus.js b/packages/docusaurus/bin/docusaurus.js index dbd4ed422ab9..279623514af1 100755 --- a/packages/docusaurus/bin/docusaurus.js +++ b/packages/docusaurus/bin/docusaurus.js @@ -206,11 +206,16 @@ cli ); cli - .command('write-heading-ids [contentDir]') + .command('write-heading-ids [contentDir] [files]') .description('Generate heading ids in Markdown content.') - .action((siteDir) => { - writeHeadingIds(siteDir); - }); + .option( + '--maintain-case', + "keep the headings' casing, otherwise make all lowercase (default: false)", + ) + .option('--overwrite', 'overwrite existing heading IDs (default: false)') + .action((siteDir, files, options) => + writeHeadingIds(resolveDir(siteDir), files, options), + ); cli.arguments('').action((cmd) => { cli.outputHelp(); diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index 665d22b4f7dd..939c72d33ec2 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": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "license": "MIT", "publishConfig": { "access": "public" @@ -31,7 +31,7 @@ "url": "https://github.com/facebook/docusaurus/issues" }, "devDependencies": { - "@docusaurus/module-type-aliases": "2.0.0-beta.7", + "@docusaurus/module-type-aliases": "2.0.0-beta.8", "@types/copy-webpack-plugin": "^8.0.1", "@types/css-minimizer-webpack-plugin": "^3.0.2", "@types/detect-port": "^1.3.0", @@ -55,12 +55,12 @@ "@babel/runtime": "^7.15.4", "@babel/runtime-corejs3": "^7.15.4", "@babel/traverse": "^7.12.13", - "@docusaurus/cssnano-preset": "2.0.0-beta.7", + "@docusaurus/cssnano-preset": "2.0.0-beta.8", "@docusaurus/react-loadable": "5.5.0", - "@docusaurus/types": "2.0.0-beta.7", - "@docusaurus/utils": "2.0.0-beta.7", - "@docusaurus/utils-common": "2.0.0-beta.7", - "@docusaurus/utils-validation": "2.0.0-beta.7", + "@docusaurus/types": "2.0.0-beta.8", + "@docusaurus/utils": "2.0.0-beta.8", + "@docusaurus/utils-common": "2.0.0-beta.8", + "@docusaurus/utils-validation": "2.0.0-beta.8", "@slorber/static-site-generator-webpack-plugin": "^4.0.0", "@svgr/webpack": "^5.5.0", "autoprefixer": "^10.3.5", @@ -87,7 +87,7 @@ "globby": "^11.0.2", "html-minifier-terser": "^6.0.2", "html-tags": "^3.1.0", - "html-webpack-plugin": "^5.3.2", + "html-webpack-plugin": "^5.4.0", "import-fresh": "^3.3.0", "is-root": "^2.1.0", "leven": "^3.1.0", diff --git a/packages/docusaurus/src/client/exports/Link.tsx b/packages/docusaurus/src/client/exports/Link.tsx index 562653c5ad30..14203a1becea 100644 --- a/packages/docusaurus/src/client/exports/Link.tsx +++ b/packages/docusaurus/src/client/exports/Link.tsx @@ -90,16 +90,16 @@ function Link({ const IOSupported = ExecutionEnvironment.canUseIntersectionObserver; - let io: IntersectionObserver; + const ioRef = useRef(); const handleIntersection = (el: HTMLAnchorElement, cb: () => void) => { - io = new window.IntersectionObserver((entries) => { + ioRef.current = new window.IntersectionObserver((entries) => { entries.forEach((entry) => { if (el === entry.target) { // If element is in viewport, stop listening/observing and run callback. // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API if (entry.isIntersecting || entry.intersectionRatio > 0) { - io.unobserve(el); - io.disconnect(); + ioRef.current!.unobserve(el); + ioRef.current!.disconnect(); cb(); } } @@ -107,7 +107,7 @@ function Link({ }); // Add element to the observer. - io.observe(el); + ioRef.current!.observe(el); }; const handleRef = (ref: HTMLAnchorElement | null) => { @@ -138,11 +138,11 @@ function Link({ // When unmounting, stop intersection observer from watching. return () => { - if (IOSupported && io) { - io.disconnect(); + if (IOSupported && ioRef.current) { + ioRef.current.disconnect(); } }; - }, [targetLink, IOSupported, isInternal]); + }, [ioRef, targetLink, IOSupported, isInternal]); const isAnchorLink = targetLink?.startsWith('#') ?? false; const isRegularHtmlLink = !targetLink || !isInternal || isAnchorLink; diff --git a/packages/docusaurus/src/client/exports/constants.ts b/packages/docusaurus/src/client/exports/constants.ts index 48fa05bd6982..e7e5a1dcc2b2 100644 --- a/packages/docusaurus/src/client/exports/constants.ts +++ b/packages/docusaurus/src/client/exports/constants.ts @@ -5,16 +5,5 @@ * LICENSE file in the root directory of this source tree. */ -/* -// eslint-disable-next-line no-restricted-imports -export { - // constants were only available on node - // this makes some useful constants available to frontend/themes too - // import {DEFAULT_PLUGIN_ID} '@docusaurus/constants' - DEFAULT_PLUGIN_ID, -} from '../../constants'; - */ - -// Not duplicating the constants seems to produce -// weird TS compilation side-effects +// Constants used on the client-side: duplicated from server-side code export const DEFAULT_PLUGIN_ID = 'default'; diff --git a/packages/docusaurus/src/client/exports/useGlobalData.ts b/packages/docusaurus/src/client/exports/useGlobalData.ts index 15c9034accc8..155ee22e6fe6 100644 --- a/packages/docusaurus/src/client/exports/useGlobalData.ts +++ b/packages/docusaurus/src/client/exports/useGlobalData.ts @@ -6,12 +6,7 @@ */ import useDocusaurusContext from './useDocusaurusContext'; - -// TODO annoying constant duplication -// if we import something from outside the /client folder, -// the tsc directory structure is affected -// import {DEFAULT_PLUGIN_ID} from '../../constants'; -const DEFAULT_PLUGIN_ID = 'default'; +import {DEFAULT_PLUGIN_ID} from './constants'; export default function useGlobalData(): Record { const {globalData} = useDocusaurusContext(); diff --git a/packages/docusaurus/src/commands/__tests__/writeHeadingIds.test.ts b/packages/docusaurus/src/commands/__tests__/writeHeadingIds.test.ts index b0fe9857ab9d..e965c5ea32f9 100644 --- a/packages/docusaurus/src/commands/__tests__/writeHeadingIds.test.ts +++ b/packages/docusaurus/src/commands/__tests__/writeHeadingIds.test.ts @@ -22,49 +22,76 @@ describe('transformMarkdownHeadingLine', () => { test('works for simple level-2 heading', () => { expect(transformMarkdownHeadingLine('## ABC', new GithubSlugger())).toEqual( - '## ABC {#-abc}', + '## ABC {#abc}', ); }); test('works for simple level-3 heading', () => { expect( transformMarkdownHeadingLine('### ABC', new GithubSlugger()), - ).toEqual('### ABC {#-abc}'); + ).toEqual('### ABC {#abc}'); }); test('works for simple level-4 heading', () => { expect( transformMarkdownHeadingLine('#### ABC', new GithubSlugger()), - ).toEqual('#### ABC {#-abc}'); + ).toEqual('#### ABC {#abc}'); }); test('works for simple level-2 heading', () => { expect(transformMarkdownHeadingLine('## ABC', new GithubSlugger())).toEqual( - '## ABC {#-abc}', + '## ABC {#abc}', ); }); test('unwraps markdown links', () => { const input = `## hello [facebook](https://facebook.com) [crowdin](https://crowdin.com/translate/docusaurus-v2/126/en-fr?filter=basic&value=0)`; expect(transformMarkdownHeadingLine(input, new GithubSlugger())).toEqual( - `${input} {#-hello-facebook-crowdin}`, + `${input} {#hello-facebook-crowdin}`, ); }); test('can slugify complex headings', () => { const input = '## abc [Hello] How are you %SΓ©bastien_-_$)( ## -56756'; expect(transformMarkdownHeadingLine(input, new GithubSlugger())).toEqual( - `${input} {#-abc-hello-how-are-you-sΓ©bastien_-_---56756}`, + `${input} {#abc-hello-how-are-you-sΓ©bastien_-_---56756}`, ); }); test('does not duplicate duplicate id', () => { expect( transformMarkdownHeadingLine( - '# hello world {#hello-world}', + '## hello world {#hello-world}', new GithubSlugger(), ), - ).toEqual('# hello world {#hello-world}'); + ).toEqual('## hello world {#hello-world}'); + }); + + test('respects existing heading', () => { + expect( + transformMarkdownHeadingLine( + '## New heading {#old-heading}', + new GithubSlugger(), + ), + ).toEqual('## New heading {#old-heading}'); + }); + + test('overwrites heading ID when asked to', () => { + expect( + transformMarkdownHeadingLine( + '## New heading {#old-heading}', + new GithubSlugger(), + {overwrite: true}, + ), + ).toEqual('## New heading {#new-heading}'); + }); + + test('maintains casing when asked to', () => { + expect( + transformMarkdownHeadingLine('## getDataFromAPI()', new GithubSlugger(), { + maintainCase: true, + }), + ).toEqual('## getDataFromAPI() {#getDataFromAPI}'); }); }); @@ -72,7 +99,7 @@ describe('transformMarkdownContent', () => { test('transform the headings', () => { const input = ` -# Ignorerd title +# Ignored title ## abc @@ -97,17 +124,17 @@ describe('transformMarkdownContent', () => { // not sure how to implement that atm const expected = ` -# Ignorerd title +# Ignored title -## abc {#-abc} +## abc {#abc} -### Hello world {#-hello-world} +### Hello world {#hello-world} \`\`\` # Heading in code block \`\`\` -## Hello world {#-hello-world-1} +## Hello world {#hello-world-1} \`\`\` # Heading in escaped code block diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index 6e94f302ad78..9bb5c3f6570b 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -167,7 +167,9 @@ Try using DEPLOYMENT_BRANCH=main or DEPLOYMENT_BRANCH=master`); const toPath = await fs.mkdtemp( path.join(os.tmpdir(), `${projectName}-${deploymentBranch}`), ); - if (shellExecLog(`git clone ${remoteBranch} ${toPath}`).code !== 0) { + if ( + shellExecLog(`git clone --depth 1 ${remoteBranch} ${toPath}`).code !== 0 + ) { throw new Error(`Running "git clone" command in "${toPath}" failed.`); } diff --git a/packages/docusaurus/src/commands/writeHeadingIds.ts b/packages/docusaurus/src/commands/writeHeadingIds.ts index 8049ce923dda..dddc9ee870d4 100644 --- a/packages/docusaurus/src/commands/writeHeadingIds.ts +++ b/packages/docusaurus/src/commands/writeHeadingIds.ts @@ -11,15 +11,23 @@ import chalk from 'chalk'; import {loadContext, loadPluginConfigs} from '../server'; import initPlugins from '../server/plugins/init'; -import {flatten} from 'lodash'; import {parseMarkdownHeadingId} from '@docusaurus/utils'; import {safeGlobby} from '../server/utils'; -export function unwrapMarkdownLinks(line: string): string { +type Options = { + maintainCase?: boolean; + overwrite?: boolean; +}; + +function unwrapMarkdownLinks(line: string): string { return line.replace(/\[([^\]]+)\]\([^)]+\)/g, (match, p1) => p1); } -function addHeadingId(line: string, slugger: GithubSlugger): string { +function addHeadingId( + line: string, + slugger: GithubSlugger, + maintainCase: boolean, +): string { let headingLevel = 0; while (line.charAt(headingLevel) === '#') { headingLevel += 1; @@ -27,7 +35,10 @@ function addHeadingId(line: string, slugger: GithubSlugger): string { const headingText = line.slice(headingLevel).trimEnd(); const headingHashes = line.slice(0, headingLevel); - const slug = slugger.slug(unwrapMarkdownLinks(headingText)); + const slug = slugger + .slug(unwrapMarkdownLinks(headingText).trim(), maintainCase) + .replace(/^-+/, '') + .replace(/-+$/, ''); return `${headingHashes}${headingText} {#${slug}}`; } @@ -35,33 +46,36 @@ function addHeadingId(line: string, slugger: GithubSlugger): string { export function transformMarkdownHeadingLine( line: string, slugger: GithubSlugger, + options: Options = {maintainCase: false, overwrite: false}, ): string { + const {maintainCase = false, overwrite = false} = options; if (!line.startsWith('#')) { throw new Error(`Line is not a Markdown heading: ${line}.`); } const parsedHeading = parseMarkdownHeadingId(line); - // Do not process if id is already therer - if (parsedHeading.id) { + // Do not process if id is already there + if (parsedHeading.id && !overwrite) { return line; } - return addHeadingId(line, slugger); + return addHeadingId(parsedHeading.text, slugger, maintainCase); } -export function transformMarkdownLine( +function transformMarkdownLine( line: string, slugger: GithubSlugger, + options?: Options, ): string { // Ignore h1 headings on purpose, as we don't create anchor links for those if (line.startsWith('##')) { - return transformMarkdownHeadingLine(line, slugger); + return transformMarkdownHeadingLine(line, slugger, options); } else { return line; } } -function transformMarkdownLines(lines: string[]): string[] { +function transformMarkdownLines(lines: string[], options?: Options): string[] { let inCode = false; const slugger = new GithubSlugger(); @@ -73,20 +87,27 @@ function transformMarkdownLines(lines: string[]): string[] { if (inCode) { return line; } - return transformMarkdownLine(line, slugger); + return transformMarkdownLine(line, slugger, options); } }); } -export function transformMarkdownContent(content: string): string { - return transformMarkdownLines(content.split('\n')).join('\n'); +export function transformMarkdownContent( + content: string, + options?: Options, +): string { + return transformMarkdownLines(content.split('\n'), options).join('\n'); } async function transformMarkdownFile( filepath: string, + options?: Options, ): Promise { const content = await fs.readFile(filepath, 'utf8'); - const updatedContent = transformMarkdownLines(content.split('\n')).join('\n'); + const updatedContent = transformMarkdownLines( + content.split('\n'), + options, + ).join('\n'); if (content !== updatedContent) { await fs.writeFile(filepath, updatedContent); return filepath; @@ -100,19 +121,28 @@ async function transformMarkdownFile( async function getPathsToWatch(siteDir: string): Promise { const context = await loadContext(siteDir); const pluginConfigs = loadPluginConfigs(context); - const plugins = await initPlugins({ + const plugins = initPlugins({ pluginConfigs, context, }); - return flatten(plugins.map((plugin) => plugin?.getPathsToWatch?.() ?? [])); + return plugins.flatMap((plugin) => plugin?.getPathsToWatch?.() ?? []); } -export default async function writeHeadingIds(siteDir: string): Promise { - const markdownFiles = await safeGlobby(await getPathsToWatch(siteDir), { - expandDirectories: ['**/*.{md,mdx}'], - }); - - const result = await Promise.all(markdownFiles.map(transformMarkdownFile)); +export default async function writeHeadingIds( + siteDir: string, + files?: string, + options?: Options, +): Promise { + const markdownFiles = await safeGlobby( + files ? [files] : await getPathsToWatch(siteDir), + { + expandDirectories: ['**/*.{md,mdx}'], + }, + ); + + const result = await Promise.all( + markdownFiles.map((p) => transformMarkdownFile(p, options)), + ); const pathsModified = result.filter(Boolean) as string[]; @@ -126,7 +156,11 @@ export default async function writeHeadingIds(siteDir: string): Promise { } else { console.log( chalk.yellow( - `${markdownFiles.length} Markdown files already have explicit heading ids.`, + `${ + markdownFiles.length + } Markdown files already have explicit heading IDs. If you intend to overwrite the existing heading IDs, use the ${chalk.cyan( + '--overwrite', + )} option.`, ), ); } diff --git a/packages/lqip-loader/package.json b/packages/lqip-loader/package.json index cf2cc82cdf35..d1a030c326fb 100644 --- a/packages/lqip-loader/package.json +++ b/packages/lqip-loader/package.json @@ -1,6 +1,6 @@ { "name": "@docusaurus/lqip-loader", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Low Quality Image Placeholders (LQIP) loader for webpack.", "main": "src/index.js", "publishConfig": { diff --git a/packages/stylelint-copyright/package.json b/packages/stylelint-copyright/package.json index 2c941fed101f..8166ec55a91b 100644 --- a/packages/stylelint-copyright/package.json +++ b/packages/stylelint-copyright/package.json @@ -1,6 +1,6 @@ { "name": "stylelint-copyright", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "description": "Stylelint plugin to check CSS files for a copyright header.", "main": "index.js", "license": "MIT", diff --git a/website/_dogfooding/_blog tests/2021-10-07-blog-post-mdx-feed-tests.mdx b/website/_dogfooding/_blog tests/2021-10-07-blog-post-mdx-feed-tests.mdx index 72db346e7256..005d1b52e81b 100644 --- a/website/_dogfooding/_blog tests/2021-10-07-blog-post-mdx-feed-tests.mdx +++ b/website/_dogfooding/_blog tests/2021-10-07-blog-post-mdx-feed-tests.mdx @@ -3,6 +3,7 @@ title: Blog post MDX Feed tests authors: - slorber tags: [blog, docusaurus, long-long, long-long-long, long-long-long-long] +hide_reading_time: true --- Some MDX tests, mostly to test how the RSS feed render those diff --git a/website/_dogfooding/_blog tests/2021-10-08-blog-post-mdx-require-feed-tests.mdx b/website/_dogfooding/_blog tests/2021-10-08-blog-post-mdx-require-feed-tests.mdx new file mode 100644 index 000000000000..29c0cd60fa84 --- /dev/null +++ b/website/_dogfooding/_blog tests/2021-10-08-blog-post-mdx-require-feed-tests.mdx @@ -0,0 +1,20 @@ +--- +title: Blog post MDX require Feed tests +authors: + - slorber +tags: [blog, docusaurus, long-long, long-long-long, long-long-long-long] +--- + +Some MDX tests, mostly to test how the RSS feed render those + + + +Test MDX with require calls + +import useBaseUrl from '@docusaurus/useBaseUrl'; + + + + + + diff --git a/website/_dogfooding/_docs tests/tests/img-tests.mdx b/website/_dogfooding/_docs tests/tests/img-tests.mdx new file mode 100644 index 000000000000..885500b6a32e --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/img-tests.mdx @@ -0,0 +1,19 @@ +# Image tests + +import Image from '@theme/IdealImage'; + +import docusaurusImport from '@site/static/img/docusaurus.png'; + +export const docusaurusRequire = require('@site/static/img/docusaurus.png'); + +## Regular images + + + + + +## Ideal images + + + + diff --git a/website/_dogfooding/docs-tests-sidebars.js b/website/_dogfooding/docs-tests-sidebars.js index 61fdaa1f2325..02682bbdd8d3 100644 --- a/website/_dogfooding/docs-tests-sidebars.js +++ b/website/_dogfooding/docs-tests-sidebars.js @@ -13,6 +13,16 @@ module.exports = { className: 'red', label: 'Index', }, + { + type: 'category', + label: 'Tests', + items: [ + { + type: 'autogenerated', + dirName: 'tests', + }, + ], + }, { type: 'category', label: 'section', diff --git a/website/_dogfooding/dogfooding.config.js b/website/_dogfooding/dogfooding.config.js index ab350802069a..be9960027238 100644 --- a/website/_dogfooding/dogfooding.config.js +++ b/website/_dogfooding/dogfooding.config.js @@ -31,6 +31,10 @@ const dogfoodingPluginInstances = [ title: 'Docusaurus Tests Blog', copyright: `Copyright Β© ${new Date().getFullYear()} Facebook, Inc.`, }, + readingTime: ({content, frontMatter, defaultReadingTime}) => + frontMatter.hide_reading_time + ? undefined + : defaultReadingTime({content, options: {wordsPerMinute: 5}}), }), ], diff --git a/website/community/2-resources.md b/website/community/2-resources.md index 1a6c6fccbade..37176ac4adc1 100644 --- a/website/community/2-resources.md +++ b/website/community/2-resources.md @@ -45,6 +45,7 @@ See the showcase - [docusaurus-prince-pdf](https://github.com/signcl/docusaurus-prince-pdf) - Generate PDF with PrinceXML for better font subsetting and ToC features. Support Docusaurus v2 sites - [mdx-mermaid](https://github.com/sjwall/mdx-mermaid) - A Docusaurus v2 compatible MDX plugin for displaying [Mermaid](https://mermaid-js.github.io/mermaid) diagrams - [redocusaurus](https://github.com/rohit-gohri/redocusaurus) - A Docusaurus preset for integrating OpenAPI documentation into your docs with [Redoc](https://github.com/redocly/redoc) +- [plugin-image-zoom](https://github.com/flexanalytics/plugin-image-zoom) - An Image Zoom plugin for Docusaurus 2 ## Enterprise usage {#enterprise-usage} diff --git a/website/docs/api/docusaurus.config.js.md b/website/docs/api/docusaurus.config.js.md index 21a5ba0ce1cd..a153a84910dc 100644 --- a/website/docs/api/docusaurus.config.js.md +++ b/website/docs/api/docusaurus.config.js.md @@ -1,7 +1,7 @@ --- id: docusaurus.config.js description: API reference for Docusaurus configuration file. -slug: /docusaurus.config.js +slug: /api/docusaurus-config --- # `docusaurus.config.js` diff --git a/website/docs/api/plugins/plugin-content-blog.md b/website/docs/api/plugins/plugin-content-blog.md index af7f8e0c9fa3..f769ab10b3f4 100644 --- a/website/docs/api/plugins/plugin-content-blog.md +++ b/website/docs/api/plugins/plugin-content-blog.md @@ -51,6 +51,7 @@ Accepted fields: | `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. | | `truncateMarker` | `string` | `//` | Truncate marker, can be a regex or string. | | `showReadingTime` | `boolean` | `true` | Show estimated reading time for the blog post. | +| `readingTime` | `ReadingTimeFunctionOption` | The default reading time | A callback to customize the reading time number displayed. | | `authorsMapPath` | `string` | `'authors.yml'` | Path to the authors map file, relative to the blog content directory specified with `path`. Can also be a `json` file. | | `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. If undefined, no rss feed will be generated. | | `feedOptions.type` | 'rss' \| 'atom' \| 'all' (or array of multiple options) | **Required** | Type of feed to be generated. | @@ -68,6 +69,23 @@ type EditUrlFunction = (params: { permalink: string; locale: string; }) => string | undefined; + +type ReadingTimeOptions = { + wordsPerMinute: number; + wordBound: (char: string) => boolean; +}; + +type ReadingTimeFunction = (params: { + content: string; + frontMatter?: BlogPostFrontMatter & Record; + options?: ReadingTimeOptions; +}) => number; + +type ReadingTimeFunctionOption = (params: { + content: string; + frontMatter: BlogPostFrontMatter & Record; + defaultReadingTime: ReadingTimeFunction; +}) => number | undefined; ``` ## Example configuration {#ex-config} diff --git a/website/docs/api/plugins/plugin-content-docs.md b/website/docs/api/plugins/plugin-content-docs.md index 942cd7ef2ee2..ab324d4a096f 100644 --- a/website/docs/api/plugins/plugin-content-docs.md +++ b/website/docs/api/plugins/plugin-content-docs.md @@ -252,6 +252,8 @@ Accepted fields: | `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. | | `toc_min_heading_level` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. | | `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | +| `pagination_next` | string \| null | 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` | string \| null | 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). | | `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. | diff --git a/website/docs/api/themes/theme-configuration.md b/website/docs/api/themes/theme-configuration.md index 572f0b4bc965..72e4dc5f04a5 100644 --- a/website/docs/api/themes/theme-configuration.md +++ b/website/docs/api/themes/theme-configuration.md @@ -2,6 +2,7 @@ id: theme-configuration title: 'Theme configuration' slug: '/api/themes/configuration' +toc_max_heading_level: 4 --- This configuration applies to all [main themes](./overview.md). @@ -251,7 +252,7 @@ module.exports = { The items can have different behaviors based on the `type` field. The sections below will introduce you to all the types of navbar items available. -### Navbar link {#navbar-link} +#### Navbar link {#navbar-link} By default, Navbar items are regular links (internal or external). @@ -306,7 +307,7 @@ module.exports = { }; ``` -### Navbar dropdown {#navbar-dropdown} +#### Navbar dropdown {#navbar-dropdown} Navbar items of the type `dropdown` has the additional `items` field, an inner array of navbar items. @@ -362,7 +363,7 @@ module.exports = { }; ``` -### Navbar doc link {#navbar-doc-link} +#### Navbar doc link {#navbar-doc-link} If you want to link to a specific doc, this special navbar item type will render the link to the doc of the provided `docId`. It will get the class `navbar__link--active` as long as you browse a doc of the same sidebar. @@ -400,7 +401,7 @@ module.exports = { }; ``` -### Navbar docs version dropdown {#navbar-docs-version-dropdown} +#### Navbar docs version dropdown {#navbar-docs-version-dropdown} If you use docs with versioning, this special navbar item type that will render a dropdown with all your site's available versions. @@ -441,7 +442,7 @@ module.exports = { }; ``` -### Navbar docs version {#navbar-docs-version} +#### Navbar docs version {#navbar-docs-version} If you use docs with versioning, this special navbar item type will link to the active/browsed version of your doc (depends on the current URL), and fallback to the latest version. @@ -479,7 +480,7 @@ module.exports = { }; ``` -### Navbar locale dropdown {#navbar-locale-dropdown} +#### Navbar locale dropdown {#navbar-locale-dropdown} If you use the [i18n feature](../../i18n/i18n-introduction.md), this special navbar item type will render a dropdown with all your site's available locales. @@ -522,7 +523,7 @@ module.exports = { }; ``` -### Navbar search {#navbar-search} +#### Navbar search {#navbar-search} If you use the [search](../../search.md), the search bar will be the rightmost element in the navbar. diff --git a/website/docs/blog.mdx b/website/docs/blog.mdx index ecb03123843e..171cc12c7607 100644 --- a/website/docs/blog.mdx +++ b/website/docs/blog.mdx @@ -335,6 +335,124 @@ website/i18n//docusaurus-plugin-content-blog/authors.yml ::: +## Reading time {#reading-time} + +Docusaurus generates a reading time estimation for each blog post based on word count. We provide an option to customize this. + +```js title="docusaurus.config.js" +module.exports = { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + showReadingTime: true, // When set to false, the "x min read" won't be shown + readingTime: ({content, frontMatter, defaultReadingTime}) => + defaultReadingTime({content, options: {wordsPerMinute: 300}}), + // highlight-end + }, + }, + ], + ], +}; +``` + +The `readingTime` callback receives three parameters: the blog content text as a string, front matter as a record of string keys and their values, and the default reading time function. It returns a number (reading time in minutes) or `undefined` (disable reading time for this page). + +The default reading time is able to accept additional options: `wordsPerMinute` as a number (default: 300), and `wordBound` as a function from string to boolean. If the string passed to `wordBound` should be a word bound (spaces, tabs, and line breaks by default), the function should return `true`. + +:::tip + +Use the callback for all your customization needs: + +````mdx-code-block + + + +**Disable reading time on one page:** + +```js title="docusaurus.config.js" +module.exports = { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + showReadingTime: true, + // highlight-start + readingTime: ({content, frontMatter, defaultReadingTime}) => + frontMatter.hide_reading_time ? undefined : defaultReadingTime({content}), + // highlight-end + }, + }, + ], + ], +}; +``` + +Usage: + +```yml "my-blog-post.md" +--- +hide_reading_time: true +--- + +This page will no longer display the reading time stats! +``` + + + + +**Pass options to the default reading time function:** + +```js title="docusaurus.config.js" +module.exports = { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + readingTime: ({content, defaultReadingTime}) => + defaultReadingTime({content, options: {wordsPerMinute: 100}}), + // highlight-end + }, + }, + ], + ], +}; +``` + + + + +**Use a custom implementation of reading time:** + +```js title="docusaurus.config.js" +const myReadingTime = require('./myReadingTime'); + +module.exports = { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-next-line + readingTime: ({content}) => myReadingTime(content), + }, + }, + ], + ], +}; +``` + + + +```` + +::: + ## Feed {#feed} You can generate RSS/Atom feed by passing feedOptions. By default, RSS and Atom feeds are generated. To disable feed generation, set `feedOptions.type` to `null`. diff --git a/website/docs/cli.md b/website/docs/cli.md index 026011d03af6..9ea0d48af1c6 100644 --- a/website/docs/cli.md +++ b/website/docs/cli.md @@ -183,6 +183,12 @@ By default, the files are written in `website/i18n//...`. | `--config` | `undefined` | Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js` | | `--messagePrefix` | `''` | Allows to add a prefix to each translation message, to help you highlight untranslated strings | -### `docusaurus write-heading-ids [siteDir]` {#docusaurus-write-heading-ids-sitedir} +### `docusaurus write-heading-ids [siteDir] [files]` {#docusaurus-write-heading-ids-sitedir} Add [explicit heading ids](./guides/markdown-features/markdown-features-headings.mdx#explicit-ids) to the Markdown documents of your site. + +| Name | Default | Description | +| --- | --- | --- | +| `files` | All MD files used by plugins | The files that you want heading IDs to be written to. | +| `--maintain-case` | `false` | Keep the headings' casing, otherwise make all lowercase. | +| `--overwrite` | `false` | Overwrite existing heading IDs. | diff --git a/website/docs/guides/docs/sidebar.md b/website/docs/guides/docs/sidebar.md index ac49def5aebb..dfc8c4175bef 100644 --- a/website/docs/guides/docs/sidebar.md +++ b/website/docs/guides/docs/sidebar.md @@ -1,6 +1,7 @@ --- id: sidebar title: Sidebar +toc_max_heading_level: 4 slug: /sidebar --- diff --git a/website/docs/i18n/i18n-crowdin.mdx b/website/docs/i18n/i18n-crowdin.mdx index f1ae9a11cd2a..953372107da5 100644 --- a/website/docs/i18n/i18n-crowdin.mdx +++ b/website/docs/i18n/i18n-crowdin.mdx @@ -2,6 +2,7 @@ id: crowdin title: i18n - Using Crowdin slug: /i18n/crowdin +toc_max_heading_level: 4 --- The i18n system of Docusaurus is **decoupled from any translation software**. diff --git a/website/docs/lifecycle-apis.md b/website/docs/lifecycle-apis.md index c30034b994c7..8dd9d25772bd 100644 --- a/website/docs/lifecycle-apis.md +++ b/website/docs/lifecycle-apis.md @@ -1,6 +1,7 @@ --- id: lifecycle-apis title: Lifecycle APIs +toc_max_heading_level: 4 --- :::caution @@ -162,9 +163,9 @@ Plugins should use the data loaded in `loadContent` and construct the pages/rout ### `actions` {#actions} -`actions` contain two functions: +`actions` contain three functions: -- `addRoute(config: RouteConfig): void` +#### `addRoute(config: RouteConfig): void` Create a route to add to the website. @@ -189,7 +190,7 @@ type Module = | string; ``` -- `createData(name: string, data: any): Promise` +#### `createData(name: string, data: any): Promise` A function to help you create static data (generally json or string), that you can provide to your routes as props. @@ -231,7 +232,7 @@ export default function friendsPlugin(context, options) { } ``` -- `setGlobalData(data: any): void` +#### `setGlobalData(data: any): void` This function permits to create some global plugin data, that can be read from any page, including the pages created by other plugins, and your theme layout. diff --git a/website/docs/migration/migration-manual.md b/website/docs/migration/migration-manual.md index a20d3622fbb3..460e07d5a708 100644 --- a/website/docs/migration/migration-manual.md +++ b/website/docs/migration/migration-manual.md @@ -2,6 +2,7 @@ id: migration-manual title: Manual migration slug: /migration/manual +toc_max_heading_level: 4 --- This manual migration process should be run after the [automated migration process](./migration-automated.md), to complete the missing parts, or debug issues in the migration CLI output. diff --git a/website/docs/using-plugins.md b/website/docs/using-plugins.md index 2ebef9f49099..308a8c826654 100644 --- a/website/docs/using-plugins.md +++ b/website/docs/using-plugins.md @@ -133,7 +133,7 @@ You can use a plugin as a function, directly in the Docusaurus config file: module.exports = { // ... plugins: [ - // highligh-start + // highlight-start function myPlugin(context, options) { // ... return { diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 5789a7b23768..722563564d35 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -38,6 +38,9 @@ const isDev = process.env.NODE_ENV === 'development'; const isDeployPreview = process.env.NETLIFY && process.env.CONTEXT === 'deploy-preview'; +// Used to debug production build issues faster +const isBuildFast = !!process.env.BUILD_FAST; + const baseUrl = process.env.BASE_URL || '/'; // Special deployment for staging locales until they get enough translations @@ -252,10 +255,11 @@ const config = { rehypePlugins: [katex], disableVersioning: isVersioningDisabled, lastVersion: isDev ? 'current' : undefined, - onlyIncludeVersions: - !isVersioningDisabled && (isDev || isDeployPreview) - ? ['current', ...versions.slice(0, 2)] - : undefined, + onlyIncludeVersions: isBuildFast + ? ['current'] + : !isVersioningDisabled && (isDev || isDeployPreview) + ? ['current', ...versions.slice(0, 2)] + : undefined, versions: { current: { label: `${getNextBetaVersionName()} 🚧`, diff --git a/website/package.json b/website/package.json index 493097b44b49..3ff20c497b4c 100644 --- a/website/package.json +++ b/website/package.json @@ -1,6 +1,6 @@ { "name": "website", - "version": "2.0.0-beta.7", + "version": "2.0.0-beta.8", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -16,6 +16,7 @@ "build:baseUrl": "cross-env BASE_URL='/build/' yarn build", "start:blogOnly": "cross-env yarn start --config=docusaurus.config-blog-only.js", "build:blogOnly": "cross-env yarn build --config=docusaurus.config-blog-only.js", + "build:fast": "cross-env BUILD_FAST=true yarn build --locale en", "netlify:build:production": "yarn docusaurus write-translations && yarn netlify:crowdin:delay && yarn netlify:crowdin:uploadSources && yarn netlify:crowdin:downloadTranslations && yarn build", "netlify:build:deployPreview": "yarn docusaurus write-translations --locale fr --messagePrefix '(fr) ' && yarn build", "netlify:crowdin:delay": "node delayCrowdin.js", @@ -30,13 +31,13 @@ "dependencies": { "@crowdin/cli": "^3.5.2", "@crowdin/crowdin-api-client": "^1.10.6", - "@docusaurus/core": "2.0.0-beta.7", - "@docusaurus/plugin-client-redirects": "2.0.0-beta.7", - "@docusaurus/plugin-ideal-image": "2.0.0-beta.7", - "@docusaurus/plugin-pwa": "2.0.0-beta.7", - "@docusaurus/preset-classic": "2.0.0-beta.7", - "@docusaurus/remark-plugin-npm2yarn": "2.0.0-beta.7", - "@docusaurus/theme-live-codeblock": "2.0.0-beta.7", + "@docusaurus/core": "2.0.0-beta.8", + "@docusaurus/plugin-client-redirects": "2.0.0-beta.8", + "@docusaurus/plugin-ideal-image": "2.0.0-beta.8", + "@docusaurus/plugin-pwa": "2.0.0-beta.8", + "@docusaurus/preset-classic": "2.0.0-beta.8", + "@docusaurus/remark-plugin-npm2yarn": "2.0.0-beta.8", + "@docusaurus/theme-live-codeblock": "2.0.0-beta.8", "clsx": "^1.1.1", "color": "^4.0.1", "esbuild-loader": "2.13.1", diff --git a/website/src/data/showcase/apexfp.png b/website/src/data/showcase/apexfp.png new file mode 100644 index 000000000000..dda28003aea8 Binary files /dev/null and b/website/src/data/showcase/apexfp.png differ diff --git a/website/src/data/showcase/zxuqian.png b/website/src/data/showcase/zxuqian.png new file mode 100644 index 000000000000..29b1c8ff68c6 Binary files /dev/null and b/website/src/data/showcase/zxuqian.png differ diff --git a/website/src/data/users.tsx b/website/src/data/users.tsx index cf648c34edd8..cdaba22d7e08 100644 --- a/website/src/data/users.tsx +++ b/website/src/data/users.tsx @@ -202,6 +202,14 @@ const Users: User[] = [ source: 'https://github.com/apache/apisix-website', tags: ['opensource','i18n','large'], }, + { + title: 'Apex FP', + description: 'Functional programming library for Salesforce Apex', + preview: require('./showcase/apexfp.png'), + website: 'https://www.apexfp.org', + source: 'https://github.com/ipavlic/apex-fp/tree/master/website', + tags: ['opensource'], + }, { title: 'AttoBot', description: @@ -465,6 +473,14 @@ const Users: User[] = [ source: 'https://github.com/facebook/fbt', tags: ['opensource', 'facebook'], }, + { + title: 'Fenghua Frontend Developer', + description: 'Blogs and videos about frontend development', + preview: require('./showcase/zxuqian.png'), + website: 'https://zxuqian.cn', + source: null, + tags: ['personal', 'design'], + }, { title: 'FireCMS', description: 'Firebase/Firestore based headless CMS', diff --git a/website/src/types.d.ts b/website/src/types.d.ts new file mode 100644 index 000000000000..75278b9bdd5d --- /dev/null +++ b/website/src/types.d.ts @@ -0,0 +1 @@ +/// diff --git a/website/static/_redirects b/website/static/_redirects index 1b7df1fc0847..086cf210c64f 100644 --- a/website/static/_redirects +++ b/website/static/_redirects @@ -1,5 +1,11 @@ # Server redirects for Netlify + +# Renamed doc routes +/docs/docusaurus.config.js /docs/api/docusaurus-config +/docs/next/docusaurus.config.js /docs/next/api/docusaurus-config + + # v2.docusaurus.io domain redirect after we put v2 on docusaurus.io https://v2.docusaurus.io/* https://docusaurus.io/:splat 301! @@ -14,10 +20,6 @@ https://docusaurus.io/docs/pt-br/* https://v1.docusaurus.io/docs/pt-br/:spl https://docusaurus.io/docs/zh-cn/* https://v1.docusaurus.io/docs/zh-cn/:splat -# Redirect to fix blog post url typo on publish :'( can be cleaned up soon -/blog/2020/01/19/docusaurus-2020-recap /blog/2021/01/19/docusaurus-2020-recap -/classic/blog/2020/01/19/docusaurus-2020-recap /classic/blog/2021/01/19/docusaurus-2020-recap - # Redirect Docusaurus v1 blog RSS feed /blog/feed.xml /blog/rss.xml diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-bootstrap.md b/website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-bootstrap.md deleted file mode 100644 index 2c2dc05a6206..000000000000 --- a/website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-bootstrap.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: theme-bootstrap -title: 'πŸ“¦ theme-bootstrap' -slug: '/api/themes/@docusaurus/theme-bootstrap' ---- - -:::danger - -The bootstrap theme is a work in progress, and is not production ready. - -::: - -🚧 The bootstrap theme for Docusaurus. - -You can refer to the [theme configuration page](theme-configuration.md) for more details on the configuration. - -```bash npm2yarn -npm install --save @docusaurus/theme-bootstrap -``` - -:::tip - -If you have installed `@docusaurus/preset-bootstrap`, you don't need to install it as a dependency. - -::: diff --git a/website/versioned_docs/version-2.0.0-beta.7/api/docusaurus.config.js.md b/website/versioned_docs/version-2.0.0-beta.7/api/docusaurus.config.js.md index 21a5ba0ce1cd..a153a84910dc 100644 --- a/website/versioned_docs/version-2.0.0-beta.7/api/docusaurus.config.js.md +++ b/website/versioned_docs/version-2.0.0-beta.7/api/docusaurus.config.js.md @@ -1,7 +1,7 @@ --- id: docusaurus.config.js description: API reference for Docusaurus configuration file. -slug: /docusaurus.config.js +slug: /api/docusaurus-config --- # `docusaurus.config.js` diff --git a/website/versioned_docs/version-2.0.0-beta.6/_partials/swizzleWarning.mdx b/website/versioned_docs/version-2.0.0-beta.8/_partials/swizzleWarning.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/_partials/swizzleWarning.mdx rename to website/versioned_docs/version-2.0.0-beta.8/_partials/swizzleWarning.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/docusaurus.config.js.md b/website/versioned_docs/version-2.0.0-beta.8/api/docusaurus.config.js.md similarity index 99% rename from website/versioned_docs/version-2.0.0-beta.6/api/docusaurus.config.js.md rename to website/versioned_docs/version-2.0.0-beta.8/api/docusaurus.config.js.md index 21a5ba0ce1cd..a153a84910dc 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/api/docusaurus.config.js.md +++ b/website/versioned_docs/version-2.0.0-beta.8/api/docusaurus.config.js.md @@ -1,7 +1,7 @@ --- id: docusaurus.config.js description: API reference for Docusaurus configuration file. -slug: /docusaurus.config.js +slug: /api/docusaurus-config --- # `docusaurus.config.js` diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/overview.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/overview.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/overview.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/overview.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-client-redirects.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-client-redirects.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-client-redirects.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-client-redirects.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-content-blog.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-content-blog.md similarity index 91% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-content-blog.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-content-blog.md index 58af14d1dd19..f769ab10b3f4 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-content-blog.md +++ b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-content-blog.md @@ -36,6 +36,7 @@ Accepted fields: | `blogSidebarCount` | number \| 'ALL' | `5` | Number of blog post elements to show in the blog sidebar. `'ALL'` to show all blog posts; `0` to disable | | `blogSidebarTitle` | `string` | `'Recent posts'` | Title of the blog sidebar. | | `routeBasePath` | `string` | `'blog'` | URL route for the blog section of your site. **DO NOT** include a trailing slash. Use `/` to put the blog at root path. | +| `tagsBasePath` | `string` | `'tags'` | URL route for the tags list page of your site. It is prepended to the `routeBasePath`. | | `archiveBasePath` | `string` | `'/archive'` | URL route for the archive blog section of your site. It is prepended to the `routeBasePath`. **DO NOT** include a trailing slash. | | `include` | `string[]` | `['**/*.{md,mdx}']` | Matching files will be included and processed. | | `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. | @@ -50,6 +51,7 @@ Accepted fields: | `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. | | `truncateMarker` | `string` | `//` | Truncate marker, can be a regex or string. | | `showReadingTime` | `boolean` | `true` | Show estimated reading time for the blog post. | +| `readingTime` | `ReadingTimeFunctionOption` | The default reading time | A callback to customize the reading time number displayed. | | `authorsMapPath` | `string` | `'authors.yml'` | Path to the authors map file, relative to the blog content directory specified with `path`. Can also be a `json` file. | | `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. If undefined, no rss feed will be generated. | | `feedOptions.type` | 'rss' \| 'atom' \| 'all' (or array of multiple options) | **Required** | Type of feed to be generated. | @@ -67,6 +69,23 @@ type EditUrlFunction = (params: { permalink: string; locale: string; }) => string | undefined; + +type ReadingTimeOptions = { + wordsPerMinute: number; + wordBound: (char: string) => boolean; +}; + +type ReadingTimeFunction = (params: { + content: string; + frontMatter?: BlogPostFrontMatter & Record; + options?: ReadingTimeOptions; +}) => number; + +type ReadingTimeFunctionOption = (params: { + content: string; + frontMatter: BlogPostFrontMatter & Record; + defaultReadingTime: ReadingTimeFunction; +}) => number | undefined; ``` ## Example configuration {#ex-config} @@ -186,6 +205,8 @@ Accepted fields: | `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your post. | | `draft` | `boolean` | `false` | A boolean flag to indicate that the blog post is work-in-progress and therefore should not be published yet. However, draft blog posts will be displayed during development. | | `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. | +| `toc_min_heading_level` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. | +| `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | | `keywords` | `string[]` | `undefined` | Keywords meta tag, which will become the `` in ``, used by search engines. | | `description` | `string` | The first line of Markdown content | The description of your document, which will become the `` and `` in ``, used by search engines. | | `image` | `string` | `undefined` | Cover or thumbnail image that will be used when displaying the link to your post. | diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-content-docs.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-content-docs.md similarity index 93% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-content-docs.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-content-docs.md index 0e947ab10910..ab324d4a096f 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-content-docs.md +++ b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-content-docs.md @@ -33,6 +33,7 @@ Accepted fields: | `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. | | `editCurrentVersion` | `boolean` | `false` | The edit URL will always target the current version doc instead of older versions. Ignored when `editUrl` is a function. | | `routeBasePath` | `string` | `'docs'` | URL route for the docs section of your site. **DO NOT** include a trailing slash. Use `/` for shipping docs without base path. | +| `tagsBasePath` | `string` | `'tags'` | URL route for the tags list page of your site. It is prepended to the `routeBasePath`. | | `include` | `string[]` | `['**/*.{md,mdx}']` | Matching files will be included and processed. | | `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. | | `sidebarPath` | false \| string | `undefined` (creates autogenerated sidebar) | Path to sidebar configuration. | @@ -246,8 +247,13 @@ Accepted fields: | `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 metadatas](/docs/sidebar#autogenerated-sidebar-metadatas). | +| `sidebar_class_name` | `string` | `undefined` | Gives the corresponding sidebar label a special class name when using autogenerated sidebars. | | `hide_title` | `boolean` | `false` | Whether to hide the title at the top of the doc. It only hides a title declared through the frontmatter, and have no effect on a Markdown title at the top of your document. | | `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. | +| `toc_min_heading_level` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. | +| `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | +| `pagination_next` | string \| null | 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` | string \| null | 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). | | `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. | diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-content-pages.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-content-pages.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-content-pages.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-content-pages.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-debug.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-debug.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-debug.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-debug.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-google-analytics.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-google-analytics.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-google-analytics.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-google-analytics.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-google-gtag.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-google-gtag.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-google-gtag.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-google-gtag.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-ideal-image.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-ideal-image.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-ideal-image.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-ideal-image.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-pwa.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-pwa.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-pwa.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-pwa.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-sitemap.md b/website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-sitemap.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/plugins/plugin-sitemap.md rename to website/versioned_docs/version-2.0.0-beta.8/api/plugins/plugin-sitemap.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/themes/overview.md b/website/versioned_docs/version-2.0.0-beta.8/api/themes/overview.md similarity index 94% rename from website/versioned_docs/version-2.0.0-beta.6/api/themes/overview.md rename to website/versioned_docs/version-2.0.0-beta.8/api/themes/overview.md index 984918726f3b..8a2ee6b50f84 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/api/themes/overview.md +++ b/website/versioned_docs/version-2.0.0-beta.8/api/themes/overview.md @@ -12,7 +12,7 @@ We provide official Docusaurus themes. The main themes implement the user interface for the [docs](../plugins/plugin-content-docs.md), [blog](../plugins/plugin-content-blog.md) and [pages](../plugins/plugin-content-pages.md) plugins. - [@docusaurus/theme-classic](./theme-classic.md) -- [@docusaurus/theme-bootstrap](./theme-bootstrap.md) 🚧 +- 🚧 other themes are planned :::caution diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-classic.md b/website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-classic.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-classic.md rename to website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-classic.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-configuration.md b/website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-configuration.md similarity index 95% rename from website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-configuration.md rename to website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-configuration.md index c22cdbe65266..72e4dc5f04a5 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-configuration.md +++ b/website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-configuration.md @@ -2,6 +2,7 @@ id: theme-configuration title: 'Theme configuration' slug: '/api/themes/configuration' +toc_max_heading_level: 4 --- This configuration applies to all [main themes](./overview.md). @@ -251,7 +252,7 @@ module.exports = { The items can have different behaviors based on the `type` field. The sections below will introduce you to all the types of navbar items available. -### Navbar link {#navbar-link} +#### Navbar link {#navbar-link} By default, Navbar items are regular links (internal or external). @@ -306,7 +307,7 @@ module.exports = { }; ``` -### Navbar dropdown {#navbar-dropdown} +#### Navbar dropdown {#navbar-dropdown} Navbar items of the type `dropdown` has the additional `items` field, an inner array of navbar items. @@ -362,7 +363,7 @@ module.exports = { }; ``` -### Navbar doc link {#navbar-doc-link} +#### Navbar doc link {#navbar-doc-link} If you want to link to a specific doc, this special navbar item type will render the link to the doc of the provided `docId`. It will get the class `navbar__link--active` as long as you browse a doc of the same sidebar. @@ -400,7 +401,7 @@ module.exports = { }; ``` -### Navbar docs version dropdown {#navbar-docs-version-dropdown} +#### Navbar docs version dropdown {#navbar-docs-version-dropdown} If you use docs with versioning, this special navbar item type that will render a dropdown with all your site's available versions. @@ -441,7 +442,7 @@ module.exports = { }; ``` -### Navbar docs version {#navbar-docs-version} +#### Navbar docs version {#navbar-docs-version} If you use docs with versioning, this special navbar item type will link to the active/browsed version of your doc (depends on the current URL), and fallback to the latest version. @@ -479,7 +480,7 @@ module.exports = { }; ``` -### Navbar locale dropdown {#navbar-locale-dropdown} +#### Navbar locale dropdown {#navbar-locale-dropdown} If you use the [i18n feature](../../i18n/i18n-introduction.md), this special navbar item type will render a dropdown with all your site's available locales. @@ -522,7 +523,7 @@ module.exports = { }; ``` -### Navbar search {#navbar-search} +#### Navbar search {#navbar-search} If you use the [search](../../search.md), the search bar will be the rightmost element in the navbar. @@ -757,6 +758,34 @@ module.exports = { }; ``` +## Table of Contents {#table-of-contents} + +You can adjust the default table of contents via `themeConfig.tableOfContents`. + + + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| `minHeadingLevel` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. | +| `maxHeadingLevel` | `number` | `3` | Max heading level displayed in the TOC. Should be an integer between 2 and 6. | + + + +Example configuration: + +```js title="docusaurus.config.js" +module.exports = { + themeConfig: { + // highlight-start + tableOfContents: { + minHeadingLevel: 2, + maxHeadingLevel: 5, + }, + // highlight-end + }, +}; +``` + ## Hooks {#hooks} ### `useThemeContext` {#usethemecontext} diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-live-codeblock.md b/website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-live-codeblock.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-live-codeblock.md rename to website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-live-codeblock.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-search-algolia.md b/website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-search-algolia.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/api/themes/theme-search-algolia.md rename to website/versioned_docs/version-2.0.0-beta.8/api/themes/theme-search-algolia.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/assets/docusaurus-asset-example-banner.png b/website/versioned_docs/version-2.0.0-beta.8/assets/docusaurus-asset-example-banner.png similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/assets/docusaurus-asset-example-banner.png rename to website/versioned_docs/version-2.0.0-beta.8/assets/docusaurus-asset-example-banner.png diff --git a/website/versioned_docs/version-2.0.0-beta.6/assets/docusaurus-asset-example-pdf.pdf b/website/versioned_docs/version-2.0.0-beta.8/assets/docusaurus-asset-example-pdf.pdf similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/assets/docusaurus-asset-example-pdf.pdf rename to website/versioned_docs/version-2.0.0-beta.8/assets/docusaurus-asset-example-pdf.pdf diff --git a/website/versioned_docs/version-2.0.0-beta.6/assets/docusaurus-asset-example.xyz b/website/versioned_docs/version-2.0.0-beta.8/assets/docusaurus-asset-example.xyz similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/assets/docusaurus-asset-example.xyz rename to website/versioned_docs/version-2.0.0-beta.8/assets/docusaurus-asset-example.xyz diff --git a/website/versioned_docs/version-2.0.0-beta.6/blog.mdx b/website/versioned_docs/version-2.0.0-beta.8/blog.mdx similarity index 77% rename from website/versioned_docs/version-2.0.0-beta.6/blog.mdx rename to website/versioned_docs/version-2.0.0-beta.8/blog.mdx index a028526023be..171cc12c7607 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/blog.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/blog.mdx @@ -176,14 +176,8 @@ Use the `authors` FrontMatter field to declare blog post authors. Blog post authors can be declared directly inside the FrontMatter: ````mdx-code-block - - + + ```yml title="my-blog-post.md" --- @@ -196,7 +190,7 @@ authors: ``` - + ```yml title="my-blog-post.md" --- @@ -226,7 +220,6 @@ This option works best to get started, or for casual, irregular authors. Prefer usage of the `authors` FrontMatter, but the legacy `author_*` FrontMatter remains supported: - ```yml title="my-blog-post.md" --- author: Joel Marcey @@ -235,7 +228,6 @@ author_url: https://github.com/JoelMarcey author_image_url: https://github.com/JoelMarcey.png --- ``` - ::: @@ -268,14 +260,8 @@ Use the `authorsMapPath` plugin option to configure the path. JSON is also suppo In blog posts FrontMatter, you can reference the authors declared in the global configuration file: ````mdx-code-block - - + + ```yml title="my-blog-post.md" --- @@ -284,7 +270,7 @@ authors: jmarcey ``` - + ```yml title="my-blog-post.md" --- @@ -305,7 +291,6 @@ The `authors` system is very flexible and can suit more advanced use-case: You can use global authors most of the time, and still use inline authors: - ```yml title="my-blog-post.md" --- authors: @@ -317,7 +302,6 @@ authors: image_url: https://github.com/inlineAuthor --- ``` - @@ -326,7 +310,6 @@ authors: You can customize the global author's data on per-blog-post basis: - ```yml title="my-blog-post.md" --- authors: @@ -336,7 +319,6 @@ authors: name: SΓ©bastien Lorber's new name --- ``` - @@ -353,6 +335,124 @@ website/i18n//docusaurus-plugin-content-blog/authors.yml ::: +## Reading time {#reading-time} + +Docusaurus generates a reading time estimation for each blog post based on word count. We provide an option to customize this. + +```js title="docusaurus.config.js" +module.exports = { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + showReadingTime: true, // When set to false, the "x min read" won't be shown + readingTime: ({content, frontMatter, defaultReadingTime}) => + defaultReadingTime({content, options: {wordsPerMinute: 300}}), + // highlight-end + }, + }, + ], + ], +}; +``` + +The `readingTime` callback receives three parameters: the blog content text as a string, front matter as a record of string keys and their values, and the default reading time function. It returns a number (reading time in minutes) or `undefined` (disable reading time for this page). + +The default reading time is able to accept additional options: `wordsPerMinute` as a number (default: 300), and `wordBound` as a function from string to boolean. If the string passed to `wordBound` should be a word bound (spaces, tabs, and line breaks by default), the function should return `true`. + +:::tip + +Use the callback for all your customization needs: + +````mdx-code-block + + + +**Disable reading time on one page:** + +```js title="docusaurus.config.js" +module.exports = { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + showReadingTime: true, + // highlight-start + readingTime: ({content, frontMatter, defaultReadingTime}) => + frontMatter.hide_reading_time ? undefined : defaultReadingTime({content}), + // highlight-end + }, + }, + ], + ], +}; +``` + +Usage: + +```yml "my-blog-post.md" +--- +hide_reading_time: true +--- + +This page will no longer display the reading time stats! +``` + + + + +**Pass options to the default reading time function:** + +```js title="docusaurus.config.js" +module.exports = { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-start + readingTime: ({content, defaultReadingTime}) => + defaultReadingTime({content, options: {wordsPerMinute: 100}}), + // highlight-end + }, + }, + ], + ], +}; +``` + + + + +**Use a custom implementation of reading time:** + +```js title="docusaurus.config.js" +const myReadingTime = require('./myReadingTime'); + +module.exports = { + presets: [ + [ + '@docusaurus/preset-classic', + { + blog: { + // highlight-next-line + readingTime: ({content}) => myReadingTime(content), + }, + }, + ], + ], +}; +``` + + + +```` + +::: + ## Feed {#feed} You can generate RSS/Atom feed by passing feedOptions. By default, RSS and Atom feeds are generated. To disable feed generation, set `feedOptions.type` to `null`. diff --git a/website/versioned_docs/version-2.0.0-beta.6/browser-support.md b/website/versioned_docs/version-2.0.0-beta.8/browser-support.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/browser-support.md rename to website/versioned_docs/version-2.0.0-beta.8/browser-support.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/cli.md b/website/versioned_docs/version-2.0.0-beta.8/cli.md similarity index 95% rename from website/versioned_docs/version-2.0.0-beta.6/cli.md rename to website/versioned_docs/version-2.0.0-beta.8/cli.md index 026011d03af6..9ea0d48af1c6 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/cli.md +++ b/website/versioned_docs/version-2.0.0-beta.8/cli.md @@ -183,6 +183,12 @@ By default, the files are written in `website/i18n//...`. | `--config` | `undefined` | Path to docusaurus config file, default to `[siteDir]/docusaurus.config.js` | | `--messagePrefix` | `''` | Allows to add a prefix to each translation message, to help you highlight untranslated strings | -### `docusaurus write-heading-ids [siteDir]` {#docusaurus-write-heading-ids-sitedir} +### `docusaurus write-heading-ids [siteDir] [files]` {#docusaurus-write-heading-ids-sitedir} Add [explicit heading ids](./guides/markdown-features/markdown-features-headings.mdx#explicit-ids) to the Markdown documents of your site. + +| Name | Default | Description | +| --- | --- | --- | +| `files` | All MD files used by plugins | The files that you want heading IDs to be written to. | +| `--maintain-case` | `false` | Keep the headings' casing, otherwise make all lowercase. | +| `--overwrite` | `false` | Overwrite existing heading IDs. | diff --git a/website/versioned_docs/version-2.0.0-beta.6/configuration.md b/website/versioned_docs/version-2.0.0-beta.8/configuration.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/configuration.md rename to website/versioned_docs/version-2.0.0-beta.8/configuration.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/deployment.mdx b/website/versioned_docs/version-2.0.0-beta.8/deployment.mdx similarity index 99% rename from website/versioned_docs/version-2.0.0-beta.6/deployment.mdx rename to website/versioned_docs/version-2.0.0-beta.8/deployment.mdx index 504d657ee5bb..d5624990918e 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/deployment.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/deployment.mdx @@ -143,28 +143,22 @@ GitHub enterprise installations should work in the same manner as github.com; yo Finally, to deploy your site to GitHub Pages, run: ````mdx-code-block - - + + ```bash GIT_USER= yarn deploy ``` - + ```batch cmd /C "set "GIT_USER=" && yarn deploy" ``` - + ```powershell cmd /C 'set "GIT_USER=" && yarn deploy' diff --git a/website/versioned_docs/version-2.0.0-beta.6/docusaurus-core.md b/website/versioned_docs/version-2.0.0-beta.8/docusaurus-core.md similarity index 98% rename from website/versioned_docs/version-2.0.0-beta.6/docusaurus-core.md rename to website/versioned_docs/version-2.0.0-beta.8/docusaurus-core.md index d144820e93ec..eb456c6a07cf 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/docusaurus-core.md +++ b/website/versioned_docs/version-2.0.0-beta.8/docusaurus-core.md @@ -253,6 +253,16 @@ export default function Home() { } ``` +:::note + +You can even omit a children prop and specify a translation string in your `code.json` file manually after running the `docusaurus write-translations` CLI command. + +```jsx + +``` + +::: + ## Hooks {#hooks} ### `useDocusaurusContext` {#usedocusauruscontext} diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/creating-pages.md b/website/versioned_docs/version-2.0.0-beta.8/guides/creating-pages.md similarity index 98% rename from website/versioned_docs/version-2.0.0-beta.6/guides/creating-pages.md rename to website/versioned_docs/version-2.0.0-beta.8/guides/creating-pages.md index c622ae5fcd4d..33306508478f 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/creating-pages.md +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/creating-pages.md @@ -45,7 +45,7 @@ function Hello() { fontSize: '20px', }}>

    - Edit pages/hello.js and save to reload. + Edit pages/helloReact.js and save to reload.

    diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-create-doc.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-create-doc.mdx similarity index 75% rename from website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-create-doc.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-create-doc.mdx index ab4d584d1555..f068973ff762 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-create-doc.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-create-doc.mdx @@ -35,7 +35,9 @@ will show up on the table of contents on the upper right So that your users will know what this page is all about without scrolling down or even without reading too much. -### Only h2 and h3 will be in the toc +### Only h2 and h3 will be in the toc by default. + +You can configure the TOC heading levels either per-document or in the theme configuration. The headers are well-spaced so that the hierarchy is clear. @@ -67,7 +69,9 @@ will show up on the table of contents on the upper right So that your users will know what this page is all about without scrolling down or even without reading too much. -

    Only h2 and h3 will be in the toc

    +

    Only h2 and h3 will be in the toc by default.

    + +You can configure the TOC heading levels either per-document or in the theme configuration. The headers are well-spaced so that the hierarchy is clear. @@ -84,11 +88,18 @@ With {#custom-id} syntax you can set your own header id. ``` +:::note + +All files prefixed with an underscore (`_`) under the `docs` directory are treated as "partial" pages and will be ignored by default. + +Read more about [importing partial pages](../markdown-features/markdown-features-react.mdx#importing-markdown). + +::: + ## Doc tags {#doc-tags} Optionally, you can add tags to your doc pages, which introduces another dimension of categorization in addition to the [docs sidebar](./sidebar.md). Tags are passed in the front matter as a list of labels: - ```yml "your-doc-page.md" --- id: doc-with-tags @@ -98,4 +109,11 @@ tags: - Getting started --- ``` - + +:::tip + +Tags can also be declared with `tags [Demo, Getting started]` + +Read more about all the possible [Yaml array syntaxes](https://www.w3schools.io/file/yaml-arrays/). + +::: diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-introduction.md b/website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-introduction.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-introduction.md rename to website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-introduction.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-markdown-features.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-markdown-features.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-markdown-features.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-markdown-features.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-multi-instance.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-multi-instance.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/docs/docs-multi-instance.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/docs/docs-multi-instance.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/docs/sidebar.md b/website/versioned_docs/version-2.0.0-beta.8/guides/docs/sidebar.md similarity index 98% rename from website/versioned_docs/version-2.0.0-beta.6/guides/docs/sidebar.md rename to website/versioned_docs/version-2.0.0-beta.8/guides/docs/sidebar.md index 47aecb43f240..dfc8c4175bef 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/docs/sidebar.md +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/docs/sidebar.md @@ -1,6 +1,7 @@ --- id: sidebar title: Sidebar +toc_max_heading_level: 4 slug: /sidebar --- @@ -173,6 +174,7 @@ type SidebarItemDoc = type: 'doc'; id: string; label: string; // Sidebar label text + className?: string; // Class name for sidebar label } // Shorthand syntax @@ -244,6 +246,7 @@ type SidebarItemLink = { type: 'link'; label: string; href: string; + className?: string; }; ``` @@ -282,6 +285,7 @@ type SidebarItemCategory = { type: 'category'; label: string; // Sidebar label text. items: SidebarItem[]; // Array of sidebar items. + className?: string; // Category options: collapsible: boolean; // Set the category to be collapsible @@ -519,7 +523,8 @@ This is the easy tutorial! ```json title="docs/tutorials/_category_.json" { "label": "Tutorial", - "position": 3 + "position": 3, + "className": "red" } ``` diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/docs/versioning.md b/website/versioned_docs/version-2.0.0-beta.8/guides/docs/versioning.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/docs/versioning.md rename to website/versioned_docs/version-2.0.0-beta.8/guides/docs/versioning.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/_markdown-partial-example.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/_markdown-partial-example.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/_markdown-partial-example.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/_markdown-partial-example.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-admonitions.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-admonitions.mdx similarity index 72% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-admonitions.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-admonitions.mdx index ccd7ae68ff56..69784e5dc131 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-admonitions.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-admonitions.mdx @@ -89,23 +89,17 @@ Some **content** with _markdown_ `syntax`. You can use MDX inside admonitions too! -```mdx +```jsx import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; :::tip Use tabs in admonitions - - This is an apple 🍎 - This is an orange 🍊 - This is a banana 🍌 + + This is an apple 🍎 + This is an orange 🍊 + This is a banana 🍌 ::: @@ -119,16 +113,10 @@ import TabItem from '@theme/TabItem'; :::tip Use tabs in admonitions ```mdx-code-block - - This is an apple 🍎 - This is an orange 🍊 - This is a banana 🍌 + + This is an apple 🍎 + This is an orange 🍊 + This is a banana 🍌 ``` diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-assets.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-assets.mdx similarity index 97% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-assets.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-assets.mdx index 8e0fa107f263..ae69e768ac90 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-assets.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-assets.mdx @@ -119,7 +119,7 @@ html[data-theme='dark'] .themedDocusaurus [fill='#FFFF50'] { ## Themed Images {#themed-images} -Docusaurus supports themed images: the `ThemedImage` component (included in the classic/bootstrap themes) allows you to switch the image source based on the current theme. +Docusaurus supports themed images: the `ThemedImage` component (included in the themes) allows you to switch the image source based on the current theme. ```jsx {5-8} import ThemedImage from '@theme/ThemedImage'; diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-code-blocks.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-code-blocks.mdx similarity index 86% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-code-blocks.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-code-blocks.mdx index 7fedb93feca3..5c355f1e4612 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-code-blocks.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-code-blocks.mdx @@ -374,15 +374,8 @@ The following example is how you can have multi-language code tabs in your docs. import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - - + + ```js function helloWorld() { @@ -391,7 +384,7 @@ function helloWorld() { ``` - + ```py def hello_world(): @@ -399,7 +392,7 @@ def hello_world(): ``` - + ```java class HelloWorld { @@ -416,15 +409,8 @@ class HelloWorld { And you will get the following: ````mdx-code-block - - + + ```js function helloWorld() { @@ -433,7 +419,7 @@ function helloWorld() { ``` - + ```py def hello_world(): @@ -441,7 +427,7 @@ def hello_world(): ``` - + ```java class HelloWorld { @@ -455,6 +441,51 @@ class HelloWorld { ```` -You may want to implement your own `` abstraction if you find the above approach too verbose. We might just implement one in future for convenience. - If you have multiple of these multi-language code tabs, and you want to sync the selection across the tab instances, refer to the [Syncing tab choices section](markdown-features-tabs.mdx#syncing-tab-choices). + +### Docusaurus npm2yarn remark plugin {#npm2yarn-remark-plugin} + +Displaying CLI commands in both NPM and Yarn is a very common need, for example: + +```bash npm2yarn +npm install @docusaurus/remark-plugin-npm2yarn +``` + +Docusaurus provides such a utility out of the box, freeing you from using the `Tabs` component every time. To enable this feature, first install the `@docusaurus/remark-plugin-npm2yarn` package as above, and then in `docusaurus.config.js`, for the plugins where you need this feature (doc, blog, pages, etc.), register it in the `remarkPlugins` option. (See [Docs configuration](../../api/plugins/plugin-content-docs.md#ex-config) for more details on configuration format) + +```js title="docusaurus.config.js" +module.exports = { + // ... + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + // highlight-start + remarkPlugins: [ + [require('@docusaurus/remark-plugin-npm2yarn'), {sync: true}], + ], + // highlight-end + }, + pages: { + // highlight-next-line + remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn')], + }, + blog: { + // ... + }, + }, + ], + ], +}; +``` + +And then use it by adding the `npm2yarn` key to the code block: + +````md +```bash npm2yarn +npm install @docusaurus/remark-plugin-npm2yarn +``` +```` + +Using the `{sync: true}` option would make all tab choices synced. Because the choice is stored under the same namespace `npm2yarn`, different `npm2yarn` plugin instances would also sync their choices. diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-head-metadatas.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-head-metadatas.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-head-metadatas.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-head-metadatas.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-headings.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-headings.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-headings.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-headings.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-inline-toc.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-inline-toc.mdx similarity index 90% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-inline-toc.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-inline-toc.mdx index 5f839da3b835..3726f048421f 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-inline-toc.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-inline-toc.mdx @@ -13,7 +13,9 @@ But it is also possible to display an inline table of contents directly inside a ## Full table of contents {#full-table-of-contents} -The `toc` variable is available in any MDX document, and contain all the top level headings of a MDX document. +The `toc` variable is available in any MDX document, and contains all the headings of a MDX document. + +By default, only `h2` and `h3` headings are displayed in the TOC. You can change which heading levels are visible by setting `minHeadingLevel` or `maxHeadingLevel`. ```jsx import TOCInline from '@theme/TOCInline'; @@ -40,6 +42,7 @@ type TOCItem = { value: string; id: string; children: TOCItem[]; + level: number; }; ``` diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-intro.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-intro.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-intro.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-intro.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-math-equations.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-math-equations.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-math-equations.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-math-equations.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-plugins.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-plugins.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-plugins.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-plugins.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-react.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-react.mdx similarity index 94% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-react.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-react.mdx index 4f920c5d201a..08aed08e3a77 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-react.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-react.mdx @@ -11,7 +11,7 @@ import BrowserWindow from '@site/src/components/BrowserWindow'; ## Using JSX in Markdown {#using-jsx-in-markdown} -Docusaurus has built-in support for [MDX](https://mdxjs.com/), which allows you to write JSX within your Markdown files and render them as React components. +Docusaurus has built-in support for [MDX v1](https://mdxjs.com/), which allows you to write JSX within your Markdown files and render them as React components. :::note @@ -23,7 +23,7 @@ While both `.md` and `.mdx` files are parsed using MDX, some of the syntax are t MDX is not [100% compatible with CommonMark](https://github.com/facebook/docusaurus/issues/3018). -Use the **[MDX playground](https://mdxjs.com/playground)** to ensure that your syntax is valid MDX. +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.0.0-beta.6/guides/markdown-features/markdown-features-tabs.mdx b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-tabs.mdx similarity index 78% rename from website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-tabs.mdx rename to website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-tabs.mdx index 4e4e2da6827b..5fc9d5acd194 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/guides/markdown-features/markdown-features-tabs.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/guides/markdown-features/markdown-features-tabs.mdx @@ -13,6 +13,7 @@ import TabItem from '@theme/TabItem'; Docusaurus provides `` components that you can use thanks to [MDX](./markdown-features-react.mdx): + ```jsx import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; @@ -27,13 +28,14 @@ import TabItem from '@theme/TabItem'; This is a banana 🍌 -; + ``` + ```mdx-code-block - This is an apple 🍎 + This is an apple 🍎 This is an orange 🍊 This is a banana 🍌 @@ -109,7 +111,7 @@ It is also possible to provide `values` and `defaultValue` props to `Tabs`: ]}> This is an apple 🍎 This is an orange 🍊 - This is a banana 🍌 + This is a banana 🍌
    @@ -121,17 +123,15 @@ It is also possible to provide `values` and `defaultValue` props to `Tabs`: By default, all tabs are rendered eagerly during the build process, and search engines can index hidden tabs. -It is possible to only render the default tab with ``. +It is possible to only render the default tab with ``. ::: ## Displaying a default tab -Add `default` to one of the tab items to make it displayed by default. You can also set the `defaultValue` prop in the `Tabs` component to the label value of your choice. - -For example, in the example above, setting `default` for the `value="apple"` tab forces it to be open by default. +The first tab is displayed by default, and to override this behavior, you can specify a default tab by adding `default` to one of the tab items. You can also set the `defaultValue` prop of the `Tabs` component to the label value of your choice. For example, in the example above, either setting `default` for the `value="apple"` tab or setting `defaultValue="apple"` for the tabs forces the "Apple" tab to be open by default. -If none of the children contains the `default` prop, neither is the `defaultValue` provided for the `Tabs`, or it refers to an non-existing value, only the tab headings appear until the user clicks on a tab. +Docusaurus will throw an error if a `defaultValue` is provided for the `Tabs` but it refers to an non-existing value. If you want none of the tabs to be shown by default, use `defaultValue={null}`. ## Syncing tab choices {#syncing-tab-choices} @@ -140,13 +140,13 @@ You may want choices of the same kind of tabs to sync with each other. For examp ```jsx // highlight-next-line - Use Ctrl + C to copy. + Use Ctrl + C to copy. Use Command + C to copy. // highlight-next-line - Use Ctrl + V to paste. + Use Ctrl + V to paste. Use Command + V to paste. ``` @@ -154,12 +154,12 @@ You may want choices of the same kind of tabs to sync with each other. For examp ```mdx-code-block - Use Ctrl + C to copy. + Use Ctrl + C to copy. Use Command + C to copy. - Use Ctrl + V to paste. + Use Ctrl + V to paste. Use Command + V to paste. @@ -170,7 +170,7 @@ For all tab groups that have the same `groupId`, the possible values do not need ```jsx - + I am Windows. @@ -185,7 +185,7 @@ For all tab groups that have the same `groupId`, the possible values do not need ```mdx-code-block - I am Windows. + I am Windows. I am macOS. I am Linux. @@ -199,13 +199,13 @@ Tab choices with different `groupId`s will not interfere with each other: ```jsx // highlight-next-line - Windows in windows. + Windows in windows. macOS is macOS. // highlight-next-line - Windows is windows. + Windows is windows. Unix is unix. ``` @@ -213,12 +213,12 @@ Tab choices with different `groupId`s will not interfere with each other: ```mdx-code-block - Windows in windows. + Windows in windows. macOS is macOS. - Windows is windows. + Windows is windows. Unix is unix. @@ -234,9 +234,7 @@ import TabItem from '@theme/TabItem'; // highlight-next-line - - This is an apple 🍎 - + This is an apple 🍎 This is an orange 🍊 This is a banana 🍌 ; @@ -245,7 +243,7 @@ import TabItem from '@theme/TabItem'; ```mdx-code-block - This is an apple 🍎 + This is an apple 🍎 This is an orange 🍊 This is a banana 🍌 diff --git a/website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-crowdin.mdx b/website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-crowdin.mdx similarity index 98% rename from website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-crowdin.mdx rename to website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-crowdin.mdx index ef038d068cf3..953372107da5 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-crowdin.mdx +++ b/website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-crowdin.mdx @@ -2,6 +2,7 @@ id: crowdin title: i18n - Using Crowdin slug: /i18n/crowdin +toc_max_heading_level: 4 --- The i18n system of Docusaurus is **decoupled from any translation software**. @@ -363,20 +364,15 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - - + + ```bash GIT_USER= yarn deploy ``` - + ```batch cmd /C "set "GIT_USER=" && yarn deploy" diff --git a/website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-git.md b/website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-git.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-git.md rename to website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-git.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-introduction.md b/website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-introduction.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-introduction.md rename to website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-introduction.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-tutorial.md b/website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-tutorial.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/i18n/i18n-tutorial.md rename to website/versioned_docs/version-2.0.0-beta.8/i18n/i18n-tutorial.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/installation.md b/website/versioned_docs/version-2.0.0-beta.8/installation.md similarity index 89% rename from website/versioned_docs/version-2.0.0-beta.6/installation.md rename to website/versioned_docs/version-2.0.0-beta.8/installation.md index 9deaa6dabbfd..92e6368bb28d 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/installation.md +++ b/website/versioned_docs/version-2.0.0-beta.8/installation.md @@ -29,10 +29,10 @@ npm init docusaurus@latest [name] [template] Example: ```bash -npm init docusaurus@latest my-website classic +npm init docusaurus@latest website classic ``` -If you do not specify `name` or `template`, it will prompt you for them. We recommend the `classic` template so that you can get started quickly and it contains features found in Docusaurus 1. The `classic` template contains `@docusaurus/preset-classic` which includes standard documentation, a blog, custom pages, and a CSS framework (with dark mode support). You can get up and running extremely quickly with the classic template and customize things later on when you have gained more familiarity with Docusaurus. +If you do not specify `name` or `template`, it will prompt you for them. We recommend the `classic` template so that you can get started quickly, and it contains features found in Docusaurus 1. The `classic` template contains `@docusaurus/preset-classic` which includes standard documentation, a blog, custom pages, and a CSS framework (with dark mode support). You can get up and running extremely quickly with the classic template and customize things later on when you have gained more familiarity with Docusaurus. **[FB-Only]:** If you are setting up a new Docusaurus website for a Facebook open source project, use the `facebook` template instead, which comes with some useful Facebook-specific defaults: @@ -40,22 +40,16 @@ If you do not specify `name` or `template`, it will prompt you for them. We reco npm init docusaurus@latest my-website facebook ``` -**[Experimental]:** If you want setting up a new website using [bootstrap](https://getbootstrap.com/), use the `bootstrap` template, like the following: - -```bash -npm init docusaurus@latest my-website bootstrap -``` - If you want to skip installing dependencies, use the `--skip-install` option, like the following: ```bash -npm init docusaurus@latest my-website classic --skip-install +npm init docusaurus@latest my-website classic -- --skip-install ``` You can also use the template's TypeScript variant by passing the `--typescript` flag. ```bash -npm init docusaurus@latest my-website classic --typescript +npm init docusaurus@latest my-website classic -- --typescript ``` ## Project structure {#project-structure} diff --git a/website/versioned_docs/version-2.0.0-beta.6/introduction.md b/website/versioned_docs/version-2.0.0-beta.8/introduction.md similarity index 99% rename from website/versioned_docs/version-2.0.0-beta.6/introduction.md rename to website/versioned_docs/version-2.0.0-beta.8/introduction.md index 97601dff31be..cf2783fee44a 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/introduction.md +++ b/website/versioned_docs/version-2.0.0-beta.8/introduction.md @@ -177,7 +177,7 @@ In comparison with statically generated HTML and interactivity added using `` +#### `createData(name: string, data: any): Promise` A function to help you create static data (generally json or string), that you can provide to your routes as props. @@ -231,7 +232,7 @@ export default function friendsPlugin(context, options) { } ``` -- `setGlobalData(data: any): void` +#### `setGlobalData(data: any): void` This function permits to create some global plugin data, that can be read from any page, including the pages created by other plugins, and your theme layout. @@ -396,7 +397,7 @@ module.exports = function (context, options) { Called when a (production) build finishes. ```ts -type Props = { +interface Props { siteDir: string; generatedFilesDir: string; siteConfig: DocusaurusConfig; @@ -407,7 +408,7 @@ type Props = { postBodyTags: string; routesPaths: string[]; plugins: Plugin[]; -}; +} ``` Example: diff --git a/website/versioned_docs/version-2.0.0-beta.6/migration/migration-automated.md b/website/versioned_docs/version-2.0.0-beta.8/migration/migration-automated.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/migration/migration-automated.md rename to website/versioned_docs/version-2.0.0-beta.8/migration/migration-automated.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/migration/migration-manual.md b/website/versioned_docs/version-2.0.0-beta.8/migration/migration-manual.md similarity index 99% rename from website/versioned_docs/version-2.0.0-beta.6/migration/migration-manual.md rename to website/versioned_docs/version-2.0.0-beta.8/migration/migration-manual.md index a20d3622fbb3..460e07d5a708 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/migration/migration-manual.md +++ b/website/versioned_docs/version-2.0.0-beta.8/migration/migration-manual.md @@ -2,6 +2,7 @@ id: migration-manual title: Manual migration slug: /migration/manual +toc_max_heading_level: 4 --- This manual migration process should be run after the [automated migration process](./migration-automated.md), to complete the missing parts, or debug issues in the migration CLI output. diff --git a/website/versioned_docs/version-2.0.0-beta.6/migration/migration-overview.md b/website/versioned_docs/version-2.0.0-beta.8/migration/migration-overview.md similarity index 96% rename from website/versioned_docs/version-2.0.0-beta.6/migration/migration-overview.md rename to website/versioned_docs/version-2.0.0-beta.8/migration/migration-overview.md index 9b2310e41a6a..8ddda200b03c 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/migration/migration-overview.md +++ b/website/versioned_docs/version-2.0.0-beta.8/migration/migration-overview.md @@ -94,7 +94,7 @@ The [manual migration guide](./migration-manual.md) will give you all the manual ## Support {#support} -For any questions, you can ask in the [`#docusaurus-1-to-2-migration` Discord channel](https://discordapp.com/invite/kYaNd6V). +For any questions, you can ask in the [`#migration-v1-to-v2` Discord channel](https://discord.gg/C3P6CxMMxY). Feel free to tag [@slorber](https://github.com/slorber) in any migration PRs if you would like us to have a look. diff --git a/website/versioned_docs/version-2.0.0-beta.6/migration/migration-translated-sites.md b/website/versioned_docs/version-2.0.0-beta.8/migration/migration-translated-sites.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/migration/migration-translated-sites.md rename to website/versioned_docs/version-2.0.0-beta.8/migration/migration-translated-sites.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/migration/migration-versioned-sites.md b/website/versioned_docs/version-2.0.0-beta.8/migration/migration-versioned-sites.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/migration/migration-versioned-sites.md rename to website/versioned_docs/version-2.0.0-beta.8/migration/migration-versioned-sites.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/playground.mdx b/website/versioned_docs/version-2.0.0-beta.8/playground.mdx similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/playground.mdx rename to website/versioned_docs/version-2.0.0-beta.8/playground.mdx diff --git a/website/versioned_docs/version-2.0.0-beta.6/presets.md b/website/versioned_docs/version-2.0.0-beta.8/presets.md similarity index 66% rename from website/versioned_docs/version-2.0.0-beta.6/presets.md rename to website/versioned_docs/version-2.0.0-beta.8/presets.md index b24a6e938094..7d3eddb070e0 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/presets.md +++ b/website/versioned_docs/version-2.0.0-beta.8/presets.md @@ -35,16 +35,13 @@ module.exports = { ## Presets -> themes and plugins {#presets---themes-and-plugins} -Presets in some way are a shorthand function to add plugins and themes to your Docusaurus config. For example, you can specify a preset that includes the following themes and plugins, +Presets are a shorthand function to add plugins and themes to your Docusaurus config. For example, you can specify a preset that includes the following themes and plugins, ```js module.exports = function preset(context, opts = {}) { return { - themes: [ - require.resolve('@docusaurus/themes-cool'), - require.resolve('@docusaurus/themes-bootstrap'), - ], - plugins: [require.resolve('@docusaurus/plugin-blog')], + themes: ['@docusaurus/theme-cool', opts.cool], + plugins: ['@docusaurus/plugin-blog', opts.blog], }; }; ``` @@ -53,8 +50,10 @@ then in your Docusaurus config, you may configure the preset instead: ```jsx {3} title="docusaurus.config.js" module.exports = { - // ... - presets: ['@docusaurus/preset-my-own'], + presets: [ + '@docusaurus/preset-my-own', + {cool: {hello: 'world'}, blog: {path: '/blog'}}, + ], }; ``` @@ -62,8 +61,8 @@ This is equivalent of doing: ```jsx title="docusaurus.config.js" module.exports = { - themes: ['@docusaurus/themes-cool', '@docusaurus/themes-bootstrap'], - plugins: ['@docusaurus/plugin-blog'], + themes: ['@docusaurus/themes-cool', {hello: 'world'}], + plugins: ['@docusaurus/plugin-blog', {path: '/blog'}], }; ``` @@ -132,51 +131,3 @@ module.exports = { ], }; ``` - -### `@docusaurus/preset-bootstrap` {#docusauruspreset-bootstrap} - -An alternative preset that uses Bootstrap styling. - -| Themes | Plugins | -| ----------------------------- | ---------------------------------- | -| `@docusaurus/theme-bootstrap` | `@docusaurus/plugin-content-docs` | -| | `@docusaurus/plugin-content-blog` | -| | `@docusaurus/plugin-content-pages` | -| | `@docusaurus/plugin-debug` | - -To specify plugin options individually, you can provide the necessary fields to certain plugins, i.e. `docs` for `@docusaurus/theme-bootstrap`, pass them in the preset field, like this: - -```js title="docusaurus.config.js" -module.exports = { - presets: [ - [ - '@docusaurus/preset-bootstrap', - { - // Debug defaults to true in dev, false in prod - debug: undefined, - // Will be passed to @docusaurus/plugin-content-docs (false to disable) - docs: {}, - // Will be passed to @docusaurus/plugin-content-blog (false to disable) - blog: {}, - }, - ], - ], -}; -``` - -:::caution - -This preset is work in progress - -::: - - diff --git a/website/versioned_docs/version-2.0.0-beta.6/search.md b/website/versioned_docs/version-2.0.0-beta.8/search.md similarity index 55% rename from website/versioned_docs/version-2.0.0-beta.6/search.md rename to website/versioned_docs/version-2.0.0-beta.8/search.md index b22ef0ed470d..ceb6541a5982 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/search.md +++ b/website/versioned_docs/version-2.0.0-beta.8/search.md @@ -6,18 +6,60 @@ keywords: - search --- -Docusaurus' own `@docusaurus/preset-classic` supports a search integration. +There are a few options you can use to add search to your website: -There are two main options, you can use [Algolia DocSearch](https://docsearch.algolia.com) or bring in your own `SearchBar` component. +- πŸ₯‡ [Algolia DocSearch](#using-algolia-docsearch) (**official**) +- πŸ‘₯ [Typesense DocSearch](#using-typesense-docsearch) +- πŸ‘₯ [Local Search](#using-local-search) +- πŸ‘₯ [Your own `SearchBar` component](#using-your-own-search) -## Using Algolia DocSearch {#using-algolia-docsearch} +:::info + +πŸ₯‡ Docusaurus provides **first-class support** for [Algolia DocSearch](#using-algolia-docsearch). + +πŸ‘₯ Other options are **maintained by the community**: please report bugs to their respective repositories. + +::: + +## πŸ₯‡ Using Algolia DocSearch {#using-algolia-docsearch} + +Docusaurus has **official support** for [Algolia DocSearch](https://docsearch.algolia.com). + +The service is **free** in most cases: just [apply to the DocSearch program](https://docsearch.algolia.com/docs/apply). + +It works by crawling the content of your website every 24 hours and putting all the content in an Algolia index. This content is then queried directly from your front-end using the Algolia API. -Algolia DocSearch works by crawling the content of your website every 24 hours and putting all the content in an Algolia index. This content is then queried directly from your front-end using the Algolia API. Note that your website needs to be publicly available for this to work (i.e., not behind a firewall). The service is free. +If your website is [not eligible](https://docsearch.algolia.com/docs/who-can-apply) for the free, hosted version of DocSearch, or if your website sits behind a firewall and is not public, then you can [run your own](https://docsearch.algolia.com/docs/run-your-own/) DocSearch crawler. -If your website is [not eligible](https://docsearch.algolia.com/docs/who-can-apply) for the free, hosted version of DocSearch, or if your website sits behind a firewall, then you can [run your own](https://docsearch.algolia.com/docs/run-your-own/) DocSearch crawler. For best results, you may want to use a config file based on the [Docusaurus 2 config](https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json). +:::note + +By default, the Docusaurus preset generates a [sitemap.xml](https://docusaurus.io/sitemap.xml) that the Algolia crawler can use. + +::: + +### Index Configuration {#algolia-index-configuration} + +After applying, your site's DocSearch config should be created at: + +``` +https://github.com/algolia/docsearch-configs/blob/master/configs/.json +``` + +This configuration file can be updated by: + +- [**asking for help**](#algolia-support): the DocSearch team can help you maintain it +- opening a pull-requests in [algolia/docsearch-configs](https://github.com/algolia/docsearch-configs) + +:::caution + +It is highly recommended using a config similar to the [**Docusaurus 2 website config**](https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json). + +::: ### Connecting Algolia {#connecting-algolia} +Docusaurus' own `@docusaurus/preset-classic` supports an Algolia DocSearch integration. + To connect your docs with Algolia, first add the package to your website: ```bash npm2yarn @@ -33,7 +75,12 @@ module.exports = { // ... // highlight-start algolia: { - apiKey: 'YOUR_API_KEY', + // If Algolia did not provide you any appId, use 'BH4D9OD16A' + appId: 'YOUR_APP_ID', + + // Public API key: it is safe to commit it + apiKey: 'YOUR_SEARCH_API_KEY', + indexName: 'YOUR_INDEX_NAME', // Optional: see doc section below @@ -58,6 +105,14 @@ The `searchParameters` option used to be named `algoliaOptions` in Docusaurus v1 ::: +:::caution + +The search feature will not work reliably until Algolia crawls your site with the **search plugin enabled**. + +If you are installing the Algolia plugin for the first time and want to ensure the search feature works before deploying it to production, you can ask the DocSearch team to trigger a crawl on a staging environment url or deploy preview. + +::: + ### Contextual search {#contextual-search} Contextual search is mostly useful for versioned Docusaurus sites. @@ -89,24 +144,6 @@ When using `contextualSearch: true`, the contextual facet filters will be merged ::: -### Custom Application ID {#custom-application-id} - -When [running your own](https://docsearch.algolia.com/docs/run-your-own/) DocSearch crawler, it is [required to set the `appId` configuration key](https://docsearch.algolia.com/docs/behavior/#appid) to your own Application ID. If left unset, the `appId` will fallback to the one used with the free, hosted version of Algolia DocSearch. - -```jsx title="docusaurus.config.js" -module.exports = { - // ... - themeConfig: { - // ... - // highlight-start - algolia: { - appId: 'YOUR_APP_ID', - }, - // highlight-end - }, -}; -``` - ### Styling your Algolia search {#styling-your-algolia-search} By default, DocSearch comes with a fine-tuned theme that was designed for accessibility, making sure that colors and contrasts respect standards. @@ -182,7 +219,37 @@ If you prefer to edit the Algolia search React component, swizzle the `SearchBar npm run swizzle @docusaurus/theme-search-algolia SearchBar ``` -## Using your own search {#using-your-own-search} +### Support {#algolia-support} + +The Algolia DocSearch team can help you figure out search problems on your site. + +You can contact them by [email](mailto:documentationsearch@algolia.com) or on [Discord](https://discord.gg/tXdr5mP). + +Docusaurus also has an `#algolia` channel on [Discord](https://discordapp.com/invite/docusaurus). + +## πŸ‘₯ Using Typesense DocSearch {#using-typesense-docsearch} + +[Typesense](https://typesense.org) DocSearch works similar to Algolia DocSearch, except that your website is indexed into a Typesense search cluster. + +Typesense is an [open source](https://github.com/typesense/typesense) instant-search engine that you can either: + +- [Self-Host](https://typesense.org/docs/latest/guide/install-typesense.html#option-2-local-machine-self-hosting) on your own servers or +- Use the Managed [Typesense Cloud](https://cloud.typesense.org) service. + +Similar to Algolia DocSearch, there are two components: + +- [typesense-docsearch-scraper](https://github.com/typesense/typesense-docsearch-scraper) - which scrapes your website and indexes the data in your Typesense cluster. +- [docusaurus-theme-search-typesense](https://github.com/typesense/docusaurus-theme-search-typesense) - a search bar UI component to add to your website. + +Read a step-by-step walk-through of how to [run typesense-docsearch-scraper here](https://typesense.org/docs/latest/guide/docsearch.html#step-1-set-up-docsearch-scraper) and how to [install the Search Bar in your Docusaurus Site here](https://typesense.org/docs/latest/guide/docsearch.html#option-a-docusaurus-powered-sites). + +## πŸ‘₯ Using Local Search {#using-local-search} + +You can use a local search plugin for websites where the search index is small and can be downloaded to your users' browsers when they visit your website. + +You'll find a list of community-supported [local search plugins listed here](https://docusaurus.io/community/resources#search). + +## πŸ‘₯ Using your own search {#using-your-own-search} To use your own search, swizzle the `SearchBar` component in `@docusaurus/theme-classic` diff --git a/website/versioned_docs/version-2.0.0-beta.6/static-assets.md b/website/versioned_docs/version-2.0.0-beta.8/static-assets.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/static-assets.md rename to website/versioned_docs/version-2.0.0-beta.8/static-assets.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/styling-layout.md b/website/versioned_docs/version-2.0.0-beta.8/styling-layout.md similarity index 100% rename from website/versioned_docs/version-2.0.0-beta.6/styling-layout.md rename to website/versioned_docs/version-2.0.0-beta.8/styling-layout.md diff --git a/website/versioned_docs/version-2.0.0-beta.6/typescript-support.md b/website/versioned_docs/version-2.0.0-beta.8/typescript-support.md similarity index 85% rename from website/versioned_docs/version-2.0.0-beta.6/typescript-support.md rename to website/versioned_docs/version-2.0.0-beta.8/typescript-support.md index 8b1cff8fefcc..dd235ddd5beb 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/typescript-support.md +++ b/website/versioned_docs/version-2.0.0-beta.8/typescript-support.md @@ -3,24 +3,24 @@ id: typescript-support title: TypeScript Support --- -Docusaurus is written in TypeScript, and provide first-class TypeScript support. +Docusaurus is written in TypeScript, and provides first-class TypeScript support. ## Initialization {#initialization} Docusaurus supports writing and using TypeScript theme components. If the init template provides a Typescript variant, you can directly initialize a site with full TypeScript support by using the `--typescript` flag. ```bash -npm init docusaurus@latest my-website classic --typescript +npm init docusaurus@latest my-website classic -- --typescript ``` Below are some guides on how to migrate an existing project to TypeScript. ## Setup {#setup} -To start using TypeScript, add `@docusaurus/module-type-aliases` and some `@types` dependencies to your project: +To start using TypeScript, add `@docusaurus/module-type-aliases` and the base TS config to your project: ```bash npm2yarn -npm install --save-dev typescript @docusaurus/module-type-aliases @types/react @types/react-router-dom @types/react-helmet @tsconfig/docusaurus +npm install --save-dev typescript @docusaurus/module-type-aliases @tsconfig/docusaurus ``` Then add `tsconfig.json` to your project root with the following content: @@ -42,8 +42,11 @@ It is **not possible** to use a TypeScript config file in Docusaurus, unless you We recommend using [JSDoc type annotations](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html): - ```js title="docusaurus.config.js" +// highlight-start +// @ts-check +// highlight-end + // highlight-start /** @type {import('@docusaurus/types').Plugin} */ // highlight-end @@ -54,9 +57,9 @@ function MyPlugin(context, options) { } // highlight-start -/** @type {import('@docusaurus/types').DocusaurusConfig} */ +/** @type {import('@docusaurus/types').Config} */ // highlight-end -(module.exports = { +const config = { title: 'Docusaurus', tagline: 'Build optimized websites quickly, focus on your content', organizationName: 'facebook', @@ -98,9 +101,10 @@ function MyPlugin(context, options) { }, }, }), -}); +}; + +module.exports = config; ``` - :::tip @@ -110,6 +114,18 @@ The best IDEs (VSCode, WebStorm, Intellij...) will provide a nice auto-completio ::: +:::info + +By default, the Docusaurus TypeScript config does not type-check JavaScript files. + +The `// @ts-check` comment ensures the config file is properly type-checked when running: + +```bash npm2yarn +npm run tsc +``` + +::: + ## Swizzling TypeScript theme components {#swizzling-typescript-theme-components} For themes that supports TypeScript theme components, you can add the `--typescript` flag to the end of swizzling command to get TypeScript source code. For example, the following command will generate `index.tsx` and `styles.module.css` into `src/theme/Footer`. diff --git a/website/versioned_docs/version-2.0.0-beta.6/using-plugins.md b/website/versioned_docs/version-2.0.0-beta.8/using-plugins.md similarity index 99% rename from website/versioned_docs/version-2.0.0-beta.6/using-plugins.md rename to website/versioned_docs/version-2.0.0-beta.8/using-plugins.md index 2ebef9f49099..308a8c826654 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/using-plugins.md +++ b/website/versioned_docs/version-2.0.0-beta.8/using-plugins.md @@ -133,7 +133,7 @@ You can use a plugin as a function, directly in the Docusaurus config file: module.exports = { // ... plugins: [ - // highligh-start + // highlight-start function myPlugin(context, options) { // ... return { diff --git a/website/versioned_docs/version-2.0.0-beta.6/using-themes.md b/website/versioned_docs/version-2.0.0-beta.8/using-themes.md similarity index 99% rename from website/versioned_docs/version-2.0.0-beta.6/using-themes.md rename to website/versioned_docs/version-2.0.0-beta.8/using-themes.md index f0f94a959f8d..2ff65c35ee30 100644 --- a/website/versioned_docs/version-2.0.0-beta.6/using-themes.md +++ b/website/versioned_docs/version-2.0.0-beta.8/using-themes.md @@ -51,7 +51,7 @@ website `website/src/theme/Navbar.js` takes precedence whenever `@theme/Navbar` is imported. This behavior is called component swizzling. In iOS, method swizzling is the process of changing the implementation of an existing selector (method). In the context of a website, component swizzling means providing an alternative component that takes precedence over the component provided by the theme. -**Themes are for providing UI components to present the content.** Most content plugins need to be paired with a theme in order to be actually useful. The UI is a separate layer from the data schema, so it makes it easy to swap out the themes for other designs (i.e., Bootstrap). +**Themes are for providing UI components to present the content.** Most content plugins need to be paired with a theme in order to be actually useful. The UI is a separate layer from the data schema, so it makes it easy to swap out the themes for other designs. For example, a Docusaurus blog consists of a blog plugin and a blog theme. diff --git a/website/versioned_sidebars/version-2.0.0-beta.6-sidebars.json b/website/versioned_sidebars/version-2.0.0-beta.8-sidebars.json similarity index 55% rename from website/versioned_sidebars/version-2.0.0-beta.6-sidebars.json rename to website/versioned_sidebars/version-2.0.0-beta.8-sidebars.json index edb9fee7eae7..da77d4031b41 100644 --- a/website/versioned_sidebars/version-2.0.0-beta.6-sidebars.json +++ b/website/versioned_sidebars/version-2.0.0-beta.8-sidebars.json @@ -1,8 +1,8 @@ { - "version-2.0.0-beta.6/docs": [ + "version-2.0.0-beta.8/docs": [ { "type": "doc", - "id": "version-2.0.0-beta.6/introduction" + "id": "version-2.0.0-beta.8/introduction" }, { "type": "category", @@ -11,19 +11,19 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/installation" + "id": "version-2.0.0-beta.8/installation" }, { "type": "doc", - "id": "version-2.0.0-beta.6/configuration" + "id": "version-2.0.0-beta.8/configuration" }, { "type": "doc", - "id": "version-2.0.0-beta.6/playground" + "id": "version-2.0.0-beta.8/playground" }, { "type": "doc", - "id": "version-2.0.0-beta.6/typescript-support" + "id": "version-2.0.0-beta.8/typescript-support" } ], "collapsible": true @@ -34,7 +34,7 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/guides/creating-pages" + "id": "version-2.0.0-beta.8/guides/creating-pages" }, { "type": "category", @@ -44,33 +44,33 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/guides/docs/introduction" + "id": "version-2.0.0-beta.8/guides/docs/introduction" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/docs/create-doc" + "id": "version-2.0.0-beta.8/guides/docs/create-doc" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/docs/sidebar" + "id": "version-2.0.0-beta.8/guides/docs/sidebar" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/docs/versioning" + "id": "version-2.0.0-beta.8/guides/docs/versioning" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/docs/markdown-features" + "id": "version-2.0.0-beta.8/guides/docs/markdown-features" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/docs/multi-instance" + "id": "version-2.0.0-beta.8/guides/docs/multi-instance" } ] }, { "type": "doc", - "id": "version-2.0.0-beta.6/blog" + "id": "version-2.0.0-beta.8/blog" }, { "type": "category", @@ -78,47 +78,47 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/introduction" + "id": "version-2.0.0-beta.8/guides/markdown-features/introduction" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/react" + "id": "version-2.0.0-beta.8/guides/markdown-features/react" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/tabs" + "id": "version-2.0.0-beta.8/guides/markdown-features/tabs" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/code-blocks" + "id": "version-2.0.0-beta.8/guides/markdown-features/code-blocks" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/admonitions" + "id": "version-2.0.0-beta.8/guides/markdown-features/admonitions" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/headings" + "id": "version-2.0.0-beta.8/guides/markdown-features/headings" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/inline-toc" + "id": "version-2.0.0-beta.8/guides/markdown-features/inline-toc" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/assets" + "id": "version-2.0.0-beta.8/guides/markdown-features/assets" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/plugins" + "id": "version-2.0.0-beta.8/guides/markdown-features/plugins" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/math-equations" + "id": "version-2.0.0-beta.8/guides/markdown-features/math-equations" }, { "type": "doc", - "id": "version-2.0.0-beta.6/guides/markdown-features/head-metadatas" + "id": "version-2.0.0-beta.8/guides/markdown-features/head-metadatas" } ], "collapsible": true, @@ -126,23 +126,23 @@ }, { "type": "doc", - "id": "version-2.0.0-beta.6/styling-layout" + "id": "version-2.0.0-beta.8/styling-layout" }, { "type": "doc", - "id": "version-2.0.0-beta.6/static-assets" + "id": "version-2.0.0-beta.8/static-assets" }, { "type": "doc", - "id": "version-2.0.0-beta.6/search" + "id": "version-2.0.0-beta.8/search" }, { "type": "doc", - "id": "version-2.0.0-beta.6/browser-support" + "id": "version-2.0.0-beta.8/browser-support" }, { "type": "doc", - "id": "version-2.0.0-beta.6/deployment" + "id": "version-2.0.0-beta.8/deployment" }, { "type": "category", @@ -150,19 +150,19 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/i18n/introduction" + "id": "version-2.0.0-beta.8/i18n/introduction" }, { "type": "doc", - "id": "version-2.0.0-beta.6/i18n/tutorial" + "id": "version-2.0.0-beta.8/i18n/tutorial" }, { "type": "doc", - "id": "version-2.0.0-beta.6/i18n/git" + "id": "version-2.0.0-beta.8/i18n/git" }, { "type": "doc", - "id": "version-2.0.0-beta.6/i18n/crowdin" + "id": "version-2.0.0-beta.8/i18n/crowdin" } ], "collapsible": true, @@ -178,15 +178,15 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/using-plugins" + "id": "version-2.0.0-beta.8/using-plugins" }, { "type": "doc", - "id": "version-2.0.0-beta.6/using-themes" + "id": "version-2.0.0-beta.8/using-themes" }, { "type": "doc", - "id": "version-2.0.0-beta.6/presets" + "id": "version-2.0.0-beta.8/presets" } ], "collapsible": true, @@ -198,45 +198,45 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/migration/migration-overview" + "id": "version-2.0.0-beta.8/migration/migration-overview" }, { "type": "doc", - "id": "version-2.0.0-beta.6/migration/migration-automated" + "id": "version-2.0.0-beta.8/migration/migration-automated" }, { "type": "doc", - "id": "version-2.0.0-beta.6/migration/migration-manual" + "id": "version-2.0.0-beta.8/migration/migration-manual" }, { "type": "doc", - "id": "version-2.0.0-beta.6/migration/migration-versioned-sites" + "id": "version-2.0.0-beta.8/migration/migration-versioned-sites" }, { "type": "doc", - "id": "version-2.0.0-beta.6/migration/migration-translated-sites" + "id": "version-2.0.0-beta.8/migration/migration-translated-sites" } ], "collapsible": true, "collapsed": true } ], - "version-2.0.0-beta.6/api": [ + "version-2.0.0-beta.8/api": [ { "type": "doc", - "id": "version-2.0.0-beta.6/cli" + "id": "version-2.0.0-beta.8/cli" }, { "type": "doc", - "id": "version-2.0.0-beta.6/docusaurus-core" + "id": "version-2.0.0-beta.8/docusaurus-core" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/docusaurus.config.js" + "id": "version-2.0.0-beta.8/api/docusaurus.config.js" }, { "type": "doc", - "id": "version-2.0.0-beta.6/lifecycle-apis" + "id": "version-2.0.0-beta.8/lifecycle-apis" }, { "type": "category", @@ -244,47 +244,47 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugins-overview" + "id": "version-2.0.0-beta.8/api/plugins/plugins-overview" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-content-docs" + "id": "version-2.0.0-beta.8/api/plugins/plugin-content-docs" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-content-blog" + "id": "version-2.0.0-beta.8/api/plugins/plugin-content-blog" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-content-pages" + "id": "version-2.0.0-beta.8/api/plugins/plugin-content-pages" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-client-redirects" + "id": "version-2.0.0-beta.8/api/plugins/plugin-client-redirects" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-debug" + "id": "version-2.0.0-beta.8/api/plugins/plugin-debug" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-google-analytics" + "id": "version-2.0.0-beta.8/api/plugins/plugin-google-analytics" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-google-gtag" + "id": "version-2.0.0-beta.8/api/plugins/plugin-google-gtag" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-ideal-image" + "id": "version-2.0.0-beta.8/api/plugins/plugin-ideal-image" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-pwa" + "id": "version-2.0.0-beta.8/api/plugins/plugin-pwa" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/plugins/plugin-sitemap" + "id": "version-2.0.0-beta.8/api/plugins/plugin-sitemap" } ], "collapsible": true, @@ -296,27 +296,23 @@ "items": [ { "type": "doc", - "id": "version-2.0.0-beta.6/api/themes/themes-overview" + "id": "version-2.0.0-beta.8/api/themes/themes-overview" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/themes/theme-configuration" + "id": "version-2.0.0-beta.8/api/themes/theme-configuration" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/themes/theme-classic" + "id": "version-2.0.0-beta.8/api/themes/theme-classic" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/themes/theme-bootstrap" + "id": "version-2.0.0-beta.8/api/themes/theme-live-codeblock" }, { "type": "doc", - "id": "version-2.0.0-beta.6/api/themes/theme-live-codeblock" - }, - { - "type": "doc", - "id": "version-2.0.0-beta.6/api/themes/theme-search-algolia" + "id": "version-2.0.0-beta.8/api/themes/theme-search-algolia" } ], "collapsible": true, diff --git a/website/versions.json b/website/versions.json index c9e89b3f44ee..228156222533 100644 --- a/website/versions.json +++ b/website/versions.json @@ -1,4 +1,4 @@ [ - "2.0.0-beta.7", - "2.0.0-beta.6" + "2.0.0-beta.8", + "2.0.0-beta.7" ] diff --git a/website/versionsArchived.json b/website/versionsArchived.json index 1e0ad914722f..1850d48c6b98 100644 --- a/website/versionsArchived.json +++ b/website/versionsArchived.json @@ -1,5 +1,6 @@ { - "2.0.0-beta.5": "https://6130eb5cde15830007fdf57b--docusaurus-2.netlify.app/docs", + "2.0.0-beta.6": "https://61716a75858b7d0007e84c89--docusaurus-2.netlify.app/docs/2.0.0-beta.6", + "2.0.0-beta.5": "https://61685d5327709b0007411bff--docusaurus-2.netlify.app/docs/2.0.0-beta.5", "2.0.0-beta.4": "https://6130eb5cde15830007fdf57b--docusaurus-2.netlify.app/docs/2.0.0-beta.4", "2.0.0-beta.3": "https://6127899cbdc82400074cdc97--docusaurus-2.netlify.app/docs/2.0.0-beta.3", "2.0.0-beta.2": "https://6107be93ef38a00008efa7eb--docusaurus-2.netlify.app/docs/2.0.0-beta.2", diff --git a/yarn.lock b/yarn.lock index c73b6d0f17b1..3ceb217f44c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4136,10 +4136,10 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.9.tgz#1cfb6d60ef3822c589f18e70f8b12f9a28ce8724" integrity sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ== -"@types/html-minifier-terser@^5.0.0": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57" - integrity sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w== +"@types/html-minifier-terser@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.0.0.tgz#563c1c6c132cd204e71512f9c0b394ff90d3fae7" + integrity sha512-NZwaaynfs1oIoLAV1vg18e7QMVDvw+6SQrdJc8w3BwUaoroVSf6EBj/Sk4PBWGxsq0dzhA2drbsuMC1/6C6KgQ== "@types/html-minifier@*": version "4.0.1" @@ -6283,7 +6283,7 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@^4.1.1, camel-case@^4.1.2: +camel-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== @@ -6576,13 +6576,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -clean-css@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" - integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== - dependencies: - source-map "~0.6.0" - clean-css@^5.1.5: version "5.1.5" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.1.5.tgz#3b0af240dcfc9a3779a08c2332df3ebd4474f232" @@ -6952,7 +6945,7 @@ commander@^3.0.2: resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== -commander@^4.0.1, commander@^4.1.1: +commander@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== @@ -10817,19 +10810,6 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -html-minifier-terser@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" - integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== - dependencies: - camel-case "^4.1.1" - clean-css "^4.2.3" - commander "^4.1.1" - he "^1.2.0" - param-case "^3.0.3" - relateurl "^0.2.7" - terser "^4.6.3" - html-minifier-terser@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.0.2.tgz#14059ad64b69bf9f8b8a33f25b53411d8321e75d" @@ -10853,13 +10833,13 @@ html-void-elements@^1.0.0: resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== -html-webpack-plugin@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.3.2.tgz#7b04bf80b1f6fe84a6d3f66c8b79d64739321b08" - integrity sha512-HvB33boVNCz2lTyBsSiMffsJ+m0YLIQ+pskblXgN9fnjS1BgEcuAfdInfXfGrkdXV406k9FiDi86eVCDBgJOyQ== +html-webpack-plugin@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.4.0.tgz#d016cd9594be5c243bb5c12287af43babbe1c094" + integrity sha512-cSUdckNOIqKc0nOrCJG7zkvzEIUcXjzEiVbKdEdIzW3BD5T4xPK6boV1mrTrPDZiL+aAr/j45eqbNL1akU2ZRA== dependencies: - "@types/html-minifier-terser" "^5.0.0" - html-minifier-terser "^5.0.1" + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" lodash "^4.17.21" pretty-error "^3.0.4" tapable "^2.0.0" @@ -15420,7 +15400,7 @@ parallel-transform@^1.1.0, parallel-transform@^1.2.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@^3.0.3, param-case@^3.0.4: +param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== @@ -18250,7 +18230,7 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.16, source-map-support@^0.5.19, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20: +source-map-support@^0.5.16, source-map-support@^0.5.19, source-map-support@^0.5.6, source-map-support@~0.5.20: version "0.5.20" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== @@ -19141,15 +19121,6 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.4: source-map "^0.6.1" terser "^5.7.2" -terser@^4.6.3: - version "4.8.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" - integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - terser@^5.0.0, terser@^5.7.2: version "5.9.0" resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351"