mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-20 12:37:01 +02:00
feat(docs,blog,pages): add support for "unlisted" front matter - hide md content in production (#8004)
Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
7a023a2c41
commit
683ba3d2a0
131 changed files with 2449 additions and 303 deletions
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
unlisted: true
|
||||
---
|
||||
|
||||
This is an unlisted document
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
custom_edit_url: null
|
||||
pagination_next: doc-unlisted
|
||||
---
|
||||
|
||||
Lorem ipsum.
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
id: unlisted-category-index
|
||||
unlisted: true
|
||||
---
|
||||
|
||||
This is an unlisted category index
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
id: unlisted-category-doc
|
||||
unlisted: true
|
||||
---
|
||||
|
||||
This is an unlisted category doc
|
|
@ -4,7 +4,16 @@
|
|||
{
|
||||
"type": "category",
|
||||
"label": "foo",
|
||||
"items": ["foo/bar", "foo/baz"]
|
||||
"items": ["foo/bar", "doc-unlisted", "foo/baz"]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"label": "Unlisted category",
|
||||
"link": {
|
||||
"type": "doc",
|
||||
"id": "unlisted-category/unlisted-category-index"
|
||||
},
|
||||
"items": ["unlisted-category/unlisted-category-doc"]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
|
|
|
@ -10,11 +10,23 @@ exports[`docsVersion first time versioning 1`] = `
|
|||
{
|
||||
"items": [
|
||||
"foo/bar",
|
||||
"doc-unlisted",
|
||||
"foo/baz",
|
||||
],
|
||||
"label": "foo",
|
||||
"type": "category",
|
||||
},
|
||||
{
|
||||
"items": [
|
||||
"unlisted-category/unlisted-category-doc",
|
||||
],
|
||||
"label": "Unlisted category",
|
||||
"link": {
|
||||
"id": "unlisted-category/unlisted-category-index",
|
||||
"type": "doc",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
{
|
||||
"items": [
|
||||
"rootAbsoluteSlug",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`simple site custom pagination 1`] = `
|
||||
exports[`simple site custom pagination - development 1`] = `
|
||||
{
|
||||
"pagination": [
|
||||
{
|
||||
|
@ -25,14 +25,25 @@ exports[`simple site custom pagination 1`] = `
|
|||
{
|
||||
"id": "doc-draft",
|
||||
"next": {
|
||||
"permalink": "/docs/foo/bar",
|
||||
"title": "Bar",
|
||||
"permalink": "/docs/doc-unlisted",
|
||||
"title": "doc-unlisted",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/doc with space",
|
||||
"title": "Hoo hoo, if this path tricks you...",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "doc-unlisted",
|
||||
"next": {
|
||||
"permalink": "/docs/foo/bar",
|
||||
"title": "Bar",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/doc-draft",
|
||||
"title": "doc-draft",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "foo/bar",
|
||||
"next": undefined,
|
||||
|
@ -74,9 +85,356 @@ exports[`simple site custom pagination 1`] = `
|
|||
{
|
||||
"id": "ipsum",
|
||||
"next": {
|
||||
"permalink": "/docs/doc-unlisted",
|
||||
"title": "doc-unlisted",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/",
|
||||
"title": "Hello sidebar_label",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "lastUpdateAuthorOnly",
|
||||
"next": {
|
||||
"permalink": "/docs/lastUpdateDateOnly",
|
||||
"title": "Last Update Date Only",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/ipsum",
|
||||
"title": "ipsum",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "lastUpdateDateOnly",
|
||||
"next": {
|
||||
"permalink": "/docs/lorem",
|
||||
"title": "lorem",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/lastUpdateAuthorOnly",
|
||||
"title": "Last Update Author Only",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "lorem",
|
||||
"next": {
|
||||
"permalink": "/docs/rootAbsoluteSlug",
|
||||
"title": "rootAbsoluteSlug",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/lastUpdateDateOnly",
|
||||
"title": "Last Update Date Only",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "rootAbsoluteSlug",
|
||||
"next": {
|
||||
"permalink": "/docs/headingAsTitle",
|
||||
"title": "My heading as title",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/foo/bazSlug.html",
|
||||
"title": "baz pagination_label",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "rootRelativeSlug",
|
||||
"next": {
|
||||
"permalink": "/docs/headingAsTitle",
|
||||
"title": "My heading as title",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/foo/bazSlug.html",
|
||||
"title": "baz pagination_label",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "rootResolvedSlug",
|
||||
"next": {
|
||||
"permalink": "/docs/headingAsTitle",
|
||||
"title": "My heading as title",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/foo/bazSlug.html",
|
||||
"title": "baz pagination_label",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "rootTryToEscapeSlug",
|
||||
"next": {
|
||||
"permalink": "/docs/headingAsTitle",
|
||||
"title": "My heading as title",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/foo/bazSlug.html",
|
||||
"title": "baz pagination_label",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "slugs/absoluteSlug",
|
||||
"next": {
|
||||
"permalink": "/docs/slugs/relativeSlug",
|
||||
"title": "relativeSlug",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/rootTryToEscapeSlug",
|
||||
"title": "rootTryToEscapeSlug",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "slugs/relativeSlug",
|
||||
"next": {
|
||||
"permalink": "/docs/slugs/hey/resolvedSlug",
|
||||
"title": "resolvedSlug",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/absoluteSlug",
|
||||
"title": "absoluteSlug",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "slugs/resolvedSlug",
|
||||
"next": {
|
||||
"permalink": "/docs/tryToEscapeSlug",
|
||||
"title": "tryToEscapeSlug",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/slugs/relativeSlug",
|
||||
"title": "relativeSlug",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "slugs/tryToEscapeSlug",
|
||||
"next": {
|
||||
"permalink": "/docs/unlisted-category/",
|
||||
"title": "unlisted-category-index",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/slugs/hey/resolvedSlug",
|
||||
"title": "resolvedSlug",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "unlisted-category/unlisted-category-doc",
|
||||
"next": undefined,
|
||||
"prev": {
|
||||
"permalink": "/docs/unlisted-category/",
|
||||
"title": "unlisted-category-index",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "unlisted-category/unlisted-category-index",
|
||||
"next": {
|
||||
"permalink": "/docs/unlisted-category/unlisted-category-doc",
|
||||
"title": "unlisted-category-doc",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/tryToEscapeSlug",
|
||||
"title": "tryToEscapeSlug",
|
||||
},
|
||||
},
|
||||
],
|
||||
"sidebars": {
|
||||
"defaultSidebar": [
|
||||
{
|
||||
"id": "customLastUpdate",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "doc with space",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "doc-draft",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "doc-unlisted",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
"items": [
|
||||
{
|
||||
"id": "foo/bar",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "foo/baz",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "foo",
|
||||
"link": undefined,
|
||||
"type": "category",
|
||||
},
|
||||
{
|
||||
"id": "headingAsTitle",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "hello",
|
||||
"label": "Hello sidebar_label",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "ipsum",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "lastUpdateAuthorOnly",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "lastUpdateDateOnly",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "lorem",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "rootAbsoluteSlug",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "rootRelativeSlug",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "rootResolvedSlug",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "rootTryToEscapeSlug",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
"items": [
|
||||
{
|
||||
"id": "slugs/absoluteSlug",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "slugs/relativeSlug",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "slugs/resolvedSlug",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "slugs/tryToEscapeSlug",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "slugs",
|
||||
"link": undefined,
|
||||
"type": "category",
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
"items": [
|
||||
{
|
||||
"id": "unlisted-category/unlisted-category-doc",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "unlisted-category-index",
|
||||
"link": {
|
||||
"id": "unlisted-category/unlisted-category-index",
|
||||
"type": "doc",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`simple site custom pagination - production 1`] = `
|
||||
{
|
||||
"pagination": [
|
||||
{
|
||||
"id": "customLastUpdate",
|
||||
"next": {
|
||||
"permalink": "/docs/doc with space",
|
||||
"title": "Hoo hoo, if this path tricks you...",
|
||||
},
|
||||
"prev": undefined,
|
||||
},
|
||||
{
|
||||
"id": "doc with space",
|
||||
"next": {
|
||||
"permalink": "/docs/doc-draft",
|
||||
"title": "doc-draft",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/customLastUpdate",
|
||||
"title": "Custom Last Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "doc-draft",
|
||||
"next": {
|
||||
"permalink": "/docs/foo/bar",
|
||||
"title": "Bar",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/doc with space",
|
||||
"title": "Hoo hoo, if this path tricks you...",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "doc-unlisted",
|
||||
"next": undefined,
|
||||
"prev": undefined,
|
||||
},
|
||||
{
|
||||
"id": "foo/bar",
|
||||
"next": undefined,
|
||||
"prev": undefined,
|
||||
},
|
||||
{
|
||||
"id": "foo/baz",
|
||||
"next": {
|
||||
"permalink": "/docs/headingAsTitle",
|
||||
"title": "My heading as title",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/foo/bar",
|
||||
"title": "Bar",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "headingAsTitle",
|
||||
"next": {
|
||||
"permalink": "/docs/",
|
||||
"title": "Hello sidebar_label",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/foo/bazSlug.html",
|
||||
"title": "baz pagination_label",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "hello",
|
||||
"next": {
|
||||
"permalink": "/docs/ipsum",
|
||||
"title": "ipsum",
|
||||
},
|
||||
"prev": {
|
||||
"permalink": "/docs/headingAsTitle",
|
||||
"title": "My heading as title",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "ipsum",
|
||||
"next": undefined,
|
||||
"prev": {
|
||||
"permalink": "/docs/",
|
||||
"title": "Hello sidebar_label",
|
||||
|
@ -200,6 +558,16 @@ exports[`simple site custom pagination 1`] = `
|
|||
"title": "resolvedSlug",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "unlisted-category/unlisted-category-doc",
|
||||
"next": undefined,
|
||||
"prev": undefined,
|
||||
},
|
||||
{
|
||||
"id": "unlisted-category/unlisted-category-index",
|
||||
"next": undefined,
|
||||
"prev": undefined,
|
||||
},
|
||||
],
|
||||
"sidebars": {
|
||||
"defaultSidebar": [
|
||||
|
@ -215,6 +583,10 @@ exports[`simple site custom pagination 1`] = `
|
|||
"id": "doc-draft",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"id": "doc-unlisted",
|
||||
"type": "doc",
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
|
@ -298,6 +670,22 @@ exports[`simple site custom pagination 1`] = `
|
|||
"link": undefined,
|
||||
"type": "category",
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
"items": [
|
||||
{
|
||||
"id": "unlisted-category/unlisted-category-doc",
|
||||
"type": "doc",
|
||||
},
|
||||
],
|
||||
"label": "unlisted-category-index",
|
||||
"link": {
|
||||
"id": "unlisted-category/unlisted-category-index",
|
||||
"type": "doc",
|
||||
},
|
||||
"type": "category",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -13,6 +13,12 @@ exports[`toGlobalDataVersion generates the right docs, sidebars, and metadata 1`
|
|||
"path": "/current/doc",
|
||||
"sidebar": "tutorial",
|
||||
},
|
||||
{
|
||||
"id": "docNoSidebarUnlisted",
|
||||
"path": "/current/docNoSidebarUnlisted",
|
||||
"sidebar": undefined,
|
||||
"unlisted": true,
|
||||
},
|
||||
{
|
||||
"id": "/current/generated",
|
||||
"path": "/current/generated",
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -153,7 +153,7 @@ function createTestUtils({
|
|||
versionMetadata,
|
||||
context,
|
||||
options,
|
||||
env: 'production',
|
||||
env,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
@ -173,11 +173,11 @@ function createTestUtils({
|
|||
const sidebarsUtils = createSidebarsUtils(sidebars);
|
||||
|
||||
return {
|
||||
pagination: addDocNavigation(
|
||||
rawDocs,
|
||||
pagination: addDocNavigation({
|
||||
docs: rawDocs,
|
||||
sidebarsUtils,
|
||||
versionMetadata.sidebarFilePath as string,
|
||||
).map((doc) => ({prev: doc.previous, next: doc.next, id: doc.id})),
|
||||
sidebarFilePath: versionMetadata.sidebarFilePath as string,
|
||||
}).map((doc) => ({prev: doc.previous, next: doc.next, id: doc.id})),
|
||||
sidebars,
|
||||
};
|
||||
}
|
||||
|
@ -247,6 +247,7 @@ describe('simple site', () => {
|
|||
'headingAsTitle.md',
|
||||
'doc with space.md',
|
||||
'doc-draft.md',
|
||||
'doc-unlisted.md',
|
||||
'customLastUpdate.md',
|
||||
'lastUpdateAuthorOnly.md',
|
||||
'lastUpdateDateOnly.md',
|
||||
|
@ -256,6 +257,8 @@ describe('simple site', () => {
|
|||
'slugs/relativeSlug.md',
|
||||
'slugs/resolvedSlug.md',
|
||||
'slugs/tryToEscapeSlug.md',
|
||||
'unlisted-category/index.md',
|
||||
'unlisted-category/unlisted-category-doc.md',
|
||||
].sort(),
|
||||
);
|
||||
});
|
||||
|
@ -279,6 +282,7 @@ describe('simple site', () => {
|
|||
pagination_prev: null,
|
||||
},
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
await defaultTestUtils.testMeta(path.join('hello.md'), {
|
||||
version: 'current',
|
||||
|
@ -306,6 +310,7 @@ describe('simple site', () => {
|
|||
permalink: '/docs/tags/tag-3',
|
||||
},
|
||||
],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -356,6 +361,7 @@ describe('simple site', () => {
|
|||
permalink: '/docs/tags/tag2-custom-permalink',
|
||||
},
|
||||
],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -377,6 +383,7 @@ describe('simple site', () => {
|
|||
unrelated_front_matter: "won't be part of metadata",
|
||||
},
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -430,6 +437,7 @@ describe('simple site', () => {
|
|||
permalink: '/docs/tags/tag2-custom-permalink',
|
||||
},
|
||||
],
|
||||
unlisted: false,
|
||||
});
|
||||
|
||||
expect(editUrlFunction).toHaveBeenCalledTimes(1);
|
||||
|
@ -476,6 +484,7 @@ describe('simple site', () => {
|
|||
formattedLastUpdatedAt: 'Oct 14, 2018',
|
||||
lastUpdatedBy: 'Author',
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -501,6 +510,44 @@ describe('simple site', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('docs with unlisted frontmatter', async () => {
|
||||
const {createTestUtilsPartial} = await loadSite();
|
||||
|
||||
const baseMeta = {
|
||||
version: 'current',
|
||||
id: 'doc-unlisted',
|
||||
unversionedId: 'doc-unlisted',
|
||||
sourceDirName: '.',
|
||||
permalink: '/docs/doc-unlisted',
|
||||
slug: '/doc-unlisted',
|
||||
title: 'doc-unlisted',
|
||||
description: 'This is an unlisted document',
|
||||
frontMatter: {
|
||||
unlisted: true,
|
||||
},
|
||||
sidebarPosition: undefined,
|
||||
tags: [],
|
||||
};
|
||||
|
||||
const testUtilsProd = createTestUtilsPartial({
|
||||
env: 'production',
|
||||
});
|
||||
|
||||
await testUtilsProd.testMeta('doc-unlisted.md', {
|
||||
...baseMeta,
|
||||
unlisted: true,
|
||||
});
|
||||
|
||||
const testUtilsDev = createTestUtilsPartial({
|
||||
env: 'development',
|
||||
});
|
||||
|
||||
await testUtilsDev.testMeta('doc-unlisted.md', {
|
||||
...baseMeta,
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('docs with last_update front matter', async () => {
|
||||
const {siteDir, context, options, currentVersion, createTestUtilsPartial} =
|
||||
await loadSite({
|
||||
|
@ -538,6 +585,7 @@ describe('simple site', () => {
|
|||
lastUpdatedBy: 'Custom Author',
|
||||
sidebarPosition: undefined,
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -577,6 +625,7 @@ describe('simple site', () => {
|
|||
lastUpdatedBy: 'Custom Author',
|
||||
sidebarPosition: undefined,
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -616,6 +665,7 @@ describe('simple site', () => {
|
|||
lastUpdatedBy: 'Author',
|
||||
sidebarPosition: undefined,
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -656,6 +706,7 @@ describe('simple site', () => {
|
|||
lastUpdatedBy: undefined,
|
||||
sidebarPosition: undefined,
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -718,12 +769,20 @@ describe('simple site', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('custom pagination', async () => {
|
||||
const {defaultTestUtils, options, versionsMetadata} = await loadSite();
|
||||
it('custom pagination - production', async () => {
|
||||
const {createTestUtilsPartial, options, versionsMetadata} =
|
||||
await loadSite();
|
||||
const testUtils = createTestUtilsPartial({env: 'production'});
|
||||
const docs = await readVersionDocs(versionsMetadata[0]!, options);
|
||||
await expect(
|
||||
defaultTestUtils.generateNavigation(docs),
|
||||
).resolves.toMatchSnapshot();
|
||||
await expect(testUtils.generateNavigation(docs)).resolves.toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('custom pagination - development', async () => {
|
||||
const {createTestUtilsPartial, options, versionsMetadata} =
|
||||
await loadSite();
|
||||
const testUtils = createTestUtilsPartial({env: 'development'});
|
||||
const docs = await readVersionDocs(versionsMetadata[0]!, options);
|
||||
await expect(testUtils.generateNavigation(docs)).resolves.toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('bad pagination', async () => {
|
||||
|
@ -847,6 +906,7 @@ describe('versioned site', () => {
|
|||
permalink: '/docs/next/tags/barTag-3-permalink',
|
||||
},
|
||||
],
|
||||
unlisted: false,
|
||||
});
|
||||
await currentVersionTestUtils.testMeta(path.join('hello.md'), {
|
||||
id: 'hello',
|
||||
|
@ -861,6 +921,7 @@ describe('versioned site', () => {
|
|||
slug: '/',
|
||||
},
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -878,6 +939,7 @@ describe('versioned site', () => {
|
|||
frontMatter: {slug: 'barSlug'},
|
||||
version: '1.0.0',
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
await version100TestUtils.testMeta(path.join('hello.md'), {
|
||||
id: 'version-1.0.0/hello',
|
||||
|
@ -894,6 +956,7 @@ describe('versioned site', () => {
|
|||
source:
|
||||
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
await version101TestUtils.testMeta(path.join('foo', 'bar.md'), {
|
||||
id: 'version-1.0.1/foo/bar',
|
||||
|
@ -906,6 +969,7 @@ describe('versioned site', () => {
|
|||
version: '1.0.1',
|
||||
frontMatter: {},
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
await version101TestUtils.testMeta(path.join('hello.md'), {
|
||||
id: 'version-1.0.1/hello',
|
||||
|
@ -920,6 +984,7 @@ describe('versioned site', () => {
|
|||
slug: '/',
|
||||
},
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1016,6 +1081,7 @@ describe('versioned site', () => {
|
|||
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
||||
editUrl: hardcodedEditUrl,
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
|
||||
expect(editUrlFunction).toHaveBeenCalledTimes(1);
|
||||
|
@ -1059,6 +1125,7 @@ describe('versioned site', () => {
|
|||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/edit/main/website/versioned_docs/version-1.0.0/hello.md',
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1094,6 +1161,7 @@ describe('versioned site', () => {
|
|||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/edit/main/website/docs/hello.md',
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1130,6 +1198,7 @@ describe('versioned site', () => {
|
|||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/edit/main/website/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1167,6 +1236,7 @@ describe('versioned site', () => {
|
|||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/edit/main/website/i18n/fr/docusaurus-plugin-content-docs/current/hello.md',
|
||||
tags: [],
|
||||
unlisted: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -44,15 +44,12 @@ function testField(params: {
|
|||
params.invalidFrontMatters?.forEach(([frontMatter, message]) => {
|
||||
try {
|
||||
validateDocFrontMatter(frontMatter);
|
||||
// eslint-disable-next-line jest/no-jasmine-globals
|
||||
fail(
|
||||
new Error(
|
||||
`Doc front matter is expected to be rejected, but was accepted successfully:\n ${JSON.stringify(
|
||||
frontMatter,
|
||||
null,
|
||||
2,
|
||||
)}`,
|
||||
),
|
||||
throw new Error(
|
||||
`Doc front matter is expected to be rejected, but was accepted successfully:\n ${JSON.stringify(
|
||||
frontMatter,
|
||||
null,
|
||||
2,
|
||||
)}`,
|
||||
);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line jest/no-conditional-expect
|
||||
|
@ -397,6 +394,41 @@ describe('validateDocFrontMatter draft', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('validateDocFrontMatter unlisted', () => {
|
||||
testField({
|
||||
prefix: 'unlisted',
|
||||
validFrontMatters: [{unlisted: true}, {unlisted: false}],
|
||||
convertibleFrontMatter: [
|
||||
[{unlisted: 'true'}, {unlisted: true}],
|
||||
[{unlisted: 'false'}, {unlisted: false}],
|
||||
],
|
||||
invalidFrontMatters: [
|
||||
[{unlisted: 'yes'}, 'must be a boolean'],
|
||||
[{unlisted: 'no'}, 'must be a boolean'],
|
||||
[{unlisted: ''}, 'must be a boolean'],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateDocFrontMatter draft XOR unlisted', () => {
|
||||
testField({
|
||||
prefix: 'draft XOR unlisted',
|
||||
validFrontMatters: [
|
||||
{draft: false},
|
||||
{unlisted: false},
|
||||
{draft: false, unlisted: false},
|
||||
{draft: true, unlisted: false},
|
||||
{draft: false, unlisted: true},
|
||||
],
|
||||
invalidFrontMatters: [
|
||||
[
|
||||
{draft: true, unlisted: true},
|
||||
"Can't be draft and unlisted at the same time.",
|
||||
],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateDocFrontMatter last_update', () => {
|
||||
testField({
|
||||
prefix: 'last_update',
|
||||
|
|
|
@ -19,12 +19,21 @@ describe('toGlobalDataVersion', () => {
|
|||
permalink: '/current/main',
|
||||
sidebar: 'tutorial',
|
||||
frontMatter: {},
|
||||
unlisted: false,
|
||||
},
|
||||
{
|
||||
unversionedId: 'doc',
|
||||
permalink: '/current/doc',
|
||||
sidebar: 'tutorial',
|
||||
frontMatter: {},
|
||||
unlisted: undefined,
|
||||
},
|
||||
{
|
||||
unversionedId: 'docNoSidebarUnlisted',
|
||||
permalink: '/current/docNoSidebarUnlisted',
|
||||
sidebar: undefined,
|
||||
frontMatter: {},
|
||||
unlisted: true,
|
||||
},
|
||||
] as DocMetadata[];
|
||||
const sidebars: Sidebars = {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {toTagDocListProp} from '../props';
|
||||
import {toSidebarDocItemLinkProp, toTagDocListProp} from '../props';
|
||||
|
||||
describe('toTagDocListProp', () => {
|
||||
type Params = Parameters<typeof toTagDocListProp>[0];
|
||||
|
@ -61,3 +61,74 @@ describe('toTagDocListProp', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toSidebarDocItemLinkProp', () => {
|
||||
type Params = Parameters<typeof toSidebarDocItemLinkProp>[0];
|
||||
type Result = ReturnType<typeof toSidebarDocItemLinkProp>;
|
||||
type DocSidebarItem = Params['item'];
|
||||
type Doc = Params['doc'];
|
||||
|
||||
const id = 'some-doc-id';
|
||||
const unversionedId = 'some-unversioned-doc-id';
|
||||
|
||||
const item: DocSidebarItem = {
|
||||
type: 'doc',
|
||||
id,
|
||||
label: 'doc sidebar item label',
|
||||
};
|
||||
|
||||
const doc: Doc = {
|
||||
id,
|
||||
unversionedId,
|
||||
title: 'doc title',
|
||||
permalink: '/docPermalink',
|
||||
frontMatter: {},
|
||||
unlisted: false,
|
||||
};
|
||||
|
||||
it('works', () => {
|
||||
const result = toSidebarDocItemLinkProp({
|
||||
item,
|
||||
doc,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
type: 'link',
|
||||
docId: unversionedId,
|
||||
unlisted: false,
|
||||
label: item.label,
|
||||
autoAddBaseUrl: undefined,
|
||||
className: undefined,
|
||||
href: doc.permalink,
|
||||
customProps: undefined,
|
||||
} as Result);
|
||||
});
|
||||
|
||||
it('uses unlisted from metadata and ignores frontMatter', () => {
|
||||
expect(
|
||||
toSidebarDocItemLinkProp({
|
||||
item,
|
||||
doc: {
|
||||
...doc,
|
||||
unlisted: true,
|
||||
frontMatter: {
|
||||
unlisted: false,
|
||||
},
|
||||
},
|
||||
}).unlisted,
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
toSidebarDocItemLinkProp({
|
||||
item,
|
||||
doc: {
|
||||
...doc,
|
||||
unlisted: false,
|
||||
frontMatter: {
|
||||
unlisted: true,
|
||||
},
|
||||
},
|
||||
}).unlisted,
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -37,7 +37,8 @@ export type GlobalDoc = {
|
|||
*/
|
||||
id: string;
|
||||
path: string;
|
||||
sidebar: string | undefined;
|
||||
sidebar?: string;
|
||||
unlisted?: boolean;
|
||||
};
|
||||
|
||||
export type GlobalVersion = {
|
||||
|
|
|
@ -18,6 +18,8 @@ import {
|
|||
posixPath,
|
||||
Globby,
|
||||
normalizeFrontMatterTags,
|
||||
isUnlisted,
|
||||
isDraft,
|
||||
} from '@docusaurus/utils';
|
||||
|
||||
import {getFileLastUpdate} from './lastUpdate';
|
||||
|
@ -35,7 +37,6 @@ import type {
|
|||
PropNavigationLink,
|
||||
LastUpdateData,
|
||||
VersionMetadata,
|
||||
DocFrontMatter,
|
||||
LoadedVersion,
|
||||
FileChange,
|
||||
} from '@docusaurus/plugin-content-docs';
|
||||
|
@ -125,17 +126,6 @@ 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;
|
||||
}
|
||||
|
||||
async function doProcessDocMetadata({
|
||||
docFile,
|
||||
versionMetadata,
|
||||
|
@ -268,7 +258,8 @@ async function doProcessDocMetadata({
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const draft = isDraftForEnvironment({env, frontMatter});
|
||||
const draft = isDraft({env, frontMatter});
|
||||
const unlisted = isUnlisted({env, frontMatter});
|
||||
|
||||
const formatDate = (locale: string, date: Date, calendar: string): string => {
|
||||
try {
|
||||
|
@ -299,6 +290,7 @@ async function doProcessDocMetadata({
|
|||
slug: docSlug,
|
||||
permalink,
|
||||
draft,
|
||||
unlisted,
|
||||
editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
|
||||
tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
|
||||
version: versionMetadata.versionName,
|
||||
|
@ -333,25 +325,32 @@ export async function processDocMetadata(args: {
|
|||
}
|
||||
}
|
||||
|
||||
export function addDocNavigation(
|
||||
docsBase: DocMetadataBase[],
|
||||
sidebarsUtils: SidebarsUtils,
|
||||
sidebarFilePath: string,
|
||||
): LoadedVersion['docs'] {
|
||||
const docsById = createDocsByIdIndex(docsBase);
|
||||
function getUnlistedIds(docs: DocMetadataBase[]): Set<string> {
|
||||
return new Set(docs.filter((doc) => doc.unlisted).map((doc) => doc.id));
|
||||
}
|
||||
|
||||
sidebarsUtils.checkSidebarsDocIds(
|
||||
docsBase.flatMap(getDocIds),
|
||||
sidebarFilePath,
|
||||
);
|
||||
export function addDocNavigation({
|
||||
docs,
|
||||
sidebarsUtils,
|
||||
sidebarFilePath,
|
||||
}: {
|
||||
docs: DocMetadataBase[];
|
||||
sidebarsUtils: SidebarsUtils;
|
||||
sidebarFilePath: string;
|
||||
}): LoadedVersion['docs'] {
|
||||
const docsById = createDocsByIdIndex(docs);
|
||||
const unlistedIds = getUnlistedIds(docs);
|
||||
|
||||
sidebarsUtils.checkSidebarsDocIds(docs.flatMap(getDocIds), sidebarFilePath);
|
||||
|
||||
// Add sidebar/next/previous to the docs
|
||||
function addNavData(doc: DocMetadataBase): DocMetadata {
|
||||
const navigation = sidebarsUtils.getDocNavigation(
|
||||
doc.unversionedId,
|
||||
doc.id,
|
||||
doc.frontMatter.displayed_sidebar,
|
||||
);
|
||||
const navigation = sidebarsUtils.getDocNavigation({
|
||||
unversionedId: doc.unversionedId,
|
||||
versionedId: doc.id,
|
||||
displayedSidebar: doc.frontMatter.displayed_sidebar,
|
||||
unlistedIds,
|
||||
});
|
||||
|
||||
const toNavigationLinkByDocId = (
|
||||
docId: string | null | undefined,
|
||||
|
@ -367,6 +366,10 @@ export function addDocNavigation(
|
|||
`Error when loading ${doc.id} in ${doc.sourceDirName}: the pagination_${type} front matter points to a non-existent ID ${docId}.`,
|
||||
);
|
||||
}
|
||||
// Gracefully handle explicitly providing an unlisted doc ID in production
|
||||
if (navDoc.unlisted) {
|
||||
return undefined;
|
||||
}
|
||||
return toDocNavigationLink(navDoc);
|
||||
};
|
||||
|
||||
|
@ -382,7 +385,7 @@ export function addDocNavigation(
|
|||
return {...doc, sidebar: navigation.sidebarName, previous, next};
|
||||
}
|
||||
|
||||
const docsWithNavigation = docsBase.map(addNavData);
|
||||
const docsWithNavigation = docs.map(addNavData);
|
||||
// Sort to ensure consistent output for tests
|
||||
docsWithNavigation.sort((a, b) => a.id.localeCompare(b.id));
|
||||
return docsWithNavigation;
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
FrontMatterTagsSchema,
|
||||
FrontMatterTOCHeadingLevels,
|
||||
validateFrontMatter,
|
||||
ContentVisibilitySchema,
|
||||
} from '@docusaurus/utils-validation';
|
||||
import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
|
@ -43,7 +44,6 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
|
|||
parse_number_prefixes: Joi.boolean(),
|
||||
pagination_next: Joi.string().allow(null),
|
||||
pagination_prev: Joi.string().allow(null),
|
||||
draft: Joi.boolean(),
|
||||
...FrontMatterTOCHeadingLevels,
|
||||
last_update: Joi.object({
|
||||
author: Joi.string(),
|
||||
|
@ -54,7 +54,9 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
|
|||
'object.missing': FrontMatterLastUpdateErrorMessage,
|
||||
'object.base': FrontMatterLastUpdateErrorMessage,
|
||||
}),
|
||||
}).unknown();
|
||||
})
|
||||
.unknown()
|
||||
.concat(ContentVisibilitySchema);
|
||||
|
||||
export function validateDocFrontMatter(frontMatter: {
|
||||
[key: string]: unknown;
|
||||
|
|
|
@ -23,6 +23,11 @@ function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
|
|||
return {
|
||||
id: doc.unversionedId,
|
||||
path: doc.permalink,
|
||||
|
||||
// optimize global data size: do not add unlisted: false/undefined
|
||||
...(doc.unlisted && {unlisted: doc.unlisted}),
|
||||
|
||||
// TODO optimize size? remove attribute when no sidebar (breaking change?)
|
||||
sidebar: doc.sidebar,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -75,6 +75,9 @@ export default async function pluginContentDocs(
|
|||
const aliasedSource = (source: string) =>
|
||||
`~docs/${posixPath(path.relative(pluginDataDirRoot, source))}`;
|
||||
|
||||
// TODO env should be injected into all plugins
|
||||
const env = process.env.NODE_ENV as DocEnv;
|
||||
|
||||
return {
|
||||
name: 'docusaurus-plugin-content-docs',
|
||||
|
||||
|
@ -143,7 +146,7 @@ export default async function pluginContentDocs(
|
|||
versionMetadata,
|
||||
context,
|
||||
options,
|
||||
env: process.env.NODE_ENV as DocEnv,
|
||||
env,
|
||||
});
|
||||
}
|
||||
return Promise.all(docFiles.map(processVersionDoc));
|
||||
|
@ -156,6 +159,9 @@ export default async function pluginContentDocs(
|
|||
versionMetadata,
|
||||
);
|
||||
|
||||
// TODO we only ever need draftIds in further code, not full draft items
|
||||
// To simplify and prevent mistakes, avoid exposing draft
|
||||
// replace draft=>draftIds in content loaded
|
||||
const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft);
|
||||
|
||||
const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, {
|
||||
|
@ -175,11 +181,11 @@ export default async function pluginContentDocs(
|
|||
|
||||
return {
|
||||
...versionMetadata,
|
||||
docs: addDocNavigation(
|
||||
docs: addDocNavigation({
|
||||
docs,
|
||||
sidebarsUtils,
|
||||
versionMetadata.sidebarFilePath as string,
|
||||
),
|
||||
sidebarFilePath: versionMetadata.sidebarFilePath as string,
|
||||
}),
|
||||
drafts,
|
||||
sidebars,
|
||||
};
|
||||
|
|
|
@ -398,6 +398,8 @@ declare module '@docusaurus/plugin-content-docs' {
|
|||
pagination_prev?: string | null;
|
||||
/** Should this doc be excluded from production builds? */
|
||||
draft?: boolean;
|
||||
/** Should this doc be accessible but hidden in production builds? */
|
||||
unlisted?: boolean;
|
||||
/** Allows overriding the last updated author and/or date. */
|
||||
last_update?: FileChange;
|
||||
};
|
||||
|
@ -448,6 +450,11 @@ declare module '@docusaurus/plugin-content-docs' {
|
|||
* Draft docs will be excluded for production environment.
|
||||
*/
|
||||
draft: boolean;
|
||||
/**
|
||||
* Unlisted docs are accessible when directly visible, but will be hidden
|
||||
* from the sidebar and pagination in production.
|
||||
*/
|
||||
unlisted: boolean;
|
||||
/**
|
||||
* Position in an autogenerated sidebar slice, acquired through front matter
|
||||
* or number prefix.
|
||||
|
|
|
@ -28,6 +28,37 @@ import type {
|
|||
LoadedVersion,
|
||||
} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
export function toSidebarDocItemLinkProp({
|
||||
item,
|
||||
doc,
|
||||
}: {
|
||||
item: SidebarItemDoc;
|
||||
doc: Pick<
|
||||
DocMetadata,
|
||||
'id' | 'title' | 'permalink' | 'unlisted' | 'frontMatter' | 'unversionedId'
|
||||
>;
|
||||
}): PropSidebarItemLink {
|
||||
const {
|
||||
title,
|
||||
permalink,
|
||||
frontMatter: {
|
||||
sidebar_label: sidebarLabel,
|
||||
sidebar_custom_props: customProps,
|
||||
},
|
||||
unlisted,
|
||||
unversionedId,
|
||||
} = doc;
|
||||
return {
|
||||
type: 'link',
|
||||
label: sidebarLabel ?? item.label ?? title,
|
||||
href: permalink,
|
||||
className: item.className,
|
||||
customProps: item.customProps ?? customProps,
|
||||
docId: unversionedId,
|
||||
unlisted,
|
||||
};
|
||||
}
|
||||
|
||||
export function toSidebarsProp(loadedVersion: LoadedVersion): PropSidebars {
|
||||
const docsById = createDocsByIdIndex(loadedVersion.docs);
|
||||
|
||||
|
@ -44,21 +75,8 @@ Available document ids are:
|
|||
}
|
||||
|
||||
const convertDocLink = (item: SidebarItemDoc): PropSidebarItemLink => {
|
||||
const docMetadata = getDocById(item.id);
|
||||
const {
|
||||
title,
|
||||
permalink,
|
||||
frontMatter: {sidebar_label: sidebarLabel},
|
||||
} = docMetadata;
|
||||
return {
|
||||
type: 'link',
|
||||
label: sidebarLabel ?? item.label ?? title,
|
||||
href: permalink,
|
||||
className: item.className,
|
||||
customProps:
|
||||
item.customProps ?? docMetadata.frontMatter.sidebar_custom_props,
|
||||
docId: docMetadata.unversionedId,
|
||||
};
|
||||
const doc = getDocById(item.id);
|
||||
return toSidebarDocItemLinkProp({item, doc});
|
||||
};
|
||||
|
||||
function getCategoryLinkHref(
|
||||
|
@ -74,6 +92,15 @@ Available document ids are:
|
|||
}
|
||||
}
|
||||
|
||||
function getCategoryLinkUnlisted(
|
||||
link: SidebarItemCategoryLink | undefined,
|
||||
): boolean {
|
||||
if (link?.type === 'doc') {
|
||||
return getDocById(link.id).unlisted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getCategoryLinkCustomProps(
|
||||
link: SidebarItemCategoryLink | undefined,
|
||||
) {
|
||||
|
@ -88,12 +115,14 @@ Available document ids are:
|
|||
function convertCategory(item: SidebarItemCategory): PropSidebarItemCategory {
|
||||
const {link, ...rest} = item;
|
||||
const href = getCategoryLinkHref(link);
|
||||
const linkUnlisted = getCategoryLinkUnlisted(link);
|
||||
const customProps = item.customProps ?? getCategoryLinkCustomProps(link);
|
||||
|
||||
return {
|
||||
...rest,
|
||||
items: item.items.map(normalizeItem),
|
||||
...(href && {href}),
|
||||
...(linkUnlisted && {linkUnlisted}),
|
||||
...(customProps && {customProps}),
|
||||
};
|
||||
}
|
||||
|
@ -180,15 +209,18 @@ export function toTagDocListProp({
|
|||
allTagsPath,
|
||||
count: tag.docIds.length,
|
||||
items: toDocListProp(),
|
||||
unlisted: tag.unlisted,
|
||||
};
|
||||
}
|
||||
|
||||
export function toTagsListTagsProp(
|
||||
versionTags: VersionTags,
|
||||
): PropTagsListPage['tags'] {
|
||||
return Object.values(versionTags).map((tagValue) => ({
|
||||
label: tagValue.label,
|
||||
permalink: tagValue.permalink,
|
||||
count: tagValue.docIds.length,
|
||||
}));
|
||||
return Object.values(versionTags)
|
||||
.filter((tagValue) => !tagValue.unlisted)
|
||||
.map((tagValue) => ({
|
||||
label: tagValue.label,
|
||||
permalink: tagValue.permalink,
|
||||
count: tagValue.docIds.length,
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -153,7 +153,14 @@ describe('createSidebarsUtils', () => {
|
|||
});
|
||||
|
||||
it('getDocNavigation', () => {
|
||||
expect(getDocNavigation('doc1', 'doc1', undefined)).toEqual({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc1',
|
||||
versionedId: 'doc1',
|
||||
displayedSidebar: undefined,
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toEqual({
|
||||
sidebarName: 'sidebar1',
|
||||
previous: undefined,
|
||||
next: {
|
||||
|
@ -161,7 +168,14 @@ describe('createSidebarsUtils', () => {
|
|||
id: 'doc2',
|
||||
},
|
||||
});
|
||||
expect(getDocNavigation('doc2', 'doc2', undefined)).toEqual({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc2',
|
||||
versionedId: 'doc2',
|
||||
displayedSidebar: undefined,
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toEqual({
|
||||
sidebarName: 'sidebar1',
|
||||
previous: {
|
||||
type: 'doc',
|
||||
|
@ -170,7 +184,14 @@ describe('createSidebarsUtils', () => {
|
|||
next: undefined,
|
||||
});
|
||||
|
||||
expect(getDocNavigation('doc3', 'doc3', undefined)).toEqual({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc3',
|
||||
versionedId: 'doc3',
|
||||
displayedSidebar: undefined,
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toEqual({
|
||||
sidebarName: 'sidebar2',
|
||||
previous: undefined,
|
||||
next: {
|
||||
|
@ -178,7 +199,14 @@ describe('createSidebarsUtils', () => {
|
|||
id: 'doc4',
|
||||
},
|
||||
});
|
||||
expect(getDocNavigation('doc4', 'doc4', undefined)).toEqual({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc4',
|
||||
versionedId: 'doc4',
|
||||
displayedSidebar: undefined,
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toEqual({
|
||||
sidebarName: 'sidebar2',
|
||||
previous: {
|
||||
type: 'doc',
|
||||
|
@ -188,7 +216,14 @@ describe('createSidebarsUtils', () => {
|
|||
next: undefined,
|
||||
});
|
||||
|
||||
expect(getDocNavigation('doc5', 'doc5', undefined)).toMatchObject({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc5',
|
||||
versionedId: 'doc5',
|
||||
displayedSidebar: undefined,
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toMatchObject({
|
||||
sidebarName: 'sidebar3',
|
||||
previous: undefined,
|
||||
next: {
|
||||
|
@ -196,7 +231,14 @@ describe('createSidebarsUtils', () => {
|
|||
label: 'S3 SubCategory',
|
||||
},
|
||||
});
|
||||
expect(getDocNavigation('doc6', 'doc6', undefined)).toMatchObject({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc6',
|
||||
versionedId: 'doc6',
|
||||
displayedSidebar: undefined,
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toMatchObject({
|
||||
sidebarName: 'sidebar3',
|
||||
previous: {
|
||||
type: 'category',
|
||||
|
@ -207,7 +249,14 @@ describe('createSidebarsUtils', () => {
|
|||
id: 'doc7',
|
||||
},
|
||||
});
|
||||
expect(getDocNavigation('doc7', 'doc7', undefined)).toEqual({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc7',
|
||||
versionedId: 'doc7',
|
||||
displayedSidebar: undefined,
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toEqual({
|
||||
sidebarName: 'sidebar3',
|
||||
previous: {
|
||||
type: 'doc',
|
||||
|
@ -215,17 +264,36 @@ describe('createSidebarsUtils', () => {
|
|||
},
|
||||
next: undefined,
|
||||
});
|
||||
expect(getDocNavigation('doc3', 'doc3', null)).toEqual({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc3',
|
||||
versionedId: 'doc3',
|
||||
displayedSidebar: null,
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toEqual({
|
||||
sidebarName: undefined,
|
||||
previous: undefined,
|
||||
next: undefined,
|
||||
});
|
||||
expect(() =>
|
||||
getDocNavigation('doc3', 'doc3', 'foo'),
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc3',
|
||||
versionedId: 'doc3',
|
||||
displayedSidebar: 'foo',
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Doc with ID doc3 wants to display sidebar foo but a sidebar with this name doesn't exist"`,
|
||||
);
|
||||
expect(getDocNavigation('doc3', 'doc3', 'sidebar1')).toEqual({
|
||||
expect(
|
||||
getDocNavigation({
|
||||
unversionedId: 'doc3',
|
||||
versionedId: 'doc3',
|
||||
displayedSidebar: 'sidebar1',
|
||||
unlistedIds: new Set(),
|
||||
}),
|
||||
).toEqual({
|
||||
sidebarName: 'sidebar1',
|
||||
previous: undefined,
|
||||
next: undefined,
|
||||
|
|
|
@ -183,11 +183,18 @@ export type PropSidebarItemCategory = Expand<
|
|||
SidebarItemCategoryBase & {
|
||||
items: PropSidebarItem[];
|
||||
href?: string;
|
||||
|
||||
// Weird name => it would have been more convenient to have link.unlisted
|
||||
// Note it is the category link that is unlisted, not the category itself
|
||||
// We want to prevent users from clicking on an unlisted category link
|
||||
// We can't use "href: undefined" otherwise sidebar item is not highlighted
|
||||
linkUnlisted?: boolean;
|
||||
}
|
||||
>;
|
||||
|
||||
export type PropSidebarItemLink = SidebarItemLink & {
|
||||
docId?: string;
|
||||
unlisted?: boolean;
|
||||
};
|
||||
|
||||
export type PropSidebarItemHtml = SidebarItemHtml;
|
||||
|
|
|
@ -135,11 +135,12 @@ export type SidebarsUtils = {
|
|||
sidebars: Sidebars;
|
||||
getFirstDocIdOfFirstSidebar: () => string | undefined;
|
||||
getSidebarNameByDocId: (docId: string) => string | undefined;
|
||||
getDocNavigation: (
|
||||
unversionedId: string,
|
||||
versionedId: string,
|
||||
displayedSidebar: string | null | undefined,
|
||||
) => SidebarNavigation;
|
||||
getDocNavigation: (params: {
|
||||
unversionedId: string;
|
||||
versionedId: string;
|
||||
displayedSidebar: string | null | undefined;
|
||||
unlistedIds: Set<string>;
|
||||
}) => SidebarNavigation;
|
||||
getCategoryGeneratedIndexList: () => SidebarItemCategoryWithGeneratedIndex[];
|
||||
getCategoryGeneratedIndexNavigation: (
|
||||
categoryGeneratedIndexPermalink: string,
|
||||
|
@ -192,11 +193,17 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils {
|
|||
};
|
||||
}
|
||||
|
||||
function getDocNavigation(
|
||||
unversionedId: string,
|
||||
versionedId: string,
|
||||
displayedSidebar: string | null | undefined,
|
||||
): SidebarNavigation {
|
||||
function getDocNavigation({
|
||||
unversionedId,
|
||||
versionedId,
|
||||
displayedSidebar,
|
||||
unlistedIds,
|
||||
}: {
|
||||
unversionedId: string;
|
||||
versionedId: string;
|
||||
displayedSidebar: string | null | undefined;
|
||||
unlistedIds: Set<string>;
|
||||
}): SidebarNavigation {
|
||||
// TODO legacy id retro-compatibility!
|
||||
let docId = unversionedId;
|
||||
let sidebarName =
|
||||
|
@ -211,12 +218,28 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils {
|
|||
if (!sidebarName) {
|
||||
return emptySidebarNavigation();
|
||||
}
|
||||
const navigationItems = sidebarNameToNavigationItems[sidebarName];
|
||||
let navigationItems = sidebarNameToNavigationItems[sidebarName];
|
||||
if (!navigationItems) {
|
||||
throw new Error(
|
||||
`Doc with ID ${docId} wants to display sidebar ${sidebarName} but a sidebar with this name doesn't exist`,
|
||||
);
|
||||
}
|
||||
|
||||
// Filter unlisted items from navigation
|
||||
navigationItems = navigationItems.filter((item) => {
|
||||
if (item.type === 'doc' && unlistedIds.has(item.id)) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
item.type === 'category' &&
|
||||
item.link.type === 'doc' &&
|
||||
unlistedIds.has(item.link.id)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const currentItemIndex = navigationItems.findIndex((item) => {
|
||||
if (item.type === 'doc') {
|
||||
return item.id === docId;
|
||||
|
|
|
@ -6,15 +6,22 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import {groupTaggedItems} from '@docusaurus/utils';
|
||||
import {getTagVisibility, groupTaggedItems} from '@docusaurus/utils';
|
||||
import type {VersionTags} from './types';
|
||||
import type {DocMetadata} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
export function getVersionTags(docs: DocMetadata[]): VersionTags {
|
||||
const groups = groupTaggedItems(docs, (doc) => doc.tags);
|
||||
return _.mapValues(groups, (group) => ({
|
||||
label: group.tag.label,
|
||||
docIds: group.items.map((item) => item.id),
|
||||
permalink: group.tag.permalink,
|
||||
}));
|
||||
return _.mapValues(groups, ({tag, items: tagDocs}) => {
|
||||
const tagVisibility = getTagVisibility({
|
||||
items: tagDocs,
|
||||
isUnlisted: (item) => item.unlisted,
|
||||
});
|
||||
return {
|
||||
label: tag.label,
|
||||
docIds: tagVisibility.listedItems.map((item) => item.id),
|
||||
permalink: tag.permalink,
|
||||
unlisted: tagVisibility.unlisted,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ export type SourceToPermalink = {
|
|||
export type VersionTag = Tag & {
|
||||
/** All doc ids having this tag. */
|
||||
docIds: string[];
|
||||
unlisted: boolean;
|
||||
};
|
||||
export type VersionTags = {
|
||||
[permalink: string]: VersionTag;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue