chore: release Docusaurus 3.7.0 (#10812)

This commit is contained in:
Sébastien Lorber 2025-01-03 18:11:21 +01:00 committed by GitHub
parent cacb973326
commit 71d682c53b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
153 changed files with 21809 additions and 232 deletions

View file

@ -1,5 +1,81 @@
# Docusaurus Changelog
## 3.7.0 (2025-01-03)
#### :rocket: New Feature
- `docusaurus-faster`, `docusaurus`
- [#10800](https://github.com/facebook/docusaurus/pull/10800) feat(core): Turn Rspack incremental on by default (again) ([@slorber](https://github.com/slorber))
- `docusaurus-plugin-content-blog`, `docusaurus-theme-classic`
- [#10768](https://github.com/facebook/docusaurus/pull/10768) feat(blog): Add author social icons for bluesky, mastodon, threads, twitch, youtube, instagram ([@GingerGeek](https://github.com/GingerGeek))
- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-module-type-aliases`, `docusaurus-plugin-client-redirects`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-google-analytics`, `docusaurus-plugin-google-gtag`, `docusaurus-plugin-google-tag-manager`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-plugin-rsdoctor`, `docusaurus-plugin-sitemap`, `docusaurus-plugin-svgr`, `docusaurus-plugin-vercel-analytics`, `docusaurus-preset-classic`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-mermaid`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus`
- [#10763](https://github.com/facebook/docusaurus/pull/10763) feat: Add React 19 support to Docusaurus v3 ([@slorber](https://github.com/slorber))
- `docusaurus-plugin-content-blog`
- [#10729](https://github.com/facebook/docusaurus/pull/10729) feat(blog): Add `frontMatter.sidebar_label` ([@slorber](https://github.com/slorber))
- `docusaurus-module-type-aliases`, `docusaurus-plugin-svgr`, `docusaurus-preset-classic`, `docusaurus-types`, `docusaurus-utils`, `docusaurus`
- [#10677](https://github.com/facebook/docusaurus/pull/10677) feat(svgr): create new Docusaurus SVGR plugin ([@slorber](https://github.com/slorber))
#### :bug: Bug Fix
- `docusaurus-remark-plugin-npm2yarn`
- [#10803](https://github.com/facebook/docusaurus/pull/10803) fix(npm-to-yarn): add missing npm-to-yarn converter for Bun ([@Lehoczky](https://github.com/Lehoczky))
- `docusaurus-theme-classic`, `docusaurus-theme-common`
- [#10796](https://github.com/facebook/docusaurus/pull/10796) fix(theme): Footer Column/Link should merge provided className ([@slorber](https://github.com/slorber))
- `docusaurus-bundler`, `docusaurus-theme-common`
- [#10786](https://github.com/facebook/docusaurus/pull/10786) fix(core): fix React hydration errors, change html minifier settings ([@slorber](https://github.com/slorber))
- `docusaurus-theme-common`
- [#10782](https://github.com/facebook/docusaurus/pull/10782) fix(theme-common): code block magic comments should support SQL block comments ([@WillBlack403](https://github.com/WillBlack403))
- `docusaurus-theme-translations`
- [#10783](https://github.com/facebook/docusaurus/pull/10783) fix(theme-translations): Add missing Dutch (nl) theme translations ([@janaukema](https://github.com/janaukema))
- [#10760](https://github.com/facebook/docusaurus/pull/10760) fix(theme-translation): add missing Korean (ko) theme translations ([@effozen](https://github.com/effozen))
- `docusaurus-plugin-content-docs`
- [#10754](https://github.com/facebook/docusaurus/pull/10754) fix(docs): fix sidebar item visibility bug for category index ([@slorber](https://github.com/slorber))
- `docusaurus`
- [#10727](https://github.com/facebook/docusaurus/pull/10727) fix(core): fix codegen routesChunkName possible hash collision ([@slorber](https://github.com/slorber))
- `docusaurus-mdx-loader`
- [#10723](https://github.com/facebook/docusaurus/pull/10723) fix(mdx-loader): fix md image paths with spaces bug related to transformImage encoding problem ([@slorber](https://github.com/slorber))
#### :memo: Documentation
- [#10740](https://github.com/facebook/docusaurus/pull/10740) docs: Link initialization docs together ([@waldyrious](https://github.com/waldyrious))
#### :robot: Dependencies
- [#10771](https://github.com/facebook/docusaurus/pull/10771) chore(deps): bump nanoid from 3.3.7 to 3.3.8 ([@dependabot[bot]](https://github.com/apps/dependabot))
- [#10721](https://github.com/facebook/docusaurus/pull/10721) chore(deps): bump actions/dependency-review-action from 4.4.0 to 4.5.0 ([@dependabot[bot]](https://github.com/apps/dependabot))
#### :wrench: Maintenance
- Other
- [#10770](https://github.com/facebook/docusaurus/pull/10770) chore: Devcontainer upgrade to Ubuntu Noble & Node 22 ([@GingerGeek](https://github.com/GingerGeek))
- `docusaurus-theme-search-algolia`
- [#10801](https://github.com/facebook/docusaurus/pull/10801) refactor(algolia): simplify SearchBar component ([@slorber](https://github.com/slorber))
- [#10672](https://github.com/facebook/docusaurus/pull/10672) chore(algolia): upgrade algoliasearch to v5 ([@millotp](https://github.com/millotp))
- `docusaurus`
- [#10798](https://github.com/facebook/docusaurus/pull/10798) refactor(core): Use Intl native API to get locale direction, remove rtl-detect depend… ([@slorber](https://github.com/slorber))
- [#10747](https://github.com/facebook/docusaurus/pull/10747) refactor(core): swizzle wrap should use ReactNode instead of JSX.Element ([@slorber](https://github.com/slorber))
- `create-docusaurus`, `docusaurus-mdx-loader`, `docusaurus-module-type-aliases`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-plugin-debug`, `docusaurus-plugin-ideal-image`, `docusaurus-plugin-pwa`, `docusaurus-theme-classic`, `docusaurus-theme-common`, `docusaurus-theme-live-codeblock`, `docusaurus-theme-mermaid`, `docusaurus-theme-search-algolia`, `docusaurus-types`, `docusaurus`
- [#10746](https://github.com/facebook/docusaurus/pull/10746) refactor: prepare types for React 19 ([@slorber](https://github.com/slorber))
- `docusaurus-theme-common`
- [#10728](https://github.com/facebook/docusaurus/pull/10728) refactor(theme-common): change storageUtils useSyncExternalCode getSnapshot workaround ([@slorber](https://github.com/slorber))
#### Committers: 14
- Alvin Bryan ([@alvinometric](https://github.com/alvinometric))
- Hichem Fantar ([@hichemfantar](https://github.com/hichemfantar))
- Ivan Cheban ([@ivancheban](https://github.com/ivancheban))
- Jake Boone ([@jakeboone02](https://github.com/jakeboone02))
- Jan Aukema ([@janaukema](https://github.com/janaukema))
- Lehoczky Zoltán ([@Lehoczky](https://github.com/Lehoczky))
- Lin Huang ([@codimiracle](https://github.com/codimiracle))
- Pierre Millot ([@millotp](https://github.com/millotp))
- Sébastien Lorber ([@slorber](https://github.com/slorber))
- Taylor Reece ([@taylorreece](https://github.com/taylorreece))
- Waldir Pimenta ([@waldyrious](https://github.com/waldyrious))
- William Black ([@WillBlack403](https://github.com/WillBlack403))
- Zed Spencer-Milnes ([@GingerGeek](https://github.com/GingerGeek))
- Zen ([@effozen](https://github.com/effozen))
## 3.6.3 (2024-11-22)
#### :bug: Bug Fix

View file

@ -1,6 +1,6 @@
{
"name": "new.docusaurus.io",
"version": "3.6.3",
"version": "3.7.0",
"private": true,
"scripts": {
"start": "npx --package netlify-cli netlify dev"

View file

@ -1,6 +1,6 @@
{
"name": "test-bad-package",
"version": "3.6.3",
"version": "3.7.0",
"private": true,
"dependencies": {
"@mdx-js/react": "1.0.1",

View file

@ -1,6 +1,6 @@
{
"name": "argos",
"version": "3.6.3",
"version": "3.7.0",
"description": "Argos visual diff tests",
"license": "MIT",
"private": true,

View file

@ -1,5 +1,5 @@
{
"version": "3.6.3",
"version": "3.7.0",
"npmClient": "yarn",
"useWorkspaces": true,
"useNx": false,

View file

@ -1,6 +1,6 @@
{
"name": "create-docusaurus",
"version": "3.6.3",
"version": "3.7.0",
"description": "Create Docusaurus apps easily.",
"type": "module",
"repository": {
@ -22,8 +22,8 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/logger": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.7.0",
"commander": "^5.1.0",
"fs-extra": "^11.1.1",
"lodash": "^4.17.21",

View file

@ -1,6 +1,6 @@
{
"name": "docusaurus-2-classic-typescript-template",
"version": "3.6.3",
"version": "3.7.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@ -15,8 +15,8 @@
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/preset-classic": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
@ -24,9 +24,9 @@
"react-dom": "^19.0.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/tsconfig": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/tsconfig": "3.7.0",
"@docusaurus/types": "3.7.0",
"typescript": "~5.6.2"
},
"browserslist": {

View file

@ -1,6 +1,6 @@
{
"name": "docusaurus-2-classic-template",
"version": "3.6.3",
"version": "3.7.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@ -14,8 +14,8 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/preset-classic": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
@ -23,8 +23,8 @@
"react-dom": "^19.0.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/types": "3.6.3"
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/types": "3.7.0"
},
"browserslist": {
"production": [

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/babel",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus package for Babel-related utils.",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@ -38,8 +38,8 @@
"@babel/runtime": "^7.25.9",
"@babel/runtime-corejs3": "^7.25.9",
"@babel/traverse": "^7.25.9",
"@docusaurus/logger": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.7.0",
"babel-plugin-dynamic-import-node": "^2.3.3",
"fs-extra": "^11.1.1",
"tslib": "^2.6.0"

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/bundler",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus util package to abstract the current bundler.",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@ -19,11 +19,11 @@
"license": "MIT",
"dependencies": {
"@babel/core": "^7.25.9",
"@docusaurus/babel": "3.6.3",
"@docusaurus/cssnano-preset": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/babel": "3.7.0",
"@docusaurus/cssnano-preset": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"babel-loader": "^9.2.1",
"clean-css": "^5.3.2",
"copy-webpack-plugin": "^11.0.0",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/cssnano-preset",
"version": "3.6.3",
"version": "3.7.0",
"description": "Advanced cssnano preset for maximum optimization.",
"main": "lib/index.js",
"license": "MIT",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/faster",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus experimental package exposing new modern dependencies to make the build faster.",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@ -18,7 +18,7 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/types": "3.6.3",
"@docusaurus/types": "3.7.0",
"@rspack/core": "1.2.0-alpha.0",
"@swc/core": "^1.7.39",
"@swc/html": "^1.7.39",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/logger",
"version": "3.6.3",
"version": "3.7.0",
"description": "An encapsulated logger for semantically formatting console messages.",
"main": "./lib/index.js",
"repository": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/mdx-loader",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus Loader for MDX",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,9 +18,9 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/logger": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@mdx-js/mdx": "^3.0.0",
"@slorber/remark-comment": "^1.0.0",
"escape-html": "^1.0.3",
@ -44,7 +44,7 @@
"webpack": "^5.88.1"
},
"devDependencies": {
"@docusaurus/types": "3.6.3",
"@docusaurus/types": "3.7.0",
"@types/escape-html": "^1.0.2",
"@types/mdast": "^4.0.2",
"@types/stringify-object": "^3.3.1",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/module-type-aliases",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus module type aliases.",
"types": "./src/index.d.ts",
"publishConfig": {
@ -12,7 +12,7 @@
"directory": "packages/docusaurus-module-type-aliases"
},
"dependencies": {
"@docusaurus/types": "3.6.3",
"@docusaurus/types": "3.7.0",
"@types/history": "^4.7.11",
"@types/react": "*",
"@types/react-router-config": "*",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-client-redirects",
"version": "3.6.3",
"version": "3.7.0",
"description": "Client redirects plugin for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,18 +18,18 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"eta": "^2.2.0",
"fs-extra": "^11.1.1",
"lodash": "^4.17.21",
"tslib": "^2.6.0"
},
"devDependencies": {
"@docusaurus/types": "3.6.3"
"@docusaurus/types": "3.7.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-content-blog",
"version": "3.6.3",
"version": "3.7.0",
"description": "Blog plugin for Docusaurus.",
"main": "lib/index.js",
"types": "src/plugin-content-blog.d.ts",
@ -31,14 +31,14 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/mdx-loader": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/mdx-loader": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"cheerio": "1.0.0-rc.12",
"feed": "^4.2.2",
"fs-extra": "^11.1.1",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-content-docs",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docs plugin for Docusaurus.",
"main": "lib/index.js",
"sideEffects": false,
@ -35,15 +35,15 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/mdx-loader": "3.6.3",
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/mdx-loader": "3.7.0",
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@types/react-router-config": "^5.0.7",
"combine-promises": "^1.1.0",
"fs-extra": "^11.1.1",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-content-pages",
"version": "3.6.3",
"version": "3.7.0",
"description": "Pages plugin for Docusaurus.",
"main": "lib/index.js",
"types": "src/plugin-content-pages.d.ts",
@ -18,11 +18,11 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/mdx-loader": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/mdx-loader": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"fs-extra": "^11.1.1",
"tslib": "^2.6.0",
"webpack": "^5.88.1"

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-debug",
"version": "3.6.3",
"version": "3.7.0",
"description": "Debug plugin for Docusaurus.",
"main": "lib/index.js",
"types": "src/plugin-debug.d.ts",
@ -20,9 +20,9 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"fs-extra": "^11.1.1",
"react-json-view-lite": "^1.2.0",
"tslib": "^2.6.0"

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-google-analytics",
"version": "3.6.3",
"version": "3.7.0",
"description": "Global analytics (analytics.js) plugin for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,9 +18,9 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"tslib": "^2.6.0"
},
"peerDependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-google-gtag",
"version": "3.6.3",
"version": "3.7.0",
"description": "Global Site Tag (gtag.js) plugin for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,9 +18,9 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@types/gtag.js": "^0.0.12",
"tslib": "^2.6.0"
},

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-google-tag-manager",
"version": "3.6.3",
"version": "3.7.0",
"description": "Google Tag Manager (gtm.js) plugin for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,9 +18,9 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"tslib": "^2.6.0"
},
"peerDependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-ideal-image",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus Plugin to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder).",
"main": "lib/index.js",
"types": "src/plugin-ideal-image.d.ts",
@ -20,12 +20,12 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/lqip-loader": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/lqip-loader": "3.7.0",
"@docusaurus/responsive-loader": "^1.7.0",
"@docusaurus/theme-translations": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/theme-translations": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@slorber/react-ideal-image": "^0.0.14",
"react-waypoint": "^10.3.0",
"sharp": "^0.32.3",
@ -33,7 +33,7 @@
"webpack": "^5.88.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/module-type-aliases": "3.7.0",
"fs-extra": "^11.1.0"
},
"peerDependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-pwa",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus Plugin to add PWA support.",
"main": "lib/index.js",
"types": "src/plugin-pwa.d.ts",
@ -22,14 +22,14 @@
"dependencies": {
"@babel/core": "^7.25.9",
"@babel/preset-env": "^7.25.9",
"@docusaurus/bundler": "3.6.3",
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/theme-translations": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/bundler": "3.7.0",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/theme-translations": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"babel-loader": "^9.2.1",
"clsx": "^2.0.0",
"core-js": "^3.31.1",
@ -41,7 +41,7 @@
"workbox-window": "^7.0.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/module-type-aliases": "3.7.0",
"fs-extra": "^11.1.0"
},
"peerDependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-rsdoctor",
"version": "3.6.3",
"version": "3.7.0",
"description": "Rsdoctor plugin for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,9 +18,9 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@rsdoctor/rspack-plugin": "^0.4.6",
"@rsdoctor/webpack-plugin": "^0.4.6",
"tslib": "^2.6.0"

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-sitemap",
"version": "3.6.3",
"version": "3.7.0",
"description": "Simple sitemap generation plugin for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,12 +18,12 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"fs-extra": "^11.1.1",
"sitemap": "^7.1.1",
"tslib": "^2.6.0"

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-svgr",
"version": "3.6.3",
"version": "3.7.0",
"description": "SVGR plugin for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,10 +18,10 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@svgr/core": "8.1.0",
"@svgr/webpack": "^8.1.0",
"tslib": "^2.6.0",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/plugin-vercel-analytics",
"version": "3.6.3",
"version": "3.7.0",
"description": "Global vercel analytics plugin for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,11 +18,11 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@vercel/analytics": "^1.1.1",
"tslib": "^2.6.0"
},

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/preset-classic",
"version": "3.6.3",
"version": "3.7.0",
"description": "Classic preset for Docusaurus.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -18,20 +18,20 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/plugin-content-blog": "3.6.3",
"@docusaurus/plugin-content-docs": "3.6.3",
"@docusaurus/plugin-content-pages": "3.6.3",
"@docusaurus/plugin-debug": "3.6.3",
"@docusaurus/plugin-google-analytics": "3.6.3",
"@docusaurus/plugin-google-gtag": "3.6.3",
"@docusaurus/plugin-google-tag-manager": "3.6.3",
"@docusaurus/plugin-sitemap": "3.6.3",
"@docusaurus/plugin-svgr": "3.6.3",
"@docusaurus/theme-classic": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/theme-search-algolia": "3.6.3",
"@docusaurus/types": "3.6.3"
"@docusaurus/core": "3.7.0",
"@docusaurus/plugin-content-blog": "3.7.0",
"@docusaurus/plugin-content-docs": "3.7.0",
"@docusaurus/plugin-content-pages": "3.7.0",
"@docusaurus/plugin-debug": "3.7.0",
"@docusaurus/plugin-google-analytics": "3.7.0",
"@docusaurus/plugin-google-gtag": "3.7.0",
"@docusaurus/plugin-google-tag-manager": "3.7.0",
"@docusaurus/plugin-sitemap": "3.7.0",
"@docusaurus/plugin-svgr": "3.7.0",
"@docusaurus/theme-classic": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/theme-search-algolia": "3.7.0",
"@docusaurus/types": "3.7.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/remark-plugin-npm2yarn",
"version": "3.6.3",
"version": "3.7.0",
"description": "Remark plugin for converting npm commands to Yarn commands as tabs.",
"main": "lib/index.js",
"publishConfig": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/theme-classic",
"version": "3.6.3",
"version": "3.7.0",
"description": "Classic theme for Docusaurus",
"main": "lib/index.js",
"types": "src/theme-classic.d.ts",
@ -20,19 +20,19 @@
"copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
},
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/mdx-loader": "3.6.3",
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/plugin-content-blog": "3.6.3",
"@docusaurus/plugin-content-docs": "3.6.3",
"@docusaurus/plugin-content-pages": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/theme-translations": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/mdx-loader": "3.7.0",
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/plugin-content-blog": "3.7.0",
"@docusaurus/plugin-content-docs": "3.7.0",
"@docusaurus/plugin-content-pages": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/theme-translations": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"copy-text-to-clipboard": "^3.2.0",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/theme-common",
"version": "3.6.3",
"version": "3.7.0",
"description": "Common code for Docusaurus themes.",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@ -30,10 +30,10 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/mdx-loader": "3.6.3",
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/mdx-loader": "3.7.0",
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"@types/history": "^4.7.11",
"@types/react": "*",
"@types/react-router-config": "*",
@ -44,8 +44,8 @@
"utility-types": "^3.10.0"
},
"devDependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/types": "3.7.0",
"fs-extra": "^11.1.1",
"lodash": "^4.17.21",
"schema-dts": "^1.1.2"

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/theme-live-codeblock",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus live code block component.",
"main": "lib/index.js",
"types": "src/theme-live-codeblock.d.ts",
@ -23,10 +23,10 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/theme-translations": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/theme-translations": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"@philpl/buble": "^0.19.7",
"clsx": "^2.0.0",
"fs-extra": "^11.1.1",
@ -34,7 +34,7 @@
"tslib": "^2.6.0"
},
"devDependencies": {
"@docusaurus/types": "3.6.3",
"@docusaurus/types": "3.7.0",
"@types/buble": "^0.20.1"
},
"peerDependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/theme-mermaid",
"version": "3.6.3",
"version": "3.7.0",
"description": "Mermaid components for Docusaurus.",
"main": "lib/index.js",
"types": "src/theme-mermaid.d.ts",
@ -33,11 +33,11 @@
"copy:watch": "node ../../admin/scripts/copyUntypedFiles.js --watch"
},
"dependencies": {
"@docusaurus/core": "3.6.3",
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"mermaid": ">=10.4",
"tslib": "^2.6.0"
},

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/theme-search-algolia",
"version": "3.6.3",
"version": "3.7.0",
"description": "Algolia search component for Docusaurus.",
"main": "lib/index.js",
"sideEffects": [
@ -34,13 +34,13 @@
},
"dependencies": {
"@docsearch/react": "^3.8.1",
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/plugin-content-docs": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/theme-translations": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/plugin-content-docs": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/theme-translations": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"algoliasearch": "^5.17.1",
"algoliasearch-helper": "^3.22.6",
"clsx": "^2.0.0",
@ -51,7 +51,7 @@
"utility-types": "^3.10.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.6.3"
"@docusaurus/module-type-aliases": "3.7.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/theme-translations",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus theme translations.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@ -23,10 +23,10 @@
"tslib": "^2.6.0"
},
"devDependencies": {
"@docusaurus/babel": "3.6.3",
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/babel": "3.7.0",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.7.0",
"lodash": "^4.17.21"
},
"engines": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/tsconfig",
"version": "3.6.3",
"version": "3.7.0",
"description": "Docusaurus base TypeScript configuration.",
"main": "tsconfig.json",
"publishConfig": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/types",
"version": "3.6.3",
"version": "3.7.0",
"description": "Common types for Docusaurus packages.",
"types": "./src/index.d.ts",
"publishConfig": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/utils-common",
"version": "3.6.3",
"version": "3.7.0",
"description": "Common (Node/Browser) utility functions for Docusaurus packages.",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@ -19,7 +19,7 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/types": "3.6.3",
"@docusaurus/types": "3.7.0",
"tslib": "^2.6.0"
},
"engines": {

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/utils-validation",
"version": "3.6.3",
"version": "3.7.0",
"description": "Node validation utility functions for Docusaurus packages.",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@ -18,9 +18,9 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/logger": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/logger": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"fs-extra": "^11.2.0",
"joi": "^17.9.2",
"js-yaml": "^4.1.0",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/utils",
"version": "3.6.3",
"version": "3.7.0",
"description": "Node utility functions for Docusaurus packages.",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@ -18,9 +18,9 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/logger": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/logger": "3.7.0",
"@docusaurus/types": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"escape-string-regexp": "^4.0.0",
"file-loader": "^6.2.0",
"fs-extra": "^11.1.1",

View file

@ -1,7 +1,7 @@
{
"name": "@docusaurus/core",
"description": "Easy to Maintain Open Source Documentation Websites",
"version": "3.6.3",
"version": "3.7.0",
"license": "MIT",
"publishConfig": {
"access": "public"
@ -33,13 +33,13 @@
"url": "https://github.com/facebook/docusaurus/issues"
},
"dependencies": {
"@docusaurus/babel": "3.6.3",
"@docusaurus/bundler": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/mdx-loader": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/utils-validation": "3.6.3",
"@docusaurus/babel": "3.7.0",
"@docusaurus/bundler": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/mdx-loader": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"@docusaurus/utils-validation": "3.7.0",
"boxen": "^6.2.1",
"chalk": "^4.1.2",
"chokidar": "^3.5.3",
@ -77,8 +77,8 @@
"webpack-merge": "^6.0.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.6.3",
"@docusaurus/types": "3.6.3",
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/types": "3.7.0",
"@total-typescript/shoehorn": "^0.1.2",
"@types/detect-port": "^1.3.3",
"@types/react-dom": "^18.2.7",

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/eslint-plugin",
"version": "3.6.3",
"version": "3.7.0",
"description": "ESLint plugin to enforce best Docusaurus practices.",
"main": "lib/index.js",
"keywords": [

View file

@ -1,6 +1,6 @@
{
"name": "@docusaurus/lqip-loader",
"version": "3.6.3",
"version": "3.7.0",
"description": "Low Quality Image Placeholders (LQIP) loader for webpack.",
"main": "lib/index.js",
"publishConfig": {
@ -17,7 +17,7 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/logger": "3.6.3",
"@docusaurus/logger": "3.7.0",
"file-loader": "^6.2.0",
"lodash": "^4.17.21",
"sharp": "^0.32.3",

View file

@ -1,6 +1,6 @@
{
"name": "stylelint-copyright",
"version": "3.6.3",
"version": "3.7.0",
"description": "Stylelint plugin to check CSS files for a copyright header.",
"main": "lib/index.js",
"license": "MIT",

View file

@ -327,8 +327,8 @@ swizzlable
Tagkey
Teik
Therox
toplevel
thisweekinreact
toplevel
Transifex
transpiles
treeified

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

View file

@ -0,0 +1,107 @@
---
title: Docusaurus 3.7
authors: [slorber]
tags: [release]
image: ./img/social-card.png
date: 2025-01-03
---
We are happy to announce **Docusaurus 3.7**.
Docusaurus is now compatible with [React 19](https://react.dev/blog/2024/12/05/react-19).
Upgrading should be easy. Our [release process](/community/release-process) respects [Semantic Versioning](https://semver.org/). Minor versions do not include any breaking changes.
![Docusaurus blog post social card](./img/social-card.png)
{/* truncate */}
## Highlight
### React 19
In [#10763](https://github.com/facebook/docusaurus/pull/10763), we added support for [React 19](https://react.dev/blog/2024/12/05/react-19), and the Docusaurus website is running on React 19 already.
From now on, all newly initialized sites will run on React 19 by default, and React 19 will be the minimum required version Docusaurus v4.
However, React 18 remains supported, and existing Docusaurus sites can either choose to stay on React 18, or upgrade their dependencies to React 19:
```diff
{
"name": "my-docusaurus-site",
"dependencies": {
- "react": "^18.0.0",
- "react-dom": "^18.0.0"
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0"
}
}
```
:::warning
There's no urge to upgrade your site immediately.
React 19 is a bit heavier than React 18. Since we support both versions, we don't leverage yet the new features that are exclusive to React 19.
However, upgrading to React 19 prepares your site for Docusaurus v4, that will drop support for React 18.
Here are good reasons to upgrade your site before Docusaurus v4:
- You have custom React code and want to ensure it is ready for React19
- You plan to leverage the brand-new React 19 features in your own code
- You use custom or third-party plugins and want to ensure their compatibility
- You have a monorepo and want to align the React dependency to v19 for all packages
:::
Along the way, we [fixed](https://github.com/facebook/docusaurus/pull/10786) all the remaining hydration errors reported by React 19, some of them produced by our aggressive HTML minifier settings.
### SVGR plugin
Docusaurus has built-in support for [SVGR](https://github.com/gregberge/svgr), allowing you to seamlessly import and use SVG files as React components:
```tsx
import DocusaurusSvg from './docusaurus.svg';
<DocusaurusSvg />;
```
This built-in support has been the source of various bug reports due to the inability to customize the [SVGR Options](https://react-svgr.com/docs/options/), in particular the [SVG Optimizer](https://svgo.dev/) options.
In [#10677](https://github.com/facebook/docusaurus/pull/10677), we extracted a new [`@docusaurus/plugin-svgr`](/docs/api/plugins/@docusaurus/plugin-svgr) that you can now configure according to your needs. It is included by default in our classic preset:
```js
export default {
presets: [
[
'classic',
{
svgr: {
svgrConfig: {
// Your SVGR options ...
svgoConfig: {
// Your SVGO options ...
// Use "svgoConfig: undefined" to use a svgo.config.js file
},
},
},
},
],
],
};
```
## Other changes
Other notable changes include:
- [#10768](https://github.com/facebook/docusaurus/pull/10768): Blog authors have built-in icons for social platforms bluesky, mastodon, threads, twitch, youtube, instagram.
- [#10729](https://github.com/facebook/docusaurus/pull/10729): Blog now supports `frontMatter.sidebar_label`
- [#10803](https://github.com/facebook/docusaurus/pull/10803): `@docusaurus/remark-plugin-npm2yarn` now supports Bun conversions.
- [#10672](https://github.com/facebook/docusaurus/pull/10672): Upgrade Algolia DocSearch to `algoliasearch` v5.
- [#10800](https://github.com/facebook/docusaurus/pull/10800): Docusaurus Faster turns Rspack incremental mode on by default.
- [#10783](https://github.com/facebook/docusaurus/pull/10783): Improve Dutch theme translations.
- [#10760](https://github.com/facebook/docusaurus/pull/10760): Improve Korean theme translations.
Check the **[3.7.0 changelog entry](/changelog/3.7.0)** for an exhaustive list of changes.

View file

@ -1,6 +1,6 @@
{
"name": "website",
"version": "3.6.3",
"version": "3.7.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@ -38,20 +38,20 @@
"dependencies": {
"@crowdin/cli": "^3.13.0",
"@crowdin/crowdin-api-client": "^1.29.5",
"@docusaurus/core": "3.6.3",
"@docusaurus/logger": "3.6.3",
"@docusaurus/plugin-client-redirects": "3.6.3",
"@docusaurus/plugin-ideal-image": "3.6.3",
"@docusaurus/plugin-pwa": "3.6.3",
"@docusaurus/plugin-rsdoctor": "3.6.3",
"@docusaurus/preset-classic": "3.6.3",
"@docusaurus/remark-plugin-npm2yarn": "3.6.3",
"@docusaurus/theme-classic": "3.6.3",
"@docusaurus/theme-common": "3.6.3",
"@docusaurus/theme-live-codeblock": "3.6.3",
"@docusaurus/theme-mermaid": "3.6.3",
"@docusaurus/utils": "3.6.3",
"@docusaurus/utils-common": "3.6.3",
"@docusaurus/core": "3.7.0",
"@docusaurus/logger": "3.7.0",
"@docusaurus/plugin-client-redirects": "3.7.0",
"@docusaurus/plugin-ideal-image": "3.7.0",
"@docusaurus/plugin-pwa": "3.7.0",
"@docusaurus/plugin-rsdoctor": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@docusaurus/remark-plugin-npm2yarn": "3.7.0",
"@docusaurus/theme-classic": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@docusaurus/theme-live-codeblock": "3.7.0",
"@docusaurus/theme-mermaid": "3.7.0",
"@docusaurus/utils": "3.7.0",
"@docusaurus/utils-common": "3.7.0",
"clsx": "^2.0.0",
"color": "^4.2.3",
"fs-extra": "^11.1.1",
@ -82,8 +82,8 @@
]
},
"devDependencies": {
"@docusaurus/eslint-plugin": "3.6.3",
"@docusaurus/tsconfig": "3.6.3",
"@docusaurus/eslint-plugin": "3.7.0",
"@docusaurus/tsconfig": "3.7.0",
"@types/color": "^3.0.4",
"@types/jest": "^29.5.3",
"cross-env": "^7.0.3",

View file

@ -0,0 +1,28 @@
---
description: How Docusaurus works to build your app
---
# Architecture
```mdx-code-block
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Zoom from 'react-medium-image-zoom';
```
<Zoom>
![Architecture overview](/img/architecture.png)
</Zoom>
This diagram shows how Docusaurus works to build your app. Plugins each collect their content and emit JSON data; themes provide layout components which receive the JSON data as route modules. The bundler bundles all the components and emits a server bundle and a client bundle.
Although you (either plugin authors or site creators) are writing JavaScript all the time, bear in mind that the JS is actually run in different environments:
- All plugin lifecycle methods are run in Node. Therefore, until we support ES Modules in our codebase, plugin source code must be provided as ES modules that can be imported, or CommonJS that can be `require`'d.
- The theme code is built with Webpack. They can be provided as ESM—following React conventions.
Plugin code and theme code never directly import each other: they only communicate through protocols (in our case, through JSON temp files and calls to `addRoute`). A useful mental model is to imagine that the plugins are not written in JavaScript, but in another language like Rust. The only way to interact with plugins for the user is through `docusaurus.config.js`, which itself is run in Node (hence you can use `require` and pass callbacks as plugin options).
During bundling, the config file itself is serialized and bundled, allowing the theme to access config options like `themeConfig` or `baseUrl` through [`useDocusaurusContext()`](../docusaurus-core.mdx#useDocusaurusContext). However, the `siteConfig` object only contains **serializable values** (values that are preserved after `JSON.stringify()`). Functions, regexes, etc. would be lost on the client side. The `themeConfig` is designed to be entirely serializable.

View file

@ -0,0 +1,184 @@
---
description: How the Docusaurus client is structured
---
# Client architecture
## Theme aliases {#theme-aliases}
A theme works by exporting a set of components, e.g. `Navbar`, `Layout`, `Footer`, to render the data passed down from plugins. Docusaurus and users use these components by importing them using the `@theme` webpack alias:
```js
import Navbar from '@theme/Navbar';
```
The alias `@theme` can refer to a few directories, in the following priority:
1. A user's `website/src/theme` directory, which is a special directory that has the higher precedence.
2. A Docusaurus theme package's `theme` directory.
3. Fallback components provided by Docusaurus core (usually not needed).
This is called a _layered architecture_: a higher-priority layer providing the component would shadow a lower-priority layer, making swizzling possible. Given the following structure:
```
website
├── node_modules
│ └── @docusaurus/theme-classic
│ └── theme
│ └── Navbar.js
└── src
└── theme
└── Navbar.js
```
`website/src/theme/Navbar.js` takes precedence whenever `@theme/Navbar` is imported. This behavior is called component swizzling. If you are familiar with Objective C where a function's implementation can be swapped during runtime, it's the exact same concept here with changing the target `@theme/Navbar` is pointing to!
We already talked about how the "userland theme" in `src/theme` can re-use a theme component through the [`@theme-original`](../swizzling.mdx#wrapping) alias. One theme package can also wrap a component from another theme, by importing the component from the initial theme, using the `@theme-init` import.
Here's an example of using this feature to enhance the default theme `CodeBlock` component with a `react-live` playground feature.
```js
import InitialCodeBlock from '@theme-init/CodeBlock';
import React from 'react';
export default function CodeBlock(props) {
return props.live ? (
<ReactLivePlayground {...props} />
) : (
<InitialCodeBlock {...props} />
);
}
```
Check the code of `@docusaurus/theme-live-codeblock` for details.
:::warning
Unless you want to publish a re-usable "theme enhancer" (like `@docusaurus/theme-live-codeblock`), you likely don't need `@theme-init`.
:::
It can be quite hard to wrap your mind around these aliases. Let's imagine the following case with a super convoluted setup with three themes/plugins and the site itself all trying to define the same component. Internally, Docusaurus loads these themes as a "stack".
```text
+-------------------------------------------------+
| `website/src/theme/CodeBlock.js` | <-- `@theme/CodeBlock` always points to the top
+-------------------------------------------------+
| `theme-live-codeblock/theme/CodeBlock/index.js` | <-- `@theme-original/CodeBlock` points to the topmost non-swizzled component
+-------------------------------------------------+
| `plugin-awesome-codeblock/theme/CodeBlock.js` |
+-------------------------------------------------+
| `theme-classic/theme/CodeBlock/index.js` | <-- `@theme-init/CodeBlock` always points to the bottom
+-------------------------------------------------+
```
The components in this "stack" are pushed in the order of `preset plugins > preset themes > plugins > themes > site`, so the swizzled component in `website/src/theme` always comes out on top because it's loaded last.
`@theme/*` always points to the topmost component—when `CodeBlock` is swizzled, all other components requesting `@theme/CodeBlock` receive the swizzled version.
`@theme-original/*` always points to the topmost non-swizzled component. That's why you can import `@theme-original/CodeBlock` in the swizzled component—it points to the next one in the "component stack", a theme-provided one. Plugin authors should not try to use this because your component could be the topmost component and cause a self-import.
`@theme-init/*` always points to the bottommost component—usually, this comes from the theme or plugin that first provides this component. Individual plugins / themes trying to enhance code block can safely use `@theme-init/CodeBlock` to get its basic version. Site creators should generally not use this because you likely want to enhance the _topmost_ instead of the _bottommost_ component. It's also possible that the `@theme-init/CodeBlock` alias does not exist at all—Docusaurus only creates it when it points to a different one from `@theme-original/CodeBlock`, i.e. when it's provided by more than one theme. We don't waste aliases!
## Client modules {#client-modules}
Client modules are part of your site's bundle, just like theme components. However, they are usually side-effect-ful. Client modules are anything that can be `import`ed by Webpack—CSS, JS, etc. JS scripts usually work on the global context, like registering event listeners, creating global variables...
These modules are imported globally before React even renders the initial UI.
```js title="@docusaurus/core/App.tsx"
// How it works under the hood
import '@generated/client-modules';
```
Plugins and sites can both declare client modules, through [`getClientModules`](../api/plugin-methods/lifecycle-apis.mdx#getClientModules) and [`siteConfig.clientModules`](../api/docusaurus.config.js.mdx#clientModules), respectively.
Client modules are called during server-side rendering as well, so remember to check the [execution environment](./ssg.mdx#escape-hatches) before accessing client-side globals.
```js title="mySiteGlobalJs.js"
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
if (ExecutionEnvironment.canUseDOM) {
// As soon as the site loads in the browser, register a global event listener
window.addEventListener('keydown', (e) => {
if (e.code === 'Period') {
location.assign(location.href.replace('.com', '.dev'));
}
});
}
```
CSS stylesheets imported as client modules are [global](../styling-layout.mdx#global-styles).
```css title="mySiteGlobalCss.css"
/* This stylesheet is global. */
.globalSelector {
color: red;
}
```
### Client module lifecycles {#client-module-lifecycles}
Besides introducing side-effects, client modules can optionally export two lifecycle functions: `onRouteUpdate` and `onRouteDidUpdate`.
Because Docusaurus builds a single-page application, `script` tags will only be executed the first time the page loads, but will not re-execute on page transitions. These lifecycles are useful if you have some imperative JS logic that should execute every time a new page has loaded, e.g., to manipulate DOM elements, to send analytics data, etc.
For every route transition, there will be several important timings:
1. The user clicks a link, which causes the router to change its current location.
2. Docusaurus preloads the next route's assets, while keeping displaying the current page's content.
3. The next route's assets have loaded.
4. The new location's route component gets rendered to DOM.
`onRouteUpdate` will be called at event (2), and `onRouteDidUpdate` will be called at (4). They both receive the current location and the previous location (which can be `null`, if this is the first screen).
`onRouteUpdate` can optionally return a "cleanup" callback, which will be called at (3). For example, if you want to display a progress bar, you can start a timeout in `onRouteUpdate`, and clear the timeout in the callback. (The classic theme already provides an `nprogress` integration this way.)
Note that the new page's DOM is only available during event (4). If you need to manipulate the new page's DOM, you'll likely want to use `onRouteDidUpdate`, which will be fired as soon as the DOM on the new page has mounted.
```js title="myClientModule.js"
export function onRouteDidUpdate({location, previousLocation}) {
// Don't execute if we are still on the same page; the lifecycle may be fired
// because the hash changes (e.g. when navigating between headings)
if (location.pathname !== previousLocation?.pathname) {
const title = document.getElementsByTagName('h1')[0];
if (title) {
title.innerText += '❤️';
}
}
}
export function onRouteUpdate({location, previousLocation}) {
if (location.pathname !== previousLocation?.pathname) {
const progressBarTimeout = window.setTimeout(() => {
nprogress.start();
}, delay);
return () => window.clearTimeout(progressBarTimeout);
}
return undefined;
}
```
Or, if you are using TypeScript and you want to leverage contextual typing:
```ts title="myClientModule.ts"
import type {ClientModule} from '@docusaurus/types';
const module: ClientModule = {
onRouteUpdate({location, previousLocation}) {
// ...
},
onRouteDidUpdate({location, previousLocation}) {
// ...
},
};
export default module;
```
Both lifecycles will fire on first render, but they will not fire on server-side, so you can safely access browser globals in them.
:::tip Prefer using React
Client module lifecycles are purely imperative, and you can't use React hooks or access React contexts within them. If your operations are state-driven or involve complicated DOM manipulations, you should consider [swizzling components](../swizzling.mdx) instead.
:::

View file

@ -0,0 +1,11 @@
# Advanced Tutorials
This section is not going to be very structured, but we will cover the following topics:
```mdx-code-block
import DocCardList from '@theme/DocCardList';
<DocCardList />
```
We will assume that you have finished the guides, and know the basics like how to configure plugins, how to write React components, etc. These sections will have plugin authors and code contributors in mind, so we may occasionally refer to [plugin APIs](../api/plugin-methods/README.mdx) or other architecture details. Don't panic if you don't understand everything😉

View file

@ -0,0 +1,129 @@
# Plugins
Plugins are the building blocks of features in a Docusaurus site. Each plugin handles its own individual feature. Plugins may work and be distributed as part of a bundle via presets.
## Creating plugins {#creating-plugins}
A plugin is a function that takes two parameters: `context` and `options`. It returns a plugin instance object (or a promise). You can create plugins as functions or modules. For more information, refer to the [plugin method references section](../api/plugin-methods/README.mdx).
### Function definition {#function-definition}
You can use a plugin as a function directly included in the Docusaurus config file:
```js title="docusaurus.config.js"
export default {
// ...
plugins: [
// highlight-start
async function myPlugin(context, options) {
// ...
return {
name: 'my-plugin',
async loadContent() {
// ...
},
async contentLoaded({content, actions}) {
// ...
},
/* other lifecycle API */
};
},
// highlight-end
],
};
```
### Module definition {#module-definition}
You can use a plugin as a module path referencing a separate file or npm package:
```js title="docusaurus.config.js"
export default {
// ...
plugins: [
// without options:
'./my-plugin',
// or with options:
['./my-plugin', options],
],
};
```
Then in the folder `my-plugin`, you can create an `index.js` such as this:
```js title="my-plugin/index.js"
export default async function myPlugin(context, options) {
// ...
return {
name: 'my-plugin',
async loadContent() {
/* ... */
},
async contentLoaded({content, actions}) {
/* ... */
},
/* other lifecycle API */
};
}
```
---
You can view all plugins installed in your site using the [debug plugin's metadata panel](/__docusaurus/debug/metadata).
Plugins come as several types:
- `package`: an external package you installed
- `project`: a plugin you created in your project, given to Docusaurus as a local file path
- `local`: a plugin created using the function definition
- `synthetic`: a "fake plugin" Docusaurus created internally, so we take advantage of our modular architecture and don't let the core do much special work. You won't see this in the metadata because it's an implementation detail.
You can access them on the client side with `useDocusaurusContext().siteMetadata.pluginVersions`.
## Plugin design {#plugin-design}
Docusaurus' implementation of the plugins system provides us with a convenient way to hook into the website's lifecycle to modify what goes on during development/build, which involves (but is not limited to) extending the webpack config, modifying the data loaded, and creating new components to be used in a page.
### Theme design {#theme-design}
When plugins have loaded their content, the data is made available to the client side through actions like [`createData` + `addRoute`](../api/plugin-methods/lifecycle-apis.mdx#addRoute) or [`setGlobalData`](../api/plugin-methods/lifecycle-apis.mdx#setGlobalData). This data has to be _serialized_ to plain strings, because [plugins and themes run in different environments](./architecture.mdx). Once the data arrives on the client side, the rest becomes familiar to React developers: data is passed along components, components are bundled with Webpack, and rendered to the window through `ReactDOM.render`...
**Themes provide the set of UI components to render 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, which makes swapping designs easy.
For example, a Docusaurus blog may consist of a blog plugin and a blog theme.
:::note
This is a contrived example: in practice, `@docusaurus/theme-classic` provides the theme for docs, blog, and layouts.
:::
```js title="docusaurus.config.js"
export default {
// highlight-next-line
themes: ['theme-blog'],
plugins: ['plugin-content-blog'],
};
```
And if you want to use Bootstrap styling, you can swap out the theme with `theme-blog-bootstrap` (another fictitious non-existing theme):
```js title="docusaurus.config.js"
export default {
// highlight-next-line
themes: ['theme-blog-bootstrap'],
plugins: ['plugin-content-blog'],
};
```
Now, although the theme receives the same data from the plugin, how the theme chooses to _render_ the data as UI can be drastically different.
While themes share the exact same lifecycle methods with plugins, themes' implementations can look very different from those of plugins based on themes' designed objectives.
Themes are designed to complete the build of your Docusaurus site and supply the components used by your site, plugins, and the themes themselves. A theme still acts like a plugin and exposes some lifecycle methods, but most likely they would not use [`loadContent`](../api/plugin-methods/lifecycle-apis.mdx#loadContent), since they only receive data from plugins, but don't generate data themselves; themes are typically also accompanied by an `src/theme` directory full of components, which are made known to the core through the [`getThemePath`](../api/plugin-methods/extend-infrastructure.mdx#getThemePath) lifecycle.
To summarize:
- Themes share the same lifecycle methods with Plugins
- Themes are run after all existing Plugins
- Themes add component aliases by providing `getThemePath`.

View file

@ -0,0 +1,289 @@
---
description: "Docusaurus' routing system follows single-page application conventions: one route, one component."
---
# Routing
```mdx-code-block
import Link from '@docusaurus/Link';
import {useLatestVersion, useActiveDocContext} from '@docusaurus/plugin-content-docs/client';
import {useLocation} from '@docusaurus/router';
import BrowserWindow from '@site/src/components/BrowserWindow';
```
Docusaurus' routing system follows single-page application conventions: one route, one component. In this section, we will begin by talking about routing within the three content plugins (docs, blog, and pages), and then go beyond to talk about the underlying routing system.
## Routing in content plugins {#routing-in-content-plugins}
Every content plugin provides a `routeBasePath` option. It defines where the plugins append their routes to. By default, the docs plugin puts its routes under `/docs`; the blog plugin, `/blog`; and the pages plugin, `/`. You can think about the route structure like this:
```mermaid
graph LR;
A(["https://example.com/"])
B(["/base-url/"])
C(["/docs/"])
D(["/blog/"])
E(["/"])
F["All docs <br/>routes"]
G["All blog <br/>routes"]
H["All pages <br/>routes"]
A---B;
B---C;
B---D;
B---E;
C---F;
D---G;
E---H;
```
Any route will be matched against this nested route config until a good match is found. For example, when given a route `/docs/configuration`, Docusaurus first enters the `/docs` branch, and then searches among the subroutes created by the docs plugin.
Changing `routeBasePath` can effectively alter your site's route structure. For example, in [Docs-only mode](../guides/docs/docs-introduction.mdx#docs-only-mode), we mentioned that configuring `routeBasePath: '/'` for docs means that all routes that the docs plugin create would not have the `/docs` prefix, yet it doesn't prevent you from having more subroutes like `/blog` created by other plugins.
Next, let's look at how the three plugins structure their own "boxes of subroutes".
### Pages routing {#pages-routing}
Pages routing are straightforward: the file paths directly map to URLs, without any other way to customize. See the [pages docs](../guides/creating-pages.mdx#routing) for more information.
The component used for Markdown pages is `@theme/MDXPage`. React pages are directly used as the route's component.
### Blog routing {#blog-routing}
The blog creates the following routes:
- **Posts list pages**: `/`, `/page/2`, `/page/3`...
- The route is customizable through the `pageBasePath` option.
- The component is `@theme/BlogListPage`.
- **Post pages**: `/2021/11/21/algolia-docsearch-migration`, `/2021/05/12/announcing-docusaurus-two-beta`...
- Generated from each Markdown post.
- The routes are fully customizable through the `slug` front matter.
- The component is `@theme/BlogPostPage`.
- **Tags list page**: `/tags`
- The route is customizable through the `tagsBasePath` option.
- The component is `@theme/BlogTagsListPage`.
- **Tag pages**: `/tags/adoption`, `/tags/beta`...
- Generated through the tags defined in each post's front matter.
- The routes always have base defined in `tagsBasePath`, but the subroutes are customizable through the tag's `permalink` field.
- The component is `@theme/BlogTagsPostsPage`.
- **Archive page**: `/archive`
- The route is customizable through the `archiveBasePath` option.
- The component is `@theme/BlogArchivePage`.
### Docs routing {#docs-routing}
The docs is the only plugin that creates **nested routes**. At the top, it registers [**version paths**](../guides/docs/versioning.mdx): `/`, `/next`, `/2.0.0-beta.13`... which provide the version context, including the layout and sidebar. This ensures that when switching between individual docs, the sidebar's state is preserved, and that you can switch between versions through the navbar dropdown while staying on the same doc. The component used is `@theme/DocPage`.
```mdx-code-block
export const URLPath = () => <code>{useLocation().pathname}</code>;
export const FilePath = () => {
const currentVersion = useActiveDocContext('default').activeVersion.name;
return <code>{currentVersion === 'current' ? './docs/' : `./versioned_docs/version-${currentVersion}/`}advanced/routing.md</code>;
}
```
The individual docs are rendered in the remaining space after the navbar, footer, sidebar, etc. have all been provided by the `DocPage` component. For example, this page, <URLPath />, is generated from the file at <FilePath />. The component used is `@theme/DocItem`.
The doc's `slug` front matter customizes the last part of the route, but the base route is always defined by the plugin's `routeBasePath` and the version's `path`.
### File paths and URL paths {#file-paths-and-url-paths}
Throughout the documentation, we always try to be unambiguous about whether we are talking about file paths or URL paths. Content plugins usually map file paths directly to URL paths, for example, `./docs/advanced/routing.md` will become `/docs/advanced/routing`. However, with `slug`, you can make URLs totally decoupled from the file structure.
When writing links in Markdown, you could either mean a _file path_, or a _URL path_, which Docusaurus would use several heuristics to determine.
- If the path has a `@site` prefix, it is _always_ an asset file path.
- If the path has an `http(s)://` prefix, it is _always_ a URL path.
- If the path doesn't have an extension, it is a URL path. For example, a link `[page](../plugins)` on a page with URL `/docs/advanced/routing` will link to `/docs/plugins`. Docusaurus will only detect broken links when building your site (when it knows the full route structure), but will make no assumptions about the existence of a file. It is exactly equivalent to writing `<a href="../plugins">page</a>` in a JSX file.
- If the path has an `.md(x)` extension, Docusaurus would try to resolve that Markdown file to a URL, and replace the file path with a URL path.
- If the path has any other extension, Docusaurus would treat it as [an asset](../guides/markdown-features/markdown-features-assets.mdx) and bundle it.
The following directory structure may help you visualize this file → URL mapping. Assume that there's no slug customization in any page.
<details>
<summary>A sample site structure</summary>
```bash
.
├── blog # blog plugin has routeBasePath: '/blog'
│ ├── 2019-05-28-first-blog-post.md # -> /blog/2019/05/28/first-blog-post
│ ├── 2019-05-29-long-blog-post.md # -> /blog/2019/05/29/long-blog-post
│ ├── 2021-08-01-mdx-blog-post.mdx # -> /blog/2021/08/01/mdx-blog-post
│ └── 2021-08-26-welcome
│ ├── docusaurus-plushie-banner.jpeg
│ └── index.md # -> /blog/2021/08/26/welcome
├── docs # docs plugin has routeBasePath: '/docs'; current version has base path '/'
│ ├── intro.md # -> /docs/intro
│ ├── tutorial-basics
│ │ ├── _category_.json
│ │ ├── congratulations.md # -> /docs/tutorial-basics/congratulations
│ │ └── markdown-features.mdx # -> /docs/tutorial-basics/markdown-features
│ └── tutorial-extras
│ ├── _category_.json
│ ├── manage-docs-versions.md # -> /docs/tutorial-extras/manage-docs-versions
│ └── translate-your-site.md # -> /docs/tutorial-extras/translate-your-site
├── src
│ └── pages # pages plugin has routeBasePath: '/'
│ ├── index.module.css
│ ├── index.tsx # -> /
│ └── markdown-page.md # -> /markdown-page
└── versioned_docs
└── version-1.0.0 # version has base path '/1.0.0'
├── intro.md # -> /docs/1.0.0/intro
├── tutorial-basics
│ ├── _category_.json
│ ├── congratulations.md # -> /docs/1.0.0/tutorial-basics/congratulations
│ └── markdown-features.mdx # -> /docs/1.0.0/tutorial-basics/markdown-features
└── tutorial-extras
├── _category_.json
├── manage-docs-versions.md # -> /docs/1.0.0/tutorial-extras/manage-docs-versions
└── translate-your-site.md # -> /docs/1.0.0/tutorial-extras/translate-your-site
```
</details>
So much about content plugins. Let's take one step back and talk about how routing works in a Docusaurus app in general.
## Routes become HTML files {#routes-become-html-files}
Because Docusaurus is a server-side rendering framework, all routes generated will be server-side rendered into static HTML files. If you are familiar with the behavior of HTTP servers like [Apache2](https://httpd.apache.org/docs/trunk/getting-started.html), you will understand how this is done: when the browser sends a request to the route `/docs/advanced/routing`, the server interprets that as request for the HTML file `/docs/advanced/routing/index.html`, and returns that.
The `/docs/advanced/routing` route can correspond to either `/docs/advanced/routing/index.html` or `/docs/advanced/routing.html`. Some hosting providers differentiate between them using the presence of a trailing slash, and may or may not tolerate the other. Read more in the [trailing slash guide](https://github.com/slorber/trailing-slash-guide).
For example, the build output of the directory above is (ignoring other assets and JS bundle):
<details>
<summary>Output of the above workspace</summary>
```bash
build
├── 404.html # /404/
├── blog
│ ├── archive
│ │ └── index.html # /blog/archive/
│ ├── first-blog-post
│ │ └── index.html # /blog/first-blog-post/
│ ├── index.html # /blog/
│ ├── long-blog-post
│ │ └── index.html # /blog/long-blog-post/
│ ├── mdx-blog-post
│ │ └── index.html # /blog/mdx-blog-post/
│ ├── tags
│ │ ├── docusaurus
│ │ │ └── index.html # /blog/tags/docusaurus/
│ │ ├── hola
│ │ │ └── index.html # /blog/tags/hola/
│ │ └── index.html # /blog/tags/
│ └── welcome
│ └── index.html # /blog/welcome/
├── docs
│ ├── 1.0.0
│ │ ├── intro
│ │ │ └── index.html # /docs/1.0.0/intro/
│ │ ├── tutorial-basics
│ │ │ ├── congratulations
│ │ │ │ └── index.html # /docs/1.0.0/tutorial-basics/congratulations/
│ │ │ └── markdown-features
│ │ │ └── index.html # /docs/1.0.0/tutorial-basics/markdown-features/
│ │ └── tutorial-extras
│ │ ├── manage-docs-versions
│ │ │ └── index.html # /docs/1.0.0/tutorial-extras/manage-docs-versions/
│ │ └── translate-your-site
│ │ └── index.html # /docs/1.0.0/tutorial-extras/translate-your-site/
│ ├── intro
│ │ └── index.html # /docs/1.0.0/intro/
│ ├── tutorial-basics
│ │ ├── congratulations
│ │ │ └── index.html # /docs/tutorial-basics/congratulations/
│ │ └── markdown-features
│ │ └── index.html # /docs/tutorial-basics/markdown-features/
│ └── tutorial-extras
│ ├── manage-docs-versions
│ │ └── index.html # /docs/tutorial-extras/manage-docs-versions/
│ └── translate-your-site
│ └── index.html # /docs/tutorial-extras/translate-your-site/
├── index.html # /
└── markdown-page
└── index.html # /markdown-page/
```
</details>
If `trailingSlash` is set to `false`, the build would emit `intro.html` instead of `intro/index.html`.
All HTML files will reference its JS assets using absolute URLs, so in order for the correct assets to be located, you have to configure the `baseUrl` field. Note that `baseUrl` doesn't affect the emitted bundle's file structure: the base URL is one level above the Docusaurus routing system. You can see the aggregate of `url` and `baseUrl` as the actual location of your Docusaurus site.
For example, the emitted HTML would contain links like `<link rel="preload" href="/assets/js/runtime~main.7ed5108a.js" as="script">`. Because absolute URLs are resolved from the host, if the bundle placed under the path `https://example.com/base/`, the link will point to `https://example.com/assets/js/runtime~main.7ed5108a.js`, which is, well, non-existent. By specifying `/base/` as base URL, the link will correctly point to `/base/assets/js/runtime~main.7ed5108a.js`.
Localized sites have the locale as part of the base URL as well. For example, `https://docusaurus.io/zh-CN/docs/advanced/routing/` has base URL `/zh-CN/`.
## Generating and accessing routes {#generating-and-accessing-routes}
The `addRoute` lifecycle action is used to generate routes. It registers a piece of route config to the route tree, giving a route, a component, and props that the component needs. The props and the component are both provided as paths for the bundler to `require`, because as explained in the [architecture overview](architecture.mdx), server and client only communicate through temp files.
All routes are aggregated in `.docusaurus/routes.js`, which you can view with the debug plugin's [routes panel](/__docusaurus/debug/routes).
On the client side, we offer `@docusaurus/router` to access the page's route. `@docusaurus/router` is a re-export of the [`react-router-dom`](https://www.npmjs.com/package/react-router-dom/v/5.3.0) package. For example, you can use `useLocation` to get the current page's [location](https://developer.mozilla.org/en-US/docs/Web/API/Location), and `useHistory` to access the [history object](https://developer.mozilla.org/en-US/docs/Web/API/History). (They are not the same as the browser API, although similar in functionality. Refer to the React Router documentation for specific APIs.)
This API is **SSR safe**, as opposed to the browser-only `window.location`.
```jsx title="myComponent.js"
import React from 'react';
import {useLocation} from '@docusaurus/router';
export function PageRoute() {
// React router provides the current component's route, even in SSR
const location = useLocation();
return (
<span>
We are currently on <code>{location.pathname}</code>
</span>
);
}
```
```mdx-code-block
export function PageRoute() {
const location = useLocation();
return (
<span>
We are currently on <code>{location.pathname}</code>
</span>
);
}
<BrowserWindow>
<PageRoute />
</BrowserWindow>
```
## Escaping from SPA redirects {#escaping-from-spa-redirects}
Docusaurus builds a [single-page application](https://developer.mozilla.org/en-US/docs/Glossary/SPA), where route transitions are done through the `history.push()` method of React router. This operation is done on the client side. However, the prerequisite for a route transition to happen this way is that the target URL is known to our router. Otherwise, the router catches this path and displays a 404 page instead.
If you put some HTML pages under the `static` folder, they will be copied to the build output and therefore become accessible as part of your website, yet it's not part of the Docusaurus route system. We provide a `pathname://` protocol that allows you to redirect to another part of your domain in a non-SPA fashion, as if this route is an external link.
```md
- [pathname:///pure-html](pathname:///pure-html)
```
<BrowserWindow>
- [`pathname:///pure-html`](pathname:///pure-html)
</BrowserWindow>
The `pathname://` protocol is useful for referencing any content in the static folder. For example, Docusaurus would convert [all Markdown static assets to require() calls](../guides/markdown-features/markdown-features-assets.mdx#static-assets). You can use `pathname://` to keep it a regular link instead of being hashed by Webpack.
```md title="my-doc.md"
![An image from the static](pathname:///img/docusaurus.png)
[An asset from the static](pathname:///files/asset.pdf)
```
Docusaurus will only strip the `pathname://` prefix without processing the content.

View file

@ -0,0 +1,218 @@
---
sidebar_label: Static site generation
description: Docusaurus statically renders your React code into HTML, allowing faster load speed and better SEO.
---
# Static site generation (SSG)
In [architecture](architecture.mdx), we mentioned that the theme is run in Webpack. But beware: that doesn't mean it always has access to browser globals! The theme is built twice:
- During **server-side rendering**, the theme is compiled in a sandbox called [React DOM Server](https://reactjs.org/docs/react-dom-server.html). You can see this as a "headless browser", where there is no `window` or `document`, only React. SSR produces static HTML pages.
- During **client-side rendering**, the theme is compiled to JavaScript that gets eventually executed in the browser, so it has access to browser variables.
:::info SSR or SSG?
_Server-side rendering_ and _static site generation_ can be different concepts, but we use them interchangeably.
Strictly speaking, Docusaurus is a static site generator, because there's no server-side runtime—we statically render to HTML files that are deployed on a CDN, instead of dynamically pre-rendering on each request. This differs from the working model of [Next.js](https://nextjs.org/).
:::
Therefore, while you probably know not to access Node globals like `process` ([or can we?](#node-env)) or the `'fs'` module, you can't freely access browser globals either.
```jsx
import React from 'react';
export default function WhereAmI() {
return <span>{window.location.href}</span>;
}
```
This looks like idiomatic React, but if you run `docusaurus build`, you will get an error:
```
ReferenceError: window is not defined
```
This is because during server-side rendering, the Docusaurus app isn't actually run in browser, and it doesn't know what `window` is.
```mdx-code-block
<details id="node-env">
<summary>What about <code>process.env.NODE_ENV</code>?</summary>
```
One exception to the "no Node globals" rule is `process.env.NODE_ENV`. In fact, you can use it in React, because Webpack injects this variable as a global:
```jsx
import React from 'react';
export default function expensiveComp() {
if (process.env.NODE_ENV === 'development') {
return <>This component is not shown in development</>;
}
const res = someExpensiveOperationThatLastsALongTime();
return <>{res}</>;
}
```
During Webpack build, the `process.env.NODE_ENV` will be replaced with the value, either `'development'` or `'production'`. You will then get different build results after dead code elimination:
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
```mdx-code-block
<Tabs>
<TabItem value="Development">
```
```diff
import React from 'react';
export default function expensiveComp() {
// highlight-next-line
if ('development' === 'development') {
+ return <>This component is not shown in development</>;
}
- const res = someExpensiveOperationThatLastsALongTime();
- return <>{res}</>;
}
```
```mdx-code-block
</TabItem>
<TabItem value="Production">
```
```diff
import React from 'react';
export default function expensiveComp() {
// highlight-next-line
- if ('production' === 'development') {
- return <>This component is not shown in development</>;
- }
+ const res = someExpensiveOperationThatLastsALongTime();
+ return <>{res}</>;
}
```
```mdx-code-block
</TabItem>
</Tabs>
</details>
```
## Understanding SSR {#understanding-ssr}
React is not just a dynamic UI runtime—it's also a templating engine. Because Docusaurus sites mostly contain static contents, it should be able to work without any JavaScript (which React runs in), but only plain HTML/CSS. And that's what server-side rendering offers: statically rendering your React code into HTML, without any dynamic content. An HTML file has no concept of client state (it's purely markup), hence it shouldn't rely on browser APIs.
These HTML files are the first to arrive at the user's browser screen when a URL is visited (see [routing](routing.mdx)). Afterwards, the browser fetches and runs other JS code to provide the "dynamic" parts of your site—anything implemented with JavaScript. However, before that, the main content of your page is already visible, allowing faster loading.
In CSR-only apps, all DOM elements are generated on client side with React, and the HTML file only ever contains one root element for React to mount DOM to; in SSR, React is already facing a fully built HTML page, and it only needs to correlate the DOM elements with the virtual DOM in its model. This step is called "hydration". After React has hydrated the static markup, the app starts to work as any normal React app.
Note that Docusaurus is ultimately a single-page application, so static site generation is only an optimization (_progressive enhancement_, as it's called), but our functionality does not fully depend on those HTML files. This is contrary to site generators like [Jekyll](https://jekyllrb.com/) and [Docusaurus v1](https://v1.docusaurus.io/), where all files are statically transformed to markup, and interactiveness is added through external JavaScript linked with `<script>` tags. If you inspect the build output, you will still see JS assets under `build/assets/js`, which are, really, the core of Docusaurus.
## Escape hatches {#escape-hatches}
If you want to render any dynamic content on your screen that relies on the browser API to be functional at all, for example:
- Our [live codeblock](../guides/markdown-features/markdown-features-code-blocks.mdx#interactive-code-editor), which runs in the browser's JS runtime
- Our [themed image](../guides/markdown-features/markdown-features-assets.mdx#themed-images) that detects the user's color scheme to display different images
- The JSON viewer of our debug panel which uses the `window` global for styling
You may need to escape from SSR since static HTML can't display anything useful without knowing the client state.
:::warning
It is important for the first client-side render to produce the exact same DOM structure as server-side rendering, otherwise, React will correlate virtual DOM with the wrong DOM elements.
Therefore, the naïve attempt of `if (typeof window !== 'undefined) {/* render something */}` won't work appropriately as a browser vs. server detection, because the first client render would instantly render different markup from the server-generated one.
You can read more about this pitfall in [The Perils of Rehydration](https://www.joshwcomeau.com/react/the-perils-of-rehydration/).
:::
We provide several more reliable ways to escape SSR.
### `<BrowserOnly>` {#browseronly}
If you need to render some component in browser only (for example, because the component relies on browser specifics to be functional at all), one common approach is to wrap your component with [`<BrowserOnly>`](../docusaurus-core.mdx#browseronly) to make sure it's invisible during SSR and only rendered in CSR.
```jsx
import BrowserOnly from '@docusaurus/BrowserOnly';
function MyComponent(props) {
return (
// highlight-start
<BrowserOnly fallback={<div>Loading...</div>}>
{() => {
const LibComponent =
require('some-lib-that-accesses-window').LibComponent;
return <LibComponent {...props} />;
}}
</BrowserOnly>
// highlight-end
);
}
```
It's important to realize that the children of `<BrowserOnly>` is not a JSX element, but a function that _returns_ an element. This is a design decision. Consider this code:
```jsx
import BrowserOnly from '@docusaurus/BrowserOnly';
function MyComponent() {
return (
<BrowserOnly>
{/* highlight-start */}
{/* DON'T DO THIS - doesn't actually work */}
<span>page url = {window.location.href}</span>
{/* highlight-end */}
</BrowserOnly>
);
}
```
While you may expect that `BrowserOnly` hides away the children during server-side rendering, it actually can't. When the React renderer tries to render this JSX tree, it does see the `{window.location.href}` variable as a node of this tree and tries to render it, although it's actually not used! Using a function ensures that we only let the renderer see the browser-only component when it's needed.
### `useIsBrowser` {#useisbrowser}
You can also use the `useIsBrowser()` hook to test if the component is currently in a browser environment. It returns `false` in SSR and `true` is CSR, after first client render. Use this hook if you only need to perform certain conditional operations on client-side, but not render an entirely different UI.
```jsx
import useIsBrowser from '@docusaurus/useIsBrowser';
function MyComponent() {
const isBrowser = useIsBrowser();
const location = isBrowser ? window.location.href : 'fetching location...';
return <span>{location}</span>;
}
```
### `useEffect` {#useeffect}
Lastly, you can put your logic in `useEffect()` to delay its execution until after first CSR. This is most appropriate if you are only performing side-effects but don't _get_ data from the client state.
```jsx
function MyComponent() {
useEffect(() => {
// Only logged in the browser console; nothing is logged during server-side rendering
console.log("I'm now in the browser");
}, []);
return <span>Some content...</span>;
}
```
### `ExecutionEnvironment` {#executionenvironment}
The [`ExecutionEnvironment`](../docusaurus-core.mdx#executionenvironment) namespace contains several values, and `canUseDOM` is an effective way to detect browser environment.
Beware that it essentially checked `typeof window !== 'undefined'` under the hood, so you should not use it for rendering-related logic, but only imperative code, like reacting to user input by sending web requests, or dynamically importing libraries, where DOM isn't updated at all.
```js title="a-client-module.js"
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
if (ExecutionEnvironment.canUseDOM) {
document.title = "I'm loaded!";
}
```

View file

@ -0,0 +1,758 @@
---
sidebar_position: 0
description: API reference for Docusaurus configuration file.
slug: /api/docusaurus-config
---
# `docusaurus.config.js`
import APITable from '@site/src/components/APITable';
:::info
Refer to the Getting Started [**Configuration**](../configuration.mdx) for examples.
:::
## Overview {#overview}
`docusaurus.config.js` contains configurations for your site and is placed in the root directory of your site.
:::note
With a [TypeScript](../typescript-support.mdx) Docusaurus codebase your config file may be called `docusaurus.config.ts`. The syntax is broadly identical to the `js` config file with the addition of types. You can see an example on the [Docusaurus Website](https://github.com/facebook/docusaurus/blob/main/website/docusaurus.config.ts) itself.
:::
This file is **run in Node.js** and should export a site configuration object, or a function that creates it.
The `docusaurus.config.js` file supports:
- [**ES Modules**](https://flaviocopes.com/es-modules/)
- [**CommonJS**](https://flaviocopes.com/commonjs/)
- [**TypeScript**](../typescript-support.mdx#typing-config)
Examples:
```js title="docusaurus.config.js"
export default {
title: 'Docusaurus',
url: 'https://docusaurus.io',
// your site config ...
};
```
```js title="docusaurus.config.js"
export default async function createConfigAsync() {
return {
title: 'Docusaurus',
url: 'https://docusaurus.io',
// your site config ...
};
}
```
:::tip
Refer to [**Syntax to declare `docusaurus.config.js`**](../configuration.mdx#syntax-to-declare-docusaurus-config) for a more exhaustive list of examples and explanations.
:::
## Required fields {#required-fields}
### `title` {#title}
- Type: `string`
Title for your website. Will be used in metadata and as browser tab title.
```js title="docusaurus.config.js"
export default {
title: 'Docusaurus',
};
```
### `url` {#url}
- Type: `string`
URL for your website. This can also be considered the top-level hostname. For example, `https://facebook.github.io` is the URL of https://facebook.github.io/metro/, and `https://docusaurus.io` is the URL for https://docusaurus.io. This field is related to the [`baseUrl`](#baseUrl) field.
```js title="docusaurus.config.js"
export default {
url: 'https://docusaurus.io',
};
```
### `baseUrl` {#baseUrl}
- Type: `string`
Base URL for your site. Can be considered as the path after the host. For example, `/metro/` is the base URL of https://facebook.github.io/metro/. For URLs that have no path, the baseUrl should be set to `/`. This field is related to the [`url`](#url) field. Always has both leading and trailing slash.
```js title="docusaurus.config.js"
export default {
baseUrl: '/',
};
```
## Optional fields {#optional-fields}
### `favicon` {#favicon}
- Type: `string | undefined`
Path to your site favicon; must be a URL that can be used in link's href. For example, if your favicon is in `static/img/favicon.ico`:
```js title="docusaurus.config.js"
export default {
favicon: '/img/favicon.ico',
};
```
### `trailingSlash` {#trailingSlash}
- Type: `boolean | undefined`
Allow to customize the presence/absence of a trailing slash at the end of URLs/links, and how static HTML files are generated:
- `undefined` (default): keeps URLs untouched, and emit `/docs/myDoc/index.html` for `/docs/myDoc.md`
- `true`: add trailing slashes to URLs/links, and emit `/docs/myDoc/index.html` for `/docs/myDoc.md`
- `false`: remove trailing slashes from URLs/links, and emit `/docs/myDoc.html` for `/docs/myDoc.md`
:::tip
Each static hosting provider serves static files differently (this behavior may even change over time).
Refer to the [deployment guide](../deployment.mdx) and [slorber/trailing-slash-guide](https://github.com/slorber/trailing-slash-guide) to choose the appropriate setting.
:::
### `i18n` {#i18n}
- Type: `Object`
The i18n configuration object to [localize your site](../i18n/i18n-introduction.mdx).
Example:
{/* cSpell:ignore فارسی */}
```js title="docusaurus.config.js"
export default {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fa'],
path: 'i18n',
localeConfigs: {
en: {
label: 'English',
direction: 'ltr',
htmlLang: 'en-US',
calendar: 'gregory',
path: 'en',
},
fa: {
label: 'فارسی',
direction: 'rtl',
htmlLang: 'fa-IR',
calendar: 'persian',
path: 'fa',
},
},
},
};
```
- `defaultLocale`: The locale that (1) does not have its name in the base URL (2) gets started with `docusaurus start` without `--locale` option (3) will be used for the `<link hrefLang="x-default">` tag
- `locales`: List of locales deployed on your site. Must contain `defaultLocale`.
- `path`: Root folder which all locale folders are relative to. Can be absolute or relative to the config file. Defaults to `i18n`.
- `localeConfigs`: Individual options for each locale.
- `label`: The label displayed for this locale in the locales dropdown.
- `direction`: `ltr` (default) or `rtl` (for [right-to-left languages](https://developer.mozilla.org/en-US/docs/Glossary/rtl) like Farsi, Arabic, Hebrew, etc.). Used to select the locale's CSS and HTML meta attribute.
- `htmlLang`: BCP 47 language tag to use in `<html lang="...">` (or any other DOM tag name) and in `<link ... hreflang="...">`
- `calendar`: the [calendar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar) used to calculate the date era. Note that it doesn't control the actual string displayed: `MM/DD/YYYY` and `DD/MM/YYYY` are both `gregory`. To choose the format (`DD/MM/YYYY` or `MM/DD/YYYY`), set your locale name to `en-GB` or `en-US` (`en` means `en-US`).
- `path`: Root folder that all plugin localization folders of this locale are relative to. Will be resolved against `i18n.path`. Defaults to the locale's name. Note: this has no effect on the locale's `baseUrl`—customization of base URL is a work-in-progress.
### `future` {#future}
- Type: `Object`
The `future` configuration object permits to opt-in for upcoming/unstable/experimental Docusaurus features that are not ready for prime time.
It is also a way to opt-in for upcoming breaking changes coming in the next major versions, enabling you to prepare your site for the next version while staying on the previous one. The [Remix Future Flags blog post](https://remix.run/blog/future-flags) greatly explains this idea.
:::danger Breaking changes in minor versions
Features prefixed by `experimental_` or `unstable_` are subject to changes in **minor versions**, and not considered as [Semantic Versioning breaking changes](/community/release-process).
Features prefixed by `v<MajorVersion>_` (`v6_` `v7_`, etc.) are future flags that are expected to be turned on by default in the next major versions. These are less likely to change, but we keep the possibility to do so.
`future` API breaking changes should be easy to handle, and will be documented in minor/major version blog posts.
:::
Example:
```js title="docusaurus.config.js"
export default {
future: {
experimental_faster: {
swcJsLoader: true,
swcJsMinimizer: true,
swcHtmlMinimizer: true,
lightningCssMinimizer: true,
rspackBundler: true,
mdxCrossCompilerCache: true,
},
experimental_storage: {
type: 'localStorage',
namespace: true,
},
experimental_router: 'hash',
},
};
```
- `experimental_faster`: An object containing feature flags to make the Docusaurus build faster. This requires adding the `@docusaurus/faster` package to your site's dependencies. Use `true` as a shorthand to enable all flags. Read more on the [Docusaurus Faster](https://github.com/facebook/docusaurus/issues/10556) issue. Available feature flags:
- [`swcJsLoader`](https://github.com/facebook/docusaurus/pull/10435): Use [SWC](https://swc.rs/) to transpile JS (instead of [Babel](https://babeljs.io/)).
- [`swcJsMinimizer`](https://github.com/facebook/docusaurus/pull/10441): Use [SWC](https://swc.rs/) to minify JS (instead of [Terser](https://github.com/terser/terser)).
- [`swcHtmlMinimizer `](https://github.com/facebook/docusaurus/pull/10554): Use [SWC](https://swc.rs/) to minify HTML and inlined JS/CSS (instead of [html-minifier-terser](https://github.com/terser/html-minifier-terser)).
- [`lightningCssMinimizer`](https://github.com/facebook/docusaurus/pull/10522): Use [Lightning CSS](https://lightningcss.dev/) to minify CSS (instead of [cssnano](https://github.com/cssnano/cssnano) and [clean-css](https://github.com/clean-css/clean-css)).
- [`rspackBundler`](https://github.com/facebook/docusaurus/pull/10402): Use [Rspack](https://rspack.dev/) to bundle your app (instead of [webpack](https://webpack.js.org/)).
- [`mdxCrossCompilerCache`](https://github.com/facebook/docusaurus/pull/10479): Compile MDX files only once for both browser/Node.js environments instead of twice.
- `experimental_storage`: Site-wide browser storage options that theme authors should strive to respect.
- `type`: The browser storage theme authors should use. Possible values are `localStorage` and `sessionStorage`. Defaults to `localStorage`.
- `namespace`: Whether to namespace the browser storage keys to avoid storage key conflicts when Docusaurus sites are hosted under the same domain, or on localhost. Possible values are `string | boolean`. The namespace is appended at the end of the storage keys `key-namespace`. Use `true` to automatically generate a random namespace from your site `url + baseUrl`. Defaults to `false` (no namespace, historical behavior).
- `experimental_router`: The router type to use. Possible values are `browser` and `hash`. Defaults to `browser`. The `hash` router is only useful for rare cases where you want to opt-out of static site generation, have a fully client-side app with a single `index.html` entrypoint file. This can be useful to distribute a Docusaurus site as a `.zip` archive that you can [browse locally without running a web server](https://github.com/facebook/docusaurus/issues/3825).
### `noIndex` {#noIndex}
- Type: `boolean`
This option adds `<meta name="robots" content="noindex, nofollow">` to every page to tell search engines to avoid indexing your site (more information [here](https://moz.com/learn/seo/robots-meta-directives)).
Example:
```js title="docusaurus.config.js"
export default {
noIndex: true, // Defaults to `false`
};
```
### `onBrokenLinks` {#onBrokenLinks}
- Type: `'ignore' | 'log' | 'warn' | 'throw'`
The behavior of Docusaurus when it detects any broken link.
By default, it throws an error, to ensure you never ship any broken link.
:::note
The broken links detection is only available for a production build (`docusaurus build`).
:::
### `onBrokenAnchors` {#onBrokenAnchors}
- Type: `'ignore' | 'log' | 'warn' | 'throw'`
The behavior of Docusaurus when it detects any broken anchor declared with the `Heading` component of Docusaurus.
By default, it prints a warning, to let you know about your broken anchors.
### `onBrokenMarkdownLinks` {#onBrokenMarkdownLinks}
- Type: `'ignore' | 'log' | 'warn' | 'throw'`
The behavior of Docusaurus when it detects any broken Markdown link.
By default, it prints a warning, to let you know about your broken Markdown link.
### `onDuplicateRoutes` {#onDuplicateRoutes}
- Type: `'ignore' | 'log' | 'warn' | 'throw'`
The behavior of Docusaurus when it detects any [duplicate routes](/guides/creating-pages.mdx#duplicate-routes).
By default, it displays a warning after you run `yarn start` or `yarn build`.
### `tagline` {#tagline}
- Type: `string`
The tagline for your website.
```js title="docusaurus.config.js"
export default {
tagline:
'Docusaurus makes it easy to maintain Open Source documentation websites.',
};
```
### `organizationName` {#organizationName}
- Type: `string`
The GitHub user or organization that owns the repository. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
export default {
// Docusaurus' organization is facebook
organizationName: 'facebook',
};
```
### `projectName` {#projectName}
- Type: `string`
The name of the GitHub repository. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
export default {
projectName: 'docusaurus',
};
```
### `deploymentBranch` {#deploymentBranch}
- Type: `string`
The name of the branch to deploy the static files to. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
export default {
deploymentBranch: 'gh-pages',
};
```
### `githubHost` {#githubHost}
- Type: `string`
The hostname of your server. Useful if you are using GitHub Enterprise. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
export default {
githubHost: 'github.com',
};
```
### `githubPort` {#githubPort}
- Type: `string`
The port of your server. Useful if you are using GitHub Enterprise. You don't need this if you are not using the `docusaurus deploy` command.
```js title="docusaurus.config.js"
export default {
githubPort: '22',
};
```
### `themeConfig` {#themeConfig}
- Type: `Object`
The [theme configuration](./themes/theme-configuration.mdx) object to customize your site UI like navbar and footer.
Example:
```js title="docusaurus.config.js"
export default {
themeConfig: {
docs: {
sidebar: {
hideable: false,
autoCollapseCategories: false,
},
},
colorMode: {
defaultMode: 'light',
disableSwitch: false,
respectPrefersColorScheme: true,
},
navbar: {
title: 'Site Title',
logo: {
alt: 'Site Logo',
src: 'img/logo.svg',
width: 32,
height: 32,
},
items: [
{
to: 'docs/docusaurus.config.js',
activeBasePath: 'docs',
label: 'docusaurus.config.js',
position: 'left',
},
// ... other links
],
},
footer: {
style: 'dark',
links: [
{
title: 'Docs',
items: [
{
label: 'Docs',
to: 'docs/doc1',
},
],
},
// ... other links
],
logo: {
alt: 'Meta Open Source Logo',
src: 'img/meta_oss_logo.png',
href: 'https://opensource.fb.com',
width: 160,
height: 51,
},
copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`, // You can also put own HTML here
},
},
};
```
### `plugins` {#plugins}
- Type: `PluginConfig[]`
```ts
type PluginConfig = string | [string, any] | PluginModule | [PluginModule, any];
```
See [plugin method references](./plugin-methods/README.mdx) for the shape of a `PluginModule`.
```js title="docusaurus.config.js"
export default {
plugins: [
'docusaurus-plugin-awesome',
['docusuarus-plugin-confetti', {fancy: false}],
() => ({
postBuild() {
console.log('Build finished');
},
}),
],
};
```
### `themes` {#themes}
- Type: `PluginConfig[]`
```js title="docusaurus.config.js"
export default {
themes: ['@docusaurus/theme-classic'],
};
```
### `presets` {#presets}
- Type: `PresetConfig[]`
```ts
type PresetConfig = string | [string, any];
```
```js title="docusaurus.config.js"
export default {
presets: [],
};
```
### `markdown` {#markdown}
The global Docusaurus Markdown config.
- Type: `MarkdownConfig`
```ts
type MarkdownPreprocessor = (args: {
filePath: string;
fileContent: string;
}) => string;
type MDX1CompatOptions =
| boolean
| {
comments: boolean;
admonitions: boolean;
headingIds: boolean;
};
export type ParseFrontMatter = (params: {
filePath: string;
fileContent: string;
defaultParseFrontMatter: ParseFrontMatter;
}) => Promise<{
frontMatter: {[key: string]: unknown};
content: string;
}>;
type MarkdownAnchorsConfig = {
maintainCase: boolean;
};
type MarkdownConfig = {
format: 'mdx' | 'md' | 'detect';
mermaid: boolean;
preprocessor?: MarkdownPreprocessor;
parseFrontMatter?: ParseFrontMatter;
mdx1Compat: MDX1CompatOptions;
remarkRehypeOptions: object; // see https://github.com/remarkjs/remark-rehype#options
anchors: MarkdownAnchorsConfig;
};
```
Example:
```js title="docusaurus.config.js"
export default {
markdown: {
format: 'mdx',
mermaid: true,
preprocessor: ({filePath, fileContent}) => {
return fileContent.replaceAll('{{MY_VAR}}', 'MY_VALUE');
},
parseFrontMatter: async (params) => {
const result = await params.defaultParseFrontMatter(params);
result.frontMatter.description =
result.frontMatter.description?.replaceAll('{{MY_VAR}}', 'MY_VALUE');
return result;
},
mdx1Compat: {
comments: true,
admonitions: true,
headingIds: true,
},
anchors: {
maintainCase: true,
},
},
};
```
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `format` | `'mdx' \| 'md' \| 'detect'` | `'mdx'` | The default parser format to use for Markdown content. Using 'detect' will select the appropriate format automatically based on file extensions: `.md` vs `.mdx`. |
| `mermaid` | `boolean` | `false` | When `true`, allows Docusaurus to render Markdown code blocks with `mermaid` language as Mermaid diagrams. |
| `preprocessor` | `MarkdownPreprocessor` | `undefined` | Gives you the ability to alter the Markdown content string before parsing. Use it as a last-resort escape hatch or workaround: it is almost always better to implement a Remark/Rehype plugin. |
| `parseFrontMatter` | `ParseFrontMatter` | `undefined` | Gives you the ability to provide your own front matter parser, or to enhance the default parser. Read our [front matter guide](../guides/markdown-features/markdown-features-intro.mdx#front-matter) for details. |
| `mdx1Compat` | `MDX1CompatOptions` | `{comments: true, admonitions: true, headingIds: true}` | Compatibility options to make it easier to upgrade to Docusaurus v3+. |
| `anchors` | `MarkdownAnchorsConfig` | `{maintainCase: false}` | Options to control the behavior of anchors generated from Markdown headings |
| `remarkRehypeOptions` | `object` | `undefined` | Makes it possible to pass custom [`remark-rehype` options](https://github.com/remarkjs/remark-rehype#options). |
```mdx-code-block
</APITable>
```
### `customFields` {#customFields}
Docusaurus guards `docusaurus.config.js` from unknown fields. To add a custom field, define it on `customFields`.
- Type: `Object`
```js title="docusaurus.config.js"
export default {
customFields: {
admin: 'endi',
superman: 'lol',
},
};
```
Attempting to add unknown fields in the config will lead to errors during build time:
```bash
Error: The field(s) 'foo', 'bar' are not recognized in docusaurus.config.js
```
### `staticDirectories` {#staticDirectories}
An array of paths, relative to the site's directory or absolute. Files under these paths will be copied to the build output as-is.
- Type: `string[]`
Example:
```js title="docusaurus.config.js"
export default {
staticDirectories: ['static'],
};
```
### `headTags` {#headTags}
An array of tags that will be inserted in the HTML `<head>`. The values must be objects that contain two properties; `tagName` and `attributes`. `tagName` must be a string that determines the tag being created; eg `"link"`. `attributes` must be an attribute-value map.
- Type: `{ tagName: string; attributes: Object; }[]`
Example:
```js title="docusaurus.config.js"
export default {
headTags: [
{
tagName: 'link',
attributes: {
rel: 'icon',
href: '/img/docusaurus.png',
},
},
],
};
```
This would become `<link rel="icon" href="img/docusaurus.png" />` in the generated HTML.
### `scripts` {#scripts}
An array of scripts to load. The values can be either strings or plain objects of attribute-value maps. The `<script>` tags will be inserted in the HTML `<head>`. If you use a plain object, the only required attribute is `src`, and any other attributes are permitted (each one should have boolean/string values).
Note that `<script>` added here are render-blocking, so you might want to add `async: true`/`defer: true` to the objects.
- Type: `(string | Object)[]`
Example:
```js title="docusaurus.config.js"
export default {
scripts: [
// String format.
'https://docusaurus.io/script.js',
// Object format.
{
src: 'https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js',
async: true,
},
],
};
```
### `stylesheets` {#stylesheets}
An array of CSS sources to load. The values can be either strings or plain objects of attribute-value maps. The `<link>` tags will be inserted in the HTML `<head>`. If you use an object, the only required attribute is `href`, and any other attributes are permitted (each one should have boolean/string values).
- Type: `(string | Object)[]`
Example:
```js title="docusaurus.config.js"
export default {
stylesheets: [
// String format.
'https://docusaurus.io/style.css',
// Object format.
{
href: 'http://mydomain.com/style.css',
},
],
};
```
:::info
By default, the `<link>` tags will have `rel="stylesheet"`, but you can explicitly add a custom `rel` value to inject any kind of `<link>` tag, not necessarily stylesheets.
:::
### `clientModules` {#clientModules}
An array of [client modules](../advanced/client.mdx#client-modules) to load globally on your site.
Example:
```js title="docusaurus.config.js"
export default {
clientModules: ['./mySiteGlobalJs.js', './mySiteGlobalCss.css'],
};
```
### `ssrTemplate` {#ssrTemplate}
An HTML template written in [Eta's syntax](https://eta.js.org/docs/syntax#syntax-overview) that will be used to render your application. This can be used to set custom attributes on the `body` tags, additional `meta` tags, customize the `viewport`, etc. Please note that Docusaurus will rely on the template to be correctly structured in order to function properly, once you do customize it, you will have to make sure that your template is compliant with the requirements from upstream.
- Type: `string`
Example:
```js title="docusaurus.config.js"
export default {
ssrTemplate: `<!DOCTYPE html>
<html <%~ it.htmlAttributes %>>
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v<%= it.version %>">
<% it.metaAttributes.forEach((metaAttribute) => { %>
<%~ metaAttribute %>
<% }); %>
<%~ it.headTags %>
<% it.stylesheets.forEach((stylesheet) => { %>
<link rel="stylesheet" href="<%= it.baseUrl %><%= stylesheet %>" />
<% }); %>
<% it.scripts.forEach((script) => { %>
<link rel="preload" href="<%= it.baseUrl %><%= script %>" as="script">
<% }); %>
</head>
<body <%~ it.bodyAttributes %>>
<%~ it.preBodyTags %>
<div id="__docusaurus">
<%~ it.appHtml %>
</div>
<% it.scripts.forEach((script) => { %>
<script src="<%= it.baseUrl %><%= script %>"></script>
<% }); %>
<%~ it.postBodyTags %>
</body>
</html>`,
};
```
### `titleDelimiter` {#titleDelimiter}
- Type: `string`
Will be used as title delimiter in the generated `<title>` tag.
Example:
```js title="docusaurus.config.js"
export default {
titleDelimiter: '🦖', // Defaults to `|`
};
```
### `baseUrlIssueBanner` {#baseUrlIssueBanner}
- Type: `boolean`
When enabled, will show a banner in case your site can't load its CSS or JavaScript files, which is a very common issue, often related to a wrong `baseUrl` in site config.
Example:
```js title="docusaurus.config.js"
export default {
baseUrlIssueBanner: true, // Defaults to `true`
};
```
![A sample base URL issue banner. The style is very raw since the stylesheets failed to load. The text says "Your Docusaurus site did not load properly... Current configured baseUrl = / (default value); We suggest trying baseUrl = /build/](/img/baseUrlIssueBanner.png)
:::warning
This banner needs to inline CSS / JS in case all asset loading fails due to wrong base URL.
If you have a strict [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), you should rather disable it.
:::

View file

@ -0,0 +1,2 @@
label: Miscellaneous
position: 4

View file

@ -0,0 +1,58 @@
---
sidebar_position: 0
slug: /api/misc/create-docusaurus
---
# 📦 create-docusaurus
A scaffolding utility to help you instantly set up a functional Docusaurus app.
## Usage {#usage}
```bash
npx create-docusaurus@latest [name] [template] [rootDir]
```
The `name` argument will be used as the site's path as well as the `name` field in the created app's package.json. It can be an absolute path, or a path relative to `rootDir`.
The `template` argument can be one of the following:
- `classic`: Uses the classic template (recommended)
- `facebook`: Uses the Facebook/Meta template, which contains some Meta-specific setup
- A git repo URL (beginning with `https://` or `git@`), which can be cloned to the destination
- A local file path relative to CWD, which contains the files to be copied to destination
The `rootDir` will be used to resolve the absolute path to the site directory. The default is CWD.
:::warning
This command should be preferably used in an interactive shell so all features are available.
:::
## Options {#options}
### `-t, --typescript` {#typescript}
Used when the template argument is a recognized name. Currently, only `classic` provides a TypeScript variant.
### `-g, --git-strategy` {#git-strategy}
Used when the template argument is a git repo. It needs to be one of:
- `deep`: preserves full git history
- `shallow`: clones with `--depth=1`
- `copy`: does a shallow clone, but does not create a git repo
- `custom`: enter your custom git clone command. We will prompt you for it. You can write something like `git clone --depth 10`, and we will append the repository URL and destination directory.
### `-p, --package-manager` {#package-manager}
Value should be one of `npm`, `yarn`, `pnpm`, or `bun`. If it's not explicitly provided, Docusaurus will infer one based on:
- The lockfile already present in the CWD (e.g. if you are setting up website in an existing project)
- The command used to invoke `create-docusaurus` (e.g. `npm init`, `npx`, `yarn create`, `bunx`, etc.)
- Interactive prompting, in case all heuristics are not present
### `-s, --skip-install` {#skip-install}
If provided, Docusaurus will not automatically install dependencies after creating the app. The `--package-manager` option is only useful when you are actually installing dependencies.

View file

@ -0,0 +1,74 @@
---
sidebar_position: 1
slug: /api/misc/@docusaurus/eslint-plugin
---
# 📦 eslint-plugin
[ESLint](https://eslint.org/) is a tool that statically analyzes your code and reports problems or suggests best practices through editor hints and command line. Docusaurus provides an ESLint plugin to enforce best Docusaurus practices.
## Installation
```bash npm2yarn
npm install --save-dev @docusaurus/eslint-plugin
```
## Usage
### Recommended config
Add `plugin:@docusaurus/recommended` to the `extends` section of your `.eslintrc` configuration file:
```json title=".eslintrc"
{
"extends": ["plugin:@docusaurus/recommended"]
}
```
This will enable the `@docusaurus` eslint plugin and use the `recommended` config. See [Supported rules](#supported-rules) below for a list of rules that this will enable.
### Manual config
For more fine-grained control, you can also enable the plugin manually and configure the rules you want to use directly:
```json title=".eslintrc"
{
"plugins": ["@docusaurus"],
"rules": {
"@docusaurus/string-literal-i18n-messages": "error",
"@docusaurus/no-untranslated-text": "warn"
}
}
```
## Supported configs
- Recommended: recommended rule set for most Docusaurus sites that should be extended from.
- All: **all** rules enabled. This will change between minor versions, so you should not use this if you want to avoid unexpected breaking changes.
## Supported rules
| Name | Description | |
| --- | --- | --- |
| [`@docusaurus/no-untranslated-text`](./no-untranslated-text.mdx) | Enforce text labels in JSX to be wrapped by translate calls | |
| [`@docusaurus/string-literal-i18n-messages`](./string-literal-i18n-messages.mdx) | Enforce translate APIs to be called on plain text labels | ✅ |
| [`@docusaurus/no-html-links`](./no-html-links.mdx) | Ensures @docusaurus/Link is used instead of `<a>` tags | ✅ |
| [`@docusaurus/prefer-docusaurus-heading`](./prefer-docusaurus-heading.mdx) | Ensures @theme/Heading is used instead of `<hn>` tags for headings | ✅ |
✅ = recommended
## Example configuration
Here's an example configuration:
```js title=".eslintrc.js"
module.exports = {
extends: ['plugin:@docusaurus/recommended'],
rules: {
'@docusaurus/no-untranslated-text': [
'warn',
{ignoredStrings: ['·', '—', '×']},
],
},
};
```

View file

@ -0,0 +1,47 @@
---
slug: /api/misc/@docusaurus/eslint-plugin/no-html-links
---
# no-html-links
import APITable from '@site/src/components/APITable';
Ensure that the Docusaurus [`<Link>`](../../../docusaurus-core.mdx#link) component is used instead of `<a>` tags.
The `<Link>` component has prefetching and preloading built-in. It also does build-time broken link detection, and helps Docusaurus understand your site's structure better.
## Rule Details {#details}
Examples of **incorrect** code for this rule:
```html
<a href="/page">go to page!</a>
<a href="https://x.com/docusaurus" target="_blank">X</a>
```
Examples of **correct** code for this rule:
```js
import Link from '@docusaurus/Link'
<Link to="/page">go to page!</Link>
<Link to="https://x.com/docusaurus">X</Link>
```
## Rule Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `ignoreFullyResolved` | `boolean` | `false` | Set to true will not report any `<a>` tags with absolute URLs including a protocol. |
```mdx-code-block
</APITable>
```

View file

@ -0,0 +1,54 @@
---
slug: /api/misc/@docusaurus/eslint-plugin/no-untranslated-text
---
# no-untranslated-text
import APITable from '@site/src/components/APITable';
Enforce text labels in JSX to be wrapped by translate calls.
When the [i18n feature](../../../i18n/i18n-introduction.mdx) is used, this rule ensures that all labels appearing on the website are translatable, so no string accidentally slips through untranslated.
## Rule Details {#details}
Examples of **incorrect** code for this rule:
```js
// Hello World is not translated
<Component>Hello World</Component>
```
Examples of **correct** code for this rule:
```js
// Hello World is translated
<Component>
<Translate>Hello World</Translate>
</Component>
```
## Rule Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `ignoredStrings` | `string[]` | `[]` | Text labels that only contain strings in this list will not be reported. |
```mdx-code-block
</APITable>
```
## When Not To Use It {#when-not-to-use}
If you're not using the [i18n feature](../../../i18n/i18n-introduction.mdx), you can disable this rule. You can also disable this rule where the text is not supposed to be translated.
## Further Reading {#further-reading}
- https://docusaurus.io/docs/docusaurus-core#translate
- https://docusaurus.io/docs/docusaurus-core#translate-imperative

View file

@ -0,0 +1,31 @@
---
slug: /api/misc/@docusaurus/eslint-plugin/prefer-docusaurus-heading
---
# prefer-docusaurus-heading
Ensures that the `@theme/Heading` theme component provided by Docusaurus [`theme-classic`](../../themes/theme-classic.mdx) is used instead of `<hn>` tags for headings.
## Rule Details {#details}
Examples of **incorrect** code for this rule:
```html
<h1>This is heading 1</h1>
<h2>This is heading 2</h2>
<h3>This is heading 3</h3>
```
Examples of **correct** code for this rule:
```javascript
import Heading from '@theme/Heading'
<Heading as='h1'>This is heading 1</Heading>
<Heading as='h2'>This is heading 2</Heading>
<Heading as='h3'>This is heading 3</Heading>
```

View file

@ -0,0 +1,50 @@
---
slug: /api/misc/@docusaurus/eslint-plugin/string-literal-i18n-messages
---
# string-literal-i18n-messages
Enforce translate APIs to be called on plain text labels.
Docusaurus offers the [`docusaurus write-translations`](../../../cli.mdx#docusaurus-write-translations-sitedir) API, which statically extracts the text labels marked as translatable. Dynamic values used in `<Translate>` or `translate()` calls will fail to be extracted. This rule will ensure that all translate calls are statically extractable.
## Rule Details {#details}
Examples of **incorrect** code for this rule:
```js
const text = 'Some text to be translated'
// Invalid <Translate> child
<Translate>{text}</Translate>
// Invalid message attribute
translate({message: text})
```
Examples of **correct** code for this rule:
```js
// Valid <Translate> child
<Translate>Some text to be translated</Translate>
// Valid message attribute
translate({message: 'Some text to be translated'})
// Valid <Translate> child using values object as prop
<Translate values={{firstName: 'Sébastien'}}>
{'Welcome, {firstName}! How are you?'}
</Translate>
// Valid message attribute using values object as second argument
translate({message: 'The logo of site {siteName}'}, {siteName: 'Docusaurus'})
```
## When Not To Use It {#when-not-to-use}
If you're not using the [i18n feature](../../../i18n/i18n-introduction.mdx), you can disable this rule.
## Further Reading {#further-reading}
- https://docusaurus.io/docs/docusaurus-core#translate
- https://docusaurus.io/docs/docusaurus-core#translate-imperative

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View file

@ -0,0 +1,71 @@
---
sidebar_position: 2
slug: /api/misc/@docusaurus/logger
---
# 📦 logger
An encapsulated logger for semantically formatting console messages.
Authors of packages in the Docusaurus ecosystem are encouraged to use this package to provide unified log formats.
## APIs
It exports a single object as default export: `logger`. `logger` has the following properties:
- Some useful colors.
- `red`
- `yellow`
- `green`
- `bold`
- `dim`
- Formatters. These functions all have the signature `(msg: unknown) => string`. Note that their implementations are not guaranteed. You should only care about their semantics.
- `path`: formats a file path.
- `url`: formats a URL.
- `name`: formats an identifier.
- `code`: formats a code snippet.
- `subdue`: subdues the text.
- `num`: formats a number.
- The `interpolate` function. It is a template literal tag. The syntax can be found below.
- Logging functions. All logging functions can both be used as normal functions (similar to the `console.log` family, but only accepts one parameter) or template literal tags.
- `info`: prints information.
- `warn`: prints a warning that should be paid attention to.
- `error`: prints an error (not necessarily halting the program) that signals significant problems.
- `success`: prints a success message.
- The `report` function. It takes a `ReportingSeverity` value (`ignore`, `log`, `warn`, `throw`) and reports a message according to the severity.
:::warning A word on the `error` formatter
Beware that an `error` message, even when it doesn't hang the program, is likely going to cause confusion. When users inspect logs and find an `[ERROR]`, even when the build succeeds, they will assume something is going wrong. Use it sparingly.
Docusaurus only uses `logger.error` when printing messages immediately before throwing an error, or when user has set the reporting severity of `onBrokenLink`, etc. to `"error"`.
In addition, `warn` and `error` will color the **entire** message for better attention. If you are printing large blocks of help text about an error, better use `logger.info`.
:::
### Using the template literal tag
The template literal tag evaluates the template and expressions embedded. `interpolate` returns a new string, while other logging functions prints it. Below is a typical usage:
```js
import logger from '@docusaurus/logger';
logger.info`Hello name=${name}! You have number=${money} dollars. Here are the ${
items.length > 1 ? 'items' : 'item'
} on the shelf: ${items}
To buy anything, enter code=${'buy x'} where code=${'x'} is the item's name; to quit, press code=${'Ctrl + C'}.`;
```
An embedded expression is optionally preceded by a flag in the form `[a-z]+=` (a few lowercase letters, followed by an equals sign, directly preceding the embedded expression). If the expression is not preceded by any flag, it's printed out as-is. Otherwise, it's formatted with one of the formatters:
- `path=`: `path`
- `url=`: `url`
- `name=`: `name`
- `code=`: `code`
- `subdue=`: `subdue`
- `number=`: `num`
If the expression is an array, it's formatted by `` `\n- ${array.join('\n- ')}\n` `` (note it automatically gets a leading line end). Each member is formatted by itself and the bullet is not formatted. So you would see the above message printed as:
![Some text output in the terminal, containing array, code, name, and number formatting](./demo.png)

View file

@ -0,0 +1,144 @@
# Plugin Method References
:::warning
This section is a work in progress. Anchor links or even URLs are not guaranteed to be stable.
:::
Plugin APIs are shared by themes and plugins—themes are loaded just like plugins.
## Plugin module {#plugin-module}
Every plugin is imported as a module. The module is expected to have the following members:
- A **default export**: the constructor function for the plugin.
- **Named exports**: the [static methods](./static-methods.mdx) called before plugins are initialized.
## Plugin constructor {#plugin-constructor}
The plugin module's default export is a constructor function with the signature `(context: LoadContext, options: PluginOptions) => Plugin | Promise<Plugin>`.
### `context` {#context}
`context` is plugin-agnostic, and the same object will be passed into all plugins used for a Docusaurus website. The `context` object contains the following fields:
```ts
type LoadContext = {
siteDir: string;
generatedFilesDir: string;
siteConfig: DocusaurusConfig;
outDir: string;
baseUrl: string;
};
```
### `options` {#options}
`options` are the [second optional parameter when the plugins are used](../../using-plugins.mdx#configuring-plugins). `options` are plugin-specific and are specified by users when they use them in `docusaurus.config.js`. If there's a [`validateOptions`](./static-methods.mdx#validateOptions) function exported, the `options` will be validated and normalized beforehand.
Alternatively, if a preset contains the plugin, the preset will then be in charge of passing the correct options into the plugin. It is up to the individual plugin to define what options it takes.
## Example {#example}
Here's a mental model for a presumptuous plugin implementation.
```js
// A JavaScript function that returns an object.
// `context` is provided by Docusaurus. Example: siteConfig can be accessed from context.
// `opts` is the user-defined options.
export default async function myPlugin(context, opts) {
return {
// A compulsory field used as the namespace for directories to cache
// the intermediate data for each plugin.
// If you're writing your own local plugin, you will want it to
// be unique in order not to potentially conflict with imported plugins.
// A good way will be to add your own project name within.
name: 'docusaurus-my-project-cool-plugin',
async loadContent() {
// The loadContent hook is executed after siteConfig and env has been loaded.
// You can return a JavaScript object that will be passed to contentLoaded hook.
},
async contentLoaded({content, actions}) {
// The contentLoaded hook is done after loadContent hook is done.
// `actions` are set of functional API provided by Docusaurus (e.g. addRoute)
},
async postBuild(props) {
// After docusaurus <build> finish.
},
// TODO
async postStart(props) {
// docusaurus <start> finish
},
// TODO
afterDevServer(app, server) {
// https://webpack.js.org/configuration/dev-server/#devserverbefore
},
// TODO
beforeDevServer(app, server) {
// https://webpack.js.org/configuration/dev-server/#devserverafter
},
configureWebpack(config, isServer, utils, content) {
// Modify internal webpack config. If returned value is an Object, it
// will be merged into the final config using webpack-merge;
// If the returned value is a function, it will receive the config as the 1st argument and an isServer flag as the 2nd argument.
},
getPathsToWatch() {
// Paths to watch.
},
getThemePath() {
// Returns the path to the directory where the theme components can
// be found.
},
getClientModules() {
// Return an array of paths to the modules that are to be imported
// in the client bundle. These modules are imported globally before
// React even renders the initial UI.
},
extendCli(cli) {
// Register an extra command to enhance the CLI of Docusaurus
},
injectHtmlTags({content}) {
// Inject head and/or body HTML tags.
},
async getTranslationFiles({content}) {
// Return translation files
},
translateContent({content, translationFiles}) {
// translate the plugin content here
},
translateThemeConfig({themeConfig, translationFiles}) {
// translate the site themeConfig here
},
async getDefaultCodeTranslationMessages() {
// return default theme translations here
},
};
}
export function validateOptions({options, validate}) {
const validatedOptions = validate(myValidationSchema, options);
return validatedOptions;
}
export function validateThemeConfig({themeConfig, validate}) {
const validatedThemeConfig = validate(myValidationSchema, options);
return validatedThemeConfig;
}
```

View file

@ -0,0 +1,2 @@
label: Plugin method references
position: 1

View file

@ -0,0 +1,132 @@
---
sidebar_position: 2
---
# Extending infrastructure
Docusaurus has some infrastructure like hot reloading, CLI, and swizzling, that can be extended by external plugins.
## `getPathsToWatch()` {#getPathsToWatch}
Specifies the paths to watch for plugins and themes. The paths are watched by the dev server so that the plugin lifecycles are reloaded when contents in the watched paths change. Note that the plugins and themes modules are initially called with `context` and `options` from Node, which you may use to find the necessary directory information about the site.
Use this for files that are consumed server-side, because theme files are automatically watched by Webpack dev server.
Example:
```js title="docusaurus-plugin/src/index.js"
import path from 'path';
export default function (context, options) {
return {
name: 'docusaurus-plugin',
// highlight-start
getPathsToWatch() {
const contentPath = path.resolve(context.siteDir, options.path);
return [`${contentPath}/**/*.{ts,tsx}`];
},
// highlight-end
};
}
```
## `extendCli(cli)` {#extendCli}
Register an extra command to enhance the CLI of Docusaurus. `cli` is a [commander](https://www.npmjs.com/package/commander/v/5.1.0) object.
:::warning
The commander version matters! We use commander v5, and make sure you are referring to the right version documentation for available APIs.
:::
Example:
```js title="docusaurus-plugin/src/index.js"
export default function (context, options) {
return {
name: 'docusaurus-plugin',
// highlight-start
extendCli(cli) {
cli
.command('roll')
.description('Roll a random number between 1 and 1000')
.action(() => {
console.log(Math.floor(Math.random() * 1000 + 1));
});
},
// highlight-end
};
}
```
## `getThemePath()` {#getThemePath}
Returns the path to the directory where the theme components can be found. When your users call `swizzle`, `getThemePath` is called and its returned path is used to find your theme components. Relative paths are resolved against the folder containing the entry point.
For example, your `getThemePath` can be:
```js title="my-theme/src/index.js"
export default function (context, options) {
return {
name: 'my-theme',
// highlight-start
getThemePath() {
return './theme';
},
// highlight-end
};
}
```
## `getTypeScriptThemePath()` {#getTypeScriptThemePath}
Similar to `getThemePath()`, it should return the path to the directory where the source code of TypeScript theme components can be found. This path is purely for swizzling TypeScript theme components, and theme components under this path will **not** be resolved by Webpack. Therefore, it is not a replacement for `getThemePath()`. Typically, you can make the path returned by `getTypeScriptThemePath()` be your source directory, and make the path returned by `getThemePath()` be the compiled JavaScript output.
:::tip
For TypeScript theme authors: you are strongly advised to make your compiled output as human-readable as possible. Only strip type annotations and don't transpile any syntaxes, because they will be handled by Webpack's Babel loader based on the targeted browser versions.
You should also format these files with Prettier. Remember—JS files can and will be directly consumed by your users.
:::
Example:
```js title="my-theme/src/index.js"
export default function (context, options) {
return {
name: 'my-theme',
// highlight-start
getThemePath() {
// Where compiled JavaScript output lives
return '../lib/theme';
},
getTypeScriptThemePath() {
// Where TypeScript source code lives
return '../src/theme';
},
// highlight-end
};
}
```
## `getSwizzleComponentList()` {#getSwizzleComponentList}
**This is a static method, not attached to any plugin instance.**
Returns a list of stable components that are considered safe for swizzling. These components will be swizzlable without `--danger`. All components are considered unstable by default. If an empty array is returned, all components are considered unstable. If `undefined` is returned, all components are considered stable.
```js title="my-theme/src/index.js"
export function getSwizzleComponentList() {
return [
'CodeBlock',
'DocSidebar',
'Footer',
'NotFound',
'SearchBar',
'hooks/useTheme',
'prism-include-languages',
];
}
```

View file

@ -0,0 +1,121 @@
---
sidebar_position: 3
---
# I18n lifecycles
Plugins use these lifecycles to load i18n-related data.
## `getTranslationFiles({content})` {#getTranslationFiles}
Plugins declare the JSON translation files they want to use.
Returns translation files `{path: string, content: ChromeI18nJSON}`:
- `path`: relative to the plugin localized folder `i18n/[locale]/[pluginName]`. Extension `.json` should be omitted to remain generic.
- `content`: using the Chrome i18n JSON format.
These files will be written by the [`write-translations` CLI](../../cli.mdx#docusaurus-write-translations-sitedir) to the plugin i18n subfolder, and will be read in the appropriate locale before calling [`translateContent()`](#translateContent) and [`translateThemeConfig()`](#translateThemeConfig)
Example:
```js title="my-plugin.js"
export default function (context, options) {
return {
name: 'my-plugin',
// highlight-start
async getTranslationFiles({content}) {
return [
{
path: 'sidebar-labels',
content: {
someSidebarLabel: {
message: 'Some Sidebar Label',
description: 'A label used in my plugin in the sidebar',
},
someLabelFromContent: content.myLabel,
},
},
];
},
// highlight-end
};
}
```
## `translateContent({content,translationFiles})` {#translateContent}
Translate the plugin content, using the localized translation files.
Returns the localized plugin content.
The `contentLoaded()` lifecycle will be called with the localized plugin content returned by `translateContent()`.
Example:
```js title="my-plugin.js"
export default function (context, options) {
return {
name: 'my-plugin',
// highlight-start
translateContent({content, translationFiles}) {
const myTranslationFile = translationFiles.find(
(f) => f.path === 'myTranslationFile',
);
return {
...content,
someContentLabel: myTranslationFile.someContentLabel.message,
};
},
// highlight-end
};
}
```
## `translateThemeConfig({themeConfig,translationFiles})` {#translateThemeConfig}
Translate the site `themeConfig` labels, using the localized translation files.
Returns the localized `themeConfig`.
Example:
```js title="my-plugin.js"
export default function (context, options) {
return {
name: 'my-theme',
// highlight-start
translateThemeConfig({themeConfig, translationFiles}) {
const myTranslationFile = translationFiles.find(
(f) => f.path === 'myTranslationFile',
);
return {
...themeConfig,
someThemeConfigLabel: myTranslationFile.someThemeConfigLabel.message,
};
},
// highlight-end
};
}
```
## `async getDefaultCodeTranslationMessages()` {#getDefaultCodeTranslationMessages}
Themes using the `<Translate>` API can provide default code translation messages.
It should return messages in `Record<string, string>`, where keys are translation IDs and values are messages (without the description) localized using the site's current locale.
Example:
```js title="my-plugin.js"
export default function (context, options) {
return {
name: 'my-theme',
// highlight-start
async getDefaultCodeTranslationMessages() {
return readJsonFile(`${context.i18n.currentLocale}.json`);
},
// highlight-end
};
}
```

View file

@ -0,0 +1,492 @@
---
sidebar_position: 1
toc_max_heading_level: 4
---
# Lifecycle APIs
During the build, plugins are loaded in parallel to fetch their own contents and render them to routes. Plugins may also configure webpack or post-process the generated files.
## `async loadContent()` {#loadContent}
Plugins should use this lifecycle to fetch from data sources (filesystem, remote API, headless CMS, etc.) or do some server processing. The return value is the content it needs.
For example, this plugin below returns a random integer between 1 and 10 as content.
```js title="docusaurus-plugin/src/index.js"
export default function (context, options) {
return {
name: 'docusaurus-plugin',
// highlight-start
async loadContent() {
return 1 + Math.floor(Math.random() * 10);
},
// highlight-end
};
}
```
## `async contentLoaded({content, actions})` {#contentLoaded}
The data that was loaded in `loadContent` will be consumed in `contentLoaded`. It can be rendered to routes, registered as global data, etc.
### `content` {#content}
`contentLoaded` will be called _after_ `loadContent` is done. The return value of `loadContent()` will be passed to `contentLoaded` as `content`.
### `actions` {#actions}
`actions` contain three functions:
#### `addRoute(config: RouteConfig): void` {#addRoute}
Create a route to add to the website.
```ts
export type RouteConfig = {
/**
* With leading slash. Trailing slash will be normalized by config.
*/
path: string;
/**
* Component used to render this route, a path that the bundler can `require`.
*/
component: string;
/**
* Props. Each entry should be `[propName]: pathToPropModule` (created with
* `createData`)
*/
modules?: RouteModules;
/**
* The route context will wrap the `component`. Use `useRouteContext` to
* retrieve what's declared here. Note that all custom route context declared
* here will be namespaced under {@link RouteContext.data}.
*/
context?: RouteModules;
/**
* Nested routes config, useful for "layout routes" having subroutes.
*/
routes?: RouteConfig[];
/**
* React router config option: `exact` routes would not match subroutes.
*/
exact?: boolean;
/**
* React router config option: `strict` routes are sensitive to the presence
* of a trailing slash.
*/
strict?: boolean;
/**
* Used to sort routes.
* Higher-priority routes will be matched first.
*/
priority?: number;
/**
* Optional route metadata
*/
metadata?: RouteMetadata;
/**
* Extra props; will be available on the client side.
*/
[propName: string]: unknown;
};
/**
* Plugin authors can assign extra metadata to the created routes
* It is only available on the Node.js side, and not sent to the browser
* Optional: plugin authors are encouraged but not required to provide it
*
* Some plugins might use this data to provide additional features.
* This is the case of the sitemap plugin to provide support for "lastmod".
* See also: https://github.com/facebook/docusaurus/pull/9954
*/
export type RouteMetadata = {
/**
* The source code file path that led to the creation of the current route
* In official content plugins, this is usually a Markdown or React file
* This path is expected to be relative to the site directory
*/
sourceFilePath?: string;
/**
* The last updated date of this route
* This is generally read from the Git history of the sourceFilePath
* but can also be provided through other means (usually front matter)
*
* This has notably been introduced for adding "lastmod" support to the
* sitemap plugin, see https://github.com/facebook/docusaurus/pull/9954
*/
lastUpdatedAt?: number;
};
type RouteModules = {
[module: string]: Module | RouteModules | RouteModules[];
};
type Module =
| {
path: string;
__import?: boolean;
query?: ParsedUrlQueryInput;
}
| string;
```
#### `createData(name: string, data: any): Promise<string>` {#createData}
A declarative callback to create static data (generally JSON or string) which can later be provided to your routes as props. Takes the file name and data to be stored, and returns the actual data file's path.
For example, this plugin below creates a `/friends` page which displays `Your friends are: Yangshun, Sebastien`:
```jsx title="website/src/components/Friends.js"
import React from 'react';
export default function FriendsComponent({friends}) {
return <div>Your friends are {friends.join(',')}</div>;
}
```
```js title="docusaurus-friends-plugin/src/index.js"
export default function friendsPlugin(context, options) {
return {
name: 'docusaurus-friends-plugin',
// highlight-start
async contentLoaded({content, actions}) {
const {createData, addRoute} = actions;
// Create friends.json
const friends = ['Yangshun', 'Sebastien'];
const friendsJsonPath = await createData(
'friends.json',
JSON.stringify(friends),
);
// Add the '/friends' routes, and ensure it receives the friends props
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
modules: {
// propName -> JSON file path
friends: friendsJsonPath,
},
exact: true,
});
},
// highlight-end
};
}
```
#### `setGlobalData(data: any): void` {#setGlobalData}
This function permits one to create some global plugin data that can be read from any page, including the pages created by other plugins, and your theme layout.
This data becomes accessible to your client-side/theme code through the [`useGlobalData`](../../docusaurus-core.mdx#useGlobalData) and [`usePluginData`](../../docusaurus-core.mdx#usePluginData) hooks.
:::warning
Global data is... global: its size affects the loading time of all pages of your site, so try to keep it small. Prefer `createData` and page-specific data whenever possible.
:::
For example, this plugin below creates a `/friends` page which displays `Your friends are: Yangshun, Sebastien`:
```jsx title="website/src/components/Friends.js"
import React from 'react';
import {usePluginData} from '@docusaurus/useGlobalData';
export default function FriendsComponent() {
const {friends} = usePluginData('docusaurus-friends-plugin');
return <div>Your friends are {friends.join(',')}</div>;
}
```
```js title="docusaurus-friends-plugin/src/index.js"
export default function friendsPlugin(context, options) {
return {
name: 'docusaurus-friends-plugin',
// highlight-start
async contentLoaded({content, actions}) {
const {setGlobalData, addRoute} = actions;
// Create friends global data
setGlobalData({friends: ['Yangshun', 'Sebastien']});
// Add the '/friends' routes
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
exact: true,
});
},
// highlight-end
};
}
```
## `configureWebpack(config, isServer, utils, content)` {#configureWebpack}
Modifies the internal webpack config. If the return value is a JavaScript object, it will be merged into the final config using [`webpack-merge`](https://github.com/survivejs/webpack-merge). If it is a function, it will be called and receive `config` as the first argument and an `isServer` flag as the second argument.
:::warning
The API of `configureWebpack` will be modified in the future to accept an object (`configureWebpack({config, isServer, utils, content})`)
:::
### `config` {#config}
`configureWebpack` is called with `config` generated according to client/server build. You may treat this as the base config to be merged with.
### `isServer` {#isServer}
`configureWebpack` will be called both in server build and in client build. The server build receives `true` and the client build receives `false` as `isServer`.
### `utils` {#utils}
`configureWebpack` also receives an util object:
- `getStyleLoaders(isServer: boolean, cssOptions: {[key: string]: any}): Loader[]`
- `getJSLoader(isServer: boolean, cacheOptions?: {}): Loader | null`
You may use them to return your webpack configuration conditionally.
For example, this plugin below modify the webpack config to transpile `.foo` files.
```js title="docusaurus-plugin/src/index.js"
export default function (context, options) {
return {
name: 'custom-docusaurus-plugin',
// highlight-start
configureWebpack(config, isServer, utils) {
const {getJSLoader} = utils;
return {
module: {
rules: [
{
test: /\.foo$/,
use: [getJSLoader(isServer), 'my-custom-webpack-loader'],
},
],
},
};
},
// highlight-end
};
}
```
### `content` {#content-1}
`configureWebpack` will be called both with the content loaded by the plugin.
### Merge strategy {#merge-strategy}
We merge the Webpack configuration parts of plugins into the global Webpack config using [webpack-merge](https://github.com/survivejs/webpack-merge).
It is possible to specify the merge strategy. For example, if you want a webpack rule to be prepended instead of appended:
```js title="docusaurus-plugin/src/index.js"
export default function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
// highlight-start
mergeStrategy: {'module.rules': 'prepend'},
module: {rules: [myRuleToPrepend]},
// highlight-end
};
},
};
}
```
Read the [webpack-merge strategy doc](https://github.com/survivejs/webpack-merge#merging-with-strategies) for more details.
### Configuring dev server {#configuring-dev-server}
The dev server can be configured through returning a `devServer` field.
```js title="docusaurus-plugin/src/index.js"
export default function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
// highlight-start
devServer: {
open: '/docs', // Opens localhost:3000/docs instead of localhost:3000/
},
// highlight-end
};
},
};
}
```
## `configurePostCss(options)` {#configurePostCss}
Modifies [`postcssOptions` of `postcss-loader`](https://webpack.js.org/loaders/postcss-loader/#postcssoptions) during the generation of the client bundle.
Should return the mutated `postcssOptions`.
By default, `postcssOptions` looks like this:
```js
const postcssOptions = {
ident: 'postcss',
plugins: [require('autoprefixer')],
};
```
Example:
```js title="docusaurus-plugin/src/index.js"
export default function (context, options) {
return {
name: 'docusaurus-plugin',
// highlight-start
configurePostCss(postcssOptions) {
// Appends new PostCSS plugin.
postcssOptions.plugins.push(require('postcss-import'));
return postcssOptions;
},
// highlight-end
};
}
```
## `postBuild(props)` {#postBuild}
Called when a (production) build finishes.
```ts
interface Props {
siteDir: string;
generatedFilesDir: string;
siteConfig: DocusaurusConfig;
outDir: string;
baseUrl: string;
headTags: string;
preBodyTags: string;
postBodyTags: string;
routesPaths: string[];
plugins: Plugin<any>[];
content: Content;
}
```
Example:
```js title="docusaurus-plugin/src/index.js"
export default function (context, options) {
return {
name: 'docusaurus-plugin',
// highlight-start
async postBuild({siteConfig = {}, routesPaths = [], outDir}) {
// Print out to console all the rendered routes.
routesPaths.map((route) => {
console.log(route);
});
},
// highlight-end
};
}
```
## `injectHtmlTags({content})` {#injectHtmlTags}
Inject head and/or body HTML tags to Docusaurus generated HTML.
`injectHtmlTags` will be called both with the content loaded by the plugin.
```ts
function injectHtmlTags(): {
headTags?: HtmlTags;
preBodyTags?: HtmlTags;
postBodyTags?: HtmlTags;
};
type HtmlTags = string | HtmlTagObject | (string | HtmlTagObject)[];
type HtmlTagObject = {
/**
* Attributes of the HTML tag
* E.g. `{'disabled': true, 'value': 'demo', 'rel': 'preconnect'}`
*/
attributes?: {
[attributeName: string]: string | boolean;
};
/**
* The tag name e.g. `div`, `script`, `link`, `meta`
*/
tagName: string;
/**
* The inner HTML
*/
innerHTML?: string;
};
```
Example:
```js title="docusaurus-plugin/src/index.js"
export default function (context, options) {
return {
name: 'docusaurus-plugin',
loadContent: async () => {
return {remoteHeadTags: await fetchHeadTagsFromAPI()};
},
// highlight-start
injectHtmlTags({content}) {
return {
headTags: [
{
tagName: 'link',
attributes: {
rel: 'preconnect',
href: 'https://www.github.com',
},
},
...content.remoteHeadTags,
],
preBodyTags: [
{
tagName: 'script',
attributes: {
charset: 'utf-8',
src: '/noflash.js',
},
},
],
postBodyTags: [`<div> This is post body </div>`],
};
},
// highlight-end
};
}
```
Tags will be added as follows:
- `headTags` will be inserted before the closing `</head>` tag after scripts added by config.
- `preBodyTags` will be inserted after the opening `<body>` tag before any child elements.
- `postBodyTags` will be inserted before the closing `</body>` tag after all child elements.
## `getClientModules()` {#getClientModules}
Returns an array of paths to the [client modules](../../advanced/client.mdx#client-modules) that are to be imported into the client bundle.
As an example, to make your theme load a `customCss` or `customJs` file path from `options` passed in by the user:
```js title="my-theme/src/index.js"
export default function (context, options) {
const {customCss, customJs} = options || {};
return {
name: 'name-of-my-theme',
// highlight-start
getClientModules() {
return [customCss, customJs];
},
// highlight-end
};
}
```

View file

@ -0,0 +1,83 @@
---
sidebar_position: 4
---
# Static methods
Static methods are not part of the plugin instance—they are attached to the constructor function. These methods are used to validate and normalize the plugin options and theme config, which are then used as constructor parameters to initialize the plugin instance.
## `validateOptions({options, validate})` {#validateOptions}
Returns validated and normalized options for the plugin. This method is called before the plugin is initialized. You must return the options since they will be passed to the plugin during initialization.
### `options` {#options}
`validateOptions` is called with `options` passed to plugin for validation and normalization.
### `validate` {#validate}
`validateOptions` is called with `validate` function which takes a **[Joi](https://www.npmjs.com/package/joi)** schema and options as the arguments, returns validated and normalized options. `validate` will automatically handle error and validation config.
:::tip
[Joi](https://www.npmjs.com/package/joi) is recommended for validation and normalization of options.
To avoid mixing Joi versions, use `import {Joi} from '@docusaurus/utils-validation'`
:::
If you don't use **[Joi](https://www.npmjs.com/package/joi)** for validation you can throw an Error in case of invalid options and return options in case of success.
```js title="my-plugin/src/index.js"
export default function myPlugin(context, options) {
return {
name: 'docusaurus-plugin',
// rest of methods
};
}
// highlight-start
export function validateOptions({options, validate}) {
const validatedOptions = validate(myValidationSchema, options);
return validatedOptions;
}
// highlight-end
```
## `validateThemeConfig({themeConfig, validate})` {#validateThemeConfig}
Return validated and normalized configuration for the theme.
### `themeConfig` {#themeConfig}
`validateThemeConfig` is called with `themeConfig` provided in `docusaurus.config.js` for validation and normalization.
### `validate` {#validate-1}
`validateThemeConfig` is called with `validate` function which takes a **[Joi](https://www.npmjs.com/package/joi)** schema and `themeConfig` as the arguments, returns validated and normalized options. `validate` will automatically handle error and validation config.
:::tip
[Joi](https://www.npmjs.com/package/joi) is recommended for validation and normalization of theme config.
To avoid mixing Joi versions, use `import {Joi} from '@docusaurus/utils-validation'`
:::
If you don't use **[Joi](https://www.npmjs.com/package/joi)** for validation you can throw an Error in case of invalid options.
```js title="my-theme/src/index.js"
export default function myPlugin(context, options) {
return {
name: 'docusaurus-plugin',
// rest of methods
};
}
// highlight-start
export function validateThemeConfig({themeConfig, validate}) {
const validatedThemeConfig = validate(myValidationSchema, options);
return validatedThemeConfig;
}
// highlight-end
```

View file

@ -0,0 +1,5 @@
label: Plugins
position: 2
link:
type: doc
id: api/plugins/plugins-overview # Dogfood using a "qualified id"

View file

@ -0,0 +1,54 @@
## Tags File {#tags-file}
Use the [`tags` plugin option](#tags) to configure the path of a YAML tags file.
By convention, the plugin will look for a `tags.yml` file at the root of your content folder(s).
This file can contain a list of predefined tags. You can reference these tags by their keys in Markdown files thanks to the [`tags` front matter](#markdown-front-matter).
:::tip Keeping tags consistent
Using a tags file, you can ensure that your tags usage is consistent across your plugin content set. Use the [`onInlineTags: 'throw'`](#onInlineTags) plugin option to enforce this consistency and prevent usage of inline tags declared on the fly.
:::
### Types {#tags-file-types}
The YAML content of the provided tags file should respect the following shape:
```tsx
type Tag = {
label?: string; // Tag display label
permalink?: string; // Tag URL pathname segment
description?: string; // Tag description displayed in the tag page
};
type TagsFileInput = Record<string, Partial<Tag> | null>;
```
### Example {#tags-file-example}
```yml title="tags.yml"
releases:
label: 'Product releases'
permalink: '/product-releases'
description: 'Content related to product releases.'
# A partial tag definition is also valid
announcements:
label: 'Announcements'
# An empty tag definition is also valid
# Other attributes will be inferred from the key
emptyTag:
```
```md title="content.md"
---
tags: [releases, announcements, emptyTag]
---
# Title
Content
```

View file

@ -0,0 +1,33 @@
---
sidebar_position: 0
id: plugins-overview
sidebar_label: Plugins overview
slug: /api/plugins
---
# Docusaurus plugins
We provide official Docusaurus plugins.
## Content plugins {#content-plugins}
These plugins are responsible for loading your site's content, and creating pages for your theme to render.
- [@docusaurus/plugin-content-docs](./plugin-content-docs.mdx)
- [@docusaurus/plugin-content-blog](./plugin-content-blog.mdx)
- [@docusaurus/plugin-content-pages](./plugin-content-pages.mdx)
## Behavior plugins {#behavior-plugins}
These plugins will add a useful behavior to your Docusaurus site.
- [@docusaurus/plugin-debug](./plugin-debug.mdx)
- [@docusaurus/plugin-sitemap](./plugin-sitemap.mdx)
- [@docusaurus/plugin-svgr](./plugin-svgr.mdx)
- [@docusaurus/plugin-rsdoctor](./plugin-rsdoctor.mdx)
- [@docusaurus/plugin-pwa](./plugin-pwa.mdx)
- [@docusaurus/plugin-client-redirects](./plugin-client-redirects.mdx)
- [@docusaurus/plugin-ideal-image](./plugin-ideal-image.mdx)
- [@docusaurus/plugin-google-analytics](./plugin-google-analytics.mdx)
- [@docusaurus/plugin-google-gtag](./plugin-google-gtag.mdx)
- [@docusaurus/plugin-google-tag-manager](./plugin-google-tag-manager.mdx)

View file

@ -0,0 +1,127 @@
---
sidebar_position: 4
slug: /api/plugins/@docusaurus/plugin-client-redirects
---
# 📦 plugin-client-redirects
import APITable from '@site/src/components/APITable';
Docusaurus Plugin to generate **client-side redirects**.
This plugin will write additional HTML pages to your static site that redirect the user to your existing Docusaurus pages with JavaScript.
:::warning production only
This plugin is always inactive in development and **only active in production** because it works on the build output.
:::
:::warning
It is better to use server-side redirects whenever possible.
Before using this plugin, you should look if your hosting provider doesn't offer this feature.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-client-redirects
```
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `fromExtensions` | `string[]` | `[]` | The extensions to be removed from the route after redirecting. |
| `toExtensions` | `string[]` | `[]` | The extensions to be appended to the route after redirecting. |
| `redirects` | <code>[RedirectRule](#RedirectRule)[]</code> | `[]` | The list of redirect rules. |
| `createRedirects` | <code>[CreateRedirectsFn](#CreateRedirectsFn)</code> | `undefined` | A callback to create a redirect rule. Docusaurus query this callback against every path it has created, and use its return value to output more paths. |
```mdx-code-block
</APITable>
```
:::note
This plugin will also read the [`siteConfig.onDuplicateRoutes`](../docusaurus.config.js.mdx#onDuplicateRoutes) config to adjust its logging level when multiple files will be emitted to the same location.
:::
### Types {#types}
#### `RedirectRule` {#RedirectRule}
```ts
type RedirectRule = {
to: string;
from: string | string[];
};
```
:::note
The idea of "from" and "to" is central in this plugin. "From" means a path that you want to _create_, i.e. an extra HTML file that will be written; "to" means a path to want to redirect _to_, usually a route that Docusaurus already knows about.
This is why you can have multiple "from" for the same "to": we will create multiple HTML files that all redirect to the same destination. On the other hand, one "from" can never have more than one "to": the written HTML file needs to have a determinate destination.
:::
#### `CreateRedirectsFn` {#CreateRedirectsFn}
```ts
// The parameter `path` is a route that Docusaurus has already created. It can
// be seen as the "to", and your return value is the "from". Returning a falsy
// value will not create any redirect pages for this particular path.
type CreateRedirectsFn = (path: string) => string[] | string | null | undefined;
```
### Example configuration {#ex-config}
Here's an example configuration:
```js title="docusaurus.config.js"
export default {
plugins: [
[
'@docusaurus/plugin-client-redirects',
// highlight-start
{
fromExtensions: ['html', 'htm'], // /myPage.html -> /myPage
toExtensions: ['exe', 'zip'], // /myAsset -> /myAsset.zip (if latter exists)
redirects: [
// /docs/oldDoc -> /docs/newDoc
{
to: '/docs/newDoc',
from: '/docs/oldDoc',
},
// Redirect from multiple old paths to the new path
{
to: '/docs/newDoc2',
from: ['/docs/oldDocFrom2019', '/docs/legacyDocFrom2016'],
},
],
createRedirects(existingPath) {
if (existingPath.includes('/community')) {
// Redirect from /docs/team/X to /community/X and /docs/support/X to /community/X
return [
existingPath.replace('/community', '/docs/team'),
existingPath.replace('/community', '/docs/support'),
];
}
return undefined; // Return a falsy value: no redirect created
},
},
// highlight-end
],
],
};
```

View file

@ -0,0 +1,416 @@
---
sidebar_position: 2
slug: /api/plugins/@docusaurus/plugin-content-blog
---
# 📦 plugin-content-blog
import APITable from '@site/src/components/APITable';
Provides the [Blog](blog.mdx) feature and is the default blog plugin for Docusaurus.
:::warning some features production only
The [feed feature](../../blog.mdx#feed) works by extracting the build output, and is **only active in production**.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-content-blog
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | `'blog'` | Path to the blog content directory on the file system, relative to site dir. |
| `editUrl` | <code>string \| [EditUrlFn](#EditUrlFn)</code> | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. |
| `blogTitle` | `string` | `'Blog'` | Blog page title for better SEO. |
| `blogDescription` | `string` | `'Blog'` | Blog page meta description for better SEO. |
| `blogSidebarCount` | <code>number \| 'ALL'</code> | `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 section of your blog. Will be appended to `routeBasePath`. |
| `pageBasePath` | `string` | `'page'` | URL route for the pages section of your blog. Will be appended to `routeBasePath`. |
| `archiveBasePath` | <code>string \| null</code> | `'archive'` | URL route for the archive section of your blog. Will be appended to `routeBasePath`. **DO NOT** include a trailing slash. Use `null` to disable generation of archive. |
| `authorsBasePath` | `string` | `'authors'` | URL route for the authors pages of your blog. Will be appended to `path`. |
| `include` | `string[]` | `['**/*.{md,mdx}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. |
| `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. |
| `postsPerPage` | <code>number \| 'ALL'</code> | `10` | Number of posts to show per page in the listing page. Use `'ALL'` to display all posts on one listing page. |
| `blogListComponent` | `string` | `'@theme/BlogListPage'` | Root component of the blog listing page. |
| `blogPostComponent` | `string` | `'@theme/BlogPostPage'` | Root component of each blog post page. |
| `blogTagsListComponent` | `string` | `'@theme/BlogTagsListPage'` | Root component of the tags list page. |
| `blogTagsPostsComponent` | `string` | `'@theme/BlogTagsPostsPage'` | Root component of the "posts containing tag" page. |
| `blogArchiveComponent` | `string` | `'@theme/BlogArchivePage'` | Root component of the blog archive page. |
| `blogAuthorsPostsComponent` | `string` | `'@theme/Blog/Pages/BlogAuthorsPostsPage'` | Root component of the blog author page. |
| `blogAuthorsListComponent` | `string` | `'@theme/Blog/Pages/BlogAuthorsListPage'` | Root component of the blog authors page index. |
| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. |
| `rehypePlugins` | `any[]` | `[]` | Rehype plugins passed to MDX. |
| `rehypePlugins` | `any[]` | `[]` | Recma plugins passed to MDX. |
| `beforeDefaultRemarkPlugins` | `any[]` | `[]` | Custom Remark plugins passed to MDX before the default Docusaurus Remark plugins. |
| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. |
| `truncateMarker` | `RegExp` | `/<!--\s*truncate\s*-->/` \| `\{\/\*\s*truncate\s*\*\/\}/` | Truncate marker marking where the summary ends. |
| `showReadingTime` | `boolean` | `true` | Show estimated reading time for the blog post. |
| `readingTime` | `ReadingTimeFn` | 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. |
| `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. |
| `feedOptions.type` | <code>[FeedType](#FeedType) \| [FeedType](#FeedType)[] \| 'all' \| null</code> | **Required** | Type of feed to be generated. Use `null` to disable generation. |
| `feedOptions.createFeedItems` | <code>[CreateFeedItemsFn](#CreateFeedItemsFn) \| undefined</code> | `undefined` | An optional function which can be used to transform and / or filter the items in the feed. |
| `feedOptions.limit` | `number \| null \| false` | `20` | Limits the feed to the specified number of posts, `false` or `null` for all entries. Defaults to `20`. |
| `feedOptions.title` | `string` | `siteConfig.title` | Title of the feed. |
| `feedOptions.description` | `string` | <code>\`$\{siteConfig.title} Blog\`</code> | Description of the feed. |
| `feedOptions.copyright` | `string` | `undefined` | Copyright message. |
| `feedOptions.xslt` | <code>boolean \| [FeedXSLTOptions](#FeedXSLTOptions)</code> | `undefined` | Permits to style the blog XML feeds with XSLT so that browsers render them nicely. |
| `feedOptions.language` | `string` (See [documentation](http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes) for possible values) | `undefined` | Language metadata of the feed. |
| `sortPosts` | <code>'descending' \| 'ascending' </code> | `'descending'` | Governs the direction of blog post sorting. |
| `processBlogPosts` | <code>[ProcessBlogPostsFn](#ProcessBlogPostsFn)</code> | `undefined` | An optional function which can be used to transform blog posts (filter, modify, delete, etc...). |
| `showLastUpdateAuthor` | `boolean` | `false` | Whether to display the author who last updated the blog post. |
| `showLastUpdateTime` | `boolean` | `false` | Whether to display the last date the blog post was updated. This requires access to git history during the build, so will not work correctly with shallow clones (a common default for CI systems). With GitHub `actions/checkout`, use`fetch-depth: 0`. |
| `tags` | `string \| false \| null \| undefined` | `tags.yml` | Path to the YAML tags file listing pre-defined tags. Relative to the blog content directory. |
| `onInlineTags` | `'ignore' \| 'log' \| 'warn' \| 'throw'` | `warn` | The plugin behavior when blog posts contain inline tags (not appearing in the list of pre-defined tags, usually `tags.yml`). |
| `onUntruncatedBlogPosts` | `'ignore' \| 'log' \| 'warn' \| 'throw'` | `warn` | The plugin behavior when blog posts do not contain a truncate marker. |
```mdx-code-block
</APITable>
```
### Types {#types}
#### `EditUrlFn` {#EditUrlFn}
```ts
type EditUrlFunction = (params: {
blogDirPath: string;
blogPath: string;
permalink: string;
locale: string;
}) => string | undefined;
```
#### `ReadingTimeFn` {#ReadingTimeFn}
```ts
type ReadingTimeOptions = {
wordsPerMinute: number;
wordBound: (char: string) => boolean;
};
type ReadingTimeCalculator = (params: {
content: string;
frontMatter?: BlogPostFrontMatter & Record<string, unknown>;
options?: ReadingTimeOptions;
}) => number;
type ReadingTimeFn = (params: {
content: string;
frontMatter: BlogPostFrontMatter & Record<string, unknown>;
defaultReadingTime: ReadingTimeCalculator;
}) => number | undefined;
```
#### `FeedType` {#FeedType}
```ts
type FeedType = 'rss' | 'atom' | 'json';
```
#### `FeedXSLTOptions` {#FeedXSLTOptions}
Permits to style the blog XML feeds so that browsers render them nicely with [XSLT](https://developer.mozilla.org/en-US/docs/Web/XSLT).
- Use `true` to let the blog use its built-in `.xsl` and `.css` files to style the blog feed
- Use a falsy value (`undefined | null | false`) to disable the feature
- Use a `string` to provide a file path to a custom `.xsl` file relative to the blog content folder. By convention, you must provide a `.css` file with the exact same name.
```ts
type FeedXSLTOptions =
| boolean
| undefined
| null
| {
rss?: string | boolean | null | undefined;
atom?: string | boolean | null | undefined;
};
```
#### `CreateFeedItemsFn` {#CreateFeedItemsFn}
```ts
type CreateFeedItemsFn = (params: {
blogPosts: BlogPost[];
siteConfig: DocusaurusConfig;
outDir: string;
defaultCreateFeedItemsFn: CreateFeedItemsFn;
}) => Promise<BlogFeedItem[]>;
```
#### `ProcessBlogPostsFn` {#ProcessBlogPostsFn}
```ts
type ProcessBlogPostsFn = (params: {
blogPosts: BlogPost[];
}) => Promise<void | BlogPost[]>;
```
### Example configuration {#ex-config}
You can configure this plugin through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```js config-tabs
// Preset Options: blog
// Plugin Options: @docusaurus/plugin-content-blog
const config = {
path: 'blog',
// Simple use-case: string editUrl
// editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/',
// Advanced use-case: functional editUrl
editUrl: ({locale, blogDirPath, blogPath, permalink}) =>
`https://github.com/facebook/docusaurus/edit/main/website/${blogDirPath}/${blogPath}`,
editLocalizedFiles: false,
blogTitle: 'Blog title',
blogDescription: 'Blog',
blogSidebarCount: 5,
blogSidebarTitle: 'All our posts',
routeBasePath: 'blog',
include: ['**/*.{md,mdx}'],
exclude: [
'**/_*.{js,jsx,ts,tsx,md,mdx}',
'**/_*/**',
'**/*.test.{js,jsx,ts,tsx}',
'**/__tests__/**',
],
postsPerPage: 10,
blogListComponent: '@theme/BlogListPage',
blogPostComponent: '@theme/BlogPostPage',
blogTagsListComponent: '@theme/BlogTagsListPage',
blogTagsPostsComponent: '@theme/BlogTagsPostsPage',
remarkPlugins: [require('./my-remark-plugin')],
rehypePlugins: [],
beforeDefaultRemarkPlugins: [],
beforeDefaultRehypePlugins: [],
truncateMarker: /<!--\s*(truncate)\s*-->/,
showReadingTime: true,
feedOptions: {
type: '',
title: '',
description: '',
copyright: '',
language: undefined,
createFeedItems: async (params) => {
const {blogPosts, defaultCreateFeedItems, ...rest} = params;
return defaultCreateFeedItems({
// keep only the 10 most recent blog posts in the feed
blogPosts: blogPosts.filter((item, index) => index < 10),
...rest,
});
},
},
};
```
## Markdown front matter {#markdown-front-matter}
Markdown documents can use the following Markdown [front matter](../../guides/markdown-features/markdown-features-intro.mdx#front-matter) metadata fields, enclosed by a line `---` on either side.
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `authors` | `Authors` | `undefined` | List of blog post authors (or unique author). Read the [`authors` guide](../../blog.mdx#blog-post-authors) for more explanations. Prefer `authors` over the `author_*` front matter fields, even for single author blog posts. |
| `author` | `string` | `undefined` | ⚠️ Prefer using `authors`. The blog post author's name. |
| `author_url` | `string` | `undefined` | ⚠️ Prefer using `authors`. The URL that the author's name will be linked to. This could be a GitHub, X, Facebook profile URL, etc. |
| `author_image_url` | `string` | `undefined` | ⚠️ Prefer using `authors`. The URL to the author's thumbnail image. |
| `author_title` | `string` | `undefined` | ⚠️ Prefer using `authors`. A description of the author. |
| `title` | `string` | Markdown title | The blog post title. |
| `sidebar_label` | `string` | `title` | A custom label for the blog sidebar, replacing the default one (`title`). |
| `date` | `string` | File name or file creation time | The blog post creation date. If not specified, this can be extracted from the file or folder name, e.g, `2021-04-15-blog-post.mdx`, `2021-04-15-blog-post/index.mdx`, `2021/04/15/blog-post.mdx`. Otherwise, it is the Markdown file creation time. |
| `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your post. Strings can be a reference to keys of a [tags file](#tags-file) (usually `tags.yml`) |
| `draft` | `boolean` | `false` | Draft blog posts will only be available during development. |
| `unlisted` | `boolean` | `false` | Unlisted blog posts will be available in both development and production. They will be "hidden" in production, not indexed, excluded from sitemaps, and can only be accessed by users having a direct link. |
| `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 `<meta name="keywords" content="keyword1,keyword2,..."/>` in `<head>`, used by search engines. |
| `description` | `string` | The first line of Markdown content | The description of your document, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. |
| `image` | `string` | `undefined` | Cover or thumbnail image that will be used as the `<meta property="og:image" content="..."/>` in the `<head>`, enhancing link previews on social media and messaging platforms. |
| `slug` | `string` | File path | Allows to customize the blog post URL (`/<routeBasePath>/<slug>`). Support multiple patterns: `slug: my-blog-post`, `slug: /my/path/to/blog/post`, slug: `/`. |
| `last_update` | `FrontMatterLastUpdate` | `undefined` | Allows overriding the last update author/date. Date can be any [parsable date string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). |
```mdx-code-block
</APITable>
```
```ts
type FrontMatterLastUpdate = {date?: string; author?: string};
type Tag = string | {label: string; permalink: string};
// An author key references an author from the global plugin authors.yml file
type AuthorKey = string;
// Social platform name -> Social platform link
// Example: {MyPlatform: 'https://myplatform.com/myusername'}
// Pre-defined platforms
// ("x", "github", "twitter", "linkedin", "stackoverflow", "instagram", "bluesky", "mastodon", "threads", "twitch", "youtube") accept handles:
// Example: {github: 'slorber'}
type AuthorSocials = Record<string, string>;
type Author = {
key?: AuthorKey;
name: string;
title?: string;
url?: string;
image_url?: string;
socials?: AuthorSocials;
};
// The front matter authors field allows various possible shapes
type Authors = AuthorKey | Author | (AuthorKey | Author)[];
```
Example:
```md
---
title: Welcome Docusaurus
authors:
- slorber
- yangshun
- name: Joel Marcey
title: Co-creator of Docusaurus 1
url: https://github.com/JoelMarcey
image_url: https://github.com/JoelMarcey.png
socials:
x: joelmarcey
github: JoelMarcey
tags: [docusaurus]
description: This is my first post on Docusaurus.
image: https://i.imgur.com/mErPwqL.png
hide_table_of_contents: false
---
A Markdown blog post
```
import TagsFileApiRefSection from './_partial-tags-file-api-ref-section.mdx';
<TagsFileApiRefSection />
## Authors File {#authors-file}
Use the [`authors` plugin option](#authors) to configure the path of a YAML authors file.
By convention, the plugin will look for a `authors.yml` file at the root of your blog content folder(s).
This file can contain a list of predefined [global blog authors](../../blog.mdx#global-authors). You can reference these authors by their keys in Markdown files thanks to the [`authors` front matter](#markdown-front-matter).
### Types {#authors-file-types}
The YAML content of the provided authors file should respect the following shape:
```tsx
type AuthorsMapInput = {
[authorKey: string]: AuthorInput;
};
type AuthorInput = {
name?: string;
title?: string;
description?: string;
imageURL?: string;
url?: string;
email?: string;
page?: boolean | {permalink: string};
socials?: Record<string, string>;
[customAuthorAttribute: string]: unknown;
};
```
### Example {#authors-file-example}
```yml title="tags.yml"
slorber:
name: Sébastien Lorber
title: Docusaurus maintainer
url: https://sebastienlorber.com
image_url: https://github.com/slorber.png
page: true
socials:
x: sebastienlorber
github: slorber
jmarcey:
name: Joel Marcey
title: Co-creator of Docusaurus 1
url: https://github.com/JoelMarcey
image_url: https://github.com/JoelMarcey.png
email: jimarcey@gmail.com
page:
permalink: '/joel-marcey'
socials:
x: joelmarcey
github: JoelMarcey
```
```md title="blog/my-blog-post.md"
---
authors: [slorber, jmarcey]
---
# My Blog Post
Content
```
## i18n {#i18n}
Read the [i18n introduction](../../i18n/i18n-introduction.mdx) first.
### Translation files location {#translation-files-location}
- **Base path**: `website/i18n/[locale]/docusaurus-plugin-content-blog`
- **Multi-instance path**: `website/i18n/[locale]/docusaurus-plugin-content-blog-[pluginId]`
- **JSON files**: extracted with [`docusaurus write-translations`](../../cli.mdx#docusaurus-write-translations-sitedir)
- **Markdown files**: `website/i18n/[locale]/docusaurus-plugin-content-blog`
### Example file-system structure {#example-file-system-structure}
```bash
website/i18n/[locale]/docusaurus-plugin-content-blog
│ # translations for website/blog
├── authors.yml
├── first-blog-post.md
├── second-blog-post.md
│ # translations for the plugin options that will be rendered
└── options.json
```

View file

@ -0,0 +1,377 @@
---
sidebar_position: 1
slug: /api/plugins/@docusaurus/plugin-content-docs
---
# 📦 plugin-content-docs
import APITable from '@site/src/components/APITable';
Provides the [Docs](../../guides/docs/docs-introduction.mdx) functionality and is the default docs plugin for Docusaurus.
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-content-docs
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | `'docs'` | Path to the docs content directory on the file system, relative to site directory. |
| `editUrl` | <code>string \| [EditUrlFunction](#EditUrlFunction)</code> | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `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}']` | Array of glob patterns matching Markdown files to be built, relative to the content path. |
| `exclude` | `string[]` | _See example configuration_ | Array of glob patterns matching Markdown files to be excluded. Serves as refinement based on the `include` option. |
| `sidebarPath` | <code>false \| string</code> | `undefined` | Path to a sidebars configuration file, loaded in a Node.js context. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. |
| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar/items#collapsible-categories) |
| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar/items#expanded-categories-by-default) |
| `sidebarItemsGenerator` | <code>[SidebarGenerator](#SidebarGenerator)</code> | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar/autogenerated#customize-the-sidebar-items-generator) |
| `numberPrefixParser` | <code>boolean \| [PrefixParser](#PrefixParser)</code> | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes) |
| `docsRootComponent` | `string` | `'@theme/DocsRoot'` | Parent component of all the docs plugin pages (including all versions). Stays mounted when navigation between docs pages and versions. |
| `docVersionRootComponent` | `string` | `'@theme/DocVersionLayout'` | Parent component of all docs pages of an individual version (doc pages with sidebars, tags pages). Stays mounted when navigation between pages of that specific version. |
| `docRootComponent` | `string` | `'@theme/DocRoot'` | Parent component of all doc pages with sidebars (regular docs pages, category generated index pages). Stays mounted when navigation between such pages. |
| `docItemComponent` | `string` | `'@theme/DocItem'` | Main doc container, with TOC, pagination, etc. |
| `docTagsListComponent` | `string` | `'@theme/DocTagsListPage'` | Root component of the tags list page |
| `docTagDocListComponent` | `string` | `'@theme/DocTagDocListPage'` | Root component of the "docs containing tag X" page. |
| `docCategoryGeneratedIndexComponent` | `string` | `'@theme/DocCategoryGeneratedIndexPage'` | Root component of the generated category index page. |
| `remarkPlugins` | `any[]` | `[]` | Remark plugins passed to MDX. |
| `rehypePlugins` | `any[]` | `[]` | Rehype plugins passed to MDX. |
| `rehypePlugins` | `any[]` | `[]` | Recma plugins passed to MDX. |
| `beforeDefaultRemarkPlugins` | `any[]` | `[]` | Custom Remark plugins passed to MDX before the default Docusaurus Remark plugins. |
| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. |
| `showLastUpdateAuthor` | `boolean` | `false` | Whether to display the author who last updated the doc. |
| `showLastUpdateTime` | `boolean` | `false` | Whether to display the last date the doc was updated. This requires access to git history during the build, so will not work correctly with shallow clones (a common default for CI systems). With GitHub `actions/checkout`, use`fetch-depth: 0`. |
| `breadcrumbs` | `boolean` | `true` | Enable or disable the breadcrumbs on doc pages. |
| `disableVersioning` | `boolean` | `false` | Explicitly disable versioning even when multiple versions exist. This will make the site only include the current version. Will error if `includeCurrentVersion: false` and `disableVersioning: true`. |
| `includeCurrentVersion` | `boolean` | `true` | Include the current version of your docs. |
| `lastVersion` | `string` | First version in `versions.json` | The version navigated to in priority and displayed by default for docs navbar items. |
| `onlyIncludeVersions` | `string[]` | All versions available | Only include a subset of all available versions. |
| `versions` | <code>[VersionsConfig](#VersionsConfig)</code> | `{}` | Independent customization of each version's properties. |
| `tags` | `string \| false \| null \| undefined` | `tags.yml` | Path to a YAML file listing pre-defined tags. Relative to the docs version content directories. |
| `onInlineTags` | `'ignore' \| 'log' \| 'warn' \| 'throw'` | `warn` | The plugin behavior when docs contain inline tags (not appearing in the list of pre-defined tags, usually `docs/tags.yml`). |
```mdx-code-block
</APITable>
```
### Types {#types}
#### `EditUrlFunction` {#EditUrlFunction}
```ts
type EditUrlFunction = (params: {
version: string;
versionDocsDirPath: string;
docPath: string;
permalink: string;
locale: string;
}) => string | undefined;
```
#### `PrefixParser` {#PrefixParser}
```ts
type PrefixParser = (filename: string) => {
filename: string;
numberPrefix?: number;
};
```
#### `SidebarGenerator` {#SidebarGenerator}
```ts
type SidebarGenerator = (generatorArgs: {
/** The sidebar item with type "autogenerated" to be transformed. */
item: {type: 'autogenerated'; dirName: string};
/** Useful metadata for the version this sidebar belongs to. */
version: {contentPath: string; versionName: string};
/** All the docs of that version (unfiltered). */
docs: {
id: string;
title: string;
frontMatter: DocFrontMatter & Record<string, unknown>;
source: string;
sourceDirName: string;
sidebarPosition?: number | undefined;
}[];
/** Number prefix parser configured for this plugin. */
numberPrefixParser: PrefixParser;
/** The default category index matcher which you can override. */
isCategoryIndex: CategoryIndexMatcher;
/**
* key is the path relative to the doc content directory, value is the
* category metadata file's content.
*/
categoriesMetadata: {[filePath: string]: CategoryMetadata};
/**
* Useful to re-use/enhance the default sidebar generation logic from
* Docusaurus.
*/
defaultSidebarItemsGenerator: SidebarGenerator;
// Returns an array of sidebar items — same as what you can declare in
// sidebars.js, except for shorthands. See https://docusaurus.io/docs/sidebar/items
}) => Promise<SidebarItem[]>;
type CategoryIndexMatcher = (param: {
/** The file name, without extension */
fileName: string;
/**
* The list of directories, from lowest level to highest.
* If there's no dir name, directories is ['.']
*/
directories: string[];
/** The extension, with a leading dot */
extension: string;
}) => boolean;
```
#### `VersionsConfig` {#VersionsConfig}
```ts
type VersionConfig = {
/**
* The base path of the version, will be appended to `baseUrl` +
* `routeBasePath`.
*/
path?: string;
/** The label of the version to be used in badges, dropdowns, etc. */
label?: string;
/** The banner to show at the top of a doc of that version. */
banner?: 'none' | 'unreleased' | 'unmaintained';
/** Show a badge with the version label at the top of each doc. */
badge?: boolean;
/** Prevents search engines from indexing this version */
noIndex?: boolean;
/** Add a custom class name to the <html> element of each doc */
className?: string;
};
type VersionsConfig = {[versionName: string]: VersionConfig};
```
### Example configuration {#ex-config}
You can configure this plugin through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```js config-tabs
// Preset Options: docs
// Plugin Options: @docusaurus/plugin-content-docs
const config = {
path: 'docs',
breadcrumbs: true,
// Simple use-case: string editUrl
// editUrl: 'https://github.com/facebook/docusaurus/edit/main/website/',
// Advanced use-case: functional editUrl
editUrl: ({versionDocsDirPath, docPath}) =>
`https://github.com/facebook/docusaurus/edit/main/website/${versionDocsDirPath}/${docPath}`,
editLocalizedFiles: false,
editCurrentVersion: false,
routeBasePath: 'docs',
include: ['**/*.md', '**/*.mdx'],
exclude: [
'**/_*.{js,jsx,ts,tsx,md,mdx}',
'**/_*/**',
'**/*.test.{js,jsx,ts,tsx}',
'**/__tests__/**',
],
sidebarPath: 'sidebars.js',
async sidebarItemsGenerator({
defaultSidebarItemsGenerator,
numberPrefixParser,
item,
version,
docs,
isCategoryIndex,
}) {
// Use the provided data to generate a custom sidebar slice
return [
{type: 'doc', id: 'intro'},
{
type: 'category',
label: 'Tutorials',
items: [
{type: 'doc', id: 'tutorial1'},
{type: 'doc', id: 'tutorial2'},
],
},
];
},
numberPrefixParser(filename) {
// Implement your own logic to extract a potential number prefix
const numberPrefix = findNumberPrefix(filename);
// Prefix found: return it with the cleaned filename
if (numberPrefix) {
return {
numberPrefix,
filename: filename.replace(prefix, ''),
};
}
// No number prefix found
return {numberPrefix: undefined, filename};
},
docsRootComponent: '@theme/DocsRoot',
docVersionRootComponent: '@theme/DocVersionRoot',
docRootComponent: '@theme/DocRoot',
docItemComponent: '@theme/DocItem',
remarkPlugins: [require('./my-remark-plugin')],
rehypePlugins: [],
beforeDefaultRemarkPlugins: [],
beforeDefaultRehypePlugins: [],
showLastUpdateAuthor: false,
showLastUpdateTime: false,
disableVersioning: false,
includeCurrentVersion: true,
lastVersion: undefined,
versions: {
current: {
label: 'Android SDK v2.0.0 (WIP)',
path: 'android-2.0.0',
banner: 'none',
},
'1.0.0': {
label: 'Android SDK v1.0.0',
path: 'android-1.0.0',
banner: 'unmaintained',
},
},
onlyIncludeVersions: ['current', '1.0.0', '2.0.0'],
};
```
## Markdown front matter {#markdown-front-matter}
Markdown documents can use the following Markdown [front matter](../../guides/markdown-features/markdown-features-intro.mdx#front-matter) metadata fields, enclosed by a line `---` on either side.
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` | file path (including folders, without the extension) | A unique document ID. |
| `title` | `string` | Markdown title or `id` | The text title of your document. Used for the page metadata and as a fallback value in multiple places (sidebar, next/previous buttons...). Automatically added at the top of your doc if it does not contain any Markdown title. |
| `title_meta` | `string` | `frontMatter.title` | The SEO metadata title of your document used in `<head>` for `<title>` and `og:title`. Permits to override `frontMatter.title` when the displayed title and SEO title should be different. |
| `pagination_label` | `string` | `sidebar_label` or `title` | The text used in the document next/previous buttons for this document. |
| `sidebar_label` | `string` | `title` | The text shown in the document sidebar for this document. |
| `sidebar_position` | `number` | Default ordering | Controls the position of a doc inside the generated sidebar slice when using `autogenerated` sidebar items. See also [Autogenerated sidebar metadata](/docs/sidebar/autogenerated#autogenerated-sidebar-metadata). |
| `sidebar_class_name` | `string` | `undefined` | Gives the corresponding sidebar label a special class name when using autogenerated sidebars. |
| `sidebar_custom_props` | `object` | `undefined` | Assign [custom props](../../guides/docs/sidebar/index.mdx#passing-custom-props) to the sidebar item referencing this doc |
| `displayed_sidebar` | `string` | `undefined` | Force the display of a given sidebar when browsing the current document. Read the [multiple sidebars guide](../../guides/docs/sidebar/multiple-sidebars.mdx) for details. |
| `hide_title` | `boolean` | `false` | Whether to hide the title at the top of the doc. It only hides a title declared through the front matter, 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` | <code>string \| null</code> | Next doc in the sidebar | The ID of the documentation you want the "Next" pagination to link to. Use `null` to disable showing "Next" for this page. |
| `pagination_prev` | <code>string \| null</code> | Previous doc in the sidebar | The ID of the documentation you want the "Previous" pagination to link to. Use `null` to disable showing "Previous" for this page. |
| `parse_number_prefixes` | `boolean` | `numberPrefixParser` plugin option | Whether number prefix parsing is disabled on this doc. See also [Using number prefixes](/docs/sidebar/autogenerated#using-number-prefixes). |
| `custom_edit_url` | <code>string \| null</code> | Computed using the `editUrl` plugin option | The URL for editing this document. Use `null` to disable showing "Edit this page" for this page. |
| `keywords` | `string[]` | `undefined` | Keywords meta tag for the document page, for search engines. |
| `description` | `string` | The first line of Markdown content | The description of your document, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. |
| `image` | `string` | `undefined` | Cover or thumbnail image that will be used as the `<meta property="og:image" content="..."/>` in the `<head>`, enhancing link previews on social media and messaging platforms. |
| `slug` | `string` | File path | Allows to customize the document URL (`/<routeBasePath>/<slug>`). Support multiple patterns: `slug: my-doc`, `slug: /my/path/myDoc`, `slug: /`. |
| `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your docs. Strings can be a reference to keys of a [tags file](#tags-file) (usually `tags.yml`) |
| `draft` | `boolean` | `false` | Draft documents will only be available during development. |
| `unlisted` | `boolean` | `false` | Unlisted documents will be available in both development and production. They will be "hidden" in production, not indexed, excluded from sitemaps, and can only be accessed by users having a direct link. |
| `last_update` | `FrontMatterLastUpdate` | `undefined` | Allows overriding the last update author/date. Date can be any [parsable date string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). |
```mdx-code-block
</APITable>
```
```ts
type FrontMatterLastUpdate = {date?: string; author?: string};
type Tag = string | {label: string; permalink: string};
```
Example:
```md
---
id: doc-markdown
title: Docs Markdown Features
hide_title: false
hide_table_of_contents: false
sidebar_label: Markdown
sidebar_position: 3
pagination_label: Markdown features
custom_edit_url: https://github.com/facebook/docusaurus/edit/main/docs/api-doc-markdown.md
description: How do I find you when I cannot solve this problem
keywords:
- docs
- docusaurus
tags: [docusaurus]
image: https://i.imgur.com/mErPwqL.png
slug: /myDoc
last_update:
date: 1/1/2000
author: custom author name
---
# Markdown Features
My Document Markdown content
```
import TagsFileApiRefSection from './_partial-tags-file-api-ref-section.mdx';
<TagsFileApiRefSection />
## i18n {#i18n}
Read the [i18n introduction](../../i18n/i18n-introduction.mdx) first.
### Translation files location {#translation-files-location}
- **Base path**: `website/i18n/[locale]/docusaurus-plugin-content-docs`
- **Multi-instance path**: `website/i18n/[locale]/docusaurus-plugin-content-docs-[pluginId]`
- **JSON files**: extracted with [`docusaurus write-translations`](../../cli.mdx#docusaurus-write-translations-sitedir)
- **Markdown files**: `website/i18n/[locale]/docusaurus-plugin-content-docs/[versionName]`
### Example file-system structure {#example-file-system-structure}
```bash
website/i18n/[locale]/docusaurus-plugin-content-docs
│ # translations for website/docs
├── current
│ ├── api
│ │ └── config.md
│ └── getting-started.md
├── current.json
│ # translations for website/versioned_docs/version-1.0.0
├── version-1.0.0
│ ├── api
│ │ └── config.md
│ └── getting-started.md
└── version-1.0.0.json
```

View file

@ -0,0 +1,158 @@
---
sidebar_position: 3
slug: /api/plugins/@docusaurus/plugin-content-pages
---
# 📦 plugin-content-pages
import APITable from '@site/src/components/APITable';
The default pages plugin for Docusaurus. The classic template ships with this plugin with default configurations. This plugin provides [creating pages](guides/creating-pages.mdx) functionality.
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-content-pages
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `path` | `string` | `'src/pages'` | Path to data on filesystem relative to site dir. Components in this directory will be automatically converted to pages. |
| `editUrl` | <code>string \| [EditUrlFn](#EditUrlFn)</code> | `undefined` | **Only for Markdown pages**. Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `editLocalizedFiles` | `boolean` | `false` | **Only for Markdown pages**. The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. |
| `routeBasePath` | `string` | `'/'` | URL route for the pages section of your site. **DO NOT** include a trailing slash. |
| `include` | `string[]` | `['**/*.{js,jsx,ts,tsx,md,mdx}']` | Matching files will be included and processed. |
| `exclude` | `string[]` | _See example configuration_ | No route will be created for matching files. |
| `mdxPageComponent` | `string` | `'@theme/MDXPage'` | Component used by each MDX page. |
| `remarkPlugins` | `[]` | `any[]` | Remark plugins passed to MDX. |
| `rehypePlugins` | `[]` | `any[]` | Rehype plugins passed to MDX. |
| `rehypePlugins` | `any[]` | `[]` | Recma plugins passed to MDX. |
| `beforeDefaultRemarkPlugins` | `any[]` | `[]` | Custom Remark plugins passed to MDX before the default Docusaurus Remark plugins. |
| `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. |
| `showLastUpdateAuthor` | `boolean` | `false` | **Only for Markdown pages**. Whether to display the author who last updated the page. |
| `showLastUpdateTime` | `boolean` | `false` | **Only for Markdown pages**. Whether to display the last date the page post was updated. This requires access to git history during the build, so will not work correctly with shallow clones (a common default for CI systems). With GitHub `actions/checkout`, use`fetch-depth: 0`. |
```mdx-code-block
</APITable>
```
### Types {#types}
#### `EditUrlFn` {#EditUrlFn}
```ts
type EditUrlFunction = (params: {
blogDirPath: string;
blogPath: string;
permalink: string;
locale: string;
}) => string | undefined;
```
### Example configuration {#ex-config}
You can configure this plugin through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```js config-tabs
// Preset Options: pages
// Plugin Options: @docusaurus/plugin-content-pages
const config = {
path: 'src/pages',
routeBasePath: '',
include: ['**/*.{js,jsx,ts,tsx,md,mdx}'],
exclude: [
'**/_*.{js,jsx,ts,tsx,md,mdx}',
'**/_*/**',
'**/*.test.{js,jsx,ts,tsx}',
'**/__tests__/**',
],
mdxPageComponent: '@theme/MDXPage',
remarkPlugins: [require('./my-remark-plugin')],
rehypePlugins: [],
beforeDefaultRemarkPlugins: [],
beforeDefaultRehypePlugins: [],
};
```
## Markdown front matter {#markdown-front-matter}
Markdown pages can use the following Markdown [front matter](../../guides/markdown-features/markdown-features-intro.mdx#front-matter) metadata fields, enclosed by a line `---` on either side.
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `title` | `string` | Markdown title | The blog post title. |
| `description` | `string` | The first line of Markdown content | The description of your page, which will become the `<meta name="description" content="..."/>` and `<meta property="og:description" content="..."/>` in `<head>`, used by search engines. |
| `keywords` | `string[]` | `undefined` | Keywords meta tag, which will become the `<meta name="keywords" content="keyword1,keyword2,..."/>` in `<head>`, used by search engines. |
| `image` | `string` | `undefined` | Cover or thumbnail image that will be used as the `<meta property="og:image" content="..."/>` in the `<head>`, enhancing link previews on social media and messaging platforms. |
| `wrapperClassName` | `string` | | Class name to be added to the wrapper element to allow targeting specific page content. |
| `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. |
| `draft` | `boolean` | `false` | Draft pages will only be available during development. |
| `unlisted` | `boolean` | `false` | Unlisted pages will be available in both development and production. They will be "hidden" in production, not indexed, excluded from sitemaps, and can only be accessed by users having a direct link. |
```mdx-code-block
</APITable>
```
Example:
```md
---
title: Markdown Page
description: Markdown page SEO description
wrapperClassName: markdown-page
hide_table_of_contents: false
draft: true
---
Markdown page content
```
## i18n {#i18n}
Read the [i18n introduction](../../i18n/i18n-introduction.mdx) first.
### Translation files location {#translation-files-location}
- **Base path**: `website/i18n/[locale]/docusaurus-plugin-content-pages`
- **Multi-instance path**: `website/i18n/[locale]/docusaurus-plugin-content-pages-[pluginId]`
- **JSON files**: extracted with [`docusaurus write-translations`](../../cli.mdx#docusaurus-write-translations-sitedir)
- **Markdown files**: `website/i18n/[locale]/docusaurus-plugin-content-pages`
### Example file-system structure {#example-file-system-structure}
```bash
website/i18n/[locale]/docusaurus-plugin-content-pages
│ # translations for website/src/pages
├── first-markdown-page.md
└── second-markdown-page.md
```

View file

@ -0,0 +1,108 @@
---
sidebar_position: 5
slug: /api/plugins/@docusaurus/plugin-debug
---
# 📦 plugin-debug
```mdx-code-block
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
```
The debug plugin will display useful debug information at [`http://localhost:3000/__docusaurus/debug`](http://localhost:3000/__docusaurus/debug).
It is mostly useful for plugin authors, that will be able to inspect more easily the content of the `.docusaurus` folder (like the creates routes), but also be able to inspect data structures that are never written to disk, like the plugin data loaded through the `contentLoaded` lifecycle.
:::info
If you use the plugin via the classic preset, the preset will **enable the plugin in development and disable it in production** by default (`debug: undefined`) to avoid exposing potentially sensitive information. You can use `debug: true` to always enable it or `debug: false` to always disable it.
If you use a standalone plugin, you may need to achieve the same effect by checking the environment:
```js title="docusaurus.config.js"
export default {
plugins: [
// highlight-next-line
process.env.NODE_ENV === 'production' && '@docusaurus/plugin-debug',
].filter(Boolean),
};
```
:::
:::note
If you report a bug, we will probably ask you to have this plugin turned on in the production, so that we can inspect your deployment config more easily.
If you don't have any sensitive information, you can keep it on in production [like we do](/__docusaurus/debug).
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-debug
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
This plugin currently has no options.
### Example configuration {#ex-config}
You can configure this plugin through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```mdx-code-block
<Tabs groupId="api-config-ex">
<TabItem value="preset" label="Preset options">
```
If you use a preset, configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic):
```js title="docusaurus.config.js"
export default {
presets: [
[
'@docusaurus/preset-classic',
{
// highlight-next-line
debug: true, // This will enable the plugin in production
},
],
],
};
```
```mdx-code-block
</TabItem>
<TabItem value="plugin" label="Plugin Options">
```
If you are using a standalone plugin, provide options directly to the plugin:
```js title="docusaurus.config.js"
export default {
// highlight-next-line
plugins: ['@docusaurus/plugin-debug'],
};
```
```mdx-code-block
</TabItem>
</Tabs>
```

View file

@ -0,0 +1,77 @@
---
sidebar_position: 6
slug: /api/plugins/@docusaurus/plugin-google-analytics
---
# 📦 plugin-google-analytics
import APITable from '@site/src/components/APITable';
The default [Google Analytics](https://developers.google.com/analytics/devguides/collection/analyticsjs/) plugin. It is a JavaScript library for measuring how users interact with your website **in the production build**. If you are using Google Analytics 4 you might need to consider using [plugin-google-gtag](./plugin-google-gtag.mdx) instead.
:::danger Deprecated
This plugin is **deprecated** and became useless on July 1, 2023.
Google is [moving away from Universal Analytics](https://blog.google/products/marketingplatform/analytics/prepare-for-future-with-google-analytics-4/).
If you are still using this plugin with a `UA-*` tracking id, you should create a Google Analytics 4 account as soon as possible, and use [`@docusaurus/plugin-google-gtag`](./plugin-google-gtag.mdx) instead of this plugin. More details [here](https://github.com/facebook/docusaurus/issues/7221).
:::
:::warning production only
This plugin is always inactive in development and **only active in production** to avoid polluting the analytics statistics.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-google-analytics
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `trackingID` | `string` | **Required** | The tracking ID of your analytics service. |
| `anonymizeIP` | `boolean` | `false` | Whether the IP should be anonymized when sending requests. |
```mdx-code-block
</APITable>
```
### Example configuration {#ex-config}
You can configure this plugin through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```js config-tabs
// Preset Options: googleAnalytics
// Plugin Options: @docusaurus/plugin-google-analytics
const config = {
trackingID: 'UA-141789564-1',
anonymizeIP: true,
};
```

View file

@ -0,0 +1,73 @@
---
sidebar_position: 7
slug: /api/plugins/@docusaurus/plugin-google-gtag
---
# 📦 plugin-google-gtag
import APITable from '@site/src/components/APITable';
The default [Global Site Tag (gtag.js)](https://developers.google.com/tag-platform/gtagjs) plugin. It is a JavaScript tagging framework and API that allows you to send event data to Google Analytics, Google Ads, and Google Marketing Platform. This section describes how to configure a Docusaurus site to enable global site tag for Google Analytics.
:::tip
You can use [Google's Tag Assistant](https://tagassistant.google.com/) tool to check if your gtag is set up correctly!
:::
:::warning production only
This plugin is always inactive in development and **only active in production** to avoid polluting the analytics statistics.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-google-gtag
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `trackingID` | <code>string \| string[]</code> | **Required** | The tracking ID of your gtag service. It is possible to provide multiple ids. |
| `anonymizeIP` | `boolean` | `false` | Whether the IP should be anonymized when sending requests. |
```mdx-code-block
</APITable>
```
### Example configuration {#ex-config}
You can configure this plugin through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```js config-tabs
// Preset Options: gtag
// Plugin Options: @docusaurus/plugin-google-gtag
const config = {
trackingID: 'G-999X9XX9XX',
anonymizeIP: true,
};
```

View file

@ -0,0 +1,71 @@
---
sidebar_position: 8
slug: /api/plugins/@docusaurus/plugin-google-tag-manager
---
# 📦 plugin-google-tag-manager
import APITable from '@site/src/components/APITable';
A plugin for adding [Google Tag Manager (gtm.js)](https://developers.google.com/tag-platform/tag-manager) to a Docusaurus site. Use this plugin in conjunction with the standard [gtag plugin](./plugin-google-gtag.mdx) for in-depth analysis of how users are using your site.
:::tip
You can use [Google's Tag Assistant](https://tagassistant.google.com/) tool to check if tag manager is set up correctly!
:::
:::warning production only
This plugin is always inactive in development and **only active in production** to avoid polluting the analytics statistics.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-google-tag-manager
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `containerId` | `string` | **Required** | Your Tag Manager container Id (usually starts with `GTM-`). |
```mdx-code-block
</APITable>
```
### Example configuration {#ex-config}
You can configure this plugin through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```js config-tabs
// Preset Options: googleTagManager
// Plugin Options: @docusaurus/plugin-google-tag-manager
const config = {
containerId: 'GTM-12345',
};
```

View file

@ -0,0 +1,92 @@
---
sidebar_position: 8
slug: /api/plugins/@docusaurus/plugin-ideal-image
---
# 📦 plugin-ideal-image
import APITable from '@site/src/components/APITable';
Docusaurus Plugin to generate an almost ideal image (responsive, lazy-loading, and low quality placeholder).
:::info
By default, the plugin is **inactive in development** so you could always view full-scale images. If you want to debug the ideal image behavior, you could set the [`disableInDev`](#disableInDev) option to `false`.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-ideal-image
```
## Usage {#usage}
This plugin supports the PNG and JPG formats only.
```jsx
import Image from '@theme/IdealImage';
import thumbnail from './path/to/img.png';
// your React code
<Image img={thumbnail} />
// or
<Image img={require('./path/to/img.png')} />
```
:::warning
This plugin registers a [Webpack loader](https://webpack.js.org/loaders/) that changes the type of imported/require images:
- Before: `string`
- After: `{preSrc: string, src: import("@theme/IdealImage").SrcImage}`
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` | `ideal-img/[name].[hash:hex:7].[width].[ext]` | Filename template for output files. |
| `sizes` | `number[]` | _original size_ | 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). |
| `size` | `number` | _original size_ | 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) |
| `min` | `number` | | As an alternative to manually specifying `sizes`, you can specify `min`, `max` and `steps`, and the sizes will be generated for you. |
| `max` | `number` | | See `min` above |
| `steps` | `number` | `4` | Configure the number of images generated between `min` and `max` (inclusive) |
| `quality` | `number` | `85` | JPEG compression quality |
| `disableInDev` | `boolean` | `true` | You can test ideal image behavior in dev mode by setting this to `false`. **Tip**: use [network throttling](https://www.browserstack.com/guide/how-to-perform-network-throttling-in-chrome) in your browser to simulate slow networks. |
```mdx-code-block
</APITable>
```
### Example configuration {#ex-config}
Here's an example configuration:
```js title="docusaurus.config.js"
export default {
plugins: [
[
'@docusaurus/plugin-ideal-image',
// highlight-start
{
quality: 70,
max: 1030, // max resized image's size.
min: 640, // min resized image's size. if original is lower, use that size.
steps: 2, // the max number of images generated between min and max (inclusive)
disableInDev: false,
},
// highlight-end
],
],
};
```

View file

@ -0,0 +1,303 @@
---
sidebar_position: 9
slug: /api/plugins/@docusaurus/plugin-pwa
---
# 📦 plugin-pwa
Docusaurus Plugin to add PWA support using [Workbox](https://developers.google.com/web/tools/workbox). This plugin generates a [Service Worker](https://developers.google.com/web/fundamentals/primers/service-workers) in production build only, and allows you to create fully PWA-compliant documentation site with offline and installation support.
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-pwa
```
## Configuration {#configuration}
Create a [PWA manifest](https://web.dev/add-manifest/) at `./static/manifest.json`.
Modify `docusaurus.config.js` with a minimal PWA config, like:
```js title="docusaurus.config.js"
export default {
plugins: [
[
'@docusaurus/plugin-pwa',
{
debug: true,
offlineModeActivationStrategies: [
'appInstalled',
'standalone',
'queryString',
],
pwaHead: [
{
tagName: 'link',
rel: 'icon',
href: '/img/docusaurus.png',
},
{
tagName: 'link',
rel: 'manifest',
href: '/manifest.json', // your PWA manifest
},
{
tagName: 'meta',
name: 'theme-color',
content: 'rgb(37, 194, 160)',
},
],
},
],
],
};
```
## Progressive Web App {#progressive-web-app}
Having a service worker installed is not enough to make your application a PWA. You'll need to at least include a [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) and have the correct tags in `<head>` ([Options > pwaHead](#pwahead)).
After deployment, you can use [Lighthouse](https://developers.google.com/web/tools/lighthouse) to run an audit on your site.
For a more exhaustive list of what it takes for your site to be a PWA, refer to the [PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist)
## App installation support {#app-installation-support}
If your browser supports it, you should be able to install a Docusaurus site as an app.
![A screen recording of the installation process. A button appears in the address bar of the browser, which displays a dialog asking "install this application?" when clicked. After clicking the "Install" button, a new application is opened in the operating system, opening to the Docusaurus homepage.](/img/pwa_install.gif)
:::note
App installation requires the HTTPS protocol and a valid manifest.
:::
## Offline mode (precaching) {#offline-mode-precaching}
We enable users to browse a Docusaurus site offline, by using service-worker precaching.
The [workbox-precaching](https://developers.google.com/web/tools/workbox/modules/workbox-precaching) page explains the idea:
> One feature of service workers is the ability to save a set of files to the cache when the service worker is installing. This is often referred to as "precaching", since you are caching content ahead of the service worker being used.
>
> The main reason for doing this is that it gives developers control over the cache, meaning they can determine when and how long a file is cached as well as serve it to the browser without going to the network, meaning it can be used to create web apps that work offline.
>
> Workbox takes a lot of the heavy lifting out of precaching by simplifying the API and ensuring assets are downloaded efficiently.
By default, offline mode is enabled when the site is installed as an app. See the `offlineModeActivationStrategies` option for details.
After the site has been precached, the service worker will serve cached responses for later visits. When a new build is deployed along with a new service worker, the new one will begin installing and eventually move to a waiting state. During this waiting state, a reload popup will show and ask the user to reload the page for new content. Until the user either clears the application cache or clicks the `reload` button on the popup, the service worker will continue serving the old content.
:::warning
Offline mode / precaching requires downloading all the static assets of the site ahead of time, and can consume unnecessary bandwidth. It may not be a good idea to activate it for all kind of sites.
:::
## Options {#options}
### `debug` {#debug}
- Type: `boolean`
- Default: `false`
Turn debug mode on:
- Workbox logs
- Additional Docusaurus logs
- Unoptimized SW file output
- Source maps
### `offlineModeActivationStrategies` {#offlinemodeactivationstrategies}
- Type: `('appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always')[]`
- Default: `['appInstalled', 'queryString', 'standalone']`
Strategies used to turn the offline mode on:
- `appInstalled`: activates for users having installed the site as an app (not 100% reliable)
- `standalone`: activates for users running the app as standalone (often the case once a PWA is installed)
- `queryString`: activates if queryString contains `offlineMode=true` (convenient for PWA debugging)
- `mobile`: activates for mobile users (`width <= 996px`)
- `saveData`: activates for users with `navigator.connection.saveData === true`
- `always`: activates for all users
:::warning
Use this carefully: some users may not like to be forced to use the offline mode.
:::
:::danger
It is not possible to detect if a page is rendered as a PWA in a reliable manner.
The `appinstalled` event has been [removed from the specification](https://github.com/w3c/manifest/pull/836), and the [`navigator.getInstalledRelatedApps()`](https://web.dev/get-installed-related-apps/) API is only supported in recent Chrome versions and require `related_applications` declared in the manifest.
The [`standalone` strategy](https://petelepage.com/blog/2019/07/is-my-pwa-installed/) is a nice fallback to activate the offline mode (at least when running the installed app).
:::
### `injectManifestConfig` {#injectmanifestconfig}
[Workbox options](https://developer.chrome.com/docs/workbox/reference/workbox-build/#type-InjectManifestOptions) to pass to `workbox.injectManifest()`. This gives you control over which assets will be precached, and be available offline.
- Type: `InjectManifestOptions`
- Default: `{}`
```js title="docusaurus.config.js"
export default {
plugins: [
[
'@docusaurus/plugin-pwa',
{
injectManifestConfig: {
manifestTransforms: [
//...
],
modifyURLPrefix: {
//...
},
// We already add regular static assets (HTML, images...) to be available offline
// You can add more files according to your needs
globPatterns: ['**/*.{pdf,docx,xlsx}'],
// ...
},
},
],
],
};
```
### `pwaHead` {#pwahead}
- Type: `({ tagName: string; [attributeName: string]: string })[]`
- Default: `[]`
Array of objects containing `tagName` and key-value pairs for attributes to inject into the `<head>` tag. Technically you can inject any head tag through this, but it's ideally used for tags to make your site PWA compliant. Here's a list of tag to make your app fully compliant:
```js
export default {
plugins: [
[
'@docusaurus/plugin-pwa',
{
pwaHead: [
{
tagName: 'link',
rel: 'icon',
href: '/img/docusaurus.png',
},
{
tagName: 'link',
rel: 'manifest',
href: '/manifest.json',
},
{
tagName: 'meta',
name: 'theme-color',
content: 'rgb(37, 194, 160)',
},
{
tagName: 'meta',
name: 'apple-mobile-web-app-capable',
content: 'yes',
},
{
tagName: 'meta',
name: 'apple-mobile-web-app-status-bar-style',
content: '#000',
},
{
tagName: 'link',
rel: 'apple-touch-icon',
href: '/img/docusaurus.png',
},
{
tagName: 'link',
rel: 'mask-icon',
href: '/img/docusaurus.svg',
color: 'rgb(37, 194, 160)',
},
{
tagName: 'meta',
name: 'msapplication-TileImage',
content: '/img/docusaurus.png',
},
{
tagName: 'meta',
name: 'msapplication-TileColor',
content: '#000',
},
],
},
],
],
};
```
### `swCustom` {#swcustom}
- Type: `string | undefined`
- Default: `undefined`
Useful for additional Workbox rules. You can do whatever a service worker can do here, and use the full power of workbox libraries. The code is transpiled, so you can use modern ES6+ syntax here.
For example, to cache files from external routes:
```js
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
// default fn export receiving some useful params
export default function swCustom(params) {
const {
debug, // :boolean
offlineMode, // :boolean
} = params;
// Cache responses from external resources
registerRoute((context) => {
return [
/graph\.facebook\.com\/.*\/picture/,
/netlify\.com\/img/,
/avatars1\.githubusercontent/,
].some((regex) => context.url.href.match(regex));
}, new StaleWhileRevalidate());
}
```
The module should have a `default` function export, and receives some params.
### `swRegister` {#swregister}
- Type: `string | false`
- Default: `'docusaurus-plugin-pwa/src/registerSW.js'`
Adds an entry before the Docusaurus app so that registration can happen before the app runs. The default `registerSW.js` file is enough for simple registration.
Passing `false` will disable registration entirely.
## Manifest example {#manifest-example}
The Docusaurus site manifest can serve as an inspiration:
```mdx-code-block
import CodeBlock from '@theme/CodeBlock';
<CodeBlock className="language-json">
{JSON.stringify(require('@site/static/manifest.json'),null,2)}
</CodeBlock>
```
## Customizing reload popup {#customizing-reload-popup}
The `@theme/PwaReloadPopup` component is rendered when a new service worker is waiting to be installed, and we suggest a reload to the user. You can [swizzle](../../swizzling.mdx) this component and implement your own UI. It will receive an `onReload` callback as props, which should be called when the `reload` button is clicked. This will tell the service worker to install the waiting service worker and reload the page.
The default theme includes an implementation for the reload popup and uses [Infima Alerts](https://infima.dev/docs/components/alert).
![A screen recording of the reload process. An alert box shows in the bottom right of the window, saying "New content available". After clicking the "Refresh" button, the page's main heading changes from "Introduction" to "PWA :))".](/img/pwa_reload.gif)
Your component can render `null`, but this is not recommended: users won't have a way to get up-to-date content.

View file

@ -0,0 +1,57 @@
---
sidebar_position: 7
slug: /api/plugins/@docusaurus/plugin-rsdoctor
---
# 📦 plugin-rsdoctor
import APITable from '@site/src/components/APITable';
A [Rsdoctor](https://rsdoctor.dev/) plugin can help you troubleshoot the bundling phase of your Docusaurus site, supporting both Webpack and Rspack.
:::tip
Use it to figure out which plugin or loader is slowing down the bundler, and focus your efforts on optimizing the bottleneck.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-rsdoctor
```
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `rsdoctorOptions` | `object` | `{}` | The [Rsdoctor bundler plugin options](https://rsdoctor.dev/config/options/options), forwarded as is |
```mdx-code-block
</APITable>
```
### Example configuration {#ex-config}
You can configure this plugin through plugin options.
```js title="docusaurus.config.js"
export default {
plugins: [
[
'rsdoctor',
{
rsdoctorOptions: {
mode: 'lite',
},
},
],
],
};
```

View file

@ -0,0 +1,110 @@
---
sidebar_position: 10
slug: /api/plugins/@docusaurus/plugin-sitemap
---
# 📦 plugin-sitemap
import APITable from '@site/src/components/APITable';
This plugin creates sitemaps for your site so that search engine crawlers can crawl your site more accurately.
:::warning production only
This plugin is always inactive in development and **only active in production** because it works on the build output.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-sitemap
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `lastmod` | `'date' \| 'datetime' \| null` | `null` | `date` is YYYY-MM-DD. `datetime` is a ISO 8601 datetime. `null` is disabled. See [sitemap docs](https://www.sitemaps.org/protocol.html#xmlTagDefinitions). |
| `changefreq` | `string \| null` | `'weekly'` | See [sitemap docs](https://www.sitemaps.org/protocol.html#xmlTagDefinitions) |
| `priority` | `number \| null` | `0.5` | See [sitemap docs](https://www.sitemaps.org/protocol.html#xmlTagDefinitions) |
| `ignorePatterns` | `string[]` | `[]` | A list of glob patterns; matching route paths will be filtered from the sitemap. Note that you may need to include the base URL in here. |
| `filename` | `string` | `sitemap.xml` | The path to the created sitemap file, relative to the output directory. Useful if you have two plugin instances outputting two files. |
| `createSitemapItems` | <code>[CreateSitemapItemsFn](#CreateSitemapItemsFn) \| undefined</code> | `undefined` | An optional function which can be used to transform and / or filter the items in the sitemap. |
```mdx-code-block
</APITable>
```
### Types {#types}
#### `CreateSitemapItemsFn` {#CreateSitemapItemsFn}
```ts
type CreateSitemapItemsFn = (params: {
siteConfig: DocusaurusConfig;
routes: RouteConfig[];
defaultCreateSitemapItems: CreateSitemapItemsFn;
}) => Promise<SitemapItem[]>;
```
:::info
This plugin also respects some site config:
- [`noIndex`](../docusaurus.config.js.mdx#noIndex): results in no sitemap generated
- [`trailingSlash`](../docusaurus.config.js.mdx#trailingSlash): determines if the URLs in the sitemap have trailing slashes
:::
:::note About `lastmod`
The `lastmod` option will only output a sitemap `<lastmod>` tag if plugins provide [route metadata](../plugin-methods/lifecycle-apis.mdx#addRoute) attributes `sourceFilePath` and/or `lastUpdatedAt`.
All the official content plugins provide the metadata for routes backed by a content file (Markdown, MDX or React page components), but it is possible third-party plugin authors do not provide this information, and the plugin will not be able to output a `<lastmod>` tag for their routes.
:::
### Example configuration {#ex-config}
You can configure this plugin through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```js config-tabs
// Preset Options: sitemap
// Plugin Options: @docusaurus/plugin-sitemap
const config = {
lastmod: 'date',
changefreq: 'weekly',
priority: 0.5,
ignorePatterns: ['/tags/**'],
filename: 'sitemap.xml',
createSitemapItems: async (params) => {
const {defaultCreateSitemapItems, ...rest} = params;
const items = await defaultCreateSitemapItems(rest);
return items.filter((item) => !item.url.includes('/page/'));
},
};
```
You can find your sitemap at `/sitemap.xml`.

View file

@ -0,0 +1,55 @@
---
sidebar_position: 7
slug: /api/plugins/@docusaurus/plugin-svgr
---
# 📦 plugin-svgr
import APITable from '@site/src/components/APITable';
An [SVGR](https://react-svgr.com/) plugin to transform SVG files into React components automatically at build time.
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-svgr
```
:::tip
If you use the preset `@docusaurus/preset-classic`, you don't need to install this plugin as a dependency.
You can configure this plugin through the [preset options](../../using-plugins.mdx#docusauruspreset-classic).
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `svgrConfig` | `object` | `{}` | The [SVGR config options](https://react-svgr.com/docs/options/), forwarded as is |
```mdx-code-block
</APITable>
```
### Example configuration {#ex-config}
You can configure this plugin through plugin options.
```js config-tabs
// Preset Options: svgr
// Plugin Options: @docusaurus/plugin-svgr
const config = {
svgrConfig: {
/* SVGR config */
},
};
```

View file

@ -0,0 +1,57 @@
---
sidebar_position: 11
slug: /api/plugins/@docusaurus/plugin-vercel-analytics
---
# 📦 plugin-vercel-analytics
import APITable from '@site/src/components/APITable';
[Vercel Analytics](https://vercel.com/docs/analytics) provides comprehensive insights into your website's visitors, tracking top pages, referrers, and demographics like location, operating systems, and browser info.
:::warning production only
This plugin is always inactive in development and **only active in production** (`docusaurus build`) to avoid polluting the analytics statistics.
:::
## Installation {#installation}
```bash npm2yarn
npm install --save @docusaurus/plugin-vercel-analytics
```
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | `string` | `'auto'` | Override the automatic environment detection. Read the [official docs](https://vercel.com/docs/analytics/package#mode) for details. |
| `debug` | `boolean` | `undefined` | Enable browser console logging of analytics events. Read the [official docs](https://vercel.com/docs/analytics/package#debug) for details. |
```mdx-code-block
</APITable>
```
### Example configuration {#ex-config}
You can configure this plugin through plugin options.
```js title="docusaurus.config.js"
export default {
plugins: [
[
'vercel-analytics',
{
debug: true,
mode: 'auto',
},
],
],
};
```

View file

@ -0,0 +1,5 @@
label: Themes
position: 3
link:
type: doc
id: themes-overview # Dogfood using a "local id"

View file

@ -0,0 +1,34 @@
---
sidebar_position: 0
id: themes-overview
sidebar_label: Themes overview
slug: /api/themes
---
# Docusaurus themes
We provide official Docusaurus themes.
## Main themes {#main-themes}
The main themes implement the user interface for the [docs](../plugins/plugin-content-docs.mdx), [blog](../plugins/plugin-content-blog.mdx) and [pages](../plugins/plugin-content-pages.mdx) plugins.
- [@docusaurus/theme-classic](./theme-classic.mdx)
- 🚧 other themes are planned
:::warning
The goal is to have all themes share the exact same features, user-experience and configuration.
Only the UI design and underlying styling framework should change, and you should be able to change theme easily.
We are not there yet: only the classic theme is production ready.
:::
## Enhancement themes {#enhancement-themes}
These themes will enhance the existing main themes with additional user-interface related features.
- [@docusaurus/theme-live-codeblock](./theme-live-codeblock.mdx)
- [@docusaurus/theme-search-algolia](./theme-search-algolia.mdx)

View file

@ -0,0 +1,63 @@
---
sidebar_position: 2
slug: /api/themes/@docusaurus/theme-classic
---
# 📦 theme-classic
import APITable from '@site/src/components/APITable';
The classic theme for Docusaurus.
You can refer to the [theme configuration page](theme-configuration.mdx) for more details on the configuration.
```bash npm2yarn
npm install --save @docusaurus/theme-classic
```
:::tip
If you have installed `@docusaurus/preset-classic`, you don't need to install it as a dependency.
:::
## Configuration {#configuration}
Accepted fields:
```mdx-code-block
<APITable>
```
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `customCss` | <code>string[] \| string</code> | `[]` | Stylesheets to be imported globally as [client modules](../../advanced/client.mdx#client-modules). Relative paths are resolved against the site directory. |
```mdx-code-block
</APITable>
```
:::note
Most configuration for the theme is done in `themeConfig`, which can be found in [theme configuration](./theme-configuration.mdx).
:::
### Example configuration {#ex-config}
You can configure this theme through preset options or plugin options.
:::tip
Most Docusaurus users configure this plugin through the preset options.
:::
```js config-tabs
// Preset Options: theme
// Plugin Options: @docusaurus/theme-classic
const config = {
customCss: './src/css/custom.css',
};
```

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
---
sidebar_position: 3
slug: /api/themes/@docusaurus/theme-live-codeblock
---
# 📦 theme-live-codeblock
This theme provides a `@theme/CodeBlock` component that is powered by react-live. You can read more on [interactive code editor](../../guides/markdown-features/markdown-features-code-blocks.mdx#interactive-code-editor) documentation.
```bash npm2yarn
npm install --save @docusaurus/theme-live-codeblock
```
### Configuration {#configuration}
```js title="docusaurus.config.js"
export default {
plugins: ['@docusaurus/theme-live-codeblock'],
themeConfig: {
liveCodeBlock: {
/**
* The position of the live playground, above or under the editor
* Possible values: "top" | "bottom"
*/
playgroundPosition: 'bottom',
},
},
};
```

View file

@ -0,0 +1,25 @@
---
sidebar_position: 5
slug: /api/themes/@docusaurus/theme-mermaid
---
# 📦 theme-mermaid
This theme provides a `@theme/Mermaid` component that is powered by [mermaid](https://mermaid-js.github.io/). You can read more on [diagrams](../../guides/markdown-features/markdown-features-diagrams.mdx) documentation.
```bash npm2yarn
npm install --save @docusaurus/theme-mermaid
```
## Configuration {#configuration}
```js title="docusaurus.config.js"
export default {
themes: ['@docusaurus/theme-mermaid'],
// In order for Mermaid code blocks in Markdown to work,
// you also need to enable the Remark plugin with this option
markdown: {
mermaid: true,
},
};
```

View file

@ -0,0 +1,20 @@
---
sidebar_position: 4
slug: /api/themes/@docusaurus/theme-search-algolia
---
# 📦 theme-search-algolia
This theme provides a `@theme/SearchBar` component that integrates with Algolia DocSearch easily. Combined with `@docusaurus/theme-classic`, it provides a very easy search integration. You can read more on [search](../../search.mdx) documentation.
```bash npm2yarn
npm install --save @docusaurus/theme-search-algolia
```
This theme also adds search page available at `/search` (as swizzlable `SearchPage` component) path with OpenSearch support. You can change this default path via `themeConfig.algolia.searchPagePath`. Use `false` to disable search page.
:::tip
If you have installed `@docusaurus/preset-classic`, you don't need to install it as a dependency.
:::

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View file

@ -0,0 +1,766 @@
---
description: Deploy a full-featured blog in no time with Docusaurus.
---
# Blog
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
The blog feature enables you to deploy a full-featured blog in no time.
:::info
Check the [Blog Plugin API Reference documentation](./api/plugins/plugin-content-blog.mdx) for an exhaustive list of options.
:::
## Initial setup {#initial-setup}
To set up your site's blog, start by creating a `blog` directory.
Then, add an item link to your blog within `docusaurus.config.js`:
```js title="docusaurus.config.js"
export default {
themeConfig: {
// ...
navbar: {
items: [
// ...
// highlight-next-line
{to: 'blog', label: 'Blog', position: 'left'}, // or position: 'right'
],
},
},
};
```
## Adding posts {#adding-posts}
To publish in the blog, create a Markdown file within the blog directory.
For example, create a file at `website/blog/2019-09-05-hello-docusaurus.md`:
```md title="website/blog/2019-09-05-hello-docusaurus.md"
---
title: Welcome Docusaurus
description: This is my first post on Docusaurus.
slug: welcome-docusaurus-v2
authors:
- name: Joel Marcey
title: Co-creator of Docusaurus 1
url: https://github.com/JoelMarcey
image_url: https://github.com/JoelMarcey.png
socials:
x: joelmarcey
github: JoelMarcey
- name: Sébastien Lorber
title: Docusaurus maintainer
url: https://sebastienlorber.com
image_url: https://github.com/slorber.png
socials:
x: sebastienlorber
github: slorber
tags: [hello, docusaurus-v2]
image: https://i.imgur.com/mErPwqL.png
hide_table_of_contents: false
---
Welcome to this blog. This blog is created with [**Docusaurus 2**](https://docusaurus.io/).
<!-- truncate -->
This is my first post on Docusaurus 2.
A whole bunch of exploration to follow.
```
The [front matter](./guides/markdown-features/markdown-features-intro.mdx#front-matter) is useful to add more metadata to your blog post, for example, author information, but Docusaurus will be able to infer all necessary metadata without the front matter. For all possible fields, see [the API documentation](api/plugins/plugin-content-blog.mdx#markdown-front-matter).
## Blog list {#blog-list}
The blog's index page (by default, it is at `/blog`) is the _blog list page_, where all blog posts are collectively displayed.
Use the `<!--truncate-->` marker in your blog post to represent what will be shown as the summary when viewing all published blog posts. Anything above `<!--truncate-->` will be part of the summary. Note that the portion above the truncate marker must be standalone renderable Markdown. For example:
```md title="website/blog/my-post.md" {7}
---
title: Markdown blog truncation example
---
All these will be part of the blog post summary.
<!-- truncate -->
But anything from here on down will not be.
```
For files using the `.mdx` extension, use a [MDX](https://mdxjs.com/) comment `{/* truncate */}` instead:
{/* prettier-ignore */}
```md title="website/blog/my-post.mdx" {7}
---
title: MDX blog truncation Example
---
All these will be part of the blog post summary.
{/* truncate */}
But anything from here on down will not be.
```
By default, 10 posts are shown on each blog list page, but you can control pagination with the `postsPerPage` option in the plugin configuration. If you set `postsPerPage: 'ALL'`, pagination will be disabled and all posts will be displayed on the first page. You can also add a meta description to the blog list page for better SEO:
```js title="docusaurus.config.js"
export default {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
blog: {
// highlight-start
blogTitle: 'Docusaurus blog!',
blogDescription: 'A Docusaurus powered blog!',
postsPerPage: 'ALL',
// highlight-end
},
},
],
],
};
```
## Blog sidebar {#blog-sidebar}
The blog sidebar displays recent blog posts. The default number of items shown is 5, but you can customize with the `blogSidebarCount` option in the plugin configuration. By setting `blogSidebarCount: 0`, the sidebar will be completely disabled, with the container removed as well. This will increase the width of the main container. Specially, if you have set `blogSidebarCount: 'ALL'`, _all_ posts will be displayed.
You can also alter the sidebar heading text with the `blogSidebarTitle` option. For example, if you have set `blogSidebarCount: 'ALL'`, instead of the default "Recent posts", you may rather make it say "All posts":
```js title="docusaurus.config.js"
export default {
presets: [
[
'@docusaurus/preset-classic',
{
blog: {
// highlight-start
blogSidebarTitle: 'All posts',
blogSidebarCount: 'ALL',
// highlight-end
},
},
],
],
};
```
## Blog post date {#blog-post-date}
Docusaurus will extract a `YYYY-MM-DD` date from many patterns such as `YYYY-MM-DD-my-blog-post-title.md` or `YYYY/MM/DD/my-blog-post-title.md`. This enables you to easily group blog posts by year, by month, or to use a flat structure.
<details>
<summary>Supported date extraction patterns</summary>
| Pattern | Example |
| --- | --- |
| Single file | `2021-05-28-my-blog-post-title.md` |
| MDX file | `2021-05-28-my-blog-post-title.mdx` |
| Single folder + `index.md` | `2021-05-28-my-blog-post-title/index.md` |
| Folder named by date | `2021-05-28/my-blog-post-title.md` |
| Nested folders by date | `2021/05/28/my-blog-post-title.md` |
| Partially nested folders by date | `2021/05-28-my-blog-post-title.md` |
| Nested folders + `index.md` | `2021/05/28/my-blog-post-title/index.md` |
| Date in the middle of path | `category/2021/05-28-my-blog-post-title.md` |
Docusaurus can extract the date from the posts using any of the naming patterns above. It is advisable to choose one pattern and apply it to all posts to avoid confusion.
</details>
:::tip
Using a folder can be convenient to co-locate blog post images alongside the Markdown file.
:::
This naming convention is optional, and you can also provide the date as front matter. Since the front matter follows YAML syntax where the datetime notation is supported, you can use front matter if you need more fine-grained publish dates. For example, if you have multiple posts published on the same day, you can order them according to the time of the day:
```md title="earlier-post.md"
---
date: 2021-09-13T10:00
---
```
```md title="later-post.md"
---
date: 2021-09-13T18:00
---
```
## Blog post authors {#blog-post-authors}
Use the `authors` front matter field to declare blog post authors. An author should have at least a `name` or an `image_url`. Docusaurus uses information like `url`, `email`, and `title`, but any other information is allowed.
### Inline authors {#inline-authors}
Blog post authors can be declared directly inside the front matter:
```mdx-code-block
<Tabs groupId="author-front-matter">
<TabItem value="single" label="Single author">
```
```md title="my-blog-post.md"
---
authors:
name: Joel Marcey
title: Co-creator of Docusaurus 1
url: https://github.com/JoelMarcey
image_url: https://github.com/JoelMarcey.png
email: jimarcey@gmail.com
socials:
x: joelmarcey
github: JoelMarcey
---
```
```mdx-code-block
</TabItem>
<TabItem value="multiple" label="Multiple authors">
```
```md title="my-blog-post.md"
---
authors:
- name: Joel Marcey
title: Co-creator of Docusaurus 1
url: https://github.com/JoelMarcey
image_url: https://github.com/JoelMarcey.png
email: jimarcey@gmail.com
socials:
x: joelmarcey
github: JoelMarcey
- name: Sébastien Lorber
title: Docusaurus maintainer
url: https://sebastienlorber.com
image_url: https://github.com/slorber.png
socials:
x: sebastienlorber
github: slorber
---
```
```mdx-code-block
</TabItem>
</Tabs>
```
:::tip
This option works best to get started, or for casual, irregular authors.
:::
:::info
Prefer using the `authors` front matter, but the legacy `author_*` front matter remains supported:
```md title="my-blog-post.md"
---
author: Joel Marcey
author_title: Co-creator of Docusaurus 1
author_url: https://github.com/JoelMarcey
author_image_url: https://github.com/JoelMarcey.png
---
```
:::
### Global authors {#global-authors}
For regular blog post authors, it can be tedious to maintain authors' information inlined in each blog post.
It is possible to declare those authors globally in a configuration file:
```yml title="website/blog/authors.yml"
jmarcey:
name: Joel Marcey
title: Co-creator of Docusaurus 1
url: https://github.com/JoelMarcey
image_url: https://github.com/JoelMarcey.png
email: jimarcey@gmail.com
socials:
x: joelmarcey
github: JoelMarcey
slorber:
name: Sébastien Lorber
title: Docusaurus maintainer
url: https://sebastienlorber.com
image_url: https://github.com/slorber.png
socials:
x: sebastienlorber
github: slorber
```
:::tip
Use the `authorsMapPath` plugin option to configure the path. JSON is also supported.
:::
In blog posts front matter, you can reference the authors declared in the global configuration file:
```mdx-code-block
<Tabs groupId="author-front-matter">
<TabItem value="single" label="Single author">
```
```md title="my-blog-post.md"
---
authors: jmarcey
---
```
```mdx-code-block
</TabItem>
<TabItem value="multiple" label="Multiple authors">
```
```md title="my-blog-post.md"
---
authors: [jmarcey, slorber]
---
```
```mdx-code-block
</TabItem>
</Tabs>
```
:::info
The `authors` system is very flexible and can suit more advanced use-case:
<details>
<summary>Mix inline authors and global authors</summary>
You can use global authors most of the time, and still use inline authors:
```md title="my-blog-post.md"
---
authors:
- jmarcey
- slorber
- name: Inline Author name
title: Inline Author Title
url: https://github.com/inlineAuthor
image_url: https://github.com/inlineAuthor
---
```
</details>
<details>
<summary>Local override of global authors</summary>
You can customize the global author's data on per-blog-post basis:
```md title="my-blog-post.md"
---
authors:
- key: jmarcey
title: Joel Marcey's new title
- key: slorber
name: Sébastien Lorber's new name
---
```
</details>
<details>
<summary>Localize the author's configuration file</summary>
The configuration file can be localized, just create a localized copy of it at:
```bash
website/i18n/[locale]/docusaurus-plugin-content-blog/authors.yml
```
</details>
:::
An author, either declared through front matter or through the authors map, needs to have a name or an avatar, or both. If all authors of a post don't have names, Docusaurus will display their avatars compactly. See [this test post](/tests/blog/2022/01/20/image-only-authors) for the effect.
:::warning Feed generation
[RSS feeds](#feed) require the author's email to be set for the author to appear in the feed.
:::
### Authors pages {#authors-pages}
The authors pages feature is optional, and mainly useful for multi-author blogs.
You can activate it independently for each author by adding a `page: true` attribute to the [global author configuration](#global-authors):
```yml title="website/blog/authors.yml"
slorber:
name: Sébastien Lorber
// highlight-start
page: true # Turns the feature on - route will be /authors/slorber
// highlight-end
jmarcey:
name: Joel Marcey
// highlight-start
page:
# Turns the feature on - route will be /authors/custom-author-url
permalink: '/custom-author-url'
// highlight-end
```
The blog plugin will now generate:
- a dedicated author page for each author ([example](/blog/authors/slorber)) listing all the blog posts they contributed to
- an authors index page ([example](/blog/authors)) listing all these authors, in the order they appear in `authors.yml`
:::warning About inline authors
Only [global authors](#global-authors) can activate this feature. [Inline authors](#inline-authors) are not supported.
:::
## Blog post tags {#blog-post-tags}
Tags are declared in the front matter and introduce another dimension of categorization.
It is possible to define tags inline, or to reference predefined tags declared in a [`tags file`](api/plugins/plugin-content-blog.mdx#tags-file) (optional, usually `blog/tags.yml`).
In the following example:
- `docusaurus` references a predefined tag key declared in `blog/tags.yml`
- `Releases` is an inline tag, because it does not exist in `blog/tags.yml`
```md title="blog/my-post.md"
---
title: 'My blog post'
tags:
- Releases
- docusaurus
---
Content
```
```yml title="blog/tags.yml"
docusaurus:
label: 'Docusaurus'
permalink: '/docusaurus'
description: 'Blog posts related to the Docusaurus framework'
```
## 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"
export default {
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
<Tabs>
<TabItem value="disable-per-post" label="Per-post disabling">
```
**Disable reading time on one page:**
```js title="docusaurus.config.js"
export default {
presets: [
[
'@docusaurus/preset-classic',
{
blog: {
showReadingTime: true,
// highlight-start
readingTime: ({content, frontMatter, defaultReadingTime}) =>
frontMatter.hide_reading_time
? undefined
: defaultReadingTime({content}),
// highlight-end
},
},
],
],
};
```
Usage:
```md "my-blog-post.md"
---
hide_reading_time: true
---
This page will no longer display the reading time stats!
```
```mdx-code-block
</TabItem>
<TabItem value="passing-options" label="Passing options">
```
**Pass options to the default reading time function:**
```js title="docusaurus.config.js"
export default {
presets: [
[
'@docusaurus/preset-classic',
{
blog: {
// highlight-start
readingTime: ({content, defaultReadingTime}) =>
defaultReadingTime({content, options: {wordsPerMinute: 100}}),
// highlight-end
},
},
],
],
};
```
```mdx-code-block
</TabItem>
<TabItem value="using-custom-algo" label="Using custom algorithms">
```
**Use a custom implementation of reading time:**
```js title="docusaurus.config.js"
import myReadingTime from './myReadingTime';
export default {
presets: [
[
'@docusaurus/preset-classic',
{
blog: {
// highlight-next-line
readingTime: ({content}) => myReadingTime(content),
},
},
],
],
};
```
```mdx-code-block
</TabItem>
</Tabs>
```
:::
## Feed {#feed}
You can generate RSS / Atom / JSON feed by passing `feedOptions`. By default, RSS and Atom feeds are generated. To disable feed generation, set `feedOptions.type` to `null`.
```ts
type FeedType = 'rss' | 'atom' | 'json';
type BlogOptions = {
feedOptions?: {
type?: FeedType | 'all' | FeedType[] | null;
title?: string;
description?: string;
copyright: string;
language?: string; // possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
limit?: number | false | null; // defaults to 20
// XSLT permits browsers to style and render nicely the feed XML files
xslt?:
| boolean
| {
//
rss?: string | boolean;
atom?: string | boolean;
};
// Allow control over the construction of BlogFeedItems
createFeedItems?: (params: {
blogPosts: BlogPost[];
siteConfig: DocusaurusConfig;
outDir: string;
defaultCreateFeedItems: (params: {
blogPosts: BlogPost[];
siteConfig: DocusaurusConfig;
outDir: string;
}) => Promise<BlogFeedItem[]>;
}) => Promise<BlogFeedItem[]>;
};
};
```
Example usage:
```js title="docusaurus.config.js"
export default {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
blog: {
// highlight-start
feedOptions: {
type: 'all',
copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`,
createFeedItems: async (params) => {
const {blogPosts, defaultCreateFeedItems, ...rest} = params;
return defaultCreateFeedItems({
// keep only the 10 most recent blog posts in the feed
blogPosts: blogPosts.filter((item, index) => index < 10),
...rest,
});
},
},
// highlight-end
},
},
],
],
};
```
The feeds can be found at:
<Tabs>
<TabItem value="RSS">
```text
https://example.com/blog/rss.xml
```
</TabItem>
<TabItem value="Atom">
```text
https://example.com/blog/atom.xml
```
</TabItem>
<TabItem value="JSON">
```text
https://example.com/blog/feed.json
```
</TabItem>
</Tabs>
## Advanced topics {#advanced-topics}
### Blog-only mode {#blog-only-mode}
You can run your Docusaurus site without a dedicated landing page and instead have your blog's post list page as the index page. Set the `routeBasePath` to be `'/'` to serve the blog through the root route `example.com/` instead of the subroute `example.com/blog/`.
```js title="docusaurus.config.js"
export default {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
// highlight-next-line
docs: false, // Optional: disable the docs plugin
blog: {
// highlight-next-line
routeBasePath: '/', // Serve the blog at the site's root
/* other blog options */
},
},
],
],
};
```
:::warning
Don't forget to delete the existing homepage at `./src/pages/index.js` or else there will be two files mapping to the same route!
:::
:::warning
If you disable the docs plugin, don't forget to delete references to the docs plugin elsewhere in your configuration file. Notably, make sure to remove the docs-related navbar items.
:::
:::tip
There's also a "Docs-only mode" for those who only want to use the docs. Read [Docs-only mode](./guides/docs/docs-introduction.mdx) for detailed instructions or a more elaborate explanation of `routeBasePath`.
:::
### Multiple blogs {#multiple-blogs}
By default, the classic theme assumes only one blog per website and hence includes only one instance of the blog plugin. If you would like to have multiple blogs on a single website, it's possible too! You can add another blog by specifying another blog plugin in the `plugins` option for `docusaurus.config.js`.
Set the `routeBasePath` to the URL route that you want your second blog to be accessed on. Note that the `routeBasePath` here has to be different from the first blog or else there could be a collision of paths! Also, set `path` to the path to the directory containing your second blog's entries.
As documented for [multi-instance plugins](./using-plugins.mdx#multi-instance-plugins-and-plugin-ids), you need to assign a unique ID to the plugins.
```js title="docusaurus.config.js"
export default {
// ...
plugins: [
[
'@docusaurus/plugin-content-blog',
{
/**
* Required for any multi-instance plugin
*/
id: 'second-blog',
/**
* URL route for the blog section of your site.
* *DO NOT* include a trailing slash.
*/
routeBasePath: 'my-second-blog',
/**
* Path to data on filesystem relative to site dir.
*/
path: './my-second-blog',
},
],
],
};
```
As an example, we host a second blog [here](/tests/blog).

Some files were not shown because too many files have changed in this diff Show more