From c037516d85a456d8a0313b1383289f9b5f044bc3 Mon Sep 17 00:00:00 2001 From: Bob Ippolito Date: Sat, 20 Apr 2024 10:39:41 -0700 Subject: [PATCH] docs: group @lexical/react API sidebar items (#5916) --- .../lexical-code/src/CodeHighlighterPrism.ts | 6 + packages/lexical-website/docusaurus.config.js | 162 +++++++++++++----- 2 files changed, 126 insertions(+), 42 deletions(-) diff --git a/packages/lexical-code/src/CodeHighlighterPrism.ts b/packages/lexical-code/src/CodeHighlighterPrism.ts index 132c092941a5..f69e65503ca6 100644 --- a/packages/lexical-code/src/CodeHighlighterPrism.ts +++ b/packages/lexical-code/src/CodeHighlighterPrism.ts @@ -23,3 +23,9 @@ import 'prismjs/components/prism-swift'; import 'prismjs/components/prism-typescript'; import 'prismjs/components/prism-java'; import 'prismjs/components/prism-cpp'; + +declare global { + interface Window { + Prism: typeof import('prismjs'); + } +} diff --git a/packages/lexical-website/docusaurus.config.js b/packages/lexical-website/docusaurus.config.js index bbd7ff808746..1e14c195d434 100644 --- a/packages/lexical-website/docusaurus.config.js +++ b/packages/lexical-website/docusaurus.config.js @@ -48,6 +48,124 @@ function lexicalReactEntryPoints() { }); } +/** @type Record */ +const labels = { + 'api/index': 'Readme', + 'api/modules': 'Table of Contents', +}; + +/** + * @type {import('@docusaurus/plugin-content-docs').PluginOptions['sidebarItemsGenerator']} + */ +const sidebarItemsGenerator = async ({ + defaultSidebarItemsGenerator, + ...args +}) => { + const items = await defaultSidebarItemsGenerator(args); + if (args.item.dirName === 'api') { + return items + .map((sidebarItem) => { + if (sidebarItem.type === 'doc' && sidebarItem.id in labels) { + return {...sidebarItem, label: labels[sidebarItem.id]}; + } else if (sidebarItem.type !== 'category') { + return sidebarItem; + } + // This makes type inference easier + const groupedItems = sidebarItem.items.slice(0, 0); + for (const item of sidebarItem.items) { + if (item.type === 'doc' && item.id.startsWith('api/modules/')) { + // autoConfiguration is disabled because the frontmatter + // sidebar_label takes precedence over anything we do here, + // so the default labels are the page titles. + const label = item.id + .replace(/^api\/modules\//, '') + .replace(/^lexical_react_/, '@lexical/react/') + .replace(/^lexical_/, '@lexical/') + .replace(/_/g, '-'); + const m = /^(@lexical\/[^/]+)\/(.*)$/.exec(label); + if (m) { + const lastItem = groupedItems[groupedItems.length - 1]; + const groupedItem = {...item, label: m[2]}; + if ( + (lastItem && lastItem.type === 'category') || + lastItem.label === m[1] + ) { + lastItem.items.push(groupedItem); + } else { + groupedItems.push({ + items: [groupedItem], + label: m[1], + type: 'category', + }); + } + continue; + } + groupedItems.push({...item, label}); + } else if (item.type === 'doc') { + groupedItems.push({...item, label: item.id.replace(/^[^.]+./, '')}); + } else { + groupedItems.push(item); + } + } + return { + ...sidebarItem, + items: groupedItems, + label: + // modules, classes, interfaces -> Modules, Classes, Interfaces + sidebarItem.label.charAt(0).toUpperCase() + + sidebarItem.label.slice(1), + }; + }) + .sort((a, b) => + // sort categories last (readme and table of contents are doc) + a.type !== b.type ? (a.type === 'category' ? 1 : -1) : 0, + ); + } + return items; +}; + +/** @type {Partial} */ +const docusaurusPluginTypedocConfig = { + ...sourceLinkOptions(), + entryPoints: [ + '../lexical/src/index.ts', + '../lexical-clipboard/src/index.ts', + '../lexical-code/src/index.ts', + '../lexical-devtools-core/src/index.ts', + '../lexical-dragon/src/index.ts', + '../lexical-file/src/index.ts', + '../lexical-hashtag/src/index.ts', + '../lexical-headless/src/index.ts', + '../lexical-history/src/index.ts', + '../lexical-html/src/index.ts', + '../lexical-link/src/index.ts', + '../lexical-list/src/index.ts', + '../lexical-mark/src/index.ts', + '../lexical-markdown/src/index.ts', + '../lexical-offset/src/index.ts', + '../lexical-overflow/src/index.ts', + '../lexical-plain-text/src/index.ts', + ...lexicalReactEntryPoints(), + '../lexical-rich-text/src/index.ts', + '../lexical-selection/src/index.ts', + '../lexical-table/src/index.ts', + '../lexical-text/src/index.ts', + '../lexical-utils/src/index.ts', + '../lexical-yjs/src/index.ts', + ], + excludeInternal: true, + plugin: [ + './src/plugins/lexical-typedoc-plugin-no-inherit', + './src/plugins/lexical-typedoc-plugin-module-name', + ], + sidebar: { + autoConfiguration: false, + position: 5, + }, + tsconfig: '../../tsconfig.json', + watch: process.env.TYPEDOC_WATCH === 'true', +}; + /** @type {import('@docusaurus/types').Config} */ const config = { baseUrl: '/', @@ -63,48 +181,7 @@ const config = { organizationName: 'facebook', plugins: [ './plugins/webpack-buffer', - [ - 'docusaurus-plugin-typedoc', - { - ...sourceLinkOptions(), - entryPoints: [ - '../lexical/src/index.ts', - '../lexical-clipboard/src/index.ts', - '../lexical-code/src/index.ts', - '../lexical-devtools-core/src/index.ts', - '../lexical-dragon/src/index.ts', - '../lexical-file/src/index.ts', - '../lexical-hashtag/src/index.ts', - '../lexical-headless/src/index.ts', - '../lexical-history/src/index.ts', - '../lexical-html/src/index.ts', - '../lexical-link/src/index.ts', - '../lexical-list/src/index.ts', - '../lexical-mark/src/index.ts', - '../lexical-markdown/src/index.ts', - '../lexical-offset/src/index.ts', - '../lexical-overflow/src/index.ts', - '../lexical-plain-text/src/index.ts', - ...lexicalReactEntryPoints(), - '../lexical-rich-text/src/index.ts', - '../lexical-selection/src/index.ts', - '../lexical-table/src/index.ts', - '../lexical-text/src/index.ts', - '../lexical-utils/src/index.ts', - '../lexical-yjs/src/index.ts', - ], - excludeInternal: true, - plugin: [ - './src/plugins/lexical-typedoc-plugin-no-inherit', - './src/plugins/lexical-typedoc-plugin-module-name', - ], - sidebar: { - position: 5, - }, - tsconfig: '../../tsconfig.json', - watch: process.env.TYPEDOC_WATCH === 'true', - }, - ], + ['docusaurus-plugin-typedoc', docusaurusPluginTypedocConfig], async function tailwindcss() { return { configurePostCss(postcssOptions) { @@ -129,6 +206,7 @@ const config = { beforeDefaultRemarkPlugins: [importPlugin, slugifyPlugin], editUrl: `${GITHUB_REPO_URL}/tree/main/packages/lexical-website/`, path: 'docs', + sidebarItemsGenerator, sidebarPath: require.resolve('./sidebars.js'), }, gtag: {