diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/doc-draft.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/doc-draft.md new file mode 100644 index 000000000000..dfc31e3f3594 --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/simple-site/docs/doc-draft.md @@ -0,0 +1,5 @@ +--- +draft: true +--- + +This is a draft document diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/docs.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/docs.test.ts.snap index eaed1c90bbbb..f05c66e2aa21 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/docs.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/docs.test.ts.snap @@ -5,11 +5,22 @@ exports[`simple site custom pagination 1`] = ` "pagination": [ { "id": "doc with space", + "next": { + "permalink": "/docs/doc-draft", + "title": "doc-draft", + }, + "prev": undefined, + }, + { + "id": "doc-draft", "next": { "permalink": "/docs/foo/bar", "title": "Bar", }, - "prev": undefined, + "prev": { + "permalink": "/docs/doc with space", + "title": "Hoo hoo, if this path tricks you...", + }, }, { "id": "foo/bar", @@ -163,6 +174,10 @@ exports[`simple site custom pagination 1`] = ` "id": "doc with space", "type": "doc", }, + { + "id": "doc-draft", + "type": "doc", + }, { "collapsed": false, "collapsible": true, diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/globalData.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/globalData.test.ts.snap index a646e0241e43..242bf1b74890 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/globalData.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/globalData.test.ts.snap @@ -19,6 +19,9 @@ exports[`toGlobalDataVersion generates the right docs, sidebars, and metadata 1` "sidebar": "tutorial", }, ], + "draftIds": [ + "some-draft-id", + ], "isLast": true, "label": "Label", "mainDocId": "main", 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 2a675b5ecfe5..c8b0408c5ee1 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 @@ -23,6 +23,7 @@ These sidebar document ids do not exist: Available document ids are: - doc with space +- doc-draft - foo/bar - foo/baz - headingAsTitle @@ -42,6 +43,7 @@ Available document ids are: exports[`simple website content 1`] = ` { "description": "Images", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -94,6 +96,7 @@ exports[`simple website content 1`] = ` exports[`simple website content 2`] = ` { "description": "Hi, Endilie here :)", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -139,6 +142,7 @@ exports[`simple website content 2`] = ` exports[`simple website content 3`] = ` { "description": "This is custom description", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -268,6 +272,11 @@ exports[`simple website content 5`] = ` "path": "/docs/doc with space", "sidebar": undefined, }, + { + "id": "doc-draft", + "path": "/docs/doc-draft", + "sidebar": undefined, + }, { "id": "foo/bar", "path": "/docs/foo/bar", @@ -344,6 +353,7 @@ exports[`simple website content 5`] = ` "sidebar": "docs", }, ], + "draftIds": [], "isLast": true, "label": "Next", "mainDocId": "hello", @@ -380,6 +390,22 @@ exports[`simple website content: data 1`] = ` "permalink": "/docs/rootAbsoluteSlug" } } +}", + "site-docs-doc-draft-md-584.json": "{ + "unversionedId": "doc-draft", + "id": "doc-draft", + "title": "doc-draft", + "description": "This is a draft document", + "source": "@site/docs/doc-draft.md", + "sourceDirName": ".", + "slug": "/doc-draft", + "permalink": "/docs/doc-draft", + "draft": false, + "tags": [], + "version": "current", + "frontMatter": { + "draft": true + } }", "site-docs-doc-with-space-md-e90.json": "{ "unversionedId": "doc with space", @@ -390,6 +416,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/doc with space", "permalink": "/docs/doc with space", + "draft": false, "tags": [], "version": "current", "frontMatter": {} @@ -403,6 +430,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": "foo", "slug": "/foo/bar", "permalink": "/docs/foo/bar", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -423,6 +451,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": "foo", "slug": "/foo/bazSlug.html", "permalink": "/docs/foo/bazSlug.html", + "draft": false, "tags": [ { "label": "tag 1", @@ -467,6 +496,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/headingAsTitle", "permalink": "/docs/headingAsTitle", + "draft": false, "tags": [], "version": "current", "frontMatter": {}, @@ -489,6 +519,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/", "permalink": "/docs/", + "draft": false, "tags": [ { "label": "tag-1", @@ -525,6 +556,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/ipsum", "permalink": "/docs/ipsum", + "draft": false, "editUrl": null, "tags": [], "version": "current", @@ -541,6 +573,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/lorem", "permalink": "/docs/lorem", + "draft": false, "editUrl": "https://github.com/customUrl/docs/lorem.md", "tags": [], "version": "current", @@ -558,6 +591,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/rootAbsoluteSlug", "permalink": "/docs/rootAbsoluteSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -584,6 +618,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/rootRelativeSlug", "permalink": "/docs/rootRelativeSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -610,6 +645,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/hey/rootResolvedSlug", "permalink": "/docs/hey/rootResolvedSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -636,6 +672,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": ".", "slug": "/rootTryToEscapeSlug", "permalink": "/docs/rootTryToEscapeSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -662,6 +699,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/absoluteSlug", "permalink": "/docs/absoluteSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -677,6 +715,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/slugs/relativeSlug", "permalink": "/docs/slugs/relativeSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -692,6 +731,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/slugs/hey/resolvedSlug", "permalink": "/docs/slugs/hey/resolvedSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -707,6 +747,7 @@ exports[`simple website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/tryToEscapeSlug", "permalink": "/docs/tryToEscapeSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -888,6 +929,11 @@ exports[`simple website content: data 1`] = ` "title": "Hoo hoo, if this path tricks you...", "description": "" }, + "doc-draft": { + "id": "doc-draft", + "title": "doc-draft", + "description": "This is a draft document" + }, "foo/bar": { "id": "foo/bar", "title": "Bar", @@ -985,6 +1031,11 @@ exports[`simple website content: global data 1`] = ` "path": "/docs/doc with space", "sidebar": undefined, }, + { + "id": "doc-draft", + "path": "/docs/doc-draft", + "sidebar": undefined, + }, { "id": "foo/bar", "path": "/docs/foo/bar", @@ -1061,6 +1112,7 @@ exports[`simple website content: global data 1`] = ` "sidebar": "docs", }, ], + "draftIds": [], "isLast": true, "label": "Next", "mainDocId": "hello", @@ -1158,6 +1210,14 @@ exports[`simple website content: route config 1`] = ` }, "path": "/docs/doc with space", }, + { + "component": "@theme/DocItem", + "exact": true, + "modules": { + "content": "@site/docs/doc-draft.md", + }, + "path": "/docs/doc-draft", + }, { "component": "@theme/DocItem", "exact": true, @@ -1562,6 +1622,7 @@ exports[`site with custom sidebar items generator sidebarItemsGenerator is calle exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 1`] = ` { "description": "Getting started text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -1589,6 +1650,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 2`] = ` { "description": "Installation text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -1619,6 +1681,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 3`] = ` { "description": "Guide 1 text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -1652,6 +1715,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 4`] = ` { "description": "Guide 2 text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -1684,6 +1748,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 5`] = ` { "description": "Guide 2.5 text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -1717,6 +1782,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 6`] = ` { "description": "Guide 3 text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -1750,6 +1816,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 7`] = ` { "description": "Guide 4 text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -1782,6 +1849,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 8`] = ` { "description": "Guide 5 text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -1814,6 +1882,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 9`] = ` { "description": "API Overview text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -1844,6 +1913,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 10`] = ` { "description": "Client API text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -1874,6 +1944,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 11`] = ` { "description": "Server API text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -1904,6 +1975,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 12`] = ` { "description": "Plugin API text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -1934,6 +2006,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 13`] = ` { "description": "Theme API text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -1964,6 +2037,7 @@ exports[`site with full autogenerated sidebar docs in fully generated sidebar ha exports[`site with full autogenerated sidebar docs in fully generated sidebar have correct metadata 14`] = ` { "description": "API End text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -2143,6 +2217,7 @@ exports[`site with partial autogenerated sidebars 2 (fix #4638) sidebar is parti exports[`site with partial autogenerated sidebars docs in partially generated sidebar have correct metadata 1`] = ` { "description": "API End text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -2170,6 +2245,7 @@ exports[`site with partial autogenerated sidebars docs in partially generated si exports[`site with partial autogenerated sidebars docs in partially generated sidebar have correct metadata 2`] = ` { "description": "API Overview text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -2200,6 +2276,7 @@ exports[`site with partial autogenerated sidebars docs in partially generated si exports[`site with partial autogenerated sidebars docs in partially generated sidebar have correct metadata 3`] = ` { "description": "Plugin API text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -2230,6 +2307,7 @@ exports[`site with partial autogenerated sidebars docs in partially generated si exports[`site with partial autogenerated sidebars docs in partially generated sidebar have correct metadata 4`] = ` { "description": "Theme API text", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -2289,6 +2367,7 @@ exports[`site with partial autogenerated sidebars sidebar is partially autogener exports[`versioned website (community) content 1`] = ` { "description": "Team current version (translated)", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -2315,6 +2394,7 @@ exports[`versioned website (community) content 1`] = ` exports[`versioned website (community) content 2`] = ` { "description": "Team 1.0.0", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -2369,6 +2449,7 @@ exports[`versioned website (community) content: data 1`] = ` "sourceDirName": ".", "slug": "/team", "permalink": "/community/team", + "draft": false, "tags": [], "version": "1.0.0", "frontMatter": {}, @@ -2383,6 +2464,7 @@ exports[`versioned website (community) content: data 1`] = ` "sourceDirName": ".", "slug": "/team", "permalink": "/community/next/team", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -2462,6 +2544,7 @@ exports[`versioned website (community) content: global data 1`] = ` "sidebar": "community", }, ], + "draftIds": [], "isLast": false, "label": "Next", "mainDocId": "team", @@ -2484,6 +2567,7 @@ exports[`versioned website (community) content: global data 1`] = ` "sidebar": "version-1.0.0/community", }, ], + "draftIds": [], "isLast": true, "label": "1.0.0", "mainDocId": "team", @@ -2565,6 +2649,7 @@ exports[`versioned website (community) getPathToWatch 1`] = ` exports[`versioned website content 1`] = ` { "description": "This is next version of bar.", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -2615,6 +2700,7 @@ exports[`versioned website content 1`] = ` exports[`versioned website content 2`] = ` { "description": "Bar 1.0.1 !", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -2642,6 +2728,7 @@ exports[`versioned website content 2`] = ` exports[`versioned website content 3`] = ` { "description": "Hello next !", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -2671,6 +2758,7 @@ exports[`versioned website content 3`] = ` exports[`versioned website content 4`] = ` { "description": "Hello 1.0.1 !", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": { @@ -2700,6 +2788,7 @@ exports[`versioned website content 4`] = ` exports[`versioned website content 5`] = ` { "description": "Baz 1.0.0 ! This will be deleted in next subsequent versions.", + "draft": false, "editUrl": undefined, "formattedLastUpdatedAt": undefined, "frontMatter": {}, @@ -2841,6 +2930,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "foo", "slug": "/foo/barSlug", "permalink": "/docs/next/foo/barSlug", + "draft": false, "tags": [ { "label": "barTag 1", @@ -2882,6 +2972,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": ".", "slug": "/", "permalink": "/docs/next/", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -2902,6 +2993,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/absoluteSlug", "permalink": "/docs/next/absoluteSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -2917,6 +3009,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/slugs/relativeSlug", "permalink": "/docs/next/slugs/relativeSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -2932,6 +3025,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/slugs/hey/resolvedSlug", "permalink": "/docs/next/slugs/hey/resolvedSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -2947,6 +3041,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/tryToEscapeSlug", "permalink": "/docs/next/tryToEscapeSlug", + "draft": false, "tags": [], "version": "current", "frontMatter": { @@ -2962,6 +3057,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": ".", "slug": "/", "permalink": "/docs/1.0.0/", + "draft": false, "tags": [], "version": "1.0.0", "frontMatter": { @@ -2982,6 +3078,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "foo", "slug": "/foo/barSlug", "permalink": "/docs/1.0.0/foo/barSlug", + "draft": false, "tags": [], "version": "1.0.0", "frontMatter": { @@ -3002,6 +3099,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "foo", "slug": "/foo/baz", "permalink": "/docs/1.0.0/foo/baz", + "draft": false, "tags": [], "version": "1.0.0", "frontMatter": {}, @@ -3024,6 +3122,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "foo", "slug": "/foo/bar", "permalink": "/docs/foo/bar", + "draft": false, "tags": [], "version": "1.0.1", "frontMatter": {}, @@ -3042,6 +3141,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": ".", "slug": "/", "permalink": "/docs/", + "draft": false, "tags": [], "version": "1.0.1", "frontMatter": { @@ -3062,6 +3162,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": ".", "slug": "/rootAbsoluteSlug", "permalink": "/docs/withSlugs/rootAbsoluteSlug", + "draft": false, "tags": [], "version": "withSlugs", "frontMatter": { @@ -3078,6 +3179,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": ".", "slug": "/rootRelativeSlug", "permalink": "/docs/withSlugs/rootRelativeSlug", + "draft": false, "tags": [], "version": "withSlugs", "frontMatter": { @@ -3093,6 +3195,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": ".", "slug": "/hey/rootResolvedSlug", "permalink": "/docs/withSlugs/hey/rootResolvedSlug", + "draft": false, "tags": [], "version": "withSlugs", "frontMatter": { @@ -3108,6 +3211,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": ".", "slug": "/rootTryToEscapeSlug", "permalink": "/docs/withSlugs/rootTryToEscapeSlug", + "draft": false, "tags": [], "version": "withSlugs", "frontMatter": { @@ -3123,6 +3227,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/absoluteSlug", "permalink": "/docs/withSlugs/absoluteSlug", + "draft": false, "tags": [], "version": "withSlugs", "frontMatter": { @@ -3138,6 +3243,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/slugs/relativeSlug", "permalink": "/docs/withSlugs/slugs/relativeSlug", + "draft": false, "tags": [], "version": "withSlugs", "frontMatter": { @@ -3153,6 +3259,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/slugs/hey/resolvedSlug", "permalink": "/docs/withSlugs/slugs/hey/resolvedSlug", + "draft": false, "tags": [], "version": "withSlugs", "frontMatter": { @@ -3168,6 +3275,7 @@ exports[`versioned website content: data 1`] = ` "sourceDirName": "slugs", "slug": "/tryToEscapeSlug", "permalink": "/docs/withSlugs/tryToEscapeSlug", + "draft": false, "tags": [], "version": "withSlugs", "frontMatter": { @@ -3543,6 +3651,7 @@ exports[`versioned website content: global data 1`] = ` "sidebar": undefined, }, ], + "draftIds": [], "isLast": false, "label": "Next", "mainDocId": "hello", @@ -3570,6 +3679,7 @@ exports[`versioned website content: global data 1`] = ` "sidebar": "VersionedSideBarNameDoesNotMatter/docs", }, ], + "draftIds": [], "isLast": true, "label": "1.0.1", "mainDocId": "hello", @@ -3602,6 +3712,7 @@ exports[`versioned website content: global data 1`] = ` "sidebar": "version-1.0.0/docs", }, ], + "draftIds": [], "isLast": false, "label": "1.0.0", "mainDocId": "hello", @@ -3659,6 +3770,7 @@ exports[`versioned website content: global data 1`] = ` "sidebar": undefined, }, ], + "draftIds": [], "isLast": false, "label": "withSlugs", "mainDocId": "rootAbsoluteSlug", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts index 727a5ab1d806..5eee85412c4d 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/docs.test.ts @@ -14,6 +14,7 @@ import { readDocFile, addDocNavigation, isCategoryIndex, + type DocEnv, } from '../docs'; import {loadSidebars} from '../sidebars'; import type {Sidebars} from '../sidebars/types'; @@ -62,46 +63,51 @@ ${markdown} }; }; +type TestUtilsArg = { + siteDir: string; + context: LoadContext; + versionMetadata: VersionMetadata; + options: MetadataOptions; + env?: DocEnv; +}; + function createTestUtils({ siteDir, context, versionMetadata, options, -}: { - siteDir: string; - context: LoadContext; - versionMetadata: VersionMetadata; - options: MetadataOptions; -}) { + env = 'production', +}: TestUtilsArg) { async function readDoc(docFileSource: string) { return readDocFile(versionMetadata, docFileSource, options); } - function processDocFile(docFile: DocFile) { + async function processDocFile(docFileArg: DocFile | string) { + const docFile: DocFile = + typeof docFileArg === 'string' ? await readDoc(docFileArg) : docFileArg; + return processDocMetadata({ docFile, versionMetadata, options, context, + env, }); } + async function testMeta( docFileSource: string, expectedMetadata: Optional< DocMetadataBase, - 'source' | 'lastUpdatedBy' | 'lastUpdatedAt' | 'editUrl' + 'source' | 'lastUpdatedBy' | 'lastUpdatedAt' | 'editUrl' | 'draft' >, ) { const docFile = await readDoc(docFileSource); - const metadata = await processDocMetadata({ - docFile, - versionMetadata, - context, - options, - }); + const metadata = await processDocFile(docFile); expect(metadata).toEqual({ lastUpdatedBy: undefined, lastUpdatedAt: undefined, editUrl: undefined, + draft: false, source: path.posix.join( '@site', posixPath(path.relative(siteDir, versionMetadata.contentPath)), @@ -118,6 +124,7 @@ function createTestUtils({ versionMetadata, context, options, + env, }); expect(metadata.permalink).toEqual(expectedPermalink); } @@ -136,6 +143,7 @@ function createTestUtils({ versionMetadata, context, options, + env: 'production', }), ); const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, { @@ -143,6 +151,7 @@ function createTestUtils({ defaultSidebarItemsGenerator({...args}), numberPrefixParser: options.numberPrefixParser, docs: rawDocs, + drafts: [], version: versionMetadata, sidebarOptions: { sidebarCollapsed: false, @@ -181,20 +190,27 @@ describe('simple site', () => { options, }); expect(versionsMetadata).toHaveLength(1); - const [currentVersion] = versionsMetadata; + const currentVersion = versionsMetadata[0]!; + + function createTestUtilsPartial(args: Partial) { + return createTestUtils({ + siteDir, + context, + options, + versionMetadata: currentVersion, + ...args, + }); + } + + const defaultTestUtils = createTestUtilsPartial({}); - const defaultTestUtils = createTestUtils({ - siteDir, - context, - options, - versionMetadata: currentVersion, - }); return { siteDir, context, options, versionsMetadata, defaultTestUtils, + createTestUtilsPartial, currentVersion, }; } @@ -213,6 +229,7 @@ describe('simple site', () => { 'rootTryToEscapeSlug.md', 'headingAsTitle.md', 'doc with space.md', + 'doc-draft.md', 'foo/bar.md', 'foo/baz.md', 'slugs/absoluteSlug.md', @@ -273,13 +290,14 @@ describe('simple site', () => { }); it('docs with editUrl', async () => { - const {siteDir, context, options, currentVersion} = await loadSite({ - options: { - editUrl: 'https://github.com/facebook/docusaurus/edit/main/website', - }, - }); + const {siteDir, context, options, currentVersion, createTestUtilsPartial} = + await loadSite({ + options: { + editUrl: 'https://github.com/facebook/docusaurus/edit/main/website', + }, + }); - const testUtilsLocal = createTestUtils({ + const testUtilsLocal = createTestUtilsPartial({ siteDir, context, options, @@ -347,13 +365,14 @@ describe('simple site', () => { const editUrlFunction: EditUrlFunction = jest.fn(() => hardcodedEditUrl); - const {siteDir, context, options, currentVersion} = await loadSite({ - options: { - editUrl: editUrlFunction, - }, - }); + const {siteDir, context, options, currentVersion, createTestUtilsPartial} = + await loadSite({ + options: { + editUrl: editUrlFunction, + }, + }); - const testUtilsLocal = createTestUtils({ + const testUtilsLocal = createTestUtilsPartial({ siteDir, context, options, @@ -404,14 +423,15 @@ describe('simple site', () => { }); it('docs with last update time and author', async () => { - const {siteDir, context, options, currentVersion} = await loadSite({ - options: { - showLastUpdateAuthor: true, - showLastUpdateTime: true, - }, - }); + const {siteDir, context, options, currentVersion, createTestUtilsPartial} = + await loadSite({ + options: { + showLastUpdateAuthor: true, + showLastUpdateTime: true, + }, + }); - const testUtilsLocal = createTestUtils({ + const testUtilsLocal = createTestUtilsPartial({ siteDir, context, options, @@ -439,6 +459,28 @@ describe('simple site', () => { }); }); + it('docs with draft frontmatter', async () => { + const {createTestUtilsPartial} = await loadSite(); + + const testUtilsProd = createTestUtilsPartial({ + env: 'production', + }); + await expect( + testUtilsProd.processDocFile('doc-draft.md'), + ).resolves.toMatchObject({ + draft: true, + }); + + const testUtilsDev = createTestUtilsPartial({ + env: 'development', + }); + await expect( + testUtilsDev.processDocFile('doc-draft.md'), + ).resolves.toMatchObject({ + draft: false, + }); + }); + it('docs with slugs', async () => { const {defaultTestUtils} = await loadSite(); @@ -495,7 +537,7 @@ describe('simple site', () => { it('custom pagination', async () => { const {defaultTestUtils, options, versionsMetadata} = await loadSite(); - const docs = await readVersionDocs(versionsMetadata[0], options); + const docs = await readVersionDocs(versionsMetadata[0]!, options); await expect( defaultTestUtils.generateNavigation(docs), ).resolves.toMatchSnapshot(); @@ -503,7 +545,7 @@ describe('simple site', () => { it('bad pagination', async () => { const {defaultTestUtils, options, versionsMetadata} = await loadSite(); - const docs = await readVersionDocs(versionsMetadata[0], options); + const docs = await readVersionDocs(versionsMetadata[0]!, options); docs.push( createFakeDocFile({ source: 'bad', @@ -539,8 +581,11 @@ describe('versioned site', () => { options, }); expect(versionsMetadata).toHaveLength(4); - const [currentVersion, version101, version100, versionWithSlugs] = - versionsMetadata; + + const currentVersion = versionsMetadata[0]!; + const version101 = versionsMetadata[1]!; + const version100 = versionsMetadata[2]!; + const versionWithSlugs = versionsMetadata[3]!; const currentVersionTestUtils = createTestUtils({ siteDir, diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/frontMatter.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/frontMatter.test.ts index 40f2f3f54fee..3a0855fe582a 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/frontMatter.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/frontMatter.test.ts @@ -378,3 +378,19 @@ describe('toc min/max consistency', () => { ], }); }); + +describe('validateDocFrontMatter draft', () => { + testField({ + prefix: 'draft', + validFrontMatters: [{draft: true}, {draft: false}], + convertibleFrontMatter: [ + [{draft: 'true'}, {draft: true}], + [{draft: 'false'}, {draft: false}], + ], + invalidFrontMatters: [ + [{draft: 'yes'}, 'must be a boolean'], + [{draft: 'no'}, 'must be a boolean'], + [{draft: ''}, 'must be a boolean'], + ], + }); +}); diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/globalData.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/globalData.test.ts index 2c9a02966317..d90dcb0e8784 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/globalData.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/globalData.test.ts @@ -28,6 +28,13 @@ describe('toGlobalDataVersion', () => { sidebar: 'tutorial', }, ], + drafts: [ + { + unversionedId: 'some-draft-id', + permalink: '/current/draft', + sidebar: undefined, + }, + ], sidebars: { another: [ { diff --git a/packages/docusaurus-plugin-content-docs/src/docs.ts b/packages/docusaurus-plugin-content-docs/src/docs.ts index c5057800f3c9..d7eae5bd74d9 100644 --- a/packages/docusaurus-plugin-content-docs/src/docs.ts +++ b/packages/docusaurus-plugin-content-docs/src/docs.ts @@ -38,6 +38,7 @@ import type { PropNavigationLink, LastUpdateData, VersionMetadata, + DocFrontMatter, } from '@docusaurus/plugin-content-docs'; type LastUpdateOptions = Pick< @@ -110,16 +111,31 @@ export async function readVersionDocs( ); } +export type DocEnv = 'production' | 'development'; + +/** Docs with draft front matter are only considered draft in production. */ +function isDraftForEnvironment({ + env, + frontMatter, +}: { + frontMatter: DocFrontMatter; + env: DocEnv; +}): boolean { + return (env === 'production' && frontMatter.draft) ?? false; +} + function doProcessDocMetadata({ docFile, versionMetadata, context, options, + env, }: { docFile: DocFile; versionMetadata: VersionMetadata; context: LoadContext; options: MetadataOptions; + env: DocEnv; }): DocMetadataBase { const {source, content, lastUpdate, contentPath, filePath} = docFile; const {siteDir, i18n} = context; @@ -235,6 +251,8 @@ function doProcessDocMetadata({ return undefined; } + const draft = isDraftForEnvironment({env, frontMatter}); + // Assign all of object properties during instantiation (if possible) for // NodeJS optimization. // Adding properties to object after instantiation will cause hidden @@ -248,6 +266,7 @@ function doProcessDocMetadata({ sourceDirName, slug: docSlug, permalink, + draft, editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(), tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags), version: versionMetadata.versionName, @@ -268,6 +287,7 @@ export function processDocMetadata(args: { versionMetadata: VersionMetadata; context: LoadContext; options: MetadataOptions; + env: DocEnv; }): DocMetadataBase { try { return doProcessDocMetadata(args); diff --git a/packages/docusaurus-plugin-content-docs/src/frontMatter.ts b/packages/docusaurus-plugin-content-docs/src/frontMatter.ts index 52e5af68b383..5c7d3bc97dba 100644 --- a/packages/docusaurus-plugin-content-docs/src/frontMatter.ts +++ b/packages/docusaurus-plugin-content-docs/src/frontMatter.ts @@ -38,6 +38,7 @@ const DocFrontMatterSchema = Joi.object({ parse_number_prefixes: Joi.boolean(), pagination_next: Joi.string().allow(null), pagination_prev: Joi.string().allow(null), + draft: Joi.boolean(), ...FrontMatterTOCHeadingLevels, }).unknown(); diff --git a/packages/docusaurus-plugin-content-docs/src/globalData.ts b/packages/docusaurus-plugin-content-docs/src/globalData.ts index ebeb61c8228e..bc3b6dd86268 100644 --- a/packages/docusaurus-plugin-content-docs/src/globalData.ts +++ b/packages/docusaurus-plugin-content-docs/src/globalData.ts @@ -72,6 +72,7 @@ export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion { docs: version.docs .map(toGlobalDataDoc) .concat(version.categoryGeneratedIndices.map(toGlobalDataGeneratedIndex)), + draftIds: version.drafts.map((doc) => doc.unversionedId), sidebars: toGlobalSidebars(version.sidebars, version), }; } diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 988927677539..eee9907eb6e6 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -22,6 +22,7 @@ import { import type {LoadContext, Plugin} from '@docusaurus/types'; import {loadSidebars, resolveSidebarPathOption} from './sidebars'; import {CategoryMetadataFilenamePattern} from './sidebars/generator'; +import type {DocEnv} from './docs'; import { readVersionDocs, processDocMetadata, @@ -58,6 +59,7 @@ import type { } from '@docusaurus/plugin-content-docs'; import {createSidebarsUtils} from './sidebars/utils'; import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex'; +import _ from 'lodash'; export default async function pluginContentDocs( context: LoadContext, @@ -147,6 +149,7 @@ export default async function pluginContentDocs( versionMetadata, context, options, + env: process.env.NODE_ENV as DocEnv, }); } return Promise.all(docFiles.map(processVersionDoc)); @@ -155,14 +158,17 @@ export default async function pluginContentDocs( async function doLoadVersion( versionMetadata: VersionMetadata, ): Promise { - const docs: DocMetadataBase[] = await loadVersionDocsBase( + const docsBase: DocMetadataBase[] = await loadVersionDocsBase( versionMetadata, ); + const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft); + const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, { sidebarItemsGenerator: options.sidebarItemsGenerator, numberPrefixParser: options.numberPrefixParser, docs, + drafts, version: versionMetadata, sidebarOptions: { sidebarCollapsed: options.sidebarCollapsed, @@ -180,6 +186,7 @@ export default async function pluginContentDocs( sidebarsUtils, versionMetadata.sidebarFilePath as string, ), + drafts, sidebars, mainDocId: getMainDocId({docs, sidebarsUtils}), categoryGeneratedIndices: getCategoryGeneratedIndexMetadataList({ diff --git a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts index bf5008ed985f..2d23b7d51a90 100644 --- a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts +++ b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts @@ -346,6 +346,8 @@ declare module '@docusaurus/plugin-content-docs' { * @see {@link DocMetadata.prev} */ pagination_prev?: string | null; + /** Should this doc be excluded from production builds? */ + draft?: boolean; }; export type LastUpdateData = { @@ -390,6 +392,10 @@ declare module '@docusaurus/plugin-content-docs' { slug: string; /** Full URL to this doc, with base URL and version path. */ permalink: string; + /** + * Draft docs will be excluded for production environment. + */ + draft: boolean; /** * Position in an autogenerated sidebar slice, acquired through front matter * or number prefix. @@ -597,6 +603,8 @@ declare module '@docusaurus/plugin-content-docs/client' { /** The doc with `slug: /`, or first doc in first sidebar */ mainDocId: string; docs: GlobalDoc[]; + /** Unversioned IDs. In development, this list is empty. */ + draftIds: string[]; sidebars?: {[sidebarId: string]: GlobalSidebar}; }; diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/index.test.ts.snap index 8657b009a855..f5b2acdd5190 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/__snapshots__/index.test.ts.snap @@ -247,6 +247,31 @@ exports[`loadSidebars sidebars with known sidebar item type 1`] = ` } `; +exports[`loadSidebars sidebars with some draft items 1`] = ` +{ + "docs": [ + { + "collapsed": true, + "collapsible": true, + "items": [ + { + "id": "foo/bar", + "type": "doc", + }, + { + "href": "https://github.com", + "label": "GitHub", + "type": "link", + }, + ], + "label": "Test", + "link": undefined, + "type": "category", + }, + ], +} +`; + exports[`loadSidebars undefined path 1`] = ` { "defaultSidebar": [ diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/index.test.ts index b94ffea65bdf..3a92144ffd8a 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/index.test.ts @@ -10,6 +10,7 @@ import path from 'path'; import {loadSidebars, DisabledSidebars} from '../index'; import type {SidebarProcessorParams} from '../types'; import {DefaultSidebarItemsGenerator} from '../generator'; +import type {DocMetadata} from '@docusaurus/plugin-content-docs'; describe('loadSidebars', () => { const fixtureDir = path.join(__dirname, '__fixtures__', 'sidebars'); @@ -24,6 +25,7 @@ describe('loadSidebars', () => { frontMatter: {}, }, ], + drafts: [], version: { contentPath: path.join(fixtureDir, 'docs'), contentPathLocalized: path.join(fixtureDir, 'docs'), @@ -37,6 +39,16 @@ describe('loadSidebars', () => { expect(result).toMatchSnapshot(); }); + it('sidebars with some draft items', async () => { + const sidebarPath = path.join(fixtureDir, 'sidebars.json'); + const paramsWithDrafts: SidebarProcessorParams = { + ...params, + drafts: [{id: 'foo/baz'} as DocMetadata, {id: 'hello'} as DocMetadata], + }; + const result = await loadSidebars(sidebarPath, paramsWithDrafts); + expect(result).toMatchSnapshot(); + }); + it('sidebars with deep level of category', async () => { const sidebarPath = path.join(fixtureDir, 'sidebars-category.js'); const result = await loadSidebars(sidebarPath, params); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts index 500eefbfe1dd..079040879ac6 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/__tests__/processor.test.ts @@ -46,6 +46,7 @@ describe('processSidebars', () => { const params: SidebarProcessorParams = { sidebarItemsGenerator: StaticSidebarItemsGenerator, docs: [], + drafts: [], version, numberPrefixParser: DefaultNumberPrefixParser, categoryLabelSlugger: createSlugger(), diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts index 7e83dd08a921..b0153e9dcbbc 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/processor.ts @@ -26,7 +26,7 @@ import {DefaultSidebarItemsGenerator} from './generator'; import {validateSidebars} from './validation'; import _ from 'lodash'; import combinePromises from 'combine-promises'; -import {isCategoryIndex} from '../docs'; +import {getDocIds, isCategoryIndex} from '../docs'; function toSidebarItemsGeneratorDoc( doc: DocMetadataBase, @@ -55,7 +55,8 @@ async function processSidebar( categoriesMetadata: {[filePath: string]: CategoryMetadataFile}, params: SidebarProcessorParams, ): Promise { - const {sidebarItemsGenerator, numberPrefixParser, docs, version} = params; + const {sidebarItemsGenerator, numberPrefixParser, docs, drafts, version} = + params; // Just a minor lazy transformation optimization const getSidebarItemsGeneratorDocsAndVersion = _.memoize(() => ({ @@ -81,6 +82,19 @@ async function processSidebar( return processItems(generatedItems); } + const draftIds = new Set(drafts.flatMap(getDocIds)); + + const isDraftItem = (item: NormalizedSidebarItem): boolean => { + if (item.type === 'doc' || item.type === 'ref') { + return draftIds.has(item.id); + } + // If a category only contains draft items, it should be filtered entirely. + if (item.type === 'category') { + return item.items.every(isDraftItem); + } + return false; + }; + async function processItem( item: NormalizedSidebarItem, ): Promise { @@ -88,7 +102,7 @@ async function processSidebar( return [ { ...item, - items: (await Promise.all(item.items.map(processItem))).flat(), + items: await processItems(item.items), }, ]; } @@ -101,7 +115,9 @@ async function processSidebar( async function processItems( items: NormalizedSidebarItem[], ): Promise { - return (await Promise.all(items.map(processItem))).flat(); + return ( + await Promise.all(items.filter((i) => !isDraftItem(i)).map(processItem)) + ).flat(); } const processedSidebar = await processItems(unprocessedSidebar); diff --git a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts index 2dfaf5b7f553..17d94b8ca3b7 100644 --- a/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/sidebars/types.ts @@ -269,6 +269,7 @@ export type SidebarProcessorParams = { sidebarItemsGenerator: SidebarItemsGeneratorOption; numberPrefixParser: NumberPrefixParser; docs: DocMetadataBase[]; + drafts: DocMetadataBase[]; version: VersionMetadata; categoryLabelSlugger: Slugger; sidebarOptions: SidebarOptions; diff --git a/packages/docusaurus-plugin-content-docs/src/types.ts b/packages/docusaurus-plugin-content-docs/src/types.ts index bb9f8e8e15d1..49156b2514ac 100644 --- a/packages/docusaurus-plugin-content-docs/src/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/types.ts @@ -40,6 +40,7 @@ export type VersionTags = { export type LoadedVersion = VersionMetadata & { mainDocId: string; docs: DocMetadata[]; + drafts: DocMetadata[]; sidebars: Sidebars; categoryGeneratedIndices: CategoryGeneratedIndexMetadata[]; }; diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 675086f69203..8517c384cafe 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -796,7 +796,9 @@ declare module '@theme/NavbarItem/DocNavbarItem' { readonly docsPluginId?: string; } - export default function DocsSidebarNavbarItem(props: Props): JSX.Element; + export default function DocsSidebarNavbarItem( + props: Props, + ): JSX.Element | null; } declare module '@theme/NavbarItem/DocSidebarNavbarItem' { diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx index a5e9b06f02bc..1ed30afe4050 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx @@ -18,9 +18,15 @@ export default function DocNavbarItem({ label: staticLabel, docsPluginId, ...props -}: Props): JSX.Element { +}: Props): JSX.Element | null { const {activeDoc} = useActiveDocContext(docsPluginId); const doc = useLayoutDoc(docId, docsPluginId); + + // Draft items are not displayed in the navbar. + if (doc === null) { + return null; + } + const activeDocInfimaClassName = getInfimaActiveClassName(props.mobile); return ( diff --git a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx index 13e63bd44def..c3d169c3e836 100644 --- a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx @@ -259,12 +259,22 @@ export function useLayoutDocsSidebar( * * @throws This hook throws if a doc with said ID is not found. */ -export function useLayoutDoc(docId: string, docsPluginId?: string): GlobalDoc { +export function useLayoutDoc( + docId: string, + docsPluginId?: string, +): GlobalDoc | null { const versions = useDocsVersionCandidates(docsPluginId); return useMemo(() => { const allDocs = versions.flatMap((version) => version.docs); const doc = allDocs.find((versionDoc) => versionDoc.id === docId); if (!doc) { + const isDraft = versions + .flatMap((version) => version.draftIds) + .includes(docId); + // drafts should be silently filtered instead of throwing + if (isDraft) { + return null; + } throw new Error( `DocNavbarItem: couldn't find any doc with id "${docId}" in version${ versions.length > 1 ? 's' : '' diff --git a/website/_dogfooding/_docs tests/test-draft.md b/website/_dogfooding/_docs tests/test-draft.md new file mode 100644 index 000000000000..2aa775b6e801 --- /dev/null +++ b/website/_dogfooding/_docs tests/test-draft.md @@ -0,0 +1,9 @@ +--- +draft: true +--- + +# Test section + +Welcome to the docs plugin test section + +Note: this draft doc (and the navbar link) should only be visible in local development diff --git a/website/_dogfooding/_docs tests/tests/another-draft.md b/website/_dogfooding/_docs tests/tests/another-draft.md new file mode 100644 index 000000000000..685d5541a1cf --- /dev/null +++ b/website/_dogfooding/_docs tests/tests/another-draft.md @@ -0,0 +1,7 @@ +--- +draft: true +--- + +# Another Draft + +This page should only be visible in local development diff --git a/website/_dogfooding/docs-tests-sidebars.js b/website/_dogfooding/docs-tests-sidebars.js index 804301319943..0143596f80a1 100644 --- a/website/_dogfooding/docs-tests-sidebars.js +++ b/website/_dogfooding/docs-tests-sidebars.js @@ -14,6 +14,7 @@ const sidebars = { className: 'red', label: 'Index', }, + 'test-draft', 'doc-without-sidebar', 'doc-with-another-sidebar', { diff --git a/website/docs/api/plugins/plugin-content-blog.md b/website/docs/api/plugins/plugin-content-blog.md index dbd658b6812e..27db9055ecc6 100644 --- a/website/docs/api/plugins/plugin-content-blog.md +++ b/website/docs/api/plugins/plugin-content-blog.md @@ -174,7 +174,7 @@ Accepted fields: | `title` | `string` | Markdown title | The blog post title. | | `date` | `string` | File name or file creation time | The blog post creation date. If not specified, this can be extracted from the file or folder name, e.g, `2021-04-15-blog-post.mdx`, `2021-04-15-blog-post/index.mdx`, `2021/04/15/blog-post.mdx`. Otherwise, it is the Markdown file creation time. | | `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your post. | -| `draft` | `boolean` | `false` | A boolean flag to indicate that the blog post is work-in-progress and therefore should not be published yet. However, draft blog posts will be displayed during development. | +| `draft` | `boolean` | `false` | A boolean flag to indicate that the blog post is work-in-progress. Draft blog posts will only be displayed during development. | | `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. | | `toc_min_heading_level` | `number` | `2` | The minimum heading level shown in the table of contents. Must be between 2 and 6 and lower or equal to the max value. | | `toc_max_heading_level` | `number` | `3` | The max heading level shown in the table of contents. Must be between 2 and 6. | diff --git a/website/docs/api/plugins/plugin-content-docs.md b/website/docs/api/plugins/plugin-content-docs.md index 7ef92f29f5b1..e5971ee2fa59 100644 --- a/website/docs/api/plugins/plugin-content-docs.md +++ b/website/docs/api/plugins/plugin-content-docs.md @@ -262,6 +262,7 @@ Accepted fields: | `image` | `string` | `undefined` | Cover or thumbnail image that will be used when displaying the link to your post. | | `slug` | `string` | File path | Allows to customize the document url (`//`). Support multiple patterns: `slug: my-doc`, `slug: /my/path/myDoc`, `slug: /`. | | `tags` | `Tag[]` | `undefined` | A list of strings or objects of two string fields `label` and `permalink` to tag to your docs. | +| `draft` | `boolean` | `false` | A boolean flag to indicate that a document is a work-in-progress. Draft documents will only be displayed during development. | diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index ff88fba0232e..8c4bebc928a8 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -97,15 +97,15 @@ const config = { loader: require.resolve('swc-loader'), options: { jsc: { - "parser": { - "syntax": "typescript", - "tsx": true + parser: { + syntax: 'typescript', + tsx: true, }, target: 'es2017', }, module: { type: isServer ? 'commonjs' : 'es6', - } + }, }, }), }, @@ -407,6 +407,12 @@ const config = { position: 'left', activeBaseRegex: `/community/`, }, + { + type: 'doc', + docId: 'test-draft', + label: 'Tests', + docsPluginId: 'docs-tests', + }, // right { type: 'docsVersionDropdown',