Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(content-docs): sidebar category linking to document or auto-generated index page #5830

Merged
merged 100 commits into from
Dec 3, 2021
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
a2bf37f
initial poc of DocCategory page
slorber Oct 29, 2021
4378c4c
Merge branch 'main' into slorber/category-index
slorber Nov 4, 2021
76ade80
refactor => extract slugification logic to @docusaurus/utils
slorber Nov 4, 2021
ef2d1c3
generateHugeSidebarItems => reduce size generated
slorber Nov 4, 2021
c1c2e1a
progress on implementing category link system
slorber Nov 4, 2021
f6d7775
isActiveSidebarItem => support for category link
slorber Nov 5, 2021
e9643a3
fix navigation ordering
slorber Nov 5, 2021
f0474a3
implementation POC for autogenerated sidebars
slorber Nov 5, 2021
15bb221
do not use conventional category doc link when an explicit "generated…
slorber Nov 5, 2021
9e95fe0
make category index page work
slorber Nov 5, 2021
24e5683
refactor routes
slorber Nov 5, 2021
895eee3
working POC of category index
slorber Nov 5, 2021
9cfebb8
working POC of category index
slorber Nov 5, 2021
73ddc70
Merge branch 'main' into slorber/category-index
slorber Nov 10, 2021
d385737
allow lodash last()
slorber Nov 10, 2021
b8ff50e
category config should support local or qualified ids
slorber Nov 10, 2021
f9d593f
better comment
slorber Nov 10, 2021
9ee14c1
move categoryMetadataFileSchema to validation.ts
slorber Nov 10, 2021
418210e
add external link for generated-index test
slorber Nov 10, 2021
9bcc798
comment
slorber Nov 10, 2021
6edf6f7
change readme case
slorber Nov 10, 2021
fe6ffe1
update category slug
slorber Nov 10, 2021
cf9eef1
isConventionalCategoryDocLink => case insensitive
slorber Nov 10, 2021
7907d07
generated sidebar items should be normalized too!
slorber Nov 10, 2021
3920e1c
fix generator category linking
slorber Nov 10, 2021
52a150f
style generated index page
slorber Nov 10, 2021
e00d597
Merge branch 'main' into slorber/category-index
slorber Nov 12, 2021
ff80f13
Clean DocCard implementation
slorber Nov 12, 2021
b547559
Merge branch 'main' into slorber/category-index
Josh-Cena Nov 16, 2021
9d06d70
Fix linting
Josh-Cena Nov 16, 2021
c5cf549
Fix tests
Josh-Cena Nov 16, 2021
5273c23
Revert snapshot change
Josh-Cena Nov 16, 2021
055b1d8
move more code to theme-common
slorber Nov 12, 2021
e1d31e4
Merge branch 'main' into slorber/category-index
slorber Nov 21, 2021
69e31fa
Add DocsVersionProvider + version.docs prop + read doc description in…
slorber Nov 21, 2021
f631795
temporary break doc navigation before refactor
slorber Nov 21, 2021
bb17c14
Let me see how it looks (lol)
Josh-Cena Nov 23, 2021
9868fb3
Test doc as index page
Josh-Cena Nov 23, 2021
28d2f51
docs: add PREFS website to showcase (#5984)
Patitotective Nov 22, 2021
61ea399
chore: cleanup dependency declaration in package.json (#5985)
armano2 Nov 23, 2021
7208bac
chore(plugin-pwa): change core-js version in package.json to v3 (#5995)
Josh-Cena Nov 23, 2021
d19cab9
fix: make hash link in heading not selectable (#6000)
Jess-2021 Nov 24, 2021
9f2e535
chore: upgrade webpack-dev-server to v4.5.0 (#5998)
lex111 Nov 24, 2021
898c226
chore(ci): add GitHub action for showcase testing (#6002)
Josh-Cena Nov 24, 2021
48af337
docs: add Dime.Scheduler SDK to showcase (#6001)
hbulens Nov 24, 2021
e63e815
fix github slugger types deps after merge
slorber Nov 24, 2021
8c19d08
restore doc navigation ordering
slorber Nov 24, 2021
fc89782
make navigation work across docs/category index
slorber Nov 24, 2021
868d12e
Polish generated index page + normalize with Docs + SEO + ability to …
slorber Nov 24, 2021
711c46b
Merge branch 'main' into slorber/category-index
Josh-Cena Nov 25, 2021
9fab3dc
Layout changes
Josh-Cena Nov 25, 2021
85af312
Fix main heading style
Josh-Cena Nov 25, 2021
03a11e6
refactor
Josh-Cena Nov 25, 2021
99f4b7b
Add tests for createSidebarsUtils
slorber Nov 25, 2021
62a62be
remove old validation error
slorber Nov 25, 2021
aec17a5
move sidebars theme methods to theme-common
slorber Nov 25, 2021
635f893
tests for isActiveSidebarItem
slorber Nov 25, 2021
dd3243d
test findFirstCategoryLink
slorber Nov 25, 2021
3c6515f
refactor + test docsUtils
slorber Nov 25, 2021
cba53f0
validation tests
slorber Nov 25, 2021
389fb09
more sidebar utils tests
slorber Nov 25, 2021
51cecdd
add basic tests for slugger
slorber Nov 25, 2021
2792eb7
test isConventionalCategoryDocLink
slorber Nov 25, 2021
68b453a
better isConventionalCategoryDocLink implementation
slorber Nov 25, 2021
2186783
sidebar generator tests
slorber Nov 25, 2021
d50ac37
Add poc of using DocCardList inline
slorber Nov 26, 2021
805f35f
refactor process api + test
slorber Nov 26, 2021
fbb9a9f
ensure processor normalize generated items
slorber Nov 26, 2021
a680085
fix docs test
slorber Nov 26, 2021
dcbde57
update simple website snapshot + fix bugs
slorber Nov 26, 2021
b5236ec
Revert "update simple website snapshot + fix bugs"
slorber Nov 26, 2021
0474e83
update single snapshot
slorber Nov 26, 2021
2134453
fix snapshots
slorber Nov 26, 2021
3420b4c
Start using unversioned ids in versioned sidebars (+ retrocompatibili…
slorber Nov 26, 2021
05e2962
update cli snapshots + tests
slorber Nov 26, 2021
53e5355
lockfile
slorber Nov 26, 2021
c3df1dc
Multiple refactors
Josh-Cena Nov 29, 2021
345b7c1
Remove types dep
Josh-Cena Nov 29, 2021
ad14d2a
Merge branch 'main' into slorber/category-index
Josh-Cena Nov 29, 2021
12c7fdd
Merge branch 'main' into slorber/category-index
slorber Dec 1, 2021
4cde989
integrate new infima version with separate sidebar category caret button
slorber Dec 1, 2021
e331bfc
import order
slorber Dec 1, 2021
908291c
polish cardlist design
slorber Dec 1, 2021
c2be921
update theme translations
slorber Dec 1, 2021
509ac40
docCategoryGeneratedIndexComponent option
slorber Dec 1, 2021
18ab129
doc docCategoryGeneratedIndexComponent
slorber Dec 1, 2021
29559b9
we should be able to navigate collapsible categories even before hydr…
slorber Dec 1, 2021
3d10908
fix options test
slorber Dec 1, 2021
eafebb5
rename getSlug param
slorber Dec 2, 2021
27178d2
doc slug logic should consider conventional doc indexes
slorber Dec 2, 2021
3105474
add some doc
slorber Dec 2, 2021
95c7a3a
move TS issue from CategoryMetadataFile to Sidebar generator (still r…
slorber Dec 2, 2021
0633320
Minor improvements: change markup, add border
lex111 Dec 2, 2021
d96e9ac
integrate new infima
slorber Dec 2, 2021
8aae9e1
minor fixes for non-collapsible sidebar items
slorber Dec 2, 2021
3f1147f
Polish docs
Josh-Cena Dec 3, 2021
7335fe9
little mobile UX issue
slorber Dec 3, 2021
ac44531
fix category guides link
slorber Dec 3, 2021
3983181
minor fix
slorber Dec 3, 2021
2daa173
ability to translate generated-index title/description
slorber Dec 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ module.exports = {
{ignore: ['^@theme', '^@docusaurus', '^@generated', 'unist', 'mdast']},
],
'import/extensions': OFF,
'no-inner-declarations': OFF,
'header/header': [
ERROR,
'block',
Expand Down
1 change: 0 additions & 1 deletion packages/docusaurus-mdx-loader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"escape-html": "^1.0.3",
"file-loader": "^6.2.0",
"fs-extra": "^10.0.0",
"github-slugger": "^1.4.0",
Josh-Cena marked this conversation as resolved.
Show resolved Hide resolved
"gray-matter": "^4.0.3",
"mdast-util-to-string": "^2.0.0",
"remark-emoji": "^2.1.0",
Expand Down
9 changes: 3 additions & 6 deletions packages/docusaurus-mdx-loader/src/remark/headings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,16 @@

/* Based on remark-slug (https://github.com/remarkjs/remark-slug) and gatsby-remark-autolink-headers (https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-remark-autolink-headers) */

import {parseMarkdownHeadingId} from '@docusaurus/utils';
import {parseMarkdownHeadingId, createSlugger} from '@docusaurus/utils';
import visit, {Visitor} from 'unist-util-visit';
import toString from 'mdast-util-to-string';
import Slugger from 'github-slugger';
import type {Transformer} from 'unified';
import type {Parent} from 'unist';
import type {Heading, Text} from 'mdast';

const slugs = new Slugger();

function headings(): Transformer {
const transformer: Transformer = (ast) => {
slugs.reset();
const slugs = createSlugger();

const visitor: Visitor<Heading> = (headingNode) => {
const data = headingNode.data || (headingNode.data = {});
Expand All @@ -29,7 +26,7 @@ function headings(): Transformer {
let {id} = properties;

if (id) {
id = slugs.slug(id, true);
id = slugs.slug(id, {maintainCase: true});
} else {
const headingTextNodes = headingNode.children.filter(
({type}) => !['html', 'jsx'].includes(type),
Expand Down
8 changes: 3 additions & 5 deletions packages/docusaurus-plugin-content-docs/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,23 @@ import path from 'path';
import type {PathOptions, SidebarOptions} from './types';
import {transformSidebarItems} from './sidebars/utils';
import type {SidebarItem, NormalizedSidebars, Sidebar} from './sidebars/types';
import {loadUnprocessedSidebars, resolveSidebarPathOption} from './sidebars';
import {loadSidebarsFile, resolveSidebarPathOption} from './sidebars';
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';

function createVersionedSidebarFile({
siteDir,
pluginId,
sidebarPath,
version,
options,
}: {
siteDir: string;
pluginId: string;
sidebarPath: string | false | undefined;
version: string;
options: SidebarOptions;
}) {
// Load current sidebar and create a new versioned sidebars file (if needed).
const loadedSidebars = loadUnprocessedSidebars(sidebarPath, options);
// Note: we don't need the sidebars file to be normalized: it's ok to let plugin option changes to impact versioned sidebars
const loadedSidebars = loadSidebarsFile(sidebarPath);
slorber marked this conversation as resolved.
Show resolved Hide resolved

// Do not create a useless versioned sidebars file if sidebars file is empty or sidebars are disabled/false)
const shouldCreateVersionedSidebarFile =
Expand Down Expand Up @@ -155,7 +154,6 @@ export function cliDocsVersionCommand(
pluginId,
version,
sidebarPath: resolveSidebarPathOption(siteDir, sidebarPath),
options,
});

// Update versions.json file.
Expand Down
110 changes: 25 additions & 85 deletions packages/docusaurus-plugin-content-docs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
addTrailingPathSeparator,
createAbsoluteFilePathMatcher,
} from '@docusaurus/utils';
import {LoadContext, Plugin, RouteConfig} from '@docusaurus/types';
import {LoadContext, Plugin} from '@docusaurus/types';
import {loadSidebars} from './sidebars';
import {CategoryMetadataFilenamePattern} from './sidebars/generator';
import {readVersionDocs, processDocMetadata, handleNavigation} from './docs';
Expand All @@ -31,7 +31,6 @@ import {
LoadedContent,
SourceToPermalink,
DocMetadataBase,
DocMetadata,
GlobalPluginData,
VersionMetadata,
LoadedVersion,
Expand All @@ -44,14 +43,15 @@ import {cliDocsVersionCommand} from './cli';
import {VERSIONS_JSON_FILE} from './constants';
import {keyBy, mapValues} from 'lodash';
import {toGlobalDataVersion} from './globalData';
import {toTagDocListProp, toVersionMetadataProp} from './props';
import {toTagDocListProp} from './props';
import {
translateLoadedContent,
getLoadedContentTranslationFiles,
} from './translations';
import chalk from 'chalk';
import {getVersionTags} from './tags';
import {PropTagsListPage} from '@docusaurus/plugin-content-docs-types';
import {createVersionRoutes} from './routes';

export default function pluginContentDocs(
context: LoadContext,
Expand Down Expand Up @@ -212,42 +212,10 @@ export default function pluginContentDocs(
const {docLayoutComponent, docItemComponent} = options;
const {addRoute, createData, setGlobalData} = actions;

const createDocRoutes = async (
docs: DocMetadata[],
): Promise<RouteConfig[]> => {
const routes = await Promise.all(
docs.map(async (metadataItem) => {
await createData(
// Note that this created data path must be in sync with
// metadataPath provided to mdx-loader.
`${docuHash(metadataItem.source)}.json`,
JSON.stringify(metadataItem, null, 2),
);

const docRoute: RouteConfig = {
path: metadataItem.permalink,
component: docItemComponent,
exact: true,
modules: {
content: metadataItem.source,
},
// Because the parent (DocPage) comp need to access it easily
// This permits to render the sidebar once without unmount/remount when navigating (and preserve sidebar state)
...(metadataItem.sidebar && {
sidebar: metadataItem.sidebar,
}),
};

return docRoute;
}),
);

return routes.sort((a, b) => a.path.localeCompare(b.path));
};

async function createVersionTagsRoutes(loadedVersion: LoadedVersion) {
const versionTags = getVersionTags(loadedVersion.docs);
async function createVersionTagsRoutes(version: LoadedVersion) {
const versionTags = getVersionTags(version.docs);

// TODO tags should be a sub route of the version route
async function createTagsListPage() {
const tagsProp: PropTagsListPage['tags'] = Object.values(
versionTags,
Expand All @@ -260,11 +228,11 @@ export default function pluginContentDocs(
// Only create /tags page if there are tags.
if (Object.keys(tagsProp).length > 0) {
const tagsPropPath = await createData(
`${docuHash(`tags-list-${loadedVersion.versionName}-prop`)}.json`,
`${docuHash(`tags-list-${version.versionName}-prop`)}.json`,
JSON.stringify(tagsProp, null, 2),
);
addRoute({
path: loadedVersion.tagsPath,
path: version.tagsPath,
exact: true,
component: options.docTagsListComponent,
modules: {
Expand All @@ -274,11 +242,12 @@ export default function pluginContentDocs(
}
}

// TODO tags should be a sub route of the version route
async function createTagDocListPage(tag: VersionTag) {
const tagProps = toTagDocListProp({
allTagsPath: loadedVersion.tagsPath,
allTagsPath: version.tagsPath,
tag,
docs: loadedVersion.docs,
docs: version.docs,
});
const tagPropPath = await createData(
`${docuHash(`tag-${tag.permalink}`)}.json`,
Expand All @@ -298,50 +267,21 @@ export default function pluginContentDocs(
await Promise.all(Object.values(versionTags).map(createTagDocListPage));
}

async function doCreateVersionRoutes(
loadedVersion: LoadedVersion,
): Promise<void> {
await createVersionTagsRoutes(loadedVersion);

const versionMetadata = toVersionMetadataProp(pluginId, loadedVersion);
const versionMetadataPropPath = await createData(
`${docuHash(
`version-${loadedVersion.versionName}-metadata-prop`,
)}.json`,
JSON.stringify(versionMetadata, null, 2),
);

addRoute({
path: loadedVersion.versionPath,
// allow matching /docs/* as well
exact: false,
// main docs component (DocPage)
component: docLayoutComponent,
// sub-routes for each doc
routes: await createDocRoutes(loadedVersion.docs),
modules: {
versionMetadata: aliasedSource(versionMetadataPropPath),
},
priority: loadedVersion.routePriority,
});
}

async function createVersionRoutes(
loadedVersion: LoadedVersion,
): Promise<void> {
try {
return await doCreateVersionRoutes(loadedVersion);
} catch (e) {
console.error(
chalk.red(
`Can't create version routes for version "${loadedVersion.versionName}"`,
),
);
throw e;
}
}
await Promise.all(
loadedVersions.map((loadedVersion) =>
createVersionRoutes({
loadedVersion,
docItemComponent,
docLayoutComponent,
pluginId,
aliasedSource,
actions,
}),
),
);

await Promise.all(loadedVersions.map(createVersionRoutes));
// TODO tags should be a sub route of the version route
await Promise.all(loadedVersions.map(createVersionTagsRoutes));

setGlobalData<GlobalPluginData>({
path: normalizeUrl([baseUrl, options.routeBasePath]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,17 @@ declare module '@docusaurus/plugin-content-docs-types' {
docsSidebars: PropSidebars;
};

export type PropCategoryGeneratedIndex = {
label: string;
slug: string;
permalink: string;
};

export type PropSidebarItemLink = import('./sidebars/types').SidebarItemLink;
export type PropSidebarItemCategory =
import('./sidebars/types').PropSidebarItemCategory;
export type PropSidebarItem = import('./sidebars/types').PropSidebarItem;
export type PropSidebar = import('./sidebars/types').PropSidebar;
export type PropSidebars = import('./sidebars/types').PropSidebars;

export type PropTagDocListDoc = {
Expand Down Expand Up @@ -115,6 +122,16 @@ declare module '@theme/DocItem' {
export default DocItem;
}

declare module '@theme/DocCategoryGeneratedIndex' {
import type {PropCategoryGeneratedIndex} from '@docusaurus/plugin-content-docs-types';

export interface Props {
categoryIndex: PropCategoryGeneratedIndex;
}

export default function DocCategoryGeneratedIndex(props: Props): JSX.Element;
}

declare module '@theme/DocItemFooter' {
import type {Props} from '@theme/DocItem';

Expand Down
36 changes: 30 additions & 6 deletions packages/docusaurus-plugin-content-docs/src/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import type {
SidebarItemDoc,
SidebarItemLink,
SidebarItem,
SidebarItemCategory,
SidebarItemCategoryLink,
} from './sidebars/types';
import type {
PropSidebars,
PropVersionMetadata,
PropSidebarItem,
PropSidebarItemCategory,
PropTagDocList,
PropTagDocListDoc,
} from '@docusaurus/plugin-content-docs-types';
Expand All @@ -23,8 +26,7 @@ import {compact, keyBy, mapValues} from 'lodash';
export function toSidebarsProp(loadedVersion: LoadedVersion): PropSidebars {
const docsById = keyBy(loadedVersion.docs, (doc) => doc.id);

const convertDocLink = (item: SidebarItemDoc): SidebarItemLink => {
const docId = item.id;
function getDocById(docId: string): DocMetadata {
const docMetadata = docsById[docId];

if (!docMetadata) {
Expand All @@ -34,13 +36,16 @@ Available document ids are:
- ${Object.keys(docsById).sort().join('\n- ')}`,
);
}
return docMetadata;
}

const convertDocLink = (item: SidebarItemDoc): SidebarItemLink => {
const docMetadata = getDocById(item.id);
const {
title,
permalink,
frontMatter: {sidebar_label: sidebarLabel},
} = docMetadata;

return {
type: 'link',
label: sidebarLabel || item.label || title,
Expand All @@ -50,18 +55,37 @@ Available document ids are:
};
};

const normalizeItem = (item: SidebarItem): PropSidebarItem => {
function getCategoryLinkHref(
link: SidebarItemCategoryLink | undefined,
): string | undefined {
switch (link?.type) {
case 'doc':
return getDocById(link.id).permalink;
case 'generated-index':
return link.permalink;
default:
return undefined;
}
}

function convertCategory(item: SidebarItemCategory): PropSidebarItemCategory {
const {link, ...rest} = item;
const href = getCategoryLinkHref(link);
return {...rest, items: item.items.map(normalizeItem), ...(href && {href})};
}

function normalizeItem(item: SidebarItem): PropSidebarItem {
switch (item.type) {
case 'category':
return {...item, items: item.items.map(normalizeItem)};
return convertCategory(item);
case 'ref':
case 'doc':
return convertDocLink(item);
case 'link':
default:
return item;
}
};
}

// Transform the sidebar so that all sidebar item will be in the
// form of 'link' or 'category' only.
Expand Down
Loading