diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 59cf43b24e..c77f082a7b 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -10,7 +10,10 @@ import kebabCase from 'lodash.kebabcase'; import path from 'path'; import admonitions from 'remark-admonitions'; import {normalizeUrl, docuHash, aliasedSitePath} from '@docusaurus/utils'; -import {STATIC_DIR_NAME} from '@docusaurus/core/lib/constants'; +import { + STATIC_DIR_NAME, + DEFAULT_PLUGIN_ID, +} from '@docusaurus/core/lib/constants'; import {ValidationError} from '@hapi/joi'; import { @@ -48,11 +51,15 @@ export default function pluginContentBlog( const {siteDir, generatedFilesDir} = context; const contentPath = path.resolve(siteDir, options.path); - const dataDir = path.join( + + const pluginDataDirRoot = path.join( generatedFilesDir, 'docusaurus-plugin-content-blog', - // options.id ?? 'default', // TODO support multi-instance ); + const dataDir = path.join(pluginDataDirRoot, options.id ?? DEFAULT_PLUGIN_ID); + const aliasedSource = (source: string) => + `~blog/${path.relative(pluginDataDirRoot, source)}`; + let blogPosts: BlogPost[] = []; return { @@ -206,8 +213,6 @@ export default function pluginContentBlog( blogTagsPostsComponent, } = options; - const aliasedSource = (source: string) => - `~blog/${path.relative(dataDir, source)}`; const {addRoute, createData} = actions; const { blogPosts: loadedBlogPosts, @@ -349,7 +354,7 @@ export default function pluginContentBlog( return { resolve: { alias: { - '~blog': dataDir, + '~blog': pluginDataDirRoot, }, }, module: { @@ -369,10 +374,10 @@ export default function pluginContentBlog( // Note that metadataPath must be the same/in-sync as // the path from createData for each MDX. metadataPath: (mdxPath: string) => { - const aliasedSource = aliasedSitePath(mdxPath, siteDir); + const aliasedPath = aliasedSitePath(mdxPath, siteDir); return path.join( dataDir, - `${docuHash(aliasedSource)}.json`, + `${docuHash(aliasedPath)}.json`, ); }, }, diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community/team.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community/team.md new file mode 100644 index 0000000000..b989b6ea00 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community/team.md @@ -0,0 +1 @@ +Team current version diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_sidebars.json b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_sidebars.json new file mode 100644 index 0000000000..42e2d114ef --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_sidebars.json @@ -0,0 +1,3 @@ +{ + "community": ["team"] +} diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md new file mode 100644 index 0000000000..2beb991291 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md @@ -0,0 +1 @@ +Team 1.0.0 diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json new file mode 100644 index 0000000000..e147407d83 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json @@ -0,0 +1,3 @@ +{ + "version-1.0.0/community": ["version-1.0.0/team"] +} diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versions.json b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versions.json new file mode 100644 index 0000000000..64de05e14b --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/versioned-site/community_versions.json @@ -0,0 +1 @@ +["1.0.0"] diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap index 0c8f98619a..41ccc9a2bb 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap @@ -54,6 +54,351 @@ Object { `; exports[`simple website content 2`] = ` +Object { + "pluginName": Object { + "pluginId": Object { + "latestVersionName": null, + "path": "/docs", + "versions": Array [ + Object { + "docs": Array [ + Object { + "id": "foo/bar", + "path": "/docs/foo/bar", + }, + Object { + "id": "foo/baz", + "path": "/docs/foo/bazSlug.html", + }, + Object { + "id": "hello", + "path": "/docs/", + }, + Object { + "id": "ipsum", + "path": "/docs/ipsum", + }, + Object { + "id": "lorem", + "path": "/docs/lorem", + }, + Object { + "id": "rootAbsoluteSlug", + "path": "/docs/rootAbsoluteSlug", + }, + Object { + "id": "rootRelativeSlug", + "path": "/docs/rootRelativeSlug", + }, + Object { + "id": "rootResolvedSlug", + "path": "/docs/hey/rootResolvedSlug", + }, + Object { + "id": "rootTryToEscapeSlug", + "path": "/docs/rootTryToEscapeSlug", + }, + Object { + "id": "slugs/absoluteSlug", + "path": "/docs/absoluteSlug", + }, + Object { + "id": "slugs/relativeSlug", + "path": "/docs/slugs/relativeSlug", + }, + Object { + "id": "slugs/resolvedSlug", + "path": "/docs/slugs/hey/resolvedSlug", + }, + Object { + "id": "slugs/tryToEscapeSlug", + "path": "/docs/tryToEscapeSlug", + }, + ], + "mainDocId": "hello", + "name": null, + "path": "/docs", + }, + ], + }, + }, +} +`; + +exports[`simple website content: data 1`] = ` +Object { + "docs-route-ff2.json": "{ + \\"docsSidebars\\": { + \\"docs\\": [ + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"Test\\", + \\"items\\": [ + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"foo\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"Bar\\", + \\"href\\": \\"/docs/foo/bar\\" + }, + { + \\"type\\": \\"link\\", + \\"label\\": \\"baz\\", + \\"href\\": \\"/docs/foo/bazSlug.html\\" + } + ] + }, + { + \\"type\\": \\"link\\", + \\"label\\": \\"Github\\", + \\"href\\": \\"https://github.com\\" + }, + { + \\"type\\": \\"link\\", + \\"label\\": \\"Hello, World !\\", + \\"href\\": \\"/docs/\\" + } + ] + }, + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"Guides\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"Hello, World !\\", + \\"href\\": \\"/docs/\\" + } + ] + } + ] + }, + \\"permalinkToSidebar\\": { + \\"/docs/\\": \\"docs\\", + \\"/docs/foo/bar\\": \\"docs\\", + \\"/docs/foo/bazSlug.html\\": \\"docs\\" + }, + \\"version\\": null +}", + "site-docs-foo-bar-md-8c2.json": "{ + \\"unversionedId\\": \\"foo/bar\\", + \\"id\\": \\"foo/bar\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"Bar\\", + \\"description\\": \\"This is custom description\\", + \\"source\\": \\"@site/docs/foo/bar.md\\", + \\"permalink\\": \\"/docs/foo/bar\\", + \\"sidebar\\": \\"docs\\", + \\"next\\": { + \\"title\\": \\"baz\\", + \\"permalink\\": \\"/docs/foo/bazSlug.html\\" + } +}", + "site-docs-foo-baz-md-a69.json": "{ + \\"unversionedId\\": \\"foo/baz\\", + \\"id\\": \\"foo/baz\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"baz\\", + \\"description\\": \\"Images\\", + \\"source\\": \\"@site/docs/foo/baz.md\\", + \\"permalink\\": \\"/docs/foo/bazSlug.html\\", + \\"sidebar\\": \\"docs\\", + \\"previous\\": { + \\"title\\": \\"Bar\\", + \\"permalink\\": \\"/docs/foo/bar\\" + }, + \\"next\\": { + \\"title\\": \\"Hello, World !\\", + \\"permalink\\": \\"/docs/\\" + } +}", + "site-docs-hello-md-9df.json": "{ + \\"unversionedId\\": \\"hello\\", + \\"id\\": \\"hello\\", + \\"isDocsHomePage\\": true, + \\"title\\": \\"Hello, World !\\", + \\"description\\": \\"Hi, Endilie here :)\\", + \\"source\\": \\"@site/docs/hello.md\\", + \\"permalink\\": \\"/docs/\\", + \\"sidebar\\": \\"docs\\", + \\"previous\\": { + \\"title\\": \\"baz\\", + \\"permalink\\": \\"/docs/foo/bazSlug.html\\" + } +}", + "site-docs-ipsum-md-c61.json": "{ + \\"unversionedId\\": \\"ipsum\\", + \\"id\\": \\"ipsum\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"ipsum\\", + \\"description\\": \\"Lorem ipsum.\\", + \\"source\\": \\"@site/docs/ipsum.md\\", + \\"permalink\\": \\"/docs/ipsum\\", + \\"editUrl\\": null +}", + "site-docs-lorem-md-b27.json": "{ + \\"unversionedId\\": \\"lorem\\", + \\"id\\": \\"lorem\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"lorem\\", + \\"description\\": \\"Lorem ipsum.\\", + \\"source\\": \\"@site/docs/lorem.md\\", + \\"permalink\\": \\"/docs/lorem\\", + \\"editUrl\\": \\"https://github.com/customUrl/docs/lorem.md\\" +}", + "site-docs-root-absolute-slug-md-db5.json": "{ + \\"unversionedId\\": \\"rootAbsoluteSlug\\", + \\"id\\": \\"rootAbsoluteSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"rootAbsoluteSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/rootAbsoluteSlug.md\\", + \\"permalink\\": \\"/docs/rootAbsoluteSlug\\" +}", + "site-docs-root-relative-slug-md-3dd.json": "{ + \\"unversionedId\\": \\"rootRelativeSlug\\", + \\"id\\": \\"rootRelativeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"rootRelativeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/rootRelativeSlug.md\\", + \\"permalink\\": \\"/docs/rootRelativeSlug\\" +}", + "site-docs-root-resolved-slug-md-4d1.json": "{ + \\"unversionedId\\": \\"rootResolvedSlug\\", + \\"id\\": \\"rootResolvedSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"rootResolvedSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/rootResolvedSlug.md\\", + \\"permalink\\": \\"/docs/hey/rootResolvedSlug\\" +}", + "site-docs-root-try-to-escape-slug-md-9ee.json": "{ + \\"unversionedId\\": \\"rootTryToEscapeSlug\\", + \\"id\\": \\"rootTryToEscapeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"rootTryToEscapeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/rootTryToEscapeSlug.md\\", + \\"permalink\\": \\"/docs/rootTryToEscapeSlug\\" +}", + "site-docs-slugs-absolute-slug-md-4e8.json": "{ + \\"unversionedId\\": \\"slugs/absoluteSlug\\", + \\"id\\": \\"slugs/absoluteSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"absoluteSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/slugs/absoluteSlug.md\\", + \\"permalink\\": \\"/docs/absoluteSlug\\" +}", + "site-docs-slugs-relative-slug-md-d1c.json": "{ + \\"unversionedId\\": \\"slugs/relativeSlug\\", + \\"id\\": \\"slugs/relativeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"relativeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/slugs/relativeSlug.md\\", + \\"permalink\\": \\"/docs/slugs/relativeSlug\\" +}", + "site-docs-slugs-resolved-slug-md-02b.json": "{ + \\"unversionedId\\": \\"slugs/resolvedSlug\\", + \\"id\\": \\"slugs/resolvedSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"resolvedSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/slugs/resolvedSlug.md\\", + \\"permalink\\": \\"/docs/slugs/hey/resolvedSlug\\" +}", + "site-docs-slugs-try-to-escape-slug-md-70d.json": "{ + \\"unversionedId\\": \\"slugs/tryToEscapeSlug\\", + \\"id\\": \\"slugs/tryToEscapeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"tryToEscapeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/slugs/tryToEscapeSlug.md\\", + \\"permalink\\": \\"/docs/tryToEscapeSlug\\" +}", +} +`; + +exports[`simple website content: global data 1`] = ` +Object { + "pluginName": Object { + "pluginId": Object { + "latestVersionName": null, + "path": "/docs", + "versions": Array [ + Object { + "docs": Array [ + Object { + "id": "foo/bar", + "path": "/docs/foo/bar", + }, + Object { + "id": "foo/baz", + "path": "/docs/foo/bazSlug.html", + }, + Object { + "id": "hello", + "path": "/docs/", + }, + Object { + "id": "ipsum", + "path": "/docs/ipsum", + }, + Object { + "id": "lorem", + "path": "/docs/lorem", + }, + Object { + "id": "rootAbsoluteSlug", + "path": "/docs/rootAbsoluteSlug", + }, + Object { + "id": "rootRelativeSlug", + "path": "/docs/rootRelativeSlug", + }, + Object { + "id": "rootResolvedSlug", + "path": "/docs/hey/rootResolvedSlug", + }, + Object { + "id": "rootTryToEscapeSlug", + "path": "/docs/rootTryToEscapeSlug", + }, + Object { + "id": "slugs/absoluteSlug", + "path": "/docs/absoluteSlug", + }, + Object { + "id": "slugs/relativeSlug", + "path": "/docs/slugs/relativeSlug", + }, + Object { + "id": "slugs/resolvedSlug", + "path": "/docs/slugs/hey/resolvedSlug", + }, + Object { + "id": "slugs/tryToEscapeSlug", + "path": "/docs/tryToEscapeSlug", + }, + ], + "mainDocId": "hello", + "name": null, + "path": "/docs", + }, + ], + }, + }, +} +`; + +exports[`simple website content: route config 1`] = ` Array [ Object { "component": "@theme/DocPage", @@ -173,78 +518,6 @@ Array [ ] `; -exports[`simple website content 3`] = ` -Object { - "pluginName": Object { - "pluginId": Object { - "latestVersionName": null, - "path": "/docs", - "versions": Array [ - Object { - "docs": Array [ - Object { - "id": "foo/bar", - "path": "/docs/foo/bar", - }, - Object { - "id": "foo/baz", - "path": "/docs/foo/bazSlug.html", - }, - Object { - "id": "hello", - "path": "/docs/", - }, - Object { - "id": "ipsum", - "path": "/docs/ipsum", - }, - Object { - "id": "lorem", - "path": "/docs/lorem", - }, - Object { - "id": "rootAbsoluteSlug", - "path": "/docs/rootAbsoluteSlug", - }, - Object { - "id": "rootRelativeSlug", - "path": "/docs/rootRelativeSlug", - }, - Object { - "id": "rootResolvedSlug", - "path": "/docs/hey/rootResolvedSlug", - }, - Object { - "id": "rootTryToEscapeSlug", - "path": "/docs/rootTryToEscapeSlug", - }, - Object { - "id": "slugs/absoluteSlug", - "path": "/docs/absoluteSlug", - }, - Object { - "id": "slugs/relativeSlug", - "path": "/docs/slugs/relativeSlug", - }, - Object { - "id": "slugs/resolvedSlug", - "path": "/docs/slugs/hey/resolvedSlug", - }, - Object { - "id": "slugs/tryToEscapeSlug", - "path": "/docs/tryToEscapeSlug", - }, - ], - "mainDocId": "hello", - "name": null, - "path": "/docs", - }, - ], - }, - }, -} -`; - exports[`site with wrong sidebar file 1`] = ` "Bad sidebars file. The document id 'goku' was used in the sidebar, but no document with this id could be found. Available document ids= @@ -263,40 +536,171 @@ Available document ids= - slugs/tryToEscapeSlug" `; -exports[`versioned website content 1`] = ` +exports[`versioned website (community) content: all sidebars 1`] = ` +Object { + "community": Array [ + Object { + "href": "/community/next/team", + "label": "team", + "type": "link", + }, + ], + "version-1.0.0/community": Array [ + Object { + "href": "/community/team", + "label": "team", + "type": "link", + }, + ], +} +`; + +exports[`versioned website (community) content: base metadata for latest version 1`] = ` +Object { + "docsSidebars": Object { + "version-1.0.0/community": Array [ + Object { + "href": "/community/team", + "label": "team", + "type": "link", + }, + ], + }, + "permalinkToSidebar": Object { + "/community/team": "version-1.0.0/community", + }, + "version": "1.0.0", +} +`; + +exports[`versioned website (community) content: base metadata for next version 1`] = ` +Object { + "docsSidebars": Object { + "community": Array [ + Object { + "href": "/community/next/team", + "label": "team", + "type": "link", + }, + ], + }, + "permalinkToSidebar": Object { + "/community/next/team": "community", + }, + "version": "next", +} +`; + +exports[`versioned website (community) content: data 1`] = ` +Object { + "community-next-route-f11.json": "{ + \\"docsSidebars\\": { + \\"community\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"team\\", + \\"href\\": \\"/community/next/team\\" + } + ] + }, + \\"permalinkToSidebar\\": { + \\"/community/next/team\\": \\"community\\" + }, + \\"version\\": \\"next\\" +}", + "community-route-aa2.json": "{ + \\"docsSidebars\\": { + \\"version-1.0.0/community\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"team\\", + \\"href\\": \\"/community/team\\" + } + ] + }, + \\"permalinkToSidebar\\": { + \\"/community/team\\": \\"version-1.0.0/community\\" + }, + \\"version\\": \\"1.0.0\\" +}", + "site-community-team-md-9d8.json": "{ + \\"unversionedId\\": \\"team\\", + \\"id\\": \\"team\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"team\\", + \\"description\\": \\"Team current version\\", + \\"source\\": \\"@site/community/team.md\\", + \\"permalink\\": \\"/community/next/team\\", + \\"version\\": \\"next\\", + \\"sidebar\\": \\"community\\" +}", + "site-community-versioned-docs-version-1-0-0-team-md-359.json": "{ + \\"unversionedId\\": \\"team\\", + \\"id\\": \\"version-1.0.0/team\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"team\\", + \\"description\\": \\"Team 1.0.0\\", + \\"source\\": \\"@site/community_versioned_docs/version-1.0.0/team.md\\", + \\"permalink\\": \\"/community/team\\", + \\"version\\": \\"1.0.0\\", + \\"sidebar\\": \\"version-1.0.0/community\\" +}", +} +`; + +exports[`versioned website (community) content: global data 1`] = ` +Object { + "pluginName": Object { + "pluginId": Object { + "latestVersionName": "1.0.0", + "path": "/community", + "versions": Array [ + Object { + "docs": Array [ + Object { + "id": "team", + "path": "/community/next/team", + }, + ], + "mainDocId": "team", + "name": "next", + "path": "/community/next", + }, + Object { + "docs": Array [ + Object { + "id": "team", + "path": "/community/team", + }, + ], + "mainDocId": "team", + "name": "1.0.0", + "path": "/community", + }, + ], + }, + }, +} +`; + +exports[`versioned website (community) content: route config 1`] = ` Array [ Object { "component": "@theme/DocPage", "exact": false, "modules": Object { - "docsMetadata": "~docs/docs-1-0-0-route-660.json", + "docsMetadata": "~docs/community-next-route-f11.json", }, - "path": "/docs/1.0.0", + "path": "/community/next", "priority": undefined, "routes": Array [ Object { "component": "@theme/DocItem", "exact": true, "modules": Object { - "content": "@site/versioned_docs/version-1.0.0/hello.md", + "content": "@site/community/team.md", }, - "path": "/docs/1.0.0/", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-1.0.0/foo/bar.md", - }, - "path": "/docs/1.0.0/foo/barSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-1.0.0/foo/baz.md", - }, - "path": "/docs/1.0.0/foo/baz", + "path": "/community/next/team", }, ], }, @@ -304,279 +708,31 @@ Array [ "component": "@theme/DocPage", "exact": false, "modules": Object { - "docsMetadata": "~docs/docs-next-route-1c8.json", + "docsMetadata": "~docs/community-route-aa2.json", }, - "path": "/docs/next", - "priority": undefined, - "routes": Array [ - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/docs/hello.md", - }, - "path": "/docs/next/", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/docs/slugs/absoluteSlug.md", - }, - "path": "/docs/next/absoluteSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/docs/foo/bar.md", - }, - "path": "/docs/next/foo/barSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/docs/slugs/resolvedSlug.md", - }, - "path": "/docs/next/slugs/hey/resolvedSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/docs/slugs/relativeSlug.md", - }, - "path": "/docs/next/slugs/relativeSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/docs/slugs/tryToEscapeSlug.md", - }, - "path": "/docs/next/tryToEscapeSlug", - }, - ], - }, - Object { - "component": "@theme/DocPage", - "exact": false, - "modules": Object { - "docsMetadata": "~docs/docs-with-slugs-route-335.json", - }, - "path": "/docs/withSlugs", - "priority": undefined, - "routes": Array [ - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md", - }, - "path": "/docs/withSlugs/absoluteSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-withSlugs/rootResolvedSlug.md", - }, - "path": "/docs/withSlugs/hey/rootResolvedSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md", - }, - "path": "/docs/withSlugs/rootAbsoluteSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-withSlugs/rootRelativeSlug.md", - }, - "path": "/docs/withSlugs/rootRelativeSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md", - }, - "path": "/docs/withSlugs/rootTryToEscapeSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md", - }, - "path": "/docs/withSlugs/slugs/hey/resolvedSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-withSlugs/slugs/relativeSlug.md", - }, - "path": "/docs/withSlugs/slugs/relativeSlug", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md", - }, - "path": "/docs/withSlugs/tryToEscapeSlug", - }, - ], - }, - Object { - "component": "@theme/DocPage", - "exact": false, - "modules": Object { - "docsMetadata": "~docs/docs-route-ff2.json", - }, - "path": "/docs", + "path": "/community", "priority": -1, "routes": Array [ Object { "component": "@theme/DocItem", "exact": true, "modules": Object { - "content": "@site/versioned_docs/version-1.0.1/hello.md", + "content": "@site/community_versioned_docs/version-1.0.0/team.md", }, - "path": "/docs/", - }, - Object { - "component": "@theme/DocItem", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-1.0.1/foo/bar.md", - }, - "path": "/docs/foo/bar", + "path": "/community/team", }, ], }, ] `; -exports[`versioned website content 2`] = ` +exports[`versioned website (community) content: sidebars needed for each version 1`] = ` Object { - "pluginName": Object { - "pluginId": Object { - "latestVersionName": "1.0.1", - "path": "/docs", - "versions": Array [ - Object { - "docs": Array [ - Object { - "id": "foo/bar", - "path": "/docs/next/foo/barSlug", - }, - Object { - "id": "hello", - "path": "/docs/next/", - }, - Object { - "id": "slugs/absoluteSlug", - "path": "/docs/next/absoluteSlug", - }, - Object { - "id": "slugs/relativeSlug", - "path": "/docs/next/slugs/relativeSlug", - }, - Object { - "id": "slugs/resolvedSlug", - "path": "/docs/next/slugs/hey/resolvedSlug", - }, - Object { - "id": "slugs/tryToEscapeSlug", - "path": "/docs/next/tryToEscapeSlug", - }, - ], - "mainDocId": "hello", - "name": "next", - "path": "/docs/next", - }, - Object { - "docs": Array [ - Object { - "id": "foo/bar", - "path": "/docs/foo/bar", - }, - Object { - "id": "hello", - "path": "/docs/", - }, - ], - "mainDocId": "hello", - "name": "1.0.1", - "path": "/docs", - }, - Object { - "docs": Array [ - Object { - "id": "foo/bar", - "path": "/docs/1.0.0/foo/barSlug", - }, - Object { - "id": "foo/baz", - "path": "/docs/1.0.0/foo/baz", - }, - Object { - "id": "hello", - "path": "/docs/1.0.0/", - }, - ], - "mainDocId": "hello", - "name": "1.0.0", - "path": "/docs/1.0.0", - }, - Object { - "docs": Array [ - Object { - "id": "rootAbsoluteSlug", - "path": "/docs/withSlugs/rootAbsoluteSlug", - }, - Object { - "id": "rootRelativeSlug", - "path": "/docs/withSlugs/rootRelativeSlug", - }, - Object { - "id": "rootResolvedSlug", - "path": "/docs/withSlugs/hey/rootResolvedSlug", - }, - Object { - "id": "rootTryToEscapeSlug", - "path": "/docs/withSlugs/rootTryToEscapeSlug", - }, - Object { - "id": "slugs/absoluteSlug", - "path": "/docs/withSlugs/absoluteSlug", - }, - Object { - "id": "slugs/relativeSlug", - "path": "/docs/withSlugs/slugs/relativeSlug", - }, - Object { - "id": "slugs/resolvedSlug", - "path": "/docs/withSlugs/slugs/hey/resolvedSlug", - }, - Object { - "id": "slugs/tryToEscapeSlug", - "path": "/docs/withSlugs/tryToEscapeSlug", - }, - ], - "mainDocId": "rootAbsoluteSlug", - "name": "withSlugs", - "path": "/docs/withSlugs", - }, - ], - }, + "1.0.0": Set { + "version-1.0.0/community", + }, + "next": Set { + "community", }, } `; @@ -789,6 +945,674 @@ Object { } `; +exports[`versioned website content: data 1`] = ` +Object { + "docs-1-0-0-route-660.json": "{ + \\"docsSidebars\\": { + \\"version-1.0.0/docs\\": [ + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"Test\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"bar\\", + \\"href\\": \\"/docs/1.0.0/foo/barSlug\\" + }, + { + \\"type\\": \\"link\\", + \\"label\\": \\"baz\\", + \\"href\\": \\"/docs/1.0.0/foo/baz\\" + } + ] + }, + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"Guides\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"hello\\", + \\"href\\": \\"/docs/1.0.0/\\" + } + ] + } + ] + }, + \\"permalinkToSidebar\\": { + \\"/docs/1.0.0/\\": \\"version-1.0.0/docs\\", + \\"/docs/1.0.0/foo/barSlug\\": \\"version-1.0.0/docs\\", + \\"/docs/1.0.0/foo/baz\\": \\"version-1.0.0/docs\\" + }, + \\"version\\": \\"1.0.0\\" +}", + "docs-next-route-1c8.json": "{ + \\"docsSidebars\\": { + \\"docs\\": [ + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"Test\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"bar\\", + \\"href\\": \\"/docs/next/foo/barSlug\\" + } + ] + }, + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"Guides\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"hello\\", + \\"href\\": \\"/docs/next/\\" + } + ] + } + ] + }, + \\"permalinkToSidebar\\": { + \\"/docs/next/\\": \\"docs\\", + \\"/docs/next/foo/barSlug\\": \\"docs\\" + }, + \\"version\\": \\"next\\" +}", + "docs-route-ff2.json": "{ + \\"docsSidebars\\": { + \\"version-1.0.1/docs\\": [ + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"Test\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"bar\\", + \\"href\\": \\"/docs/foo/bar\\" + } + ] + }, + { + \\"collapsed\\": true, + \\"type\\": \\"category\\", + \\"label\\": \\"Guides\\", + \\"items\\": [ + { + \\"type\\": \\"link\\", + \\"label\\": \\"hello\\", + \\"href\\": \\"/docs/\\" + } + ] + } + ] + }, + \\"permalinkToSidebar\\": { + \\"/docs/\\": \\"version-1.0.1/docs\\", + \\"/docs/foo/bar\\": \\"version-1.0.1/docs\\" + }, + \\"version\\": \\"1.0.1\\" +}", + "docs-with-slugs-route-335.json": "{ + \\"docsSidebars\\": {}, + \\"permalinkToSidebar\\": {}, + \\"version\\": \\"withSlugs\\" +}", + "site-docs-foo-bar-md-8c2.json": "{ + \\"unversionedId\\": \\"foo/bar\\", + \\"id\\": \\"foo/bar\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"bar\\", + \\"description\\": \\"This is next version of bar.\\", + \\"source\\": \\"@site/docs/foo/bar.md\\", + \\"permalink\\": \\"/docs/next/foo/barSlug\\", + \\"version\\": \\"next\\", + \\"sidebar\\": \\"docs\\", + \\"next\\": { + \\"title\\": \\"hello\\", + \\"permalink\\": \\"/docs/next/\\" + } +}", + "site-docs-hello-md-9df.json": "{ + \\"unversionedId\\": \\"hello\\", + \\"id\\": \\"hello\\", + \\"isDocsHomePage\\": true, + \\"title\\": \\"hello\\", + \\"description\\": \\"Hello next !\\", + \\"source\\": \\"@site/docs/hello.md\\", + \\"permalink\\": \\"/docs/next/\\", + \\"version\\": \\"next\\", + \\"sidebar\\": \\"docs\\", + \\"previous\\": { + \\"title\\": \\"bar\\", + \\"permalink\\": \\"/docs/next/foo/barSlug\\" + } +}", + "site-docs-slugs-absolute-slug-md-4e8.json": "{ + \\"unversionedId\\": \\"slugs/absoluteSlug\\", + \\"id\\": \\"slugs/absoluteSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"absoluteSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/slugs/absoluteSlug.md\\", + \\"permalink\\": \\"/docs/next/absoluteSlug\\", + \\"version\\": \\"next\\" +}", + "site-docs-slugs-relative-slug-md-d1c.json": "{ + \\"unversionedId\\": \\"slugs/relativeSlug\\", + \\"id\\": \\"slugs/relativeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"relativeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/slugs/relativeSlug.md\\", + \\"permalink\\": \\"/docs/next/slugs/relativeSlug\\", + \\"version\\": \\"next\\" +}", + "site-docs-slugs-resolved-slug-md-02b.json": "{ + \\"unversionedId\\": \\"slugs/resolvedSlug\\", + \\"id\\": \\"slugs/resolvedSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"resolvedSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/slugs/resolvedSlug.md\\", + \\"permalink\\": \\"/docs/next/slugs/hey/resolvedSlug\\", + \\"version\\": \\"next\\" +}", + "site-docs-slugs-try-to-escape-slug-md-70d.json": "{ + \\"unversionedId\\": \\"slugs/tryToEscapeSlug\\", + \\"id\\": \\"slugs/tryToEscapeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"tryToEscapeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/docs/slugs/tryToEscapeSlug.md\\", + \\"permalink\\": \\"/docs/next/tryToEscapeSlug\\", + \\"version\\": \\"next\\" +}", + "site-versioned-docs-version-1-0-0-foo-bar-md-7a6.json": "{ + \\"unversionedId\\": \\"foo/bar\\", + \\"id\\": \\"version-1.0.0/foo/bar\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"bar\\", + \\"description\\": \\"Bar 1.0.0 !\\", + \\"source\\": \\"@site/versioned_docs/version-1.0.0/foo/bar.md\\", + \\"permalink\\": \\"/docs/1.0.0/foo/barSlug\\", + \\"version\\": \\"1.0.0\\", + \\"sidebar\\": \\"version-1.0.0/docs\\", + \\"next\\": { + \\"title\\": \\"baz\\", + \\"permalink\\": \\"/docs/1.0.0/foo/baz\\" + } +}", + "site-versioned-docs-version-1-0-0-foo-baz-md-883.json": "{ + \\"unversionedId\\": \\"foo/baz\\", + \\"id\\": \\"version-1.0.0/foo/baz\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"baz\\", + \\"description\\": \\"Baz 1.0.0 ! This will be deleted in next subsequent versions.\\", + \\"source\\": \\"@site/versioned_docs/version-1.0.0/foo/baz.md\\", + \\"permalink\\": \\"/docs/1.0.0/foo/baz\\", + \\"version\\": \\"1.0.0\\", + \\"sidebar\\": \\"version-1.0.0/docs\\", + \\"previous\\": { + \\"title\\": \\"bar\\", + \\"permalink\\": \\"/docs/1.0.0/foo/barSlug\\" + }, + \\"next\\": { + \\"title\\": \\"hello\\", + \\"permalink\\": \\"/docs/1.0.0/\\" + } +}", + "site-versioned-docs-version-1-0-0-hello-md-3ef.json": "{ + \\"unversionedId\\": \\"hello\\", + \\"id\\": \\"version-1.0.0/hello\\", + \\"isDocsHomePage\\": true, + \\"title\\": \\"hello\\", + \\"description\\": \\"Hello 1.0.0 !\\", + \\"source\\": \\"@site/versioned_docs/version-1.0.0/hello.md\\", + \\"permalink\\": \\"/docs/1.0.0/\\", + \\"version\\": \\"1.0.0\\", + \\"sidebar\\": \\"version-1.0.0/docs\\", + \\"previous\\": { + \\"title\\": \\"baz\\", + \\"permalink\\": \\"/docs/1.0.0/foo/baz\\" + } +}", + "site-versioned-docs-version-1-0-1-foo-bar-md-7a3.json": "{ + \\"unversionedId\\": \\"foo/bar\\", + \\"id\\": \\"version-1.0.1/foo/bar\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"bar\\", + \\"description\\": \\"Bar 1.0.1 !\\", + \\"source\\": \\"@site/versioned_docs/version-1.0.1/foo/bar.md\\", + \\"permalink\\": \\"/docs/foo/bar\\", + \\"version\\": \\"1.0.1\\", + \\"sidebar\\": \\"version-1.0.1/docs\\", + \\"next\\": { + \\"title\\": \\"hello\\", + \\"permalink\\": \\"/docs/\\" + } +}", + "site-versioned-docs-version-1-0-1-hello-md-0c7.json": "{ + \\"unversionedId\\": \\"hello\\", + \\"id\\": \\"version-1.0.1/hello\\", + \\"isDocsHomePage\\": true, + \\"title\\": \\"hello\\", + \\"description\\": \\"Hello 1.0.1 !\\", + \\"source\\": \\"@site/versioned_docs/version-1.0.1/hello.md\\", + \\"permalink\\": \\"/docs/\\", + \\"version\\": \\"1.0.1\\", + \\"sidebar\\": \\"version-1.0.1/docs\\", + \\"previous\\": { + \\"title\\": \\"bar\\", + \\"permalink\\": \\"/docs/foo/bar\\" + } +}", + "site-versioned-docs-version-with-slugs-root-absolute-slug-md-4d2.json": "{ + \\"unversionedId\\": \\"rootAbsoluteSlug\\", + \\"id\\": \\"version-withSlugs/rootAbsoluteSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"rootAbsoluteSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md\\", + \\"permalink\\": \\"/docs/withSlugs/rootAbsoluteSlug\\", + \\"version\\": \\"withSlugs\\" +}", + "site-versioned-docs-version-with-slugs-root-relative-slug-md-32a.json": "{ + \\"unversionedId\\": \\"rootRelativeSlug\\", + \\"id\\": \\"version-withSlugs/rootRelativeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"rootRelativeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/versioned_docs/version-withSlugs/rootRelativeSlug.md\\", + \\"permalink\\": \\"/docs/withSlugs/rootRelativeSlug\\", + \\"version\\": \\"withSlugs\\" +}", + "site-versioned-docs-version-with-slugs-root-resolved-slug-md-aee.json": "{ + \\"unversionedId\\": \\"rootResolvedSlug\\", + \\"id\\": \\"version-withSlugs/rootResolvedSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"rootResolvedSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/versioned_docs/version-withSlugs/rootResolvedSlug.md\\", + \\"permalink\\": \\"/docs/withSlugs/hey/rootResolvedSlug\\", + \\"version\\": \\"withSlugs\\" +}", + "site-versioned-docs-version-with-slugs-root-try-to-escape-slug-md-b5d.json": "{ + \\"unversionedId\\": \\"rootTryToEscapeSlug\\", + \\"id\\": \\"version-withSlugs/rootTryToEscapeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"rootTryToEscapeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md\\", + \\"permalink\\": \\"/docs/withSlugs/rootTryToEscapeSlug\\", + \\"version\\": \\"withSlugs\\" +}", + "site-versioned-docs-version-with-slugs-slugs-absolute-slug-md-47a.json": "{ + \\"unversionedId\\": \\"slugs/absoluteSlug\\", + \\"id\\": \\"version-withSlugs/slugs/absoluteSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"absoluteSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md\\", + \\"permalink\\": \\"/docs/withSlugs/absoluteSlug\\", + \\"version\\": \\"withSlugs\\" +}", + "site-versioned-docs-version-with-slugs-slugs-relative-slug-md-a95.json": "{ + \\"unversionedId\\": \\"slugs/relativeSlug\\", + \\"id\\": \\"version-withSlugs/slugs/relativeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"relativeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/versioned_docs/version-withSlugs/slugs/relativeSlug.md\\", + \\"permalink\\": \\"/docs/withSlugs/slugs/relativeSlug\\", + \\"version\\": \\"withSlugs\\" +}", + "site-versioned-docs-version-with-slugs-slugs-resolved-slug-md-5a1.json": "{ + \\"unversionedId\\": \\"slugs/resolvedSlug\\", + \\"id\\": \\"version-withSlugs/slugs/resolvedSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"resolvedSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md\\", + \\"permalink\\": \\"/docs/withSlugs/slugs/hey/resolvedSlug\\", + \\"version\\": \\"withSlugs\\" +}", + "site-versioned-docs-version-with-slugs-slugs-try-to-escape-slug-md-4e1.json": "{ + \\"unversionedId\\": \\"slugs/tryToEscapeSlug\\", + \\"id\\": \\"version-withSlugs/slugs/tryToEscapeSlug\\", + \\"isDocsHomePage\\": false, + \\"title\\": \\"tryToEscapeSlug\\", + \\"description\\": \\"Lorem\\", + \\"source\\": \\"@site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md\\", + \\"permalink\\": \\"/docs/withSlugs/tryToEscapeSlug\\", + \\"version\\": \\"withSlugs\\" +}", +} +`; + +exports[`versioned website content: global data 1`] = ` +Object { + "pluginName": Object { + "pluginId": Object { + "latestVersionName": "1.0.1", + "path": "/docs", + "versions": Array [ + Object { + "docs": Array [ + Object { + "id": "foo/bar", + "path": "/docs/next/foo/barSlug", + }, + Object { + "id": "hello", + "path": "/docs/next/", + }, + Object { + "id": "slugs/absoluteSlug", + "path": "/docs/next/absoluteSlug", + }, + Object { + "id": "slugs/relativeSlug", + "path": "/docs/next/slugs/relativeSlug", + }, + Object { + "id": "slugs/resolvedSlug", + "path": "/docs/next/slugs/hey/resolvedSlug", + }, + Object { + "id": "slugs/tryToEscapeSlug", + "path": "/docs/next/tryToEscapeSlug", + }, + ], + "mainDocId": "hello", + "name": "next", + "path": "/docs/next", + }, + Object { + "docs": Array [ + Object { + "id": "foo/bar", + "path": "/docs/foo/bar", + }, + Object { + "id": "hello", + "path": "/docs/", + }, + ], + "mainDocId": "hello", + "name": "1.0.1", + "path": "/docs", + }, + Object { + "docs": Array [ + Object { + "id": "foo/bar", + "path": "/docs/1.0.0/foo/barSlug", + }, + Object { + "id": "foo/baz", + "path": "/docs/1.0.0/foo/baz", + }, + Object { + "id": "hello", + "path": "/docs/1.0.0/", + }, + ], + "mainDocId": "hello", + "name": "1.0.0", + "path": "/docs/1.0.0", + }, + Object { + "docs": Array [ + Object { + "id": "rootAbsoluteSlug", + "path": "/docs/withSlugs/rootAbsoluteSlug", + }, + Object { + "id": "rootRelativeSlug", + "path": "/docs/withSlugs/rootRelativeSlug", + }, + Object { + "id": "rootResolvedSlug", + "path": "/docs/withSlugs/hey/rootResolvedSlug", + }, + Object { + "id": "rootTryToEscapeSlug", + "path": "/docs/withSlugs/rootTryToEscapeSlug", + }, + Object { + "id": "slugs/absoluteSlug", + "path": "/docs/withSlugs/absoluteSlug", + }, + Object { + "id": "slugs/relativeSlug", + "path": "/docs/withSlugs/slugs/relativeSlug", + }, + Object { + "id": "slugs/resolvedSlug", + "path": "/docs/withSlugs/slugs/hey/resolvedSlug", + }, + Object { + "id": "slugs/tryToEscapeSlug", + "path": "/docs/withSlugs/tryToEscapeSlug", + }, + ], + "mainDocId": "rootAbsoluteSlug", + "name": "withSlugs", + "path": "/docs/withSlugs", + }, + ], + }, + }, +} +`; + +exports[`versioned website content: route config 1`] = ` +Array [ + Object { + "component": "@theme/DocPage", + "exact": false, + "modules": Object { + "docsMetadata": "~docs/docs-1-0-0-route-660.json", + }, + "path": "/docs/1.0.0", + "priority": undefined, + "routes": Array [ + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-1.0.0/hello.md", + }, + "path": "/docs/1.0.0/", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-1.0.0/foo/bar.md", + }, + "path": "/docs/1.0.0/foo/barSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-1.0.0/foo/baz.md", + }, + "path": "/docs/1.0.0/foo/baz", + }, + ], + }, + Object { + "component": "@theme/DocPage", + "exact": false, + "modules": Object { + "docsMetadata": "~docs/docs-next-route-1c8.json", + }, + "path": "/docs/next", + "priority": undefined, + "routes": Array [ + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/docs/hello.md", + }, + "path": "/docs/next/", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/docs/slugs/absoluteSlug.md", + }, + "path": "/docs/next/absoluteSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/docs/foo/bar.md", + }, + "path": "/docs/next/foo/barSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/docs/slugs/resolvedSlug.md", + }, + "path": "/docs/next/slugs/hey/resolvedSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/docs/slugs/relativeSlug.md", + }, + "path": "/docs/next/slugs/relativeSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/docs/slugs/tryToEscapeSlug.md", + }, + "path": "/docs/next/tryToEscapeSlug", + }, + ], + }, + Object { + "component": "@theme/DocPage", + "exact": false, + "modules": Object { + "docsMetadata": "~docs/docs-with-slugs-route-335.json", + }, + "path": "/docs/withSlugs", + "priority": undefined, + "routes": Array [ + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md", + }, + "path": "/docs/withSlugs/absoluteSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-withSlugs/rootResolvedSlug.md", + }, + "path": "/docs/withSlugs/hey/rootResolvedSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md", + }, + "path": "/docs/withSlugs/rootAbsoluteSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-withSlugs/rootRelativeSlug.md", + }, + "path": "/docs/withSlugs/rootRelativeSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md", + }, + "path": "/docs/withSlugs/rootTryToEscapeSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md", + }, + "path": "/docs/withSlugs/slugs/hey/resolvedSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-withSlugs/slugs/relativeSlug.md", + }, + "path": "/docs/withSlugs/slugs/relativeSlug", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md", + }, + "path": "/docs/withSlugs/tryToEscapeSlug", + }, + ], + }, + Object { + "component": "@theme/DocPage", + "exact": false, + "modules": Object { + "docsMetadata": "~docs/docs-route-ff2.json", + }, + "path": "/docs", + "priority": -1, + "routes": Array [ + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-1.0.1/hello.md", + }, + "path": "/docs/", + }, + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-1.0.1/foo/bar.md", + }, + "path": "/docs/foo/bar", + }, + ], + }, +] +`; + exports[`versioned website content: sidebars needed for each version 1`] = ` Object { "1.0.0": Set { diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/version.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/version.test.ts.snap index 6f2a9ce513..660a0ad549 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/version.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/version.test.ts.snap @@ -77,3 +77,14 @@ Object { ], } `; + +exports[`docsVersion second docs instance versioning 1`] = ` +Object { + "version-2.0.0/community": Array [ + Object { + "id": "version-2.0.0/team", + "type": "doc", + }, + ], +} +`; diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/env.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/env.test.ts index 8733898f1b..017ab47bab 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/env.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/env.test.ts @@ -7,18 +7,19 @@ import path from 'path'; import loadEnv from '../env'; +import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants'; describe('loadEnv', () => { test('website with versioning disabled', () => { const siteDir = path.join(__dirname, '__fixtures__', 'simple-site'); - const env = loadEnv(siteDir); + const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID); expect(env.versioning.enabled).toBe(false); expect(env.versioning.versions).toStrictEqual([]); }); test('website with versioning enabled', () => { const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site'); - const env = loadEnv(siteDir); + const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID); expect(env.versioning.enabled).toBe(true); expect(env.versioning.latestVersion).toBe('1.0.1'); expect(env.versioning.versions).toStrictEqual([ @@ -28,9 +29,17 @@ describe('loadEnv', () => { ]); }); + test('website with versioning enabled, 2nd docs plugin instance', () => { + const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site'); + const env = loadEnv(siteDir, 'community'); + expect(env.versioning.enabled).toBe(true); + expect(env.versioning.latestVersion).toBe('1.0.0'); + expect(env.versioning.versions).toStrictEqual(['1.0.0']); + }); + test('website with versioning but disabled', () => { const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site'); - const env = loadEnv(siteDir, {disableVersioning: true}); + const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID, {disableVersioning: true}); expect(env.versioning.enabled).toBe(false); expect(env.versioning.versions).toStrictEqual([]); }); @@ -42,7 +51,7 @@ describe('loadEnv', () => { invalid: 'json', }; }); - const env = loadEnv(siteDir); + const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID); expect(env.versioning.enabled).toBe(false); mock.mockRestore(); }); diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index eaeeaea61c..d6e55173ee 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -12,35 +12,65 @@ import commander from 'commander'; import fs from 'fs-extra'; import pluginContentDocs from '../index'; import loadEnv from '../env'; -import normalizePluginOptions from './pluginOptionSchema.test'; import {loadContext} from '@docusaurus/core/src/server/index'; import {applyConfigureWebpack} from '@docusaurus/core/src/webpack/utils'; import {RouteConfig} from '@docusaurus/types'; import {posixPath} from '@docusaurus/utils'; import {sortConfig} from '@docusaurus/core/src/server/plugins'; +import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants'; import * as version from '../version'; +import {PluginOptionSchema} from '../pluginOptionSchema'; +import {normalizePluginOptions} from '@docusaurus/utils-validation'; -const createFakeActions = ( - routeConfigs: RouteConfig[], - contentDir, - dataContainer?, - globalDataContainer?, -) => { - return { +const createFakeActions = (contentDir: string) => { + const routeConfigs: RouteConfig[] = []; + const dataContainer: any = {}; + const globalDataContainer: any = {}; + + const actions = { addRoute: (config: RouteConfig) => { routeConfigs.push(config); }, - createData: async (name, content) => { - if (dataContainer) { - dataContainer[name] = content; - } + createData: async (name: string, content: unknown) => { + dataContainer[name] = content; return path.join(contentDir, name); }, - setGlobalData: (data) => { + setGlobalData: (data: any) => { globalDataContainer.pluginName = {pluginId: data}; }, }; + + // Extra fns useful for tests! + const utils = { + getGlobalData: () => globalDataContainer, + getRouteConfigs: () => routeConfigs, + // query by prefix, because files have a hash at the end + // so it's not convenient to query by full filename + getCreatedDataByPrefix: (prefix: string) => { + const entry = Object.entries(dataContainer).find(([key]) => + key.startsWith(prefix), + ); + if (!entry) { + throw new Error(`No entry found for prefix=${prefix}`); + } + return JSON.parse(entry[1] as string); + }, + + expectSnapshot: () => { + // Sort the route config like in src/server/plugins/index.ts for consistent snapshot ordering + sortConfig(routeConfigs); + expect(routeConfigs).not.toEqual([]); + expect(routeConfigs).toMatchSnapshot('route config'); + expect(dataContainer).toMatchSnapshot('data'); + expect(globalDataContainer).toMatchSnapshot('global data'); + }, + }; + + return { + actions, + utils, + }; }; test('site with wrong sidebar file', async () => { @@ -49,7 +79,7 @@ test('site with wrong sidebar file', async () => { const sidebarPath = path.join(siteDir, 'wrong-sidebars.json'); const plugin = pluginContentDocs( context, - normalizePluginOptions({ + normalizePluginOptions(PluginOptionSchema, { sidebarPath, }), ); @@ -62,28 +92,30 @@ describe('empty/no docs website', () => { test('no files in docs folder', async () => { await fs.ensureDir(path.join(siteDir, 'docs')); - const plugin = pluginContentDocs(context, normalizePluginOptions({})); + const plugin = pluginContentDocs( + context, + normalizePluginOptions(PluginOptionSchema, {}), + ); const content = await plugin.loadContent(); const {docsMetadata, docsSidebars} = content; expect(docsMetadata).toMatchInlineSnapshot(`Object {}`); expect(docsSidebars).toMatchInlineSnapshot(`Object {}`); - const routeConfigs = []; const pluginContentDir = path.join(context.generatedFilesDir, plugin.name); - const actions = createFakeActions(routeConfigs, pluginContentDir); + const {actions, utils} = createFakeActions(pluginContentDir); await plugin.contentLoaded({ content, actions, }); - expect(routeConfigs).toEqual([]); + expect(utils.getRouteConfigs()).toEqual([]); }); test('docs folder does not exist', async () => { const plugin = pluginContentDocs( context, - normalizePluginOptions({ + normalizePluginOptions(PluginOptionSchema, { path: '/path/does/not/exist/', }), ); @@ -99,7 +131,7 @@ describe('simple website', () => { const pluginPath = 'docs'; const plugin = pluginContentDocs( context, - normalizePluginOptions({ + normalizePluginOptions(PluginOptionSchema, { path: pluginPath, sidebarPath, homePageId: 'hello', @@ -112,7 +144,7 @@ describe('simple website', () => { const cli = new commander.Command(); plugin.extendCli(cli); cli.parse(['node', 'test', 'docs:version', '1.0.0']); - expect(mock).toHaveBeenCalledWith('1.0.0', siteDir, { + expect(mock).toHaveBeenCalledWith('1.0.0', siteDir, DEFAULT_PLUGIN_ID, { path: pluginPath, sidebarPath, }); @@ -200,15 +232,7 @@ describe('simple website', () => { expect(docsSidebars).toMatchSnapshot(); - const routeConfigs = []; - const dataContainer = {}; - const globalDataContainer = {}; - const actions = createFakeActions( - routeConfigs, - pluginContentDir, - dataContainer, - globalDataContainer, - ); + const {actions, utils} = createFakeActions(pluginContentDir); await plugin.contentLoaded({ content, @@ -216,16 +240,12 @@ describe('simple website', () => { }); // There is only one nested docs route for simple site - const baseMetadata = JSON.parse(dataContainer['docs-route-ff2.json']); + const baseMetadata = utils.getCreatedDataByPrefix('docs-route-'); expect(baseMetadata.docsSidebars).toEqual(docsSidebars); expect(baseMetadata.permalinkToSidebar).toEqual(permalinkToSidebar); - // Sort the route config like in src/server/plugins/index.ts for consistent snapshot ordering - sortConfig(routeConfigs); - - expect(routeConfigs).not.toEqual([]); - expect(routeConfigs).toMatchSnapshot(); - expect(globalDataContainer).toMatchSnapshot(); + utils.expectSnapshot(); + expect(utils.getGlobalData()).toMatchSnapshot(); }); }); @@ -236,22 +256,26 @@ describe('versioned website', () => { const routeBasePath = 'docs'; const plugin = pluginContentDocs( context, - normalizePluginOptions({ + normalizePluginOptions(PluginOptionSchema, { routeBasePath, sidebarPath, homePageId: 'hello', }), ); - const env = loadEnv(siteDir); + const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID); const {docsDir: versionedDir} = env.versioning; const pluginContentDir = path.join(context.generatedFilesDir, plugin.name); + test('isVersioned', () => { + expect(env.versioning.enabled).toEqual(true); + }); + test('extendCli - docsVersion', () => { const mock = jest.spyOn(version, 'docsVersion').mockImplementation(); const cli = new commander.Command(); plugin.extendCli(cli); cli.parse(['node', 'test', 'docs:version', '2.0.0']); - expect(mock).toHaveBeenCalledWith('2.0.0', siteDir, { + expect(mock).toHaveBeenCalledWith('2.0.0', siteDir, DEFAULT_PLUGIN_ID, { path: routeBasePath, sidebarPath, }); @@ -401,23 +425,15 @@ describe('versioned website', () => { expect(versionToSidebars).toMatchSnapshot( 'sidebars needed for each version', ); - const routeConfigs = []; - const dataContainer = {}; - const globalDataContainer = {}; - const actions = createFakeActions( - routeConfigs, - pluginContentDir, - dataContainer, - globalDataContainer, - ); + const {actions, utils} = createFakeActions(pluginContentDir); await plugin.contentLoaded({ content, actions, }); // The created base metadata for each nested docs route is smartly chunked/ splitted across version - const latestVersionBaseMetadata = JSON.parse( - dataContainer['docs-route-ff2.json'], + const latestVersionBaseMetadata = utils.getCreatedDataByPrefix( + 'docs-route-', ); expect(latestVersionBaseMetadata).toMatchSnapshot( 'base metadata for latest version', @@ -426,8 +442,8 @@ describe('versioned website', () => { expect(latestVersionBaseMetadata.permalinkToSidebar).not.toEqual( permalinkToSidebar, ); - const nextVersionBaseMetadata = JSON.parse( - dataContainer['docs-next-route-1c8.json'], + const nextVersionBaseMetadata = utils.getCreatedDataByPrefix( + 'docs-next-route-', ); expect(nextVersionBaseMetadata).toMatchSnapshot( 'base metadata for next version', @@ -436,8 +452,8 @@ describe('versioned website', () => { expect(nextVersionBaseMetadata.permalinkToSidebar).not.toEqual( permalinkToSidebar, ); - const firstVersionBaseMetadata = JSON.parse( - dataContainer['docs-1-0-0-route-660.json'], + const firstVersionBaseMetadata = utils.getCreatedDataByPrefix( + 'docs-1-0-0-route-', ); expect(firstVersionBaseMetadata).toMatchSnapshot( 'base metadata for first version', @@ -447,11 +463,151 @@ describe('versioned website', () => { permalinkToSidebar, ); - // Sort the route config like in src/server/plugins/index.ts for consistent snapshot ordering - sortConfig(routeConfigs); - - expect(routeConfigs).not.toEqual([]); - expect(routeConfigs).toMatchSnapshot(); - expect(globalDataContainer).toMatchSnapshot(); + utils.expectSnapshot(); + }); +}); + +describe('versioned website (community)', () => { + const siteDir = path.join(__dirname, '__fixtures__', 'versioned-site'); + const context = loadContext(siteDir); + const sidebarPath = path.join(siteDir, 'community_sidebars.json'); + const routeBasePath = 'community'; + const pluginId = 'community'; + const plugin = pluginContentDocs( + context, + normalizePluginOptions(PluginOptionSchema, { + id: 'community', + path: 'community', + routeBasePath, + sidebarPath, + }), + ); + const env = loadEnv(siteDir, pluginId); + const {docsDir: versionedDir} = env.versioning; + const pluginContentDir = path.join(context.generatedFilesDir, plugin.name); + + test('isVersioned', () => { + expect(env.versioning.enabled).toEqual(true); + }); + + test('extendCli - docsVersion', () => { + const mock = jest.spyOn(version, 'docsVersion').mockImplementation(); + const cli = new commander.Command(); + plugin.extendCli(cli); + cli.parse(['node', 'test', `docs:version:${pluginId}`, '2.0.0']); + expect(mock).toHaveBeenCalledWith('2.0.0', siteDir, pluginId, { + path: routeBasePath, + sidebarPath, + }); + mock.mockRestore(); + }); + + test('getPathToWatch', () => { + const pathToWatch = plugin.getPathsToWatch(); + const matchPattern = pathToWatch.map((filepath) => + posixPath(path.relative(siteDir, filepath)), + ); + expect(matchPattern).not.toEqual([]); + expect(matchPattern).toMatchInlineSnapshot(` + Array [ + "community/**/*.{md,mdx}", + "community_versioned_sidebars/version-1.0.0-sidebars.json", + "community_versioned_docs/version-1.0.0/**/*.{md,mdx}", + "community_sidebars.json", + ] + `); + expect(isMatch('community/team.md', matchPattern)).toEqual(true); + expect( + isMatch('community_versioned_docs/version-1.0.0/team.md', matchPattern), + ).toEqual(true); + + // Non existing version + expect( + isMatch('community_versioned_docs/version-2.0.0/team.md', matchPattern), + ).toEqual(false); + expect( + isMatch( + 'community_versioned_sidebars/version-2.0.0-sidebars.json', + matchPattern, + ), + ).toEqual(false); + + expect(isMatch('community/team.js', matchPattern)).toEqual(false); + expect( + isMatch('community_versioned_docs/version-1.0.0/team.js', matchPattern), + ).toEqual(false); + }); + + test('content', async () => { + const content = await plugin.loadContent(); + const { + docsMetadata, + docsSidebars, + versionToSidebars, + permalinkToSidebar, + } = content; + + expect(docsMetadata.team).toEqual({ + id: 'team', + unversionedId: 'team', + isDocsHomePage: false, + permalink: '/community/next/team', + source: path.join('@site', routeBasePath, 'team.md'), + title: 'team', + description: 'Team current version', + version: 'next', + sidebar: 'community', + }); + expect(docsMetadata['version-1.0.0/team']).toEqual({ + id: 'version-1.0.0/team', + unversionedId: 'team', + isDocsHomePage: false, + permalink: '/community/team', + source: path.join( + '@site', + path.relative(siteDir, versionedDir), + 'version-1.0.0', + 'team.md', + ), + title: 'team', + description: 'Team 1.0.0', + version: '1.0.0', + sidebar: 'version-1.0.0/community', + }); + + expect(docsSidebars).toMatchSnapshot('all sidebars'); + expect(versionToSidebars).toMatchSnapshot( + 'sidebars needed for each version', + ); + + const {actions, utils} = createFakeActions(pluginContentDir); + await plugin.contentLoaded({ + content, + actions, + }); + + // The created base metadata for each nested docs route is smartly chunked/ splitted across version + const latestVersionBaseMetadata = utils.getCreatedDataByPrefix( + 'community-route-', + ); + expect(latestVersionBaseMetadata).toMatchSnapshot( + 'base metadata for latest version', + ); + expect(latestVersionBaseMetadata.docsSidebars).not.toEqual(docsSidebars); + expect(latestVersionBaseMetadata.permalinkToSidebar).not.toEqual( + permalinkToSidebar, + ); + const nextVersionBaseMetadata = utils.getCreatedDataByPrefix( + 'community-next-route-', + ); + expect(nextVersionBaseMetadata).toMatchSnapshot( + 'base metadata for next version', + ); + expect(nextVersionBaseMetadata.docsSidebars).not.toEqual(docsSidebars); + expect(nextVersionBaseMetadata.permalinkToSidebar).not.toEqual( + permalinkToSidebar, + ); + + utils.expectSnapshot(); }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/metadata.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/metadata.test.ts index 79bd219365..ba2934c443 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/metadata.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/metadata.test.ts @@ -11,6 +11,7 @@ import processMetadata from '../metadata'; import loadEnv from '../env'; import {MetadataRaw, Env, MetadataOptions} from '../types'; import {LoadContext} from '@docusaurus/types'; +import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants'; const fixtureDir = path.join(__dirname, '__fixtures__'); @@ -66,7 +67,7 @@ describe('simple site', () => { const context = loadContext(siteDir); const routeBasePath = 'docs'; const docsDir = path.resolve(siteDir, routeBasePath); - const env = loadEnv(siteDir); + const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID); const options = {routeBasePath}; const {testMeta, testSlug} = createTestHelpers({ @@ -309,7 +310,7 @@ describe('versioned site', () => { const context = loadContext(siteDir); const routeBasePath = 'docs'; const docsDir = path.resolve(siteDir, routeBasePath); - const env = loadEnv(siteDir); + const env = loadEnv(siteDir, DEFAULT_PLUGIN_ID); const {docsDir: versionedDir} = env.versioning; const options = {routeBasePath}; diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/pluginOptionSchema.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/pluginOptionSchema.test.ts index 1a05be086e..08ddaf7f1f 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/pluginOptionSchema.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/pluginOptionSchema.test.ts @@ -6,17 +6,7 @@ */ import {PluginOptionSchema, DEFAULT_OPTIONS} from '../pluginOptionSchema'; - -export default function normalizePluginOptions(options) { - const {value, error} = PluginOptionSchema.validate(options, { - convert: false, - }); - if (error) { - throw error; - } else { - return value; - } -} +import {normalizePluginOptions} from '@docusaurus/utils-validation'; // the type of remark/rehype plugins is function const remarkRehypePluginStub = () => {}; @@ -63,7 +53,7 @@ describe('normalizeDocsPluginOptions', () => { test('should reject bad path inputs', () => { expect(() => { - normalizePluginOptions({ + normalizePluginOptions(PluginOptionSchema, { path: 2, }); }).toThrowErrorMatchingInlineSnapshot(`"\\"path\\" must be a string"`); @@ -71,7 +61,7 @@ describe('normalizeDocsPluginOptions', () => { test('should reject bad include inputs', () => { expect(() => { - normalizePluginOptions({ + normalizePluginOptions(PluginOptionSchema, { include: '**/*.{md,mdx}', }); }).toThrowErrorMatchingInlineSnapshot(`"\\"include\\" must be an array"`); @@ -79,7 +69,7 @@ describe('normalizeDocsPluginOptions', () => { test('should reject bad showLastUpdateTime inputs', () => { expect(() => { - normalizePluginOptions({ + normalizePluginOptions(PluginOptionSchema, { showLastUpdateTime: 'true', }); }).toThrowErrorMatchingInlineSnapshot( @@ -89,7 +79,7 @@ describe('normalizeDocsPluginOptions', () => { test('should reject bad remarkPlugins input', () => { expect(() => { - normalizePluginOptions({ + normalizePluginOptions(PluginOptionSchema, { remarkPlugins: 'remark-math', }); }).toThrowErrorMatchingInlineSnapshot( diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/version.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/version.test.ts index ef125d8d57..a7a70fc1c6 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/version.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/version.test.ts @@ -14,6 +14,7 @@ import { getVersionsJSONFile, getVersionedSidebarsDir, } from '../env'; +import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants'; const fixtureDir = path.join(__dirname, '__fixtures__'); @@ -27,87 +28,114 @@ describe('docsVersion', () => { test('no version tag provided', () => { expect(() => - docsVersion(null, simpleSiteDir, DEFAULT_OPTIONS), + docsVersion(null, simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS), ).toThrowErrorMatchingInlineSnapshot( - `"No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`, + `"[docs] No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`, ); expect(() => - docsVersion(undefined, simpleSiteDir, DEFAULT_OPTIONS), + docsVersion(undefined, simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS), ).toThrowErrorMatchingInlineSnapshot( - `"No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`, + `"[docs] No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`, ); expect(() => - docsVersion('', simpleSiteDir, DEFAULT_OPTIONS), + docsVersion('', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS), ).toThrowErrorMatchingInlineSnapshot( - `"No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`, + `"[docs] No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0"`, ); }); test('version tag should not have slash', () => { expect(() => - docsVersion('foo/bar', simpleSiteDir, DEFAULT_OPTIONS), + docsVersion('foo/bar', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid version tag specified! Do not include slash (/) or (\\\\). Try something like: 1.0.0"`, + `"[docs] Invalid version tag specified! Do not include slash (/) or (\\\\). Try something like: 1.0.0"`, ); expect(() => - docsVersion('foo\\bar', simpleSiteDir, DEFAULT_OPTIONS), + docsVersion( + 'foo\\bar', + simpleSiteDir, + DEFAULT_PLUGIN_ID, + DEFAULT_OPTIONS, + ), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid version tag specified! Do not include slash (/) or (\\\\). Try something like: 1.0.0"`, + `"[docs] Invalid version tag specified! Do not include slash (/) or (\\\\). Try something like: 1.0.0"`, ); }); test('version tag should not be too long', () => { expect(() => - docsVersion('a'.repeat(255), simpleSiteDir, DEFAULT_OPTIONS), + docsVersion( + 'a'.repeat(255), + simpleSiteDir, + DEFAULT_PLUGIN_ID, + DEFAULT_OPTIONS, + ), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid version tag specified! Length must <= 32 characters. Try something like: 1.0.0"`, + `"[docs] Invalid version tag specified! Length must <= 32 characters. Try something like: 1.0.0"`, ); }); test('version tag should not be a dot or two dots', () => { expect(() => - docsVersion('..', simpleSiteDir, DEFAULT_OPTIONS), + docsVersion('..', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid version tag specified! Do not name your version \\".\\" or \\"..\\". Try something like: 1.0.0"`, + `"[docs] Invalid version tag specified! Do not name your version \\".\\" or \\"..\\". Try something like: 1.0.0"`, ); expect(() => - docsVersion('.', simpleSiteDir, DEFAULT_OPTIONS), + docsVersion('.', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid version tag specified! Do not name your version \\".\\" or \\"..\\". Try something like: 1.0.0"`, + `"[docs] Invalid version tag specified! Do not name your version \\".\\" or \\"..\\". Try something like: 1.0.0"`, ); }); test('version tag should be a valid pathname', () => { expect(() => - docsVersion('', simpleSiteDir, DEFAULT_OPTIONS), + docsVersion( + '', + simpleSiteDir, + DEFAULT_PLUGIN_ID, + DEFAULT_OPTIONS, + ), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`, + `"[docs] Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`, ); expect(() => - docsVersion('foo\x00bar', simpleSiteDir, DEFAULT_OPTIONS), + docsVersion( + 'foo\x00bar', + simpleSiteDir, + DEFAULT_PLUGIN_ID, + DEFAULT_OPTIONS, + ), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`, + `"[docs] Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`, ); expect(() => - docsVersion('foo:bar', simpleSiteDir, DEFAULT_OPTIONS), + docsVersion('foo:bar', simpleSiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`, + `"[docs] Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0"`, ); }); test('version tag already exist', () => { expect(() => - docsVersion('1.0.0', versionedSiteDir, DEFAULT_OPTIONS), + docsVersion( + '1.0.0', + versionedSiteDir, + DEFAULT_PLUGIN_ID, + DEFAULT_OPTIONS, + ), ).toThrowErrorMatchingInlineSnapshot( - `"This version already exists!. Use a version tag that does not already exist."`, + `"[docs] This version already exists!. Use a version tag that does not already exist."`, ); }); test('no docs file to version', () => { const emptySiteDir = path.join(fixtureDir, 'empty-site'); expect(() => - docsVersion('1.0.0', emptySiteDir, DEFAULT_OPTIONS), - ).toThrowErrorMatchingInlineSnapshot(`"There is no docs to version !"`); + docsVersion('1.0.0', emptySiteDir, DEFAULT_PLUGIN_ID, DEFAULT_OPTIONS), + ).toThrowErrorMatchingInlineSnapshot( + `"[docs] There is no docs to version !"`, + ); }); test('first time versioning', () => { @@ -131,21 +159,26 @@ describe('docsVersion', () => { path: 'docs', sidebarPath: path.join(simpleSiteDir, 'sidebars.json'), }; - docsVersion('1.0.0', simpleSiteDir, options); + docsVersion('1.0.0', simpleSiteDir, DEFAULT_PLUGIN_ID, options); expect(copyMock).toHaveBeenCalledWith( path.join(simpleSiteDir, options.path), - path.join(getVersionedDocsDir(simpleSiteDir), 'version-1.0.0'), + path.join( + getVersionedDocsDir(simpleSiteDir, DEFAULT_PLUGIN_ID), + 'version-1.0.0', + ), ); expect(versionedSidebar).toMatchSnapshot(); expect(versionedSidebarPath).toEqual( path.join( - getVersionedSidebarsDir(simpleSiteDir), + getVersionedSidebarsDir(simpleSiteDir, DEFAULT_PLUGIN_ID), 'version-1.0.0-sidebars.json', ), ); - expect(versionsPath).toEqual(getVersionsJSONFile(simpleSiteDir)); + expect(versionsPath).toEqual( + getVersionsJSONFile(simpleSiteDir, DEFAULT_PLUGIN_ID), + ); expect(versions).toEqual(['1.0.0']); - expect(consoleMock).toHaveBeenCalledWith('Version 1.0.0 created!'); + expect(consoleMock).toHaveBeenCalledWith('[docs] Version 1.0.0 created!'); copyMock.mockRestore(); writeMock.mockRestore(); @@ -174,21 +207,78 @@ describe('docsVersion', () => { path: 'docs', sidebarPath: path.join(versionedSiteDir, 'sidebars.json'), }; - docsVersion('2.0.0', versionedSiteDir, options); + docsVersion('2.0.0', versionedSiteDir, DEFAULT_PLUGIN_ID, options); expect(copyMock).toHaveBeenCalledWith( path.join(versionedSiteDir, options.path), - path.join(getVersionedDocsDir(versionedSiteDir), 'version-2.0.0'), + path.join( + getVersionedDocsDir(versionedSiteDir, DEFAULT_PLUGIN_ID), + 'version-2.0.0', + ), ); expect(versionedSidebar).toMatchSnapshot(); expect(versionedSidebarPath).toEqual( path.join( - getVersionedSidebarsDir(versionedSiteDir), + getVersionedSidebarsDir(versionedSiteDir, DEFAULT_PLUGIN_ID), 'version-2.0.0-sidebars.json', ), ); - expect(versionsPath).toEqual(getVersionsJSONFile(versionedSiteDir)); + expect(versionsPath).toEqual( + getVersionsJSONFile(versionedSiteDir, DEFAULT_PLUGIN_ID), + ); expect(versions).toEqual(['2.0.0', '1.0.1', '1.0.0', 'withSlugs']); - expect(consoleMock).toHaveBeenCalledWith('Version 2.0.0 created!'); + expect(consoleMock).toHaveBeenCalledWith('[docs] Version 2.0.0 created!'); + + copyMock.mockRestore(); + writeMock.mockRestore(); + consoleMock.mockRestore(); + ensureMock.mockRestore(); + }); + + test('second docs instance versioning', () => { + const pluginId = 'community'; + + const copyMock = jest.spyOn(fs, 'copySync').mockImplementation(); + const ensureMock = jest.spyOn(fs, 'ensureDirSync').mockImplementation(); + const writeMock = jest.spyOn(fs, 'writeFileSync'); + let versionedSidebar; + let versionedSidebarPath; + writeMock.mockImplementationOnce((filepath, content) => { + versionedSidebarPath = filepath; + versionedSidebar = JSON.parse(content); + }); + let versionsPath; + let versions; + writeMock.mockImplementationOnce((filepath, content) => { + versionsPath = filepath; + versions = JSON.parse(content); + }); + const consoleMock = jest.spyOn(console, 'log').mockImplementation(); + const options = { + path: 'community', + sidebarPath: path.join(versionedSiteDir, 'community_sidebars.json'), + }; + docsVersion('2.0.0', versionedSiteDir, pluginId, options); + expect(copyMock).toHaveBeenCalledWith( + path.join(versionedSiteDir, options.path), + path.join( + getVersionedDocsDir(versionedSiteDir, pluginId), + 'version-2.0.0', + ), + ); + expect(versionedSidebar).toMatchSnapshot(); + expect(versionedSidebarPath).toEqual( + path.join( + getVersionedSidebarsDir(versionedSiteDir, pluginId), + 'version-2.0.0-sidebars.json', + ), + ); + expect(versionsPath).toEqual( + getVersionsJSONFile(versionedSiteDir, pluginId), + ); + expect(versions).toEqual(['2.0.0', '1.0.0']); + expect(consoleMock).toHaveBeenCalledWith( + '[community] Version 2.0.0 created!', + ); copyMock.mockRestore(); writeMock.mockRestore(); diff --git a/packages/docusaurus-plugin-content-docs/src/env.ts b/packages/docusaurus-plugin-content-docs/src/env.ts index 19f3e8e4a4..a5062ae0f4 100644 --- a/packages/docusaurus-plugin-content-docs/src/env.ts +++ b/packages/docusaurus-plugin-content-docs/src/env.ts @@ -14,24 +14,49 @@ import { VERSIONED_SIDEBARS_DIR, } from './constants'; -export function getVersionedDocsDir(siteDir: string): string { - return path.join(siteDir, VERSIONED_DOCS_DIR); +import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants'; + +// retro-compatibility: no prefix for the default plugin id +function addPluginIdPrefix(fileOrDir: string, pluginId: string): string { + if (pluginId === DEFAULT_PLUGIN_ID) { + return fileOrDir; + } else { + return `${pluginId}_${fileOrDir}`; + } } -export function getVersionedSidebarsDir(siteDir: string): string { - return path.join(siteDir, VERSIONED_SIDEBARS_DIR); +export function getVersionedDocsDir(siteDir: string, pluginId: string): string { + return path.join(siteDir, addPluginIdPrefix(VERSIONED_DOCS_DIR, pluginId)); } -export function getVersionsJSONFile(siteDir: string): string { - return path.join(siteDir, VERSIONS_JSON_FILE); +export function getVersionedSidebarsDir( + siteDir: string, + pluginId: string, +): string { + return path.join( + siteDir, + addPluginIdPrefix(VERSIONED_SIDEBARS_DIR, pluginId), + ); +} + +export function getVersionsJSONFile(siteDir: string, pluginId: string): string { + return path.join(siteDir, addPluginIdPrefix(VERSIONS_JSON_FILE, pluginId)); } type EnvOptions = Partial<{disableVersioning: boolean}>; export default function ( siteDir: string, + pluginId: string, options: EnvOptions = {disableVersioning: false}, ): Env { + if (!siteDir) { + throw new Error('unexpected, missing siteDir'); + } + if (!pluginId) { + throw new Error('unexpected, missing pluginId'); + } + const versioning: VersioningEnv = { enabled: false, versions: [], @@ -40,7 +65,7 @@ export default function ( sidebarsDir: '', }; - const versionsJSONFile = getVersionsJSONFile(siteDir); + const versionsJSONFile = getVersionsJSONFile(siteDir, pluginId); if (fs.existsSync(versionsJSONFile)) { if (!options.disableVersioning) { const parsedVersions = JSON.parse( @@ -51,8 +76,8 @@ export default function ( versioning.latestVersion = parsedVersions[0]; versioning.enabled = true; versioning.versions = parsedVersions; - versioning.docsDir = getVersionedDocsDir(siteDir); - versioning.sidebarsDir = getVersionedSidebarsDir(siteDir); + versioning.docsDir = getVersionedDocsDir(siteDir, pluginId); + versioning.sidebarsDir = getVersionedSidebarsDir(siteDir, pluginId); } } } diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 120d584534..b8c39d1fc4 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -15,7 +15,10 @@ import path from 'path'; import chalk from 'chalk'; import admonitions from 'remark-admonitions'; -import {STATIC_DIR_NAME} from '@docusaurus/core/lib/constants'; +import { + STATIC_DIR_NAME, + DEFAULT_PLUGIN_ID, +} from '@docusaurus/core/lib/constants'; import { normalizeUrl, docuHash, @@ -77,15 +80,21 @@ export default function pluginContentDocs( const {siteDir, generatedFilesDir, baseUrl} = context; const docsDir = path.resolve(siteDir, options.path); const sourceToPermalink: SourceToPermalink = {}; + const pluginId = options.id ?? DEFAULT_PLUGIN_ID; + const isDefaultPluginId = pluginId === DEFAULT_PLUGIN_ID; - const dataDir = path.join( + const pluginDataDirRoot = path.join( generatedFilesDir, 'docusaurus-plugin-content-docs', - // options.id ?? 'default', // TODO support multi-instance ); + const dataDir = path.join(pluginDataDirRoot, pluginId); + const aliasedSource = (source: string) => + `~docs/${path.relative(pluginDataDirRoot, source)}`; // Versioning. - const env = loadEnv(siteDir, {disableVersioning: options.disableVersioning}); + const env = loadEnv(siteDir, pluginId, { + disableVersioning: options.disableVersioning, + }); const {versioning} = env; const { versions, @@ -102,12 +111,19 @@ export default function pluginContentDocs( }, extendCli(cli) { + const command = isDefaultPluginId + ? 'docs:version' + : `docs:version:${pluginId}`; + const commandDescription = isDefaultPluginId + ? 'Tag a new docs version' + : `Tag a new docs version (${pluginId})`; + cli - .command('docs:version') + .command(command) .arguments('') - .description('Tag a new version for docs') + .description(commandDescription) .action((version) => { - docsVersion(version, siteDir, { + docsVersion(version, siteDir, pluginId, { path: options.path, sidebarPath: options.sidebarPath, }); @@ -335,9 +351,6 @@ Available document ids= setGlobalData(pluginInstanceGlobalData); - const aliasedSource = (source: string) => - `~docs/${path.relative(dataDir, source)}`; - const createDocsBaseMetadata = ( version: DocsVersion, ): DocsBaseMetadata => { @@ -499,7 +512,7 @@ Available document ids= }, resolve: { alias: { - '~docs': dataDir, + '~docs': pluginDataDirRoot, }, }, module: { @@ -519,10 +532,10 @@ Available document ids= metadataPath: (mdxPath: string) => { // Note that metadataPath must be the same/in-sync as // the path from createData for each MDX. - const aliasedSource = aliasedSitePath(mdxPath, siteDir); + const aliasedPath = aliasedSitePath(mdxPath, siteDir); return path.join( dataDir, - `${docuHash(aliasedSource)}.json`, + `${docuHash(aliasedPath)}.json`, ); }, }, diff --git a/packages/docusaurus-plugin-content-docs/src/version.ts b/packages/docusaurus-plugin-content-docs/src/version.ts index 755dbc0276..860beaffb5 100644 --- a/packages/docusaurus-plugin-content-docs/src/version.ts +++ b/packages/docusaurus-plugin-content-docs/src/version.ts @@ -14,29 +14,36 @@ import fs from 'fs-extra'; import path from 'path'; import {Sidebar, PathOptions, SidebarItem} from './types'; import loadSidebars from './sidebars'; +import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants'; // Tests depend on non-default export for mocking. // eslint-disable-next-line import/prefer-default-export export function docsVersion( version: string | null | undefined, siteDir: string, + pluginId: string, options: PathOptions, ): void { + // It wouldn't be very user-friendly to show a [default] log prefix, + // so we use [docs] instead of [default] + const pluginIdLogPrefix = + pluginId === DEFAULT_PLUGIN_ID ? '[docs] ' : `[${pluginId}] `; + if (!version) { throw new Error( - 'No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0', + `${pluginIdLogPrefix}No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0`, ); } if (version.includes('/') || version.includes('\\')) { throw new Error( - `Invalid version tag specified! Do not include slash (/) or (\\). Try something like: 1.0.0`, + `${pluginIdLogPrefix}Invalid version tag specified! Do not include slash (/) or (\\). Try something like: 1.0.0`, ); } if (version.length > 32) { throw new Error( - 'Invalid version tag specified! Length must <= 32 characters. Try something like: 1.0.0', + `${pluginIdLogPrefix}Invalid version tag specified! Length must <= 32 characters. Try something like: 1.0.0`, ); } @@ -44,19 +51,19 @@ export function docsVersion( // sure it's a valid pathname. if (/[<>:"\/\\|?*\x00-\x1F]/g.test(version)) { throw new Error( - 'Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0', + `${pluginIdLogPrefix}Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0`, ); } if (/^\.\.?$/.test(version)) { throw new Error( - 'Invalid version tag specified! Do not name your version "." or "..". Try something like: 1.0.0', + `${pluginIdLogPrefix}Invalid version tag specified! Do not name your version "." or "..". Try something like: 1.0.0`, ); } // Load existing versions. let versions = []; - const versionsJSONFile = getVersionsJSONFile(siteDir); + const versionsJSONFile = getVersionsJSONFile(siteDir, pluginId); if (fs.existsSync(versionsJSONFile)) { versions = JSON.parse(fs.readFileSync(versionsJSONFile, 'utf8')); } @@ -64,7 +71,7 @@ export function docsVersion( // Check if version already exists. if (versions.includes(version)) { throw new Error( - 'This version already exists!. Use a version tag that does not already exist.', + `${pluginIdLogPrefix}This version already exists!. Use a version tag that does not already exist.`, ); } @@ -73,11 +80,11 @@ export function docsVersion( // Copy docs files. const docsDir = path.join(siteDir, docsPath); if (fs.existsSync(docsDir) && fs.readdirSync(docsDir).length > 0) { - const versionedDir = getVersionedDocsDir(siteDir); + const versionedDir = getVersionedDocsDir(siteDir, pluginId); const newVersionDir = path.join(versionedDir, `version-${version}`); fs.copySync(docsDir, newVersionDir); } else { - throw new Error('There is no docs to version !'); + throw new Error(`${pluginIdLogPrefix}There is no docs to version !`); } // Load current sidebar and create a new versioned sidebars file. @@ -109,7 +116,7 @@ export function docsVersion( {}, ); - const versionedSidebarsDir = getVersionedSidebarsDir(siteDir); + const versionedSidebarsDir = getVersionedSidebarsDir(siteDir, pluginId); const newSidebarFile = path.join( versionedSidebarsDir, `version-${version}-sidebars.json`, @@ -127,5 +134,5 @@ export function docsVersion( fs.ensureDirSync(path.dirname(versionsJSONFile)); fs.writeFileSync(versionsJSONFile, `${JSON.stringify(versions, null, 2)}\n`); - console.log(`Version ${version} created!`); + console.log(`${pluginIdLogPrefix}Version ${version} created!`); } diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index 92836d58ac..ba7958b5d4 100644 --- a/packages/docusaurus-plugin-content-pages/package.json +++ b/packages/docusaurus-plugin-content-pages/package.json @@ -15,6 +15,7 @@ "@types/hapi__joi": "^17.1.2" }, "dependencies": { + "@docusaurus/core": "^2.0.0-alpha.61", "@docusaurus/mdx-loader": "^2.0.0-alpha.61", "@docusaurus/types": "^2.0.0-alpha.61", "@docusaurus/utils": "^2.0.0-alpha.61", diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index f20e4fa3e5..8a29d781c6 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -25,6 +25,7 @@ import {Configuration, Loader} from 'webpack'; import admonitions from 'remark-admonitions'; import {PluginOptionSchema} from './pluginOptionSchema'; import {ValidationError} from '@hapi/joi'; +import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants'; import {PluginOptions, LoadedContent, Metadata} from './types'; @@ -44,10 +45,11 @@ export default function pluginContentPages( const contentPath = path.resolve(siteDir, options.path); - const dataDir = path.join( + const pluginDataDirRoot = path.join( generatedFilesDir, 'docusaurus-plugin-content-pages', ); + const dataDir = path.join(pluginDataDirRoot, options.id ?? DEFAULT_PLUGIN_ID); return { name: 'docusaurus-plugin-content-pages', @@ -83,20 +85,20 @@ export default function pluginContentPages( function toMetadata(relativeSource: string): Metadata { const source = path.join(pagesDir, relativeSource); - const aliasedSource = aliasedSitePath(source, siteDir); + const aliasedSourcePath = aliasedSitePath(source, siteDir); const pathName = encodePath(fileToPath(relativeSource)); const permalink = pathName.replace(/^\//, baseUrl || ''); if (isMarkdownSource(relativeSource)) { return { type: 'mdx', permalink, - source: aliasedSource, + source: aliasedSourcePath, }; } else { return { type: 'jsx', permalink, - source: aliasedSource, + source: aliasedSourcePath, }; } } @@ -152,7 +154,7 @@ export default function pluginContentPages( return { resolve: { alias: { - '~pages': dataDir, + '~pages': pluginDataDirRoot, }, }, module: { @@ -171,10 +173,10 @@ export default function pluginContentPages( // Note that metadataPath must be the same/in-sync as // the path from createData for each MDX. metadataPath: (mdxPath: string) => { - const aliasedSource = aliasedSitePath(mdxPath, siteDir); + const aliasedPath = aliasedSitePath(mdxPath, siteDir); return path.join( dataDir, - `${docuHash(aliasedSource)}.json`, + `${docuHash(aliasedPath)}.json`, ); }, }, diff --git a/packages/docusaurus-plugin-content-pages/src/types.ts b/packages/docusaurus-plugin-content-pages/src/types.ts index 9c9e2706d9..99f3f00d34 100644 --- a/packages/docusaurus-plugin-content-pages/src/types.ts +++ b/packages/docusaurus-plugin-content-pages/src/types.ts @@ -6,6 +6,7 @@ */ export interface PluginOptions { + id?: string; path: string; routeBasePath: string; include: string[]; diff --git a/packages/docusaurus-utils-validation/package.json b/packages/docusaurus-utils-validation/package.json index d95aa07b06..e77f40c9ff 100644 --- a/packages/docusaurus-utils-validation/package.json +++ b/packages/docusaurus-utils-validation/package.json @@ -16,7 +16,8 @@ "@types/hapi__joi": "^17.1.2" }, "dependencies": { - "@hapi/joi": "17.1.1" + "@hapi/joi": "17.1.1", + "chalk": "^3.0.0" }, "engines": { "node": ">=10.15.1" diff --git a/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/index.test.ts.snap deleted file mode 100644 index a6d659ab1f..0000000000 --- a/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,45 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`validation schemas AdmonitionsSchema 1`] = `"\\"value\\" must be of type object"`; - -exports[`validation schemas AdmonitionsSchema 2`] = `"\\"value\\" must be of type object"`; - -exports[`validation schemas AdmonitionsSchema 3`] = `"\\"value\\" must be of type object"`; - -exports[`validation schemas AdmonitionsSchema 4`] = `"\\"value\\" must be of type object"`; - -exports[`validation schemas RehypePluginsSchema 1`] = `"\\"value\\" must be an array"`; - -exports[`validation schemas RehypePluginsSchema 2`] = `"\\"value\\" must be an array"`; - -exports[`validation schemas RehypePluginsSchema 3`] = `"\\"value\\" must be an array"`; - -exports[`validation schemas RehypePluginsSchema 4`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RehypePluginsSchema 5`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RehypePluginsSchema 6`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RehypePluginsSchema 7`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RehypePluginsSchema 8`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RehypePluginsSchema 9`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RemarkPluginsSchema 1`] = `"\\"value\\" must be an array"`; - -exports[`validation schemas RemarkPluginsSchema 2`] = `"\\"value\\" must be an array"`; - -exports[`validation schemas RemarkPluginsSchema 3`] = `"\\"value\\" must be an array"`; - -exports[`validation schemas RemarkPluginsSchema 4`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RemarkPluginsSchema 5`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RemarkPluginsSchema 6`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RemarkPluginsSchema 7`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RemarkPluginsSchema 8`] = `"\\"[0]\\" does not match any of the allowed types"`; - -exports[`validation schemas RemarkPluginsSchema 9`] = `"\\"[0]\\" does not match any of the allowed types"`; diff --git a/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/validationSchemas.test.ts.snap b/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/validationSchemas.test.ts.snap new file mode 100644 index 0000000000..ff5d788094 --- /dev/null +++ b/packages/docusaurus-utils-validation/src/__tests__/__snapshots__/validationSchemas.test.ts.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`validation schemas AdmonitionsSchema: for value=[] 1`] = `"\\"value\\" must be of type object"`; + +exports[`validation schemas AdmonitionsSchema: for value=3 1`] = `"\\"value\\" must be of type object"`; + +exports[`validation schemas AdmonitionsSchema: for value=null 1`] = `"\\"value\\" must be of type object"`; + +exports[`validation schemas AdmonitionsSchema: for value=true 1`] = `"\\"value\\" must be of type object"`; + +exports[`validation schemas PluginIdSchema: for value="/docs" 1`] = `"\\"value\\" with value \\"/docs\\" fails to match the required pattern: /^[a-zA-Z_\\\\-]+$/"`; + +exports[`validation schemas PluginIdSchema: for value="do cs" 1`] = `"\\"value\\" with value \\"do cs\\" fails to match the required pattern: /^[a-zA-Z_\\\\-]+$/"`; + +exports[`validation schemas PluginIdSchema: for value="do/cs" 1`] = `"\\"value\\" with value \\"do/cs\\" fails to match the required pattern: /^[a-zA-Z_\\\\-]+$/"`; + +exports[`validation schemas PluginIdSchema: for value="docs/" 1`] = `"\\"value\\" with value \\"docs/\\" fails to match the required pattern: /^[a-zA-Z_\\\\-]+$/"`; + +exports[`validation schemas PluginIdSchema: for value=[] 1`] = `"\\"value\\" must be a string"`; + +exports[`validation schemas PluginIdSchema: for value=3 1`] = `"\\"value\\" must be a string"`; + +exports[`validation schemas PluginIdSchema: for value=null 1`] = `"\\"value\\" must be a string"`; + +exports[`validation schemas PluginIdSchema: for value=true 1`] = `"\\"value\\" must be a string"`; + +exports[`validation schemas RehypePluginsSchema: for value=[[]] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RehypePluginsSchema: for value=[[null,null]] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RehypePluginsSchema: for value=[[null,true]] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RehypePluginsSchema: for value=[3] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RehypePluginsSchema: for value=[false] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RehypePluginsSchema: for value=[null] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RehypePluginsSchema: for value=3 1`] = `"\\"value\\" must be an array"`; + +exports[`validation schemas RehypePluginsSchema: for value=false 1`] = `"\\"value\\" must be an array"`; + +exports[`validation schemas RehypePluginsSchema: for value=null 1`] = `"\\"value\\" must be an array"`; + +exports[`validation schemas RemarkPluginsSchema: for value=[[]] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RemarkPluginsSchema: for value=[[null,null]] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RemarkPluginsSchema: for value=[[null,true]] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RemarkPluginsSchema: for value=[3] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RemarkPluginsSchema: for value=[false] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RemarkPluginsSchema: for value=[null] 1`] = `"\\"[0]\\" does not match any of the allowed types"`; + +exports[`validation schemas RemarkPluginsSchema: for value=3 1`] = `"\\"value\\" must be an array"`; + +exports[`validation schemas RemarkPluginsSchema: for value=false 1`] = `"\\"value\\" must be an array"`; + +exports[`validation schemas RemarkPluginsSchema: for value=null 1`] = `"\\"value\\" must be an array"`; diff --git a/packages/docusaurus-utils-validation/src/__tests__/index.test.ts b/packages/docusaurus-utils-validation/src/__tests__/validationSchemas.test.ts similarity index 74% rename from packages/docusaurus-utils-validation/src/__tests__/index.test.ts rename to packages/docusaurus-utils-validation/src/__tests__/validationSchemas.test.ts index 8812686d40..05a614bd0d 100644 --- a/packages/docusaurus-utils-validation/src/__tests__/index.test.ts +++ b/packages/docusaurus-utils-validation/src/__tests__/validationSchemas.test.ts @@ -11,7 +11,8 @@ import { AdmonitionsSchema, RehypePluginsSchema, RemarkPluginsSchema, -} from '../index'; + PluginIdSchema, +} from '../validationSchemas'; function createTestHelpers({ schema, @@ -25,7 +26,10 @@ function createTestHelpers({ } function testFail(value: unknown) { - expect(() => Joi.attempt(value, schema)).toThrowErrorMatchingSnapshot(); + expect(() => Joi.attempt(value, schema)).toThrowErrorMatchingSnapshot( + // @ts-expect-error: seems ok at runtime, but bad typedef + `for value=${JSON.stringify(value)}`, + ); } return {testOK, testFail}; @@ -58,6 +62,27 @@ function testMarkdownPluginSchemas(schema: Joi.SchemaLike) { } describe('validation schemas', () => { + test('PluginIdSchema', () => { + const {testOK, testFail} = createTestHelpers({ + schema: PluginIdSchema, + defaultValue: 'default', + }); + + testOK(undefined); + testOK('docs'); + testOK('default'); + testOK('plugin-id_with-simple-special-chars'); + + testFail('/docs'); + testFail('docs/'); + testFail('do/cs'); + testFail('do cs'); + testFail(null); + testFail(3); + testFail(true); + testFail([]); + }); + test('AdmonitionsSchema', () => { const {testOK, testFail} = createTestHelpers({ schema: AdmonitionsSchema, diff --git a/packages/docusaurus-utils-validation/src/index.ts b/packages/docusaurus-utils-validation/src/index.ts index f918e5cf9e..f8e104bb38 100644 --- a/packages/docusaurus-utils-validation/src/index.ts +++ b/packages/docusaurus-utils-validation/src/index.ts @@ -4,19 +4,6 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import * as Joi from '@hapi/joi'; -const MarkdownPluginsSchema = Joi.array() - .items( - Joi.array() - // TODO, this allows [config,fn] too? - .items(Joi.function().required(), Joi.object().required()) - .length(2), - Joi.function(), - ) - .default([]); - -export const RemarkPluginsSchema = MarkdownPluginsSchema; -export const RehypePluginsSchema = MarkdownPluginsSchema; - -export const AdmonitionsSchema = Joi.object().default({}); +export * from './validationUtils'; +export * from './validationSchemas'; diff --git a/packages/docusaurus-utils-validation/src/validationSchemas.ts b/packages/docusaurus-utils-validation/src/validationSchemas.ts new file mode 100644 index 0000000000..70f6925e9e --- /dev/null +++ b/packages/docusaurus-utils-validation/src/validationSchemas.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import * as Joi from '@hapi/joi'; + +export const PluginIdSchema = Joi.string() + .regex(/^[a-zA-Z_\-]+$/) + // duplicate core constant, otherwise cyclic dependency is created :( + .default('default'); + +const MarkdownPluginsSchema = Joi.array() + .items( + Joi.array() + // TODO, this allows [config,fn] too? + .items(Joi.function().required(), Joi.object().required()) + .length(2), + Joi.function(), + ) + .default([]); + +export const RemarkPluginsSchema = MarkdownPluginsSchema; +export const RehypePluginsSchema = MarkdownPluginsSchema; + +export const AdmonitionsSchema = Joi.object().default({}); diff --git a/packages/docusaurus-utils-validation/src/validationUtils.ts b/packages/docusaurus-utils-validation/src/validationUtils.ts new file mode 100644 index 0000000000..794b287df7 --- /dev/null +++ b/packages/docusaurus-utils-validation/src/validationUtils.ts @@ -0,0 +1,85 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import * as Joi from '@hapi/joi'; +import chalk from 'chalk'; +import {PluginIdSchema} from './validationSchemas'; + +// TODO temporary escape hatch for alpha-60: to be removed soon +// Our validation schemas might be buggy at first +// will permit users to bypass validation until we fix all validation errors +// see for example: https://github.com/facebook/docusaurus/pull/3120 +// Undocumented on purpose, as we don't want users to keep using it over time +// Maybe we'll make this escape hatch official some day, with a better api? +export const isValidationDisabledEscapeHatch = + process.env.DISABLE_DOCUSAURUS_VALIDATION === 'true'; + +if (isValidationDisabledEscapeHatch) { + console.error( + chalk.red( + 'You should avoid using DISABLE_DOCUSAURUS_VALIDATION escape hatch, this will be removed', + ), + ); +} + +export const logValidationBugReportHint = () => { + console.log( + `\n${chalk.red('A validation error occured.')}${chalk.cyanBright( + '\nThe validation system was added recently to Docusaurus as an attempt to avoid user configuration errors.' + + '\nWe may have made some mistakes.' + + '\nIf you think your configuration is valid and should keep working, please open a bug report.', + )}\n`, + ); +}; + +export function normalizePluginOptions( + schema: Joi.ObjectSchema, + options: unknown, +) { + // All plugins can be provided an "id" option (multi-instance support) + // we add schema validation automatically + const finalSchema = schema.append({ + id: PluginIdSchema, + }); + const {error, value} = finalSchema.validate(options, { + convert: false, + }); + if (error) { + logValidationBugReportHint(); + if (isValidationDisabledEscapeHatch) { + console.error(error); + return options; + } else { + throw error; + } + } + return value; +} + +export function normalizeThemeConfig( + schema: Joi.ObjectSchema, + themeConfig: unknown, +) { + // A theme should only validate his "slice" of the full themeConfig, + // not the whole object, so we allow unknown attributes + // otherwise one theme would fail validating the data of another theme + const finalSchema = schema.unknown(); + + const {error, value} = finalSchema.validate(themeConfig, { + convert: false, + }); + + if (error) { + logValidationBugReportHint(); + if (isValidationDisabledEscapeHatch) { + console.error(error); + return themeConfig; + } else { + throw error; + } + } + return value; +} diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index 219ba059a8..8c994328c3 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -47,6 +47,7 @@ "@babel/runtime-corejs3": "^7.10.4", "@docusaurus/types": "^2.0.0-alpha.61", "@docusaurus/utils": "^2.0.0-alpha.61", + "@docusaurus/utils-validation": "^2.0.0-alpha.61", "@endiliey/static-site-generator-webpack-plugin": "^4.0.0", "@hapi/joi": "^17.1.1", "@svgr/webpack": "^5.4.0", diff --git a/packages/docusaurus/src/client/.eslintrc.js b/packages/docusaurus/src/client/.eslintrc.js new file mode 100644 index 0000000000..0a60804545 --- /dev/null +++ b/packages/docusaurus/src/client/.eslintrc.js @@ -0,0 +1,29 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +module.exports = { + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: [ + // prevent importing lodash in client bundle + // prefer shipping vanilla JS + 'lodash', + 'lodash.**', + 'lodash/**', + // prevent importing server code in client bundle + '**/../babel/**', + '**/../server/**', + '**/../commands/**', + '**/../webpack/**', + '**/../constants', + ], + }, + ], + }, +}; diff --git a/packages/docusaurus/src/client/exports/useGlobalData.ts b/packages/docusaurus/src/client/exports/useGlobalData.ts index 11e2e127db..b98fc32c35 100644 --- a/packages/docusaurus/src/client/exports/useGlobalData.ts +++ b/packages/docusaurus/src/client/exports/useGlobalData.ts @@ -7,6 +7,12 @@ import useDocusaurusContext from './useDocusaurusContext'; +// TODO annoying constant duplication +// if we import something from outside the /client folder, +// the tsc directory structure is affected +// import {DEFAULT_PLUGIN_ID} from '../../constants'; +const DEFAULT_PLUGIN_ID = 'default'; + export default function useGlobalData() { const {globalData} = useDocusaurusContext(); if (!globalData) { @@ -30,7 +36,7 @@ export function useAllPluginInstancesData( export function usePluginData( pluginName: string, - pluginId: string = 'default', + pluginId: string = DEFAULT_PLUGIN_ID, ): T { const pluginGlobalData = useAllPluginInstancesData(pluginName); const pluginInstanceGlobalData = pluginGlobalData[pluginId]; diff --git a/packages/docusaurus/src/constants.ts b/packages/docusaurus/src/constants.ts index f73e914615..a3020e4948 100644 --- a/packages/docusaurus/src/constants.ts +++ b/packages/docusaurus/src/constants.ts @@ -14,3 +14,4 @@ export const STATIC_DIR_NAME = 'static'; export const STATIC_ASSETS_DIR_NAME = 'assets'; // files handled by webpack export const THEME_PATH = `${SRC_DIR_NAME}/theme`; export const DEFAULT_PORT = 3000; +export const DEFAULT_PLUGIN_ID = 'default'; diff --git a/packages/docusaurus/src/server/configValidation.ts b/packages/docusaurus/src/server/configValidation.ts index 0672cd69cf..2294432117 100644 --- a/packages/docusaurus/src/server/configValidation.ts +++ b/packages/docusaurus/src/server/configValidation.ts @@ -9,9 +9,9 @@ import {DocusaurusConfig} from '@docusaurus/types'; import {CONFIG_FILE_NAME} from '../constants'; import Joi from '@hapi/joi'; import { - isValidationDisabledEscapeHatch, logValidationBugReportHint, -} from './utils'; + isValidationDisabledEscapeHatch, +} from '@docusaurus/utils-validation'; export const DEFAULT_CONFIG: Pick< DocusaurusConfig, @@ -47,6 +47,7 @@ const PresetSchema = Joi.alternatives().try( Joi.array().items(Joi.string().required(), Joi.object().required()).length(2), ); +// TODO move to @docusaurus/utils-validation const ConfigSchema = Joi.object({ baseUrl: Joi.string() .required() @@ -87,6 +88,7 @@ const ConfigSchema = Joi.object({ tagline: Joi.string().allow(''), }); +// TODO move to @docusaurus/utils-validation export function validateConfig( config: Partial, ): DocusaurusConfig { diff --git a/packages/docusaurus/src/server/plugins/index.ts b/packages/docusaurus/src/server/plugins/index.ts index 814961da10..619afeed6a 100644 --- a/packages/docusaurus/src/server/plugins/index.ts +++ b/packages/docusaurus/src/server/plugins/index.ts @@ -16,8 +16,7 @@ import { } from '@docusaurus/types'; import initPlugins, {InitPlugin} from './init'; import chalk from 'chalk'; - -const DefaultPluginId = 'default'; +import {DEFAULT_PLUGIN_ID} from '../../constants'; export function sortConfig(routeConfigs: RouteConfig[]): void { // Sort the route config. This ensures that route with nested @@ -90,14 +89,11 @@ export async function loadPlugins({ return; } - const pluginId = plugin.options.id ?? DefaultPluginId; + const pluginId = plugin.options.id ?? DEFAULT_PLUGIN_ID; - const pluginContentDir = path.join( - context.generatedFilesDir, - plugin.name, - // TODO each plugin instance should have its folder - // pluginId, - ); + // plugins data files are namespaced by pluginName/pluginId + const dataDirRoot = path.join(context.generatedFilesDir, plugin.name); + const dataDir = path.join(dataDirRoot, pluginId); const addRoute: PluginContentLoadedActions['addRoute'] = (config) => pluginsRouteConfigs.push(config); @@ -106,9 +102,9 @@ export async function loadPlugins({ name, content, ) => { - const modulePath = path.join(pluginContentDir, name); + const modulePath = path.join(dataDir, name); await fs.ensureDir(path.dirname(modulePath)); - await generate(pluginContentDir, name, content); + await generate(dataDir, name, content); return modulePath; }; diff --git a/packages/docusaurus/src/server/plugins/init.ts b/packages/docusaurus/src/server/plugins/init.ts index 9a2cb7ed36..09f0e08ef5 100644 --- a/packages/docusaurus/src/server/plugins/init.ts +++ b/packages/docusaurus/src/server/plugins/init.ts @@ -13,65 +13,15 @@ import { Plugin, PluginOptions, PluginConfig, - ValidationSchema, DocusaurusPluginVersionInformation, } from '@docusaurus/types'; import {CONFIG_FILE_NAME} from '../../constants'; import {getPluginVersion} from '../versions'; import {ensureUniquePluginInstanceIds} from './pluginIds'; -import * as Joi from '@hapi/joi'; import { - isValidationDisabledEscapeHatch, - logValidationBugReportHint, -} from '../utils'; - -function pluginOptionsValidator( - schema: ValidationSchema, - options: Partial, -) { - // All plugins can be provided an "id" for multi-instance support - // we don't ask the user to implement id validation, we add it automatically - const finalSchema = schema.append({ - id: Joi.string(), - }); - const {error, value} = finalSchema.validate(options, { - convert: false, - }); - if (error) { - logValidationBugReportHint(); - if (isValidationDisabledEscapeHatch) { - console.error(error); - return options; - } else { - throw error; - } - } - return value; -} - -function themeConfigValidator( - schema: ValidationSchema, - themeConfig: Partial, -) { - // A theme should only validate his "slice" of the full themeConfig, - // not the whole object, so we allow unknown attributes to pass a theme validation - const finalSchema = schema.unknown(); - - const {error, value} = finalSchema.validate(themeConfig, { - convert: false, - }); - - if (error) { - logValidationBugReportHint(); - if (isValidationDisabledEscapeHatch) { - console.error(error); - return themeConfig; - } else { - throw error; - } - } - return value; -} + normalizePluginOptions, + normalizeThemeConfig, +} from '@docusaurus/utils-validation'; export type InitPlugin = Plugin & { readonly options: PluginOptions; @@ -125,7 +75,7 @@ export default function initPlugins({ if (validateOptions) { const normalizedOptions = validateOptions({ - validate: pluginOptionsValidator, + validate: normalizePluginOptions, options: pluginOptions, }); pluginOptions = normalizedOptions; @@ -138,7 +88,7 @@ export default function initPlugins({ if (validateThemeConfig) { const normalizedThemeConfig = validateThemeConfig({ - validate: themeConfigValidator, + validate: normalizeThemeConfig, themeConfig: context.siteConfig.themeConfig, }); diff --git a/packages/docusaurus/src/server/plugins/pluginIds.ts b/packages/docusaurus/src/server/plugins/pluginIds.ts index d80b6d4900..e3fff3b9dd 100644 --- a/packages/docusaurus/src/server/plugins/pluginIds.ts +++ b/packages/docusaurus/src/server/plugins/pluginIds.ts @@ -7,6 +7,7 @@ import {groupBy} from 'lodash'; import {InitPlugin} from './init'; +import {DEFAULT_PLUGIN_ID} from '../../constants'; // It is forbidden to have 2 plugins of the same name sharind the same id // this is required to support multi-instance plugins without conflict @@ -15,7 +16,7 @@ export function ensureUniquePluginInstanceIds(plugins: InitPlugin[]) { Object.entries(pluginsByName).forEach(([pluginName, pluginInstances]) => { const pluginInstancesById = groupBy( pluginInstances, - (p) => p.options.id ?? 'default', + (p) => p.options.id ?? DEFAULT_PLUGIN_ID, ); Object.entries(pluginInstancesById).forEach( ([pluginId, pluginInstancesWithId]) => { diff --git a/packages/docusaurus/src/server/utils.ts b/packages/docusaurus/src/server/utils.ts index 12f2247993..1421604f11 100644 --- a/packages/docusaurus/src/server/utils.ts +++ b/packages/docusaurus/src/server/utils.ts @@ -8,32 +8,6 @@ import chalk from 'chalk'; import flatMap from 'lodash.flatmap'; import {RouteConfig, ReportingSeverity} from '@docusaurus/types'; -// TODO temporary escape hatch for alpha-60: to be removed soon -// Our validation schemas might be buggy at first -// will permit users to bypass validation until we fix all validation errors -// see for example: https://github.com/facebook/docusaurus/pull/3120 -// Undocumented on purpose, as we don't want users to keep using it over time -// Maybe we'll make this escape hatch official some day, with a better api? -export const isValidationDisabledEscapeHatch = - process.env.DISABLE_DOCUSAURUS_VALIDATION === 'true'; - -isValidationDisabledEscapeHatch && - console.error( - chalk.red( - 'You should avoid using DISABLE_DOCUSAURUS_VALIDATION escape hatch, this will be removed', - ), - ); - -export const logValidationBugReportHint = () => { - console.log( - `\n${chalk.red('A validation error occured.')}${chalk.cyanBright( - '\nThe validation system was added recently to Docusaurus as an attempt to avoid user configuration errors.' + - '\nWe may have made some mistakes.' + - '\nIf you think your configuration is valid and should keep working, please open a bug report.', - )}\n`, - ); -}; - // Recursively get the final routes (routes with no subroutes) export function getAllFinalRoutes(routeConfig: RouteConfig[]): RouteConfig[] { function getFinalRoutes(route: RouteConfig): RouteConfig[] { diff --git a/website/versioned_docs/version-2.0.0-alpha.60/community/resources.md b/website/community/resources.md similarity index 71% rename from website/versioned_docs/version-2.0.0-alpha.60/community/resources.md rename to website/community/resources.md index 4e93baf92b..9158a367e7 100644 --- a/website/versioned_docs/version-2.0.0-alpha.60/community/resources.md +++ b/website/community/resources.md @@ -20,13 +20,13 @@ See the showcase ## Official plugins -- [@docusaurus/plugin-content-blog](using-plugins.md#docusaurusplugin-content-blog) -- [@docusaurus/plugin-content-docs](using-plugins.md#docusaurusplugin-content-docs) -- [@docusaurus/plugin-content-pages](using-plugins.md#docusaurusplugin-content-pages) -- [@docusaurus/plugin-google-analytics](using-plugins.md#docusaurusplugin-google-analytics) -- [@docusaurus/plugin-google-gtag](using-plugins.md#docusaurusplugin-google-gtag) -- [@docusaurus/plugin-sitemap](using-plugins.md#docusaurusplugin-sitemap) -- [@docusaurus/plugin-ideal-image](using-plugins.md#docusaurusplugin-ideal-image) +- [@docusaurus/plugin-content-blog](/docs/using-plugins#docusaurusplugin-content-blog) +- [@docusaurus/plugin-content-docs](/docs/using-plugins#docusaurusplugin-content-docs) +- [@docusaurus/plugin-content-pages](/docs/using-plugins#docusaurusplugin-content-pages) +- [@docusaurus/plugin-google-analytics](/docs/using-plugins#docusaurusplugin-google-analytics) +- [@docusaurus/plugin-google-gtag](/docs/using-plugins#docusaurusplugin-google-gtag) +- [@docusaurus/plugin-sitemap](/docs/using-plugins#docusaurusplugin-sitemap) +- [@docusaurus/plugin-ideal-image](/docs/using-plugins#docusaurusplugin-ideal-image) ## Community plugins diff --git a/website/docs/community/support.md b/website/community/support.md similarity index 100% rename from website/docs/community/support.md rename to website/community/support.md diff --git a/website/versioned_docs/version-2.0.0-alpha.60/community/team.md b/website/community/team.md similarity index 94% rename from website/versioned_docs/version-2.0.0-alpha.60/community/team.md rename to website/community/team.md index fb149dd1d9..07155fae77 100644 --- a/website/versioned_docs/version-2.0.0-alpha.60/community/team.md +++ b/website/community/team.md @@ -36,7 +36,7 @@ export function TeamProfileCardCol(props) { return - React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. + React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. He writes regularly, on his website and Dev.to. +As an example, we host a second blog [here](/second-blog). diff --git a/website/docs/community/resources.md b/website/docs/community/resources.md deleted file mode 100644 index 4e93baf92b..0000000000 --- a/website/docs/community/resources.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: resources -title: Awesome Resources -slug: /resources ---- - -A curated list of interesting Docusaurus community projects. - -## Videos - -- [F8 2019: Using Docusaurus to Create Open Source Websites](https://www.youtube.com/watch?v=QcGJsf6mgZE) - -## Articles - -- [Live code editing in Docusaurus](https://dev.to/mrmuhammadali/live-code-editing-in-docusaurus-28k) - -## Showcase - -See the showcase. - -## Official plugins - -- [@docusaurus/plugin-content-blog](using-plugins.md#docusaurusplugin-content-blog) -- [@docusaurus/plugin-content-docs](using-plugins.md#docusaurusplugin-content-docs) -- [@docusaurus/plugin-content-pages](using-plugins.md#docusaurusplugin-content-pages) -- [@docusaurus/plugin-google-analytics](using-plugins.md#docusaurusplugin-google-analytics) -- [@docusaurus/plugin-google-gtag](using-plugins.md#docusaurusplugin-google-gtag) -- [@docusaurus/plugin-sitemap](using-plugins.md#docusaurusplugin-sitemap) -- [@docusaurus/plugin-ideal-image](using-plugins.md#docusaurusplugin-ideal-image) - -## Community plugins - -- [docusaurus-plugin-lunr](https://github.com/daldridge/docusaurus-plugin-lunr) - Docusaurus v2 plugin to create a local search index for use with Lunr.js -- [docusaurus-lunr-search](https://github.com/lelouch77/docusurus-lunr-search) - Offline Search for Docusaurus v2 -- [docusaurus-search-local](https://github.com/cmfcmf/docusaurus-search-local) - Offline/local search for Docusaurus v2 -- [docusaurus-pdf](https://github.com/KohheePeace/docusaurus-pdf) - Generate documentation into PDF format -- [docusaurus-plugin-sass](https://github.com/rlamana/docusaurus-plugin-sass) - Sass/SCSS stylesheets support -- [docusaurus2-dotenv](https://github.com/jonnynabors/docusaurus2-dotenv) - A Docusaurus 2 plugin that supports dotenv and other environment variables -- [posthog-docusaurus](https://github.com/PostHog/posthog-docusaurus) - Integrate [PostHog](https://posthog.com/) product analytics with Docusaurus v2 - -## Enterprise usage - -- Facebook -- Google -- Stripe -- Algolia -- Callstack diff --git a/website/docs/community/team.md b/website/docs/community/team.md deleted file mode 100644 index fb149dd1d9..0000000000 --- a/website/docs/community/team.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: team -title: Team -slug: /team ---- - -import TeamProfileCard from "@site/src/components/TeamProfileCard" - -export function TeamProfileCardCol(props) { return } - -## Active Team - -
- - Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 - - - Fanny got started with web development in high school, building a project for the school kitchen. In her free time she loves contributing to Open Source, occasionally writing on her blog about her experiences, cooking, and creating Spotify playlists. - - - Docusaurus founder and now ever grateful Docusaurus cheerleader to those who actually write code for it. - - - React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. - - - Full Front End Stack developer who likes working on the Jamstack. Working on Docusaurus made him Facebook's unofficial part-time Open Source webmaster, which is an awesome role to be in. - -
- -## Honorary Alumni - -
- - Maintainer @docusaurus · 🔥🔥🔥 - - - 🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes docs and spams this world with many websites. - -
- -## Acknowledgements - -Docusaurus was originally created by Joel Marcey. Today, Docusaurus has a few hundred open source contributors. We’d like to recognize a few people who have made significant contributions to Docusaurus and its documentation in the past and have helped maintain them over the years: - -- [Amy Lam](https://github.com/amyrlam) -- [Cheng Lou](https://github.com/chenglou) -- [Christine Abernathy](https://github.com/caabernathy) -- [Christopher Chedeau](https://github.com/vjeux) -- [Elvis Wolcott](https://github.com/elviswolcott) -- [Eric Nakagawa](https://github.com/ericnakagawa) -- [Fienny Angelina](https://github.com/fiennyangeln) -- [Frank Li](https://github.com/deltice) -- [Héctor Ramos](https://github.com/hramos) -- [Ramón Lamana](https://github.com/rlamana) -- [Ricky Vetter](https://github.com/rickyvetter) -- [Sam Zhou](https://github.com/SamChou19815) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index afa2b1c2d8..90360052cd 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -31,6 +31,33 @@ module.exports = { }, themes: ['@docusaurus/theme-live-codeblock'], plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + id: 'community', + path: 'community', + editUrl: 'https://github.com/facebook/docusaurus/edit/master/website/', + routeBasePath: 'community', + sidebarPath: require.resolve('./sidebarsCommunity.js'), + showLastUpdateAuthor: true, + showLastUpdateTime: true, + }, + ], + [ + '@docusaurus/plugin-content-blog', + { + id: 'second-blog', + path: 'dogfooding/second-blog', + routeBasePath: 'second-blog', + editUrl: + 'https://github.com/facebook/docusaurus/edit/master/website/dogfooding', + postsPerPage: 3, + feedOptions: { + type: 'all', + copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`, + }, + }, + ], [ '@docusaurus/plugin-client-redirects', { @@ -42,6 +69,20 @@ module.exports = { return [`${path}/introduction`]; } }, + redirects: [ + { + from: ['/docs/support', '/docs/next/support'], + to: '/community/support', + }, + { + from: ['/docs/team', '/docs/next/team'], + to: '/community/team', + }, + { + from: ['/docs/resources', '/docs/next/resources'], + to: '/community/resources', + }, + ], }, ], [ @@ -116,6 +157,7 @@ module.exports = { '@docusaurus/preset-classic', { docs: { + // routeBasePath: '/', homePageId: 'introduction', path: 'docs', sidebarPath: require.resolve('./sidebars.js'), @@ -127,6 +169,7 @@ module.exports = { disableVersioning: !!process.env.DISABLE_VERSIONING, }, blog: { + // routeBasePath: '/', path: '../website-1.x/blog', editUrl: 'https://github.com/facebook/docusaurus/edit/master/website-1.x/', @@ -188,10 +231,10 @@ module.exports = { {to: 'blog', label: 'Blog', position: 'left'}, {to: 'showcase', label: 'Showcase', position: 'left'}, { - to: 'docs/next/support', + to: '/community/support', label: 'Community', position: 'left', - activeBaseRegex: `docs/next/(support|team|resources)`, + activeBaseRegex: `/community/`, }, { to: '/versions', @@ -243,7 +286,7 @@ module.exports = { }, { label: 'Help', - to: 'docs/next/support', + to: '/community/support', }, ], }, diff --git a/website/dogfooding/second-blog/2020-08-03-second-blog-intro.md b/website/dogfooding/second-blog/2020-08-03-second-blog-intro.md new file mode 100644 index 0000000000..6c4990bb12 --- /dev/null +++ b/website/dogfooding/second-blog/2020-08-03-second-blog-intro.md @@ -0,0 +1,19 @@ +--- +title: Using twice the blog plugin +author: Sebastien Lorber +authorURL: https://sebastienlorber.com +authorImageURL: https://github.com/slorber.png +authorFBID: 611217057 +authorTwitter: sebastienlorber +tags: [blog, docusaurus] +--- + +Did you know you can use multiple instances of the same plugin? + + + +:::tip + +Using twice the blog plugin permits you to create more than one blog on the same Docusaurus website! + +::: diff --git a/website/sidebars.js b/website/sidebars.js index 1114e81c5f..18d6622046 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -51,19 +51,4 @@ module.exports = { ], }, ], - community: [ - 'community/support', - 'community/team', - 'community/resources', - { - type: 'link', - href: '/showcase', - label: 'Showcase', - }, - { - type: 'link', - href: '/feedback', - label: 'Feedback', - }, - ], }; diff --git a/website/sidebarsCommunity.js b/website/sidebarsCommunity.js new file mode 100644 index 0000000000..7af164c055 --- /dev/null +++ b/website/sidebarsCommunity.js @@ -0,0 +1,24 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +module.exports = { + community: [ + 'support', + 'team', + 'resources', + { + type: 'link', + href: '/showcase', + label: 'Showcase', + }, + { + type: 'link', + href: '/feedback', + label: 'Feedback', + }, + ], +}; diff --git a/website/versioned_docs/version-2.0.0-alpha.54/resources.md b/website/versioned_docs/version-2.0.0-alpha.54/resources.md deleted file mode 100644 index c01a1a903d..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.54/resources.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: resources -title: Awesome Resources ---- - -A curated list of interesting Docusaurus community projects. - -## Videos - -- [F8 2019: Using Docusaurus to Create Open Source Websites](https://www.youtube.com/watch?v=QcGJsf6mgZE) - -## Showcase - -See the showcase. - -## Official plugins - -- [@docusaurus/plugin-content-blog](using-plugins.md#docusaurusplugin-content-blog) -- [@docusaurus/plugin-content-docs](using-plugins.md#docusaurusplugin-content-docs) -- [@docusaurus/plugin-content-pages](using-plugins.md#docusaurusplugin-content-pages) -- [@docusaurus/plugin-google-analytics](using-plugins.md#docusaurusplugin-google-analytics) -- [@docusaurus/plugin-google-gtag](using-plugins.md#docusaurusplugin-google-gtag) -- [@docusaurus/plugin-sitemap](using-plugins.md#docusaurusplugin-sitemap) -- [@docusaurus/plugin-ideal-image](using-plugins.md#docusaurusplugin-ideal-image) - -## Community plugins - -- [docusaurus-plugin-lunr](https://github.com/daldridge/docusaurus-plugin-lunr) - Docusaurus v2 plugin to create a local search index for use with Lunr.js -- [docusaurus-lunr-search](https://github.com/lelouch77/docusurus-lunr-search) - Offline Search for Docusaurus v2 -- [docusaurus-search-local](https://github.com/cmfcmf/docusaurus-search-local) - Offline/local search for Docusaurus v2 -- [docusaurus-pdf](https://github.com/KohheePeace/docusaurus-pdf) - Generate documentation into PDF format -- [docusaurus-plugin-sass](https://github.com/rlamana/docusaurus-plugin-sass) - Sass/SCSS stylesheets support - -## Enterprise usage - -- Facebook -- Google -- Stripe -- Algolia -- Callstack diff --git a/website/versioned_docs/version-2.0.0-alpha.54/support.md b/website/versioned_docs/version-2.0.0-alpha.54/support.md deleted file mode 100644 index f58b73dca0..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.54/support.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -id: support -title: Support ---- - -Docusaurus has a community of thousands of developers. - -On this page we've listed some Docusaurus-related communities that you can be a part of; see the other pages in this section for additional online and in-person learning materials. - -Before participating in Docusaurus' communities, [please read our Code of Conduct](https://engineering.fb.com/codeofconduct/). We have adopted the [Contributor Covenant](https://www.contributor-covenant.org/) and we expect that all community members adhere to the guidelines within. - -## Stack Overflow - -Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/docusaurus) tagged with **docusaurus** or [ask your own](https://stackoverflow.com/questions/ask?tags=docusaurus)! - -## Discussion forums - -There are many online forums which are a great place for discussion about best practices and application architecture as well as the future of Docusaurus. If you have an answerable code-level question, Stack Overflow is usually a better fit. - -- [Docusaurus online chat](https://discord.gg/docusaurus) - - [#docusaurus-2-dogfooding](https://discord.gg/7wjJ9yH) for user help - - [#docusaurus-2-dev](https://discord.gg/6g6ASPA) for contributing help -- [Reddit's Docusaurus community](https://www.reddit.com/r/docusaurus/) - -## Feature requests - -For new feature requests, you can create a post on our [Canny board](/feedback), which is a handy tool for roadmapping and allows for sorting by upvotes, which gives the core team a better indicator of what features are in high demand, as compared to GitHub issues which are harder to triage. Refrain from making a Pull Request for new features (especially large ones) as someone might already be working on it or will be part of our roadmap. Talk to us first! - -## News - -For the latest news about Docusaurus, [follow **@docusaurus** on Twitter](https://twitter.com/docusaurus) and the [official Docusaurus blog](/blog) on this website. diff --git a/website/versioned_docs/version-2.0.0-alpha.54/team.md b/website/versioned_docs/version-2.0.0-alpha.54/team.md deleted file mode 100644 index 8d3b0678f0..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.54/team.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: team -title: Team ---- - -## Meet the Docusaurus Team - -### Alexey Pyltsyn - -
- -![](https://github.com/lex111.png) - -[@lex111 on GitHub](https://github.com/lex111) - -### Fanny Vieira - -
- -![](https://github.com/fanny.png) -[@fanny on GitHub](https://github.com/fanny) · [@fannyvieiira on Twitter](https://twitter.com/fannyvieiira) - -### Joel Marcey - -
- -![](https://github.com/joelmarcey.png) -[@joelmarcey on GitHub](https://github.com/joelmarcey) · [@joelmarcey on Twitter](https://twitter.com/joelmarcey) - -### Yangshun Tay - -
- -![](https://github.com/yangshun.png) -[@yangshun on GitHub](https://github.com/yangshun) · [@yangshunz on Twitter](https://twitter.com/yangshunz) - -## Honorary Alumni - -### Endilie Yacop Sucipto - -
- -![](https://github.com/endiliey.png?width=75&height=75) -[@endiliey on GitHub](https://github.com/endiliey) · [@endiliey on Twitter](https://twitter.com/endiliey) - -### Wei Gao - -
- -![](https://avatars3.githubusercontent.com/u/2055384?s=460&u=09248b65169cb9909246dfa39b796deffc7bd251&v=4) -[@wgao19 on GitHub](https://github.com/wgao19) · [@wgao19 on Twitter](https://twitter.com/wgao19) - -## Acknowledgements - -Docusaurus was originally created by Joel Marcey. Today, Docusaurus has a few hundred open source contributors. We’d like to recognize a few people who have made significant contributions to Docusaurus and its documentation in the past and have helped maintain them over the years: - -- [Amy Lam](https://github.com/amyrlam) -- [Cheng Lou](https://github.com/chenglou) -- [Christine Abernathy](https://github.com/caabernathy) -- [Christopher Chedeau](https://github.com/vjeux) -- Elvis Wolcott -- [Eric Nakagawa](https://github.com/ericnakagawa) -- Fienny Angelina -- Frank Li -- [Héctor Ramos](https://github.com/hramos) -- Ramón Lamana -- Ricky Vetter -- [Sam Zhou](https://github.com/SamChou19815) diff --git a/website/versioned_docs/version-2.0.0-alpha.55/resources.md b/website/versioned_docs/version-2.0.0-alpha.55/resources.md deleted file mode 100644 index b2da82a2fe..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.55/resources.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -id: resources -title: Awesome Resources ---- - -A curated list of interesting Docusaurus community projects. - -## Videos - -- [F8 2019: Using Docusaurus to Create Open Source Websites](https://www.youtube.com/watch?v=QcGJsf6mgZE) - -## Showcase - -See the showcase. - -## Official plugins - -- [@docusaurus/plugin-content-blog](using-plugins.md#docusaurusplugin-content-blog) -- [@docusaurus/plugin-content-docs](using-plugins.md#docusaurusplugin-content-docs) -- [@docusaurus/plugin-content-pages](using-plugins.md#docusaurusplugin-content-pages) -- [@docusaurus/plugin-google-analytics](using-plugins.md#docusaurusplugin-google-analytics) -- [@docusaurus/plugin-google-gtag](using-plugins.md#docusaurusplugin-google-gtag) -- [@docusaurus/plugin-sitemap](using-plugins.md#docusaurusplugin-sitemap) -- [@docusaurus/plugin-ideal-image](using-plugins.md#docusaurusplugin-ideal-image) - -## Community plugins - -- [docusaurus-plugin-lunr](https://github.com/daldridge/docusaurus-plugin-lunr) - Docusaurus v2 plugin to create a local search index for use with Lunr.js -- [docusaurus-lunr-search](https://github.com/lelouch77/docusurus-lunr-search) - Offline Search for Docusaurus v2 -- [docusaurus-search-local](https://github.com/cmfcmf/docusaurus-search-local) - Offline/local search for Docusaurus v2 -- [docusaurus-pdf](https://github.com/KohheePeace/docusaurus-pdf) - Generate documentation into PDF format -- [docusaurus-plugin-sass](https://github.com/rlamana/docusaurus-plugin-sass) - Sass/SCSS stylesheets support -- [docusaurus2-dotenv](https://github.com/jonnynabors/docusaurus2-dotenv) - A Docusaurus 2 plugin that supports dotenv and other environment variables - -## Enterprise usage - -- Facebook -- Google -- Stripe -- Algolia -- Callstack diff --git a/website/versioned_docs/version-2.0.0-alpha.55/support.md b/website/versioned_docs/version-2.0.0-alpha.55/support.md deleted file mode 100644 index f58b73dca0..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.55/support.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -id: support -title: Support ---- - -Docusaurus has a community of thousands of developers. - -On this page we've listed some Docusaurus-related communities that you can be a part of; see the other pages in this section for additional online and in-person learning materials. - -Before participating in Docusaurus' communities, [please read our Code of Conduct](https://engineering.fb.com/codeofconduct/). We have adopted the [Contributor Covenant](https://www.contributor-covenant.org/) and we expect that all community members adhere to the guidelines within. - -## Stack Overflow - -Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/docusaurus) tagged with **docusaurus** or [ask your own](https://stackoverflow.com/questions/ask?tags=docusaurus)! - -## Discussion forums - -There are many online forums which are a great place for discussion about best practices and application architecture as well as the future of Docusaurus. If you have an answerable code-level question, Stack Overflow is usually a better fit. - -- [Docusaurus online chat](https://discord.gg/docusaurus) - - [#docusaurus-2-dogfooding](https://discord.gg/7wjJ9yH) for user help - - [#docusaurus-2-dev](https://discord.gg/6g6ASPA) for contributing help -- [Reddit's Docusaurus community](https://www.reddit.com/r/docusaurus/) - -## Feature requests - -For new feature requests, you can create a post on our [Canny board](/feedback), which is a handy tool for roadmapping and allows for sorting by upvotes, which gives the core team a better indicator of what features are in high demand, as compared to GitHub issues which are harder to triage. Refrain from making a Pull Request for new features (especially large ones) as someone might already be working on it or will be part of our roadmap. Talk to us first! - -## News - -For the latest news about Docusaurus, [follow **@docusaurus** on Twitter](https://twitter.com/docusaurus) and the [official Docusaurus blog](/blog) on this website. diff --git a/website/versioned_docs/version-2.0.0-alpha.55/team.md b/website/versioned_docs/version-2.0.0-alpha.55/team.md deleted file mode 100644 index b0ca0e0497..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.55/team.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -id: team -title: Team ---- - -## Active Team - -
-
-
-
-
- -
-

Alexey Pyltsyn

-
-
-
-
- Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 -
-
-
- GitHub -
-
-
-
-
-
-
-
- -
-

Fanny Vieira

-
-
-
-
- Fanny got started with web development in high school, building a project for the school kitchen. In her free time she loves contributing to Open Source, occasionally writing on her blog about her experiences, cooking, and creating Spotify playlists. -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Joel Marcey

-
-
-
-
- Docusaurus founder and now ever grateful Docusaurus cheerleader to those who actually write code for it. -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Yangshun Tay

-
-
-
-
- Full Front End Stack developer who likes working on the Jamstack. Working on Docusaurus made him Facebook's unofficial part-time Open Source webmaster, which is an awesome role to be in. -
-
-
- GitHub - Twitter -
-
-
-
-
- -## Honorary Alumni - -
-
-
-
-
- -
-

Endilie Yacop Sucipto

-
-
-
-
- Maintainer @docusaurus · 🔥🔥🔥 -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Wei Gao

-
-
-
-
- 👩🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes docs and spams this world with many websites. -
-
-
- GitHub - Twitter -
-
-
-
-
- -## Acknowledgements - -Docusaurus was originally created by Joel Marcey. Today, Docusaurus has a few hundred open source contributors. We’d like to recognize a few people who have made significant contributions to Docusaurus and its documentation in the past and have helped maintain them over the years: - -- [Amy Lam](https://github.com/amyrlam) -- [Cheng Lou](https://github.com/chenglou) -- [Christine Abernathy](https://github.com/caabernathy) -- [Christopher Chedeau](https://github.com/vjeux) -- [Elvis Wolcott](https://github.com/elviswolcott) -- [Eric Nakagawa](https://github.com/ericnakagawa) -- [Fienny Angelina](https://github.com/fiennyangeln) -- [Frank Li](https://github.com/deltice) -- [Héctor Ramos](https://github.com/hramos) -- [Ramón Lamana](https://github.com/rlamana) -- [Ricky Vetter](https://github.com/rickyvetter) -- [Sam Zhou](https://github.com/SamChou19815) diff --git a/website/versioned_docs/version-2.0.0-alpha.56/resources.md b/website/versioned_docs/version-2.0.0-alpha.56/resources.md deleted file mode 100644 index 6bda806368..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.56/resources.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: resources -title: Awesome Resources ---- - -A curated list of interesting Docusaurus community projects. - -## Videos - -- [F8 2019: Using Docusaurus to Create Open Source Websites](https://www.youtube.com/watch?v=QcGJsf6mgZE) - -## Articles - -- [Live code editing in Docusaurus](https://dev.to/mrmuhammadali/live-code-editing-in-docusaurus-28k) - -## Showcase - -See the showcase. - -## Official plugins - -- [@docusaurus/plugin-content-blog](using-plugins.md#docusaurusplugin-content-blog) -- [@docusaurus/plugin-content-docs](using-plugins.md#docusaurusplugin-content-docs) -- [@docusaurus/plugin-content-pages](using-plugins.md#docusaurusplugin-content-pages) -- [@docusaurus/plugin-google-analytics](using-plugins.md#docusaurusplugin-google-analytics) -- [@docusaurus/plugin-google-gtag](using-plugins.md#docusaurusplugin-google-gtag) -- [@docusaurus/plugin-sitemap](using-plugins.md#docusaurusplugin-sitemap) -- [@docusaurus/plugin-ideal-image](using-plugins.md#docusaurusplugin-ideal-image) - -## Community plugins - -- [docusaurus-plugin-lunr](https://github.com/daldridge/docusaurus-plugin-lunr) - Docusaurus v2 plugin to create a local search index for use with Lunr.js -- [docusaurus-lunr-search](https://github.com/lelouch77/docusurus-lunr-search) - Offline Search for Docusaurus v2 -- [docusaurus-search-local](https://github.com/cmfcmf/docusaurus-search-local) - Offline/local search for Docusaurus v2 -- [docusaurus-pdf](https://github.com/KohheePeace/docusaurus-pdf) - Generate documentation into PDF format -- [docusaurus-plugin-sass](https://github.com/rlamana/docusaurus-plugin-sass) - Sass/SCSS stylesheets support -- [docusaurus2-dotenv](https://github.com/jonnynabors/docusaurus2-dotenv) - A Docusaurus 2 plugin that supports dotenv and other environment variables - -## Enterprise usage - -- Facebook -- Google -- Stripe -- Algolia -- Callstack diff --git a/website/versioned_docs/version-2.0.0-alpha.56/support.md b/website/versioned_docs/version-2.0.0-alpha.56/support.md deleted file mode 100644 index f58b73dca0..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.56/support.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -id: support -title: Support ---- - -Docusaurus has a community of thousands of developers. - -On this page we've listed some Docusaurus-related communities that you can be a part of; see the other pages in this section for additional online and in-person learning materials. - -Before participating in Docusaurus' communities, [please read our Code of Conduct](https://engineering.fb.com/codeofconduct/). We have adopted the [Contributor Covenant](https://www.contributor-covenant.org/) and we expect that all community members adhere to the guidelines within. - -## Stack Overflow - -Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/docusaurus) tagged with **docusaurus** or [ask your own](https://stackoverflow.com/questions/ask?tags=docusaurus)! - -## Discussion forums - -There are many online forums which are a great place for discussion about best practices and application architecture as well as the future of Docusaurus. If you have an answerable code-level question, Stack Overflow is usually a better fit. - -- [Docusaurus online chat](https://discord.gg/docusaurus) - - [#docusaurus-2-dogfooding](https://discord.gg/7wjJ9yH) for user help - - [#docusaurus-2-dev](https://discord.gg/6g6ASPA) for contributing help -- [Reddit's Docusaurus community](https://www.reddit.com/r/docusaurus/) - -## Feature requests - -For new feature requests, you can create a post on our [Canny board](/feedback), which is a handy tool for roadmapping and allows for sorting by upvotes, which gives the core team a better indicator of what features are in high demand, as compared to GitHub issues which are harder to triage. Refrain from making a Pull Request for new features (especially large ones) as someone might already be working on it or will be part of our roadmap. Talk to us first! - -## News - -For the latest news about Docusaurus, [follow **@docusaurus** on Twitter](https://twitter.com/docusaurus) and the [official Docusaurus blog](/blog) on this website. diff --git a/website/versioned_docs/version-2.0.0-alpha.56/team.md b/website/versioned_docs/version-2.0.0-alpha.56/team.md deleted file mode 100644 index b0ca0e0497..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.56/team.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -id: team -title: Team ---- - -## Active Team - -
-
-
-
-
- -
-

Alexey Pyltsyn

-
-
-
-
- Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 -
-
-
- GitHub -
-
-
-
-
-
-
-
- -
-

Fanny Vieira

-
-
-
-
- Fanny got started with web development in high school, building a project for the school kitchen. In her free time she loves contributing to Open Source, occasionally writing on her blog about her experiences, cooking, and creating Spotify playlists. -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Joel Marcey

-
-
-
-
- Docusaurus founder and now ever grateful Docusaurus cheerleader to those who actually write code for it. -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Yangshun Tay

-
-
-
-
- Full Front End Stack developer who likes working on the Jamstack. Working on Docusaurus made him Facebook's unofficial part-time Open Source webmaster, which is an awesome role to be in. -
-
-
- GitHub - Twitter -
-
-
-
-
- -## Honorary Alumni - -
-
-
-
-
- -
-

Endilie Yacop Sucipto

-
-
-
-
- Maintainer @docusaurus · 🔥🔥🔥 -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Wei Gao

-
-
-
-
- 👩🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes docs and spams this world with many websites. -
-
-
- GitHub - Twitter -
-
-
-
-
- -## Acknowledgements - -Docusaurus was originally created by Joel Marcey. Today, Docusaurus has a few hundred open source contributors. We’d like to recognize a few people who have made significant contributions to Docusaurus and its documentation in the past and have helped maintain them over the years: - -- [Amy Lam](https://github.com/amyrlam) -- [Cheng Lou](https://github.com/chenglou) -- [Christine Abernathy](https://github.com/caabernathy) -- [Christopher Chedeau](https://github.com/vjeux) -- [Elvis Wolcott](https://github.com/elviswolcott) -- [Eric Nakagawa](https://github.com/ericnakagawa) -- [Fienny Angelina](https://github.com/fiennyangeln) -- [Frank Li](https://github.com/deltice) -- [Héctor Ramos](https://github.com/hramos) -- [Ramón Lamana](https://github.com/rlamana) -- [Ricky Vetter](https://github.com/rickyvetter) -- [Sam Zhou](https://github.com/SamChou19815) diff --git a/website/versioned_docs/version-2.0.0-alpha.58/resources.md b/website/versioned_docs/version-2.0.0-alpha.58/resources.md deleted file mode 100644 index 6bda806368..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.58/resources.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: resources -title: Awesome Resources ---- - -A curated list of interesting Docusaurus community projects. - -## Videos - -- [F8 2019: Using Docusaurus to Create Open Source Websites](https://www.youtube.com/watch?v=QcGJsf6mgZE) - -## Articles - -- [Live code editing in Docusaurus](https://dev.to/mrmuhammadali/live-code-editing-in-docusaurus-28k) - -## Showcase - -See the showcase. - -## Official plugins - -- [@docusaurus/plugin-content-blog](using-plugins.md#docusaurusplugin-content-blog) -- [@docusaurus/plugin-content-docs](using-plugins.md#docusaurusplugin-content-docs) -- [@docusaurus/plugin-content-pages](using-plugins.md#docusaurusplugin-content-pages) -- [@docusaurus/plugin-google-analytics](using-plugins.md#docusaurusplugin-google-analytics) -- [@docusaurus/plugin-google-gtag](using-plugins.md#docusaurusplugin-google-gtag) -- [@docusaurus/plugin-sitemap](using-plugins.md#docusaurusplugin-sitemap) -- [@docusaurus/plugin-ideal-image](using-plugins.md#docusaurusplugin-ideal-image) - -## Community plugins - -- [docusaurus-plugin-lunr](https://github.com/daldridge/docusaurus-plugin-lunr) - Docusaurus v2 plugin to create a local search index for use with Lunr.js -- [docusaurus-lunr-search](https://github.com/lelouch77/docusurus-lunr-search) - Offline Search for Docusaurus v2 -- [docusaurus-search-local](https://github.com/cmfcmf/docusaurus-search-local) - Offline/local search for Docusaurus v2 -- [docusaurus-pdf](https://github.com/KohheePeace/docusaurus-pdf) - Generate documentation into PDF format -- [docusaurus-plugin-sass](https://github.com/rlamana/docusaurus-plugin-sass) - Sass/SCSS stylesheets support -- [docusaurus2-dotenv](https://github.com/jonnynabors/docusaurus2-dotenv) - A Docusaurus 2 plugin that supports dotenv and other environment variables - -## Enterprise usage - -- Facebook -- Google -- Stripe -- Algolia -- Callstack diff --git a/website/versioned_docs/version-2.0.0-alpha.58/support.md b/website/versioned_docs/version-2.0.0-alpha.58/support.md deleted file mode 100644 index f58b73dca0..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.58/support.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -id: support -title: Support ---- - -Docusaurus has a community of thousands of developers. - -On this page we've listed some Docusaurus-related communities that you can be a part of; see the other pages in this section for additional online and in-person learning materials. - -Before participating in Docusaurus' communities, [please read our Code of Conduct](https://engineering.fb.com/codeofconduct/). We have adopted the [Contributor Covenant](https://www.contributor-covenant.org/) and we expect that all community members adhere to the guidelines within. - -## Stack Overflow - -Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/docusaurus) tagged with **docusaurus** or [ask your own](https://stackoverflow.com/questions/ask?tags=docusaurus)! - -## Discussion forums - -There are many online forums which are a great place for discussion about best practices and application architecture as well as the future of Docusaurus. If you have an answerable code-level question, Stack Overflow is usually a better fit. - -- [Docusaurus online chat](https://discord.gg/docusaurus) - - [#docusaurus-2-dogfooding](https://discord.gg/7wjJ9yH) for user help - - [#docusaurus-2-dev](https://discord.gg/6g6ASPA) for contributing help -- [Reddit's Docusaurus community](https://www.reddit.com/r/docusaurus/) - -## Feature requests - -For new feature requests, you can create a post on our [Canny board](/feedback), which is a handy tool for roadmapping and allows for sorting by upvotes, which gives the core team a better indicator of what features are in high demand, as compared to GitHub issues which are harder to triage. Refrain from making a Pull Request for new features (especially large ones) as someone might already be working on it or will be part of our roadmap. Talk to us first! - -## News - -For the latest news about Docusaurus, [follow **@docusaurus** on Twitter](https://twitter.com/docusaurus) and the [official Docusaurus blog](/blog) on this website. diff --git a/website/versioned_docs/version-2.0.0-alpha.58/team.md b/website/versioned_docs/version-2.0.0-alpha.58/team.md deleted file mode 100644 index b0ca0e0497..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.58/team.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -id: team -title: Team ---- - -## Active Team - -
-
-
-
-
- -
-

Alexey Pyltsyn

-
-
-
-
- Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 -
-
-
- GitHub -
-
-
-
-
-
-
-
- -
-

Fanny Vieira

-
-
-
-
- Fanny got started with web development in high school, building a project for the school kitchen. In her free time she loves contributing to Open Source, occasionally writing on her blog about her experiences, cooking, and creating Spotify playlists. -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Joel Marcey

-
-
-
-
- Docusaurus founder and now ever grateful Docusaurus cheerleader to those who actually write code for it. -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Yangshun Tay

-
-
-
-
- Full Front End Stack developer who likes working on the Jamstack. Working on Docusaurus made him Facebook's unofficial part-time Open Source webmaster, which is an awesome role to be in. -
-
-
- GitHub - Twitter -
-
-
-
-
- -## Honorary Alumni - -
-
-
-
-
- -
-

Endilie Yacop Sucipto

-
-
-
-
- Maintainer @docusaurus · 🔥🔥🔥 -
-
-
- GitHub - Twitter -
-
-
-
-
-
-
-
- -
-

Wei Gao

-
-
-
-
- 👩🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes docs and spams this world with many websites. -
-
-
- GitHub - Twitter -
-
-
-
-
- -## Acknowledgements - -Docusaurus was originally created by Joel Marcey. Today, Docusaurus has a few hundred open source contributors. We’d like to recognize a few people who have made significant contributions to Docusaurus and its documentation in the past and have helped maintain them over the years: - -- [Amy Lam](https://github.com/amyrlam) -- [Cheng Lou](https://github.com/chenglou) -- [Christine Abernathy](https://github.com/caabernathy) -- [Christopher Chedeau](https://github.com/vjeux) -- [Elvis Wolcott](https://github.com/elviswolcott) -- [Eric Nakagawa](https://github.com/ericnakagawa) -- [Fienny Angelina](https://github.com/fiennyangeln) -- [Frank Li](https://github.com/deltice) -- [Héctor Ramos](https://github.com/hramos) -- [Ramón Lamana](https://github.com/rlamana) -- [Ricky Vetter](https://github.com/rickyvetter) -- [Sam Zhou](https://github.com/SamChou19815) diff --git a/website/versioned_docs/version-2.0.0-alpha.60/community/support.md b/website/versioned_docs/version-2.0.0-alpha.60/community/support.md deleted file mode 100644 index 26269330d9..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.60/community/support.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: support -title: Support -slug: /support ---- - -Docusaurus has a community of thousands of developers. - -On this page we've listed some Docusaurus-related communities that you can be a part of; see the other pages in this section for additional online and in-person learning materials. - -Before participating in Docusaurus' communities, [please read our Code of Conduct](https://engineering.fb.com/codeofconduct/). We have adopted the [Contributor Covenant](https://www.contributor-covenant.org/) and we expect that all community members adhere to the guidelines within. - -## Stack Overflow - -Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/docusaurus) tagged with **docusaurus** or [ask your own](https://stackoverflow.com/questions/ask?tags=docusaurus)! - -## Discussion forums - -There are many online forums which are a great place for discussion about best practices and application architecture as well as the future of Docusaurus. If you have an answerable code-level question, Stack Overflow is usually a better fit. - -- [Docusaurus online chat](https://discord.gg/docusaurus) - - [#docusaurus-2-dogfooding](https://discord.gg/7wjJ9yH) for user help - - [#docusaurus-2-dev](https://discord.gg/6g6ASPA) for contributing help -- [Reddit's Docusaurus community](https://www.reddit.com/r/docusaurus/) - -## Feature requests - -For new feature requests, you can create a post on our [Canny board](/feedback), which is a handy tool for roadmapping and allows for sorting by upvotes, which gives the core team a better indicator of what features are in high demand, as compared to GitHub issues which are harder to triage. Refrain from making a Pull Request for new features (especially large ones) as someone might already be working on it or will be part of our roadmap. Talk to us first! - -## News - -For the latest news about Docusaurus, [follow **@docusaurus** on Twitter](https://twitter.com/docusaurus) and the [official Docusaurus blog](/blog) on this website. diff --git a/website/versioned_docs/version-2.0.0-alpha.61/community/resources.md b/website/versioned_docs/version-2.0.0-alpha.61/community/resources.md deleted file mode 100644 index 4e93baf92b..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.61/community/resources.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: resources -title: Awesome Resources -slug: /resources ---- - -A curated list of interesting Docusaurus community projects. - -## Videos - -- [F8 2019: Using Docusaurus to Create Open Source Websites](https://www.youtube.com/watch?v=QcGJsf6mgZE) - -## Articles - -- [Live code editing in Docusaurus](https://dev.to/mrmuhammadali/live-code-editing-in-docusaurus-28k) - -## Showcase - -See the showcase. - -## Official plugins - -- [@docusaurus/plugin-content-blog](using-plugins.md#docusaurusplugin-content-blog) -- [@docusaurus/plugin-content-docs](using-plugins.md#docusaurusplugin-content-docs) -- [@docusaurus/plugin-content-pages](using-plugins.md#docusaurusplugin-content-pages) -- [@docusaurus/plugin-google-analytics](using-plugins.md#docusaurusplugin-google-analytics) -- [@docusaurus/plugin-google-gtag](using-plugins.md#docusaurusplugin-google-gtag) -- [@docusaurus/plugin-sitemap](using-plugins.md#docusaurusplugin-sitemap) -- [@docusaurus/plugin-ideal-image](using-plugins.md#docusaurusplugin-ideal-image) - -## Community plugins - -- [docusaurus-plugin-lunr](https://github.com/daldridge/docusaurus-plugin-lunr) - Docusaurus v2 plugin to create a local search index for use with Lunr.js -- [docusaurus-lunr-search](https://github.com/lelouch77/docusurus-lunr-search) - Offline Search for Docusaurus v2 -- [docusaurus-search-local](https://github.com/cmfcmf/docusaurus-search-local) - Offline/local search for Docusaurus v2 -- [docusaurus-pdf](https://github.com/KohheePeace/docusaurus-pdf) - Generate documentation into PDF format -- [docusaurus-plugin-sass](https://github.com/rlamana/docusaurus-plugin-sass) - Sass/SCSS stylesheets support -- [docusaurus2-dotenv](https://github.com/jonnynabors/docusaurus2-dotenv) - A Docusaurus 2 plugin that supports dotenv and other environment variables -- [posthog-docusaurus](https://github.com/PostHog/posthog-docusaurus) - Integrate [PostHog](https://posthog.com/) product analytics with Docusaurus v2 - -## Enterprise usage - -- Facebook -- Google -- Stripe -- Algolia -- Callstack diff --git a/website/versioned_docs/version-2.0.0-alpha.61/community/support.md b/website/versioned_docs/version-2.0.0-alpha.61/community/support.md deleted file mode 100644 index 26269330d9..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.61/community/support.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: support -title: Support -slug: /support ---- - -Docusaurus has a community of thousands of developers. - -On this page we've listed some Docusaurus-related communities that you can be a part of; see the other pages in this section for additional online and in-person learning materials. - -Before participating in Docusaurus' communities, [please read our Code of Conduct](https://engineering.fb.com/codeofconduct/). We have adopted the [Contributor Covenant](https://www.contributor-covenant.org/) and we expect that all community members adhere to the guidelines within. - -## Stack Overflow - -Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/docusaurus) tagged with **docusaurus** or [ask your own](https://stackoverflow.com/questions/ask?tags=docusaurus)! - -## Discussion forums - -There are many online forums which are a great place for discussion about best practices and application architecture as well as the future of Docusaurus. If you have an answerable code-level question, Stack Overflow is usually a better fit. - -- [Docusaurus online chat](https://discord.gg/docusaurus) - - [#docusaurus-2-dogfooding](https://discord.gg/7wjJ9yH) for user help - - [#docusaurus-2-dev](https://discord.gg/6g6ASPA) for contributing help -- [Reddit's Docusaurus community](https://www.reddit.com/r/docusaurus/) - -## Feature requests - -For new feature requests, you can create a post on our [Canny board](/feedback), which is a handy tool for roadmapping and allows for sorting by upvotes, which gives the core team a better indicator of what features are in high demand, as compared to GitHub issues which are harder to triage. Refrain from making a Pull Request for new features (especially large ones) as someone might already be working on it or will be part of our roadmap. Talk to us first! - -## News - -For the latest news about Docusaurus, [follow **@docusaurus** on Twitter](https://twitter.com/docusaurus) and the [official Docusaurus blog](/blog) on this website. diff --git a/website/versioned_docs/version-2.0.0-alpha.61/community/team.md b/website/versioned_docs/version-2.0.0-alpha.61/community/team.md deleted file mode 100644 index fb149dd1d9..0000000000 --- a/website/versioned_docs/version-2.0.0-alpha.61/community/team.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: team -title: Team -slug: /team ---- - -import TeamProfileCard from "@site/src/components/TeamProfileCard" - -export function TeamProfileCardCol(props) { return } - -## Active Team - -
- - Obsessed open-source enthusiast 👋 Eternal amateur at everything 🤷‍♂️ Maintainer of Russian docs on PHP, React, Kubernetes and much more 🧐 - - - Fanny got started with web development in high school, building a project for the school kitchen. In her free time she loves contributing to Open Source, occasionally writing on her blog about her experiences, cooking, and creating Spotify playlists. - - - Docusaurus founder and now ever grateful Docusaurus cheerleader to those who actually write code for it. - - - React lover since 2014. Freelance, helping Facebook ship Docusaurus v2. - - - Full Front End Stack developer who likes working on the Jamstack. Working on Docusaurus made him Facebook's unofficial part-time Open Source webmaster, which is an awesome role to be in. - -
- -## Honorary Alumni - -
- - Maintainer @docusaurus · 🔥🔥🔥 - - - 🏻‍🌾 Work in progress React developer, maintains Docusaurus, writes docs and spams this world with many websites. - -
- -## Acknowledgements - -Docusaurus was originally created by Joel Marcey. Today, Docusaurus has a few hundred open source contributors. We’d like to recognize a few people who have made significant contributions to Docusaurus and its documentation in the past and have helped maintain them over the years: - -- [Amy Lam](https://github.com/amyrlam) -- [Cheng Lou](https://github.com/chenglou) -- [Christine Abernathy](https://github.com/caabernathy) -- [Christopher Chedeau](https://github.com/vjeux) -- [Elvis Wolcott](https://github.com/elviswolcott) -- [Eric Nakagawa](https://github.com/ericnakagawa) -- [Fienny Angelina](https://github.com/fiennyangeln) -- [Frank Li](https://github.com/deltice) -- [Héctor Ramos](https://github.com/hramos) -- [Ramón Lamana](https://github.com/rlamana) -- [Ricky Vetter](https://github.com/rickyvetter) -- [Sam Zhou](https://github.com/SamChou19815) diff --git a/website/versioned_sidebars/version-2.0.0-alpha.54-sidebars.json b/website/versioned_sidebars/version-2.0.0-alpha.54-sidebars.json index f5cdf76cd7..9c56ce8f8e 100644 --- a/website/versioned_sidebars/version-2.0.0-alpha.54-sidebars.json +++ b/website/versioned_sidebars/version-2.0.0-alpha.54-sidebars.json @@ -128,29 +128,5 @@ } ] } - ], - "version-2.0.0-alpha.54/community": [ - { - "type": "doc", - "id": "version-2.0.0-alpha.54/support" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.54/team" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.54/resources" - }, - { - "type": "link", - "href": "/showcase", - "label": "Showcase" - }, - { - "type": "link", - "href": "/feedback", - "label": "Feedback" - } ] } diff --git a/website/versioned_sidebars/version-2.0.0-alpha.55-sidebars.json b/website/versioned_sidebars/version-2.0.0-alpha.55-sidebars.json index 7c55d38c31..099977d142 100644 --- a/website/versioned_sidebars/version-2.0.0-alpha.55-sidebars.json +++ b/website/versioned_sidebars/version-2.0.0-alpha.55-sidebars.json @@ -128,29 +128,5 @@ } ] } - ], - "version-2.0.0-alpha.55/community": [ - { - "type": "doc", - "id": "version-2.0.0-alpha.55/support" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.55/team" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.55/resources" - }, - { - "type": "link", - "href": "/showcase", - "label": "Showcase" - }, - { - "type": "link", - "href": "/feedback", - "label": "Feedback" - } ] } diff --git a/website/versioned_sidebars/version-2.0.0-alpha.56-sidebars.json b/website/versioned_sidebars/version-2.0.0-alpha.56-sidebars.json index bd46c7ad48..66385bd34a 100644 --- a/website/versioned_sidebars/version-2.0.0-alpha.56-sidebars.json +++ b/website/versioned_sidebars/version-2.0.0-alpha.56-sidebars.json @@ -128,29 +128,5 @@ } ] } - ], - "version-2.0.0-alpha.56/community": [ - { - "type": "doc", - "id": "version-2.0.0-alpha.56/support" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.56/team" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.56/resources" - }, - { - "type": "link", - "href": "/showcase", - "label": "Showcase" - }, - { - "type": "link", - "href": "/feedback", - "label": "Feedback" - } ] } diff --git a/website/versioned_sidebars/version-2.0.0-alpha.58-sidebars.json b/website/versioned_sidebars/version-2.0.0-alpha.58-sidebars.json index f8739e9b87..9e8cf45929 100644 --- a/website/versioned_sidebars/version-2.0.0-alpha.58-sidebars.json +++ b/website/versioned_sidebars/version-2.0.0-alpha.58-sidebars.json @@ -134,29 +134,5 @@ } ] } - ], - "version-2.0.0-alpha.58/community": [ - { - "type": "doc", - "id": "version-2.0.0-alpha.58/support" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.58/team" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.58/resources" - }, - { - "type": "link", - "href": "/showcase", - "label": "Showcase" - }, - { - "type": "link", - "href": "/feedback", - "label": "Feedback" - } ] } diff --git a/website/versioned_sidebars/version-2.0.0-alpha.60-sidebars.json b/website/versioned_sidebars/version-2.0.0-alpha.60-sidebars.json index b65be02fab..45afd7a015 100644 --- a/website/versioned_sidebars/version-2.0.0-alpha.60-sidebars.json +++ b/website/versioned_sidebars/version-2.0.0-alpha.60-sidebars.json @@ -138,29 +138,5 @@ } ] } - ], - "version-2.0.0-alpha.60/community": [ - { - "type": "doc", - "id": "version-2.0.0-alpha.60/community/support" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.60/community/team" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.60/community/resources" - }, - { - "type": "link", - "href": "/showcase", - "label": "Showcase" - }, - { - "type": "link", - "href": "/feedback", - "label": "Feedback" - } ] } diff --git a/website/versioned_sidebars/version-2.0.0-alpha.61-sidebars.json b/website/versioned_sidebars/version-2.0.0-alpha.61-sidebars.json index ea910c4503..3011abf888 100644 --- a/website/versioned_sidebars/version-2.0.0-alpha.61-sidebars.json +++ b/website/versioned_sidebars/version-2.0.0-alpha.61-sidebars.json @@ -138,29 +138,5 @@ } ] } - ], - "version-2.0.0-alpha.61/community": [ - { - "type": "doc", - "id": "version-2.0.0-alpha.61/community/support" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.61/community/team" - }, - { - "type": "doc", - "id": "version-2.0.0-alpha.61/community/resources" - }, - { - "type": "link", - "href": "/showcase", - "label": "Showcase" - }, - { - "type": "link", - "href": "/feedback", - "label": "Feedback" - } ] }