From cd21a31005eefb4e04124d3cd1f53334e1f76254 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Wed, 25 May 2022 15:38:44 +0800 Subject: [PATCH 01/16] test: strengthen internal types (#7488) --- jest/deps.d.ts | 13 +++++++-- .../__tests__/index.test.ts | 12 ++++----- packages/docusaurus-migrate/src/index.ts | 2 +- packages/docusaurus-migrate/src/types.ts | 27 +++++++++---------- .../src/__tests__/index.test.ts | 11 ++++---- .../src/utils/reactUtils.tsx | 2 +- .../src/theme/SearchBar/index.tsx | 4 ++- .../src/__tests__/validationUtils.test.ts | 7 +++-- .../src/client/PendingNavigation.tsx | 6 ++--- packages/docusaurus/src/commands/deploy.ts | 20 +++++++------- .../commands/swizzle/__tests__/index.test.ts | 2 +- .../server/plugins/__tests__/index.test.ts | 2 +- .../docs/api/plugins/plugin-content-docs.md | 4 +-- website/docs/api/plugins/plugin-pwa.md | 6 ++--- .../markdown-features-toc.mdx | 4 +-- 15 files changed, 67 insertions(+), 55 deletions(-) diff --git a/jest/deps.d.ts b/jest/deps.d.ts index a0694f5b8128..16ad1b75fdbd 100644 --- a/jest/deps.d.ts +++ b/jest/deps.d.ts @@ -7,9 +7,18 @@ // modules only used in tests -declare module 'to-vfile'; +declare module 'to-vfile' { + import type {VFile} from 'vfile'; -declare module 'remark-mdx'; + export function read(path: string, encoding?: string): Promise; +} + +declare module 'remark-mdx' { + import type {Plugin} from 'unified'; + + const mdx: Plugin; + export = mdx; +} declare module '@testing-utils/git' { const createTempRepo: typeof import('./utils/git').createTempRepo; diff --git a/packages/docusaurus-cssnano-preset/src/remove-overridden-custom-properties/__tests__/index.test.ts b/packages/docusaurus-cssnano-preset/src/remove-overridden-custom-properties/__tests__/index.test.ts index 8e50db5a74bd..9ce352bd90c5 100644 --- a/packages/docusaurus-cssnano-preset/src/remove-overridden-custom-properties/__tests__/index.test.ts +++ b/packages/docusaurus-cssnano-preset/src/remove-overridden-custom-properties/__tests__/index.test.ts @@ -10,8 +10,8 @@ import vfile from 'to-vfile'; import postcss from 'postcss'; import postCssRemoveOverriddenCustomProperties from '../index'; -const processFixture = (name: string) => { - const input = vfile.readSync( +const processFixture = async (name: string) => { + const input = await vfile.read( path.join(__dirname, '__fixtures__', `${name}.css`), 'utf8', ); @@ -23,11 +23,11 @@ const processFixture = (name: string) => { }; describe('remove-overridden-custom-properties', () => { - it('overridden custom properties should be removed', () => { - expect(processFixture('normal')).toMatchSnapshot(); + it('overridden custom properties should be removed', async () => { + await expect(processFixture('normal')).resolves.toMatchSnapshot(); }); - it('overridden custom properties with `!important` rule should not be removed', () => { - expect(processFixture('important_rule')).toMatchSnapshot(); + it('overridden custom properties with `!important` rule should not be removed', async () => { + await expect(processFixture('important_rule')).resolves.toMatchSnapshot(); }); }); diff --git a/packages/docusaurus-migrate/src/index.ts b/packages/docusaurus-migrate/src/index.ts index 165c7c2fd32f..f5bf38134bc0 100644 --- a/packages/docusaurus-migrate/src/index.ts +++ b/packages/docusaurus-migrate/src/index.ts @@ -552,7 +552,7 @@ async function migrateVersionedSidebar( (topLevel: SidebarEntries, value) => { const key = value[0].replace(versionRegex, ''); topLevel[key] = Object.entries(value[1]).reduce<{ - [key: string]: Array; + [key: string]: (string | {[key: string]: unknown})[]; }>((acc, val) => { acc[val[0].replace(versionRegex, '')] = ( val[1] as SidebarEntry[] diff --git a/packages/docusaurus-migrate/src/types.ts b/packages/docusaurus-migrate/src/types.ts index 022139f3489d..39b5fc2d53ae 100644 --- a/packages/docusaurus-migrate/src/types.ts +++ b/packages/docusaurus-migrate/src/types.ts @@ -34,7 +34,7 @@ export type SidebarEntry = export type SidebarEntries = { [key: string]: | {[key: string]: unknown} - | Array<{[key: string]: unknown} | string>; + | ({[key: string]: unknown} | string)[]; }; export type VersionTwoConfig = { @@ -49,7 +49,7 @@ export type VersionTwoConfig = { githubHost?: string; onBrokenLinks: string; onBrokenMarkdownLinks: string; - plugins: Array<[string, {[key: string]: unknown}]>; + plugins: [string, {[key: string]: unknown}][]; themes?: []; presets: [[string, ClassicPresetEntries]]; themeConfig: { @@ -58,17 +58,14 @@ export type VersionTwoConfig = { logo?: { src?: string; }; - items: Array<{[key: string]: unknown} | null>; + items: ({[key: string]: unknown} | null)[]; }; image?: string; footer: { - links: Array<{ + links: { title: string; - items: Array<{ - label: string; - to: string; - }>; - }>; + items: {label: string; to: string}[]; + }[]; copyright?: string; logo: { src?: string; @@ -104,26 +101,26 @@ export type VersionOneConfig = { organizationName?: string; projectName?: string; noIndex?: boolean; - headerLinks?: Array<{doc: string; href: string; label: string; page: string}>; + headerLinks?: {doc: string; href: string; label: string; page: string}[]; headerIcon?: string; favicon?: string; colors?: {primaryColor: string}; copyright?: string; editUrl?: string; customDocsPath?: string; - users?: Array<{[key: string]: unknown}>; + users?: {[key: string]: unknown}[]; disableHeaderTitle?: string; disableTitleTagline?: string; - separateCss?: Array<{[key: string]: unknown}>; + separateCss?: {[key: string]: unknown}[]; footerIcon?: string; translationRecruitingLink?: string; algolia?: {[key: string]: unknown}; gaTrackingId?: string; gaGtag?: boolean; highlight?: {[key: string]: unknown}; - markdownPlugins?: Array<() => void>; - scripts?: Array<{src: string; [key: string]: unknown} | string>; - stylesheets?: Array<{href: string; [key: string]: unknown} | string>; + markdownPlugins?: (() => void)[]; + scripts?: ({src: string; [key: string]: unknown} | string)[]; + stylesheets?: ({href: string; [key: string]: unknown} | string)[]; facebookAppId?: string; facebookComments?: true; facebookPixelId?: string; diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index 746288ca95e9..11e54417d884 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -31,6 +31,7 @@ import type { Options, PluginOptions, PropSidebarItemLink, + PropSidebars, } from '@docusaurus/plugin-content-docs'; import type { SidebarItemsGeneratorOption, @@ -82,7 +83,7 @@ const createFakeActions = (contentDir: string) => { // Query by prefix, because files have a hash at the end so it's not // convenient to query by full filename - const getCreatedDataByPrefix = (prefix: string) => { + function getCreatedDataByPrefix(prefix: string) { const entry = Object.entries(dataContainer).find(([key]) => key.startsWith(prefix), ); @@ -92,8 +93,8 @@ Entries created: - ${Object.keys(dataContainer).join('\n- ')} `); } - return JSON.parse(entry[1] as string); - }; + return JSON.parse(entry[1] as string) as PropSidebars; + } // Extra fns useful for tests! const utils = { @@ -571,8 +572,8 @@ describe('versioned website (community)', () => { allContent: {}, }); - utils.checkVersionMetadataPropCreated(currentVersion!); - utils.checkVersionMetadataPropCreated(version100!); + utils.checkVersionMetadataPropCreated(currentVersion); + utils.checkVersionMetadataPropCreated(version100); utils.expectSnapshot(); }); diff --git a/packages/docusaurus-theme-common/src/utils/reactUtils.tsx b/packages/docusaurus-theme-common/src/utils/reactUtils.tsx index 4a7410e3fb6d..4e0982807121 100644 --- a/packages/docusaurus-theme-common/src/utils/reactUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/reactUtils.tsx @@ -71,6 +71,6 @@ export class ReactContextError extends Error { this.message = `Hook ${ this.stack?.split('\n')[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups! .name ?? '' - } is called outside the <${providerName}>. ${additionalInfo || ''}`; + } is called outside the <${providerName}>. ${additionalInfo ?? ''}`; } } diff --git a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx index bd36e353aa6a..beef496dffcd 100644 --- a/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx +++ b/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx @@ -120,7 +120,9 @@ function DocSearch({ } return Promise.all([ - import('@docsearch/react/modal'), + import('@docsearch/react/modal') as Promise< + typeof import('@docsearch/react') + >, import('@docsearch/react/style'), import('./styles.css'), ]).then(([{DocSearchModal: Modal}]) => { diff --git a/packages/docusaurus-utils-validation/src/__tests__/validationUtils.test.ts b/packages/docusaurus-utils-validation/src/__tests__/validationUtils.test.ts index 771ff94c855c..0bb0fd99a9f3 100644 --- a/packages/docusaurus-utils-validation/src/__tests__/validationUtils.test.ts +++ b/packages/docusaurus-utils-validation/src/__tests__/validationUtils.test.ts @@ -42,7 +42,7 @@ describe('normalizePluginOptions', () => { it('throws for invalid options', () => { const options = {foo: 1}; expect(() => - normalizePluginOptions(Joi.object({foo: Joi.string()}), options), + normalizePluginOptions(Joi.object({foo: Joi.string()}), options), ).toThrowErrorMatchingInlineSnapshot(`""foo" must be a string"`); }); @@ -90,7 +90,10 @@ describe('normalizeThemeConfig', () => { it('throws for invalid options', () => { const themeConfig = {foo: 1, bar: 1}; expect(() => - normalizeThemeConfig(Joi.object({foo: Joi.string()}), themeConfig), + normalizeThemeConfig( + Joi.object({foo: Joi.string()}), + themeConfig, + ), ).toThrowErrorMatchingInlineSnapshot(`""foo" must be a string"`); }); diff --git a/packages/docusaurus/src/client/PendingNavigation.tsx b/packages/docusaurus/src/client/PendingNavigation.tsx index 24e1e38faa2d..e1e38f40f817 100644 --- a/packages/docusaurus/src/client/PendingNavigation.tsx +++ b/packages/docusaurus/src/client/PendingNavigation.tsx @@ -35,7 +35,7 @@ class PendingNavigation extends React.Component { ? dispatchLifecycleAction('onRouteUpdate', { previousLocation: null, location: this.props.location, - })! + }) : () => {}; this.state = { nextRouteHasLoaded: true, @@ -60,14 +60,14 @@ class PendingNavigation extends React.Component { this.routeUpdateCleanupCb = dispatchLifecycleAction('onRouteUpdate', { previousLocation: this.previousLocation, location: nextLocation, - })!; + }); // Load data while the old screen remains. Force preload instead of using // `window.docusaurus`, because we want to avoid loading screen even when // user is on saveData preload(nextLocation.pathname) .then(() => { - this.routeUpdateCleanupCb?.(); + this.routeUpdateCleanupCb(); this.setState({nextRouteHasLoaded: true}); }) .catch((e: unknown) => console.warn(e)); diff --git a/packages/docusaurus/src/commands/deploy.ts b/packages/docusaurus/src/commands/deploy.ts index e35783ddb745..9b5f233f5bf4 100644 --- a/packages/docusaurus/src/commands/deploy.ts +++ b/packages/docusaurus/src/commands/deploy.ts @@ -69,7 +69,7 @@ This behavior can have SEO impacts and create relative link issues. // The source branch; defaults to the currently checked out branch const sourceBranch = - process.env.CURRENT_BRANCH || + process.env.CURRENT_BRANCH ?? shell.exec('git rev-parse --abbrev-ref HEAD', {silent: true}).stdout.trim(); const gitUser = process.env.GIT_USER; @@ -90,8 +90,8 @@ This behavior can have SEO impacts and create relative link issues. } const organizationName = - process.env.ORGANIZATION_NAME || - process.env.CIRCLE_PROJECT_USERNAME || + process.env.ORGANIZATION_NAME ?? + process.env.CIRCLE_PROJECT_USERNAME ?? siteConfig.organizationName; if (!organizationName) { throw new Error( @@ -101,8 +101,8 @@ This behavior can have SEO impacts and create relative link issues. logger.info`organizationName: name=${organizationName}`; const projectName = - process.env.PROJECT_NAME || - process.env.CIRCLE_PROJECT_REPONAME || + process.env.PROJECT_NAME ?? + process.env.CIRCLE_PROJECT_REPONAME ?? siteConfig.projectName; if (!projectName) { throw new Error( @@ -113,7 +113,7 @@ This behavior can have SEO impacts and create relative link issues. // We never deploy on pull request. const isPullRequest = - process.env.CI_PULL_REQUEST || process.env.CIRCLE_PULL_REQUEST; + process.env.CI_PULL_REQUEST ?? process.env.CIRCLE_PULL_REQUEST; if (isPullRequest) { shell.echo('Skipping deploy on a pull request.'); shell.exit(0); @@ -136,12 +136,12 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); } const deploymentBranch = - process.env.DEPLOYMENT_BRANCH || siteConfig.deploymentBranch || 'gh-pages'; + process.env.DEPLOYMENT_BRANCH ?? siteConfig.deploymentBranch ?? 'gh-pages'; logger.info`deploymentBranch: name=${deploymentBranch}`; const githubHost = - process.env.GITHUB_HOST || siteConfig.githubHost || 'github.com'; - const githubPort = process.env.GITHUB_PORT || siteConfig.githubPort; + process.env.GITHUB_HOST ?? siteConfig.githubHost ?? 'github.com'; + const githubPort = process.env.GITHUB_PORT ?? siteConfig.githubPort; let deploymentRepoURL: string; if (useSSH) { @@ -214,7 +214,7 @@ You can also set the deploymentBranch property in docusaurus.config.js .`); shellExecLog('git add --all'); const commitMessage = - process.env.CUSTOM_COMMIT_MESSAGE || + process.env.CUSTOM_COMMIT_MESSAGE ?? `Deploy website - based on ${currentCommit}`; const commitResults = shellExecLog(`git commit -m "${commitMessage}"`); if ( diff --git a/packages/docusaurus/src/commands/swizzle/__tests__/index.test.ts b/packages/docusaurus/src/commands/swizzle/__tests__/index.test.ts index 74e94678f3c2..462c44c1a09e 100644 --- a/packages/docusaurus/src/commands/swizzle/__tests__/index.test.ts +++ b/packages/docusaurus/src/commands/swizzle/__tests__/index.test.ts @@ -65,7 +65,7 @@ function createExitMock() { }); // eslint-disable-next-line jest/require-top-level-describe afterEach(async () => { - mock?.mockRestore(); + mock.mockRestore(); }); return { diff --git a/packages/docusaurus/src/server/plugins/__tests__/index.test.ts b/packages/docusaurus/src/server/plugins/__tests__/index.test.ts index 2d85798e3633..0ace57b22cd9 100644 --- a/packages/docusaurus/src/server/plugins/__tests__/index.test.ts +++ b/packages/docusaurus/src/server/plugins/__tests__/index.test.ts @@ -28,7 +28,7 @@ describe('loadPlugins', () => { name: 'test1', prop: 'a', async loadContent() { - // Testing that plugin lifecycle is bound to the plugin instance + // Testing that plugin lifecycle is bound to the instance return this.prop; }, async contentLoaded({content, actions}) { diff --git a/website/docs/api/plugins/plugin-content-docs.md b/website/docs/api/plugins/plugin-content-docs.md index e5971ee2fa59..331c7cb0a9f9 100644 --- a/website/docs/api/plugins/plugin-content-docs.md +++ b/website/docs/api/plugins/plugin-content-docs.md @@ -96,14 +96,14 @@ type SidebarGenerator = (generatorArgs: { /** Useful metadata for the version this sidebar belongs to. */ version: {contentPath: string; versionName: string}; /** All the docs of that version (unfiltered). */ - docs: Array<{ + docs: { id: string; title: string; frontMatter: DocFrontMatter & Record; source: string; sourceDirName: string; sidebarPosition?: number | undefined; - }>; + }[]; /** Number prefix parser configured for this plugin. */ numberPrefixParser: PrefixParser; /** The default category index matcher which you can override. */ diff --git a/website/docs/api/plugins/plugin-pwa.md b/website/docs/api/plugins/plugin-pwa.md index 1a7ab67bbe01..7dc019fe97fb 100644 --- a/website/docs/api/plugins/plugin-pwa.md +++ b/website/docs/api/plugins/plugin-pwa.md @@ -112,8 +112,8 @@ Turn debug mode on: ### `offlineModeActivationStrategies` {#offlinemodeactivationstrategies} -- Type: `Array<'appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always'>` -- Default: `['appInstalled','queryString','standalone']` +- Type: `('appInstalled' | 'mobile' | 'saveData'| 'queryString' | 'always')[]` +- Default: `['appInstalled', 'queryString', 'standalone']` Strategies used to turn the offline mode on: @@ -194,7 +194,7 @@ The default theme includes an implementation for the reload popup and uses [Infi ### `pwaHead` {#pwahead} -- Type: `Array<{ tagName: string } & Record>` +- Type: `({ tagName: string; [attributeName: string]: string })[]` - Default: `[]` Array of objects containing `tagName` and key-value pairs for attributes to inject into the `` tag. Technically you can inject any head tag through this, but it's ideally used for tags to make your site PWA compliant. Here's a list of tag to make your app fully compliant: diff --git a/website/docs/guides/markdown-features/markdown-features-toc.mdx b/website/docs/guides/markdown-features/markdown-features-toc.mdx index 18e2d5d17614..1cc1ed43d27c 100644 --- a/website/docs/guides/markdown-features/markdown-features-toc.mdx +++ b/website/docs/guides/markdown-features/markdown-features-toc.mdx @@ -83,11 +83,11 @@ import TOCInline from '@theme/TOCInline'; The `toc` global is just a list of heading items: ```ts -declare const toc: Array<{ +declare const toc: { value: string; id: string; level: number; -}>; +}[]; ``` Note that the `toc` global is a flat array, so you can easily cut out unwanted nodes or insert extra nodes, and create a new TOC tree. From 5fcb742aa1a378833e83607f8ca7249db8fce261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Peer=20St=C3=B6cklmair?= Date: Wed, 25 May 2022 12:41:05 +0200 Subject: [PATCH 02/16] feat(theme-classic): allow className as option for type: "search" (#7357) * feat(theme-classic): allow className as option for type: "search" * fixup! feat(theme-classic): allow className as option for type: "search" * refactor Co-authored-by: Jan Peer Stoecklmair Co-authored-by: Joshua Chen --- .../src/__tests__/validateThemeConfig.test.ts | 6 ++++++ packages/docusaurus-theme-classic/src/theme-classic.d.ts | 2 ++ .../src/theme/Navbar/Content/index.tsx | 4 ++-- .../src/theme/Navbar/Search/index.tsx | 8 ++++++-- .../src/theme/NavbarItem/SearchNavbarItem.tsx | 7 +++++-- .../docusaurus-theme-classic/src/validateThemeConfig.ts | 1 + website/docs/api/themes/theme-configuration.md | 1 + 7 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.ts b/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.ts index da76d5edd34e..850eeb044255 100644 --- a/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.ts +++ b/packages/docusaurus-theme-classic/src/__tests__/validateThemeConfig.test.ts @@ -243,6 +243,12 @@ describe('themeConfig', () => { position: 'left', label: 'Current version', }, + // Search with className + { + type: 'search', + position: 'right', + className: 'search-bar-wrapper', + }, ], }, }; diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index bc9b9c9bbaf3..82ebfdf45d1b 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -777,6 +777,7 @@ declare module '@theme/Navbar/Search' { export interface Props { readonly children: ReactNode; + readonly className?: string; } export default function NavbarSearch(props: Props): JSX.Element; @@ -834,6 +835,7 @@ declare module '@theme/NavbarItem/DropdownNavbarItem' { declare module '@theme/NavbarItem/SearchNavbarItem' { export interface Props { readonly mobile?: boolean; + readonly className?: string; } export default function SearchNavbarItem(props: Props): JSX.Element; diff --git a/packages/docusaurus-theme-classic/src/theme/Navbar/Content/index.tsx b/packages/docusaurus-theme-classic/src/theme/Navbar/Content/index.tsx index cf087e6cefd5..c81437a3fa8b 100644 --- a/packages/docusaurus-theme-classic/src/theme/Navbar/Content/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Navbar/Content/index.tsx @@ -56,7 +56,7 @@ export default function NavbarContent(): JSX.Element { const items = useNavbarItems(); const [leftItems, rightItems] = splitNavbarItems(items); - const autoAddSearchBar = !items.some((item) => item.type === 'search'); + const searchBarItem = items.find((item) => item.type === 'search'); return ( - {autoAddSearchBar && ( + {!searchBarItem && ( diff --git a/packages/docusaurus-theme-classic/src/theme/Navbar/Search/index.tsx b/packages/docusaurus-theme-classic/src/theme/Navbar/Search/index.tsx index 8d3fe1b19d2f..236d237aa082 100644 --- a/packages/docusaurus-theme-classic/src/theme/Navbar/Search/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Navbar/Search/index.tsx @@ -6,10 +6,14 @@ */ import React from 'react'; +import clsx from 'clsx'; import type {Props} from '@theme/Navbar/Search'; import styles from './styles.module.css'; -export default function NavbarSearch({children}: Props): JSX.Element { - return
{children}
; +export default function NavbarSearch({ + children, + className, +}: Props): JSX.Element { + return
{children}
; } diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/SearchNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/SearchNavbarItem.tsx index 9e95436025b2..f401f8f17621 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/SearchNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/SearchNavbarItem.tsx @@ -10,13 +10,16 @@ import SearchBar from '@theme/SearchBar'; import NavbarSearch from '@theme/Navbar/Search'; import type {Props} from '@theme/NavbarItem/SearchNavbarItem'; -export default function SearchNavbarItem({mobile}: Props): JSX.Element | null { +export default function SearchNavbarItem({ + mobile, + className, +}: Props): JSX.Element | null { if (mobile) { return null; } return ( - + ); diff --git a/packages/docusaurus-theme-classic/src/validateThemeConfig.ts b/packages/docusaurus-theme-classic/src/validateThemeConfig.ts index d5bdb78e53e7..d64b671f0270 100644 --- a/packages/docusaurus-theme-classic/src/validateThemeConfig.ts +++ b/packages/docusaurus-theme-classic/src/validateThemeConfig.ts @@ -200,6 +200,7 @@ const LocaleDropdownNavbarItemSchema = NavbarItemBaseSchema.append({ const SearchItemSchema = Joi.object({ type: Joi.string().equal('search').required(), + className: Joi.string(), }); const NavbarItemSchema = Joi.object({ diff --git a/website/docs/api/themes/theme-configuration.md b/website/docs/api/themes/theme-configuration.md index 02e3c66db8f5..d1291bbc3cbc 100644 --- a/website/docs/api/themes/theme-configuration.md +++ b/website/docs/api/themes/theme-configuration.md @@ -602,6 +602,7 @@ However, with this special navbar item type, you can change the default location | --- | --- | --- | --- | | `type` | `'search'` | **Required** | Sets the type of this item to a search bar. | | `position` | 'left' \| 'right' | `'left'` | The side of the navbar this item should appear on. | +| `className` | `string` | / | Custom CSS class for this navbar item. | From f609acab4f4ea2bf001432e216c3ddb3f362abdf Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 26 May 2022 01:01:29 +0800 Subject: [PATCH 03/16] fix(theme-classic): consistently apply the right active class name for all navbar items (#7430) --- .../src/getSwizzleConfig.ts | 7 ------- .../src/theme-classic.d.ts | 14 ++------------ .../src/theme/NavbarItem/DefaultNavbarItem.tsx | 5 +++-- .../src/theme/NavbarItem/DocNavbarItem.tsx | 16 ++++------------ .../theme/NavbarItem/DocSidebarNavbarItem.tsx | 9 +-------- .../NavbarItem/DocsVersionDropdownNavbarItem.tsx | 1 - .../src/theme/NavbarItem/DropdownNavbarItem.tsx | 12 ++++++------ .../LocaleDropdownNavbarItem/index.tsx | 12 ++++++++++-- .../src/theme/NavbarItem/NavbarNavLink.tsx | 8 +------- .../src/theme/NavbarItem/utils.ts | 13 ------------- 10 files changed, 27 insertions(+), 70 deletions(-) delete mode 100644 packages/docusaurus-theme-classic/src/theme/NavbarItem/utils.ts diff --git a/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts b/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts index 0c34618bdc32..a0549256e98f 100644 --- a/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts +++ b/packages/docusaurus-theme-classic/src/getSwizzleConfig.ts @@ -214,13 +214,6 @@ export default function getSwizzleConfig(): SwizzleConfig { description: 'The Navbar item components mapping. Can be ejected to add custom navbar item types. See https://github.com/facebook/docusaurus/issues/7227.', }, - // TODO should probably not even appear here - 'NavbarItem/utils': { - actions: { - eject: 'forbidden', - wrap: 'forbidden', - }, - }, NotFound: { actions: { eject: 'safe', diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 82ebfdf45d1b..1986158d8e22 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -809,7 +809,8 @@ declare module '@theme/NavbarItem/NavbarNavLink' { readonly exact?: boolean; readonly label?: ReactNode; readonly html?: string; - readonly prependBaseUrlToHref?: string; + readonly prependBaseUrlToHref?: boolean; + readonly isDropdownLink?: boolean; } export default function NavbarNavLink(props: Props): JSX.Element; @@ -982,17 +983,6 @@ declare module '@theme/NavbarItem' { export default function NavbarItem(props: Props): JSX.Element; } -declare module '@theme/NavbarItem/utils' { - /** - * On desktop and mobile, we would apply different class names for dropdown - * items. - * @see https://github.com/facebook/docusaurus/pull/5431 - */ - export function getInfimaActiveClassName( - mobile?: boolean, - ): `${'menu' | 'navbar'}__link--active`; -} - declare module '@theme/PaginatorNavLink' { import type {ReactNode} from 'react'; import type {PropNavigationLink} from '@docusaurus/plugin-content-docs'; diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DefaultNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DefaultNavbarItem.tsx index 7036b2b6c12e..948d6507d7bc 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DefaultNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DefaultNavbarItem.tsx @@ -8,7 +8,6 @@ import React from 'react'; import clsx from 'clsx'; import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink'; -import {getInfimaActiveClassName} from '@theme/NavbarItem/utils'; import type { DesktopOrMobileNavBarItemProps, Props, @@ -25,6 +24,7 @@ function DefaultNavbarItemDesktop({ isDropdownItem ? 'dropdown__link' : 'navbar__item navbar__link', className, )} + isDropdownLink={isDropdownItem} {...props} /> ); @@ -58,7 +58,8 @@ export default function DefaultNavbarItem({ ); diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx index 797ef1ec2d50..76df1591ba90 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx @@ -6,11 +6,9 @@ */ import React from 'react'; -import clsx from 'clsx'; import {useActiveDocContext} from '@docusaurus/plugin-content-docs/client'; import {useLayoutDoc} from '@docusaurus/theme-common'; import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem'; -import {getInfimaActiveClassName} from '@theme/NavbarItem/utils'; import type {Props} from '@theme/NavbarItem/DocNavbarItem'; export default function DocNavbarItem({ @@ -27,20 +25,14 @@ export default function DocNavbarItem({ return null; } - const activeDocInfimaClassName = getInfimaActiveClassName(props.mobile); - return ( + activeDoc?.path === doc.path || + (!!activeDoc?.sidebar && activeDoc.sidebar === doc.sidebar) + } label={staticLabel ?? doc.id} to={doc.path} /> diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocSidebarNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocSidebarNavbarItem.tsx index 874605bcf1a1..08771f8aa6c7 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocSidebarNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocSidebarNavbarItem.tsx @@ -6,11 +6,9 @@ */ import React from 'react'; -import clsx from 'clsx'; import {useActiveDocContext} from '@docusaurus/plugin-content-docs/client'; import {useLayoutDocsSidebar} from '@docusaurus/theme-common'; import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem'; -import {getInfimaActiveClassName} from '@theme/NavbarItem/utils'; import type {Props} from '@theme/NavbarItem/DocSidebarNavbarItem'; export default function DocSidebarNavbarItem({ @@ -26,16 +24,11 @@ export default function DocSidebarNavbarItem({ `DocSidebarNavbarItem: Sidebar with ID "${sidebarId}" doesn't have anything to be linked to.`, ); } - const activeDocInfimaClassName = getInfimaActiveClassName(props.mobile); - return ( activeDoc?.sidebar === sidebarId} label={label ?? sidebarLink.label} to={sidebarLink.path} /> diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx index 47903ce0aa35..8893306f7abd 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx @@ -41,7 +41,6 @@ export default function DocsVersionDropdownNavbarItem({ activeDocContext.alternateDocVersions[version.name] ?? getVersionMainDoc(version); return { - isNavLink: true, label: version.label, to: versionDoc.path, isActive: () => version === activeDocContext.activeVersion, diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx index 45c61dac60e7..3678d9d0bb03 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx @@ -21,8 +21,6 @@ import type { Props, } from '@theme/NavbarItem/DropdownNavbarItem'; -const dropdownLinkActiveClass = 'dropdown__link--active'; - function isItemActive( item: LinkLikeNavbarItemProps, localPathname: string, @@ -50,6 +48,7 @@ function DropdownNavbarItemDesktop({ items, position, className, + onClick, ...props }: DesktopOrMobileNavBarItemProps) { const dropdownRef = useRef(null); @@ -113,12 +112,12 @@ function DropdownNavbarItemDesktop({ ? nextNavbarItem : // Next item is another dropdown; focus on the inner // anchor element instead so there's outline - nextNavbarItem.querySelector('a'); - (targetItem as HTMLElement).focus(); + nextNavbarItem.querySelector('a')!; + targetItem.focus(); } } }} - activeClassName={dropdownLinkActiveClass} + activeClassName="dropdown__link--active" {...childItemProps} key={i} /> @@ -132,6 +131,7 @@ function DropdownNavbarItemMobile({ items, className, position, // Need to destructure position from props so that it doesn't get passed on. + onClick, ...props }: DesktopOrMobileNavBarItemProps) { const localPathname = useLocalPathname(); @@ -171,7 +171,7 @@ function DropdownNavbarItemMobile({ activeBaseRegex diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/utils.ts b/packages/docusaurus-theme-classic/src/theme/NavbarItem/utils.ts deleted file mode 100644 index a98db455f25e..000000000000 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* eslint-disable import/no-named-export */ - -export const getInfimaActiveClassName = ( - mobile?: boolean, -): `${'menu' | 'navbar'}__link--active` => - mobile ? 'menu__link--active' : 'navbar__link--active'; From 89ddc6d258d1ad8ddb48bf9760abeda38b12a931 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 26 May 2022 01:02:32 -0400 Subject: [PATCH 04/16] misc: avoid using fs.realpathSync in website (#7496) * dogfood fix * remove other mentions Co-authored-by: Joshua Chen --- website/_dogfooding/README.md | 1 - website/_dogfooding/docs-tests-symlink | 1 - website/_dogfooding/dogfooding.config.js | 8 ++------ 3 files changed, 2 insertions(+), 8 deletions(-) delete mode 120000 website/_dogfooding/docs-tests-symlink diff --git a/website/_dogfooding/README.md b/website/_dogfooding/README.md index 0b6ba0b479f0..8acadfac2e9b 100644 --- a/website/_dogfooding/README.md +++ b/website/_dogfooding/README.md @@ -11,7 +11,6 @@ Eventually, we could move these tests later so another test site? Note there is Fancy things we can test for here: - Plugin Multi-instance -- Symlinks support - Webpack configs - \_ prefix convention - Huge sidebars impact diff --git a/website/_dogfooding/docs-tests-symlink b/website/_dogfooding/docs-tests-symlink deleted file mode 120000 index 4a3222e9fd36..000000000000 --- a/website/_dogfooding/docs-tests-symlink +++ /dev/null @@ -1 +0,0 @@ -_docs tests \ No newline at end of file diff --git a/website/_dogfooding/dogfooding.config.js b/website/_dogfooding/dogfooding.config.js index 95c1d5161843..b6239f787b42 100644 --- a/website/_dogfooding/dogfooding.config.js +++ b/website/_dogfooding/dogfooding.config.js @@ -5,8 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -const fs = require('fs'); - /** @type {import('@docusaurus/types').PluginConfig[]} */ const dogfoodingThemeInstances = [ /** @type {import('@docusaurus/types').PluginModule} */ @@ -29,10 +27,8 @@ const dogfoodingPluginInstances = [ routeBasePath: '/tests/docs', sidebarPath: '_dogfooding/docs-tests-sidebars.js', - // Using a symlinked folder as source, test for use-case https://github.com/facebook/docusaurus/issues/3272 - // The target folder uses a _ prefix to test against an edge case regarding MDX partials: https://github.com/facebook/docusaurus/discussions/5181#discussioncomment-1018079 - // eslint-disable-next-line no-restricted-properties - path: fs.realpathSync('_dogfooding/docs-tests-symlink'), + // Using a _ prefix to test against an edge case regarding MDX partials: https://github.com/facebook/docusaurus/discussions/5181#discussioncomment-1018079 + path: '_dogfooding/_docs tests', showLastUpdateTime: true, sidebarItemsGenerator(args) { return args.defaultSidebarItemsGenerator({ From f94701569b35f8ee59a02580c60ff7c34acbb7b0 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 26 May 2022 03:06:22 -0400 Subject: [PATCH 05/16] fix: avoid printing period after localhost URL (#7499) * fix: output of URL * fix: adding formatting to start.ts --- packages/docusaurus/src/commands/serve.ts | 4 ++-- packages/docusaurus/src/commands/start.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/docusaurus/src/commands/serve.ts b/packages/docusaurus/src/commands/serve.ts index 64845cb5ced4..7777d448f734 100644 --- a/packages/docusaurus/src/commands/serve.ts +++ b/packages/docusaurus/src/commands/serve.ts @@ -76,8 +76,8 @@ export async function serve( }); }); - logger.success`Serving path=${buildDir} directory at url=${ + logger.success`Serving path=${buildDir} directory at: url=${ servingUrl + baseUrl - }.`; + }`; server.listen(port); } diff --git a/packages/docusaurus/src/commands/start.ts b/packages/docusaurus/src/commands/start.ts index a0cae8416493..f49874839d68 100644 --- a/packages/docusaurus/src/commands/start.ts +++ b/packages/docusaurus/src/commands/start.ts @@ -67,7 +67,7 @@ export async function start( const urls = prepareUrls(protocol, host, port); const openUrl = normalizeUrl([urls.localUrlForBrowser, baseUrl]); - logger.success`Docusaurus website is running at url=${openUrl}.`; + logger.success`Docusaurus website is running at: url=${openUrl}`; // Reload files processing. const reload = _.debounce(() => { @@ -75,7 +75,7 @@ export async function start( .then(({baseUrl: newBaseUrl}) => { const newOpenUrl = normalizeUrl([urls.localUrlForBrowser, newBaseUrl]); if (newOpenUrl !== openUrl) { - logger.success`Docusaurus website is running at url=${newOpenUrl}.`; + logger.success`Docusaurus website is running at: url=${newOpenUrl}`; } }) .catch((err: Error) => { From 4f97c7b52c5621af201a62912848b73ddcdf4b7a Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Thu, 26 May 2022 03:06:36 -0400 Subject: [PATCH 06/16] docs: link every reference of types in API table to the type definition (#7497) * dogfood fix * feat: links for plugin types * better syntax * little refactor * use code title * complete the rest Co-authored-by: Joshua Chen --- .../api/plugins/plugin-client-redirects.md | 12 ++++- .../docs/api/plugins/plugin-content-blog.md | 24 +++++++--- .../docs/api/plugins/plugin-content-docs.md | 48 +++++++++++++------ 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/website/docs/api/plugins/plugin-client-redirects.md b/website/docs/api/plugins/plugin-client-redirects.md index 3b881f58810a..991ea778ad91 100644 --- a/website/docs/api/plugins/plugin-client-redirects.md +++ b/website/docs/api/plugins/plugin-client-redirects.md @@ -41,17 +41,25 @@ Accepted fields: | --- | --- | --- | --- | | `fromExtensions` | `string[]` | `[]` | The extensions to be removed from the route after redirecting. | | `toExtensions` | `string[]` | `[]` | The extensions to be appended to the route after redirecting. | -| `redirects` | `RedirectRule[]` | `[]` | The list of redirect rules. | -| `createRedirects` | `CreateRedirectsFn` | `undefined` | A callback to create a redirect rule. | +| `redirects` | RedirectRule[] | `[]` | The list of redirect rules. | +| `createRedirects` | CreateRedirectsFn | `undefined` | A callback to create a redirect rule. | +### Types {#types} + +#### `RedirectRule` {#RedirectRule} + ```ts type RedirectRule = { to: string; from: string | string[]; }; +``` +#### `CreateRedirectsFn` {#CreateRedirectsFn} + +```ts type CreateRedirectsFn = (path: string) => string[] | string | null | undefined; ``` diff --git a/website/docs/api/plugins/plugin-content-blog.md b/website/docs/api/plugins/plugin-content-blog.md index 27db9055ecc6..8cdc51d7c668 100644 --- a/website/docs/api/plugins/plugin-content-blog.md +++ b/website/docs/api/plugins/plugin-content-blog.md @@ -38,7 +38,7 @@ Accepted fields: | Name | Type | Default | Description | | --- | --- | --- | --- | | `path` | `string` | `'blog'` | Path to the blog content directory on the file system, relative to site dir. | -| `editUrl` | string \| EditUrlFunction | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. | +| `editUrl` | string \| EditUrlFn | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. | | `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. | | `blogTitle` | `string` | `'Blog'` | Blog page title for better SEO. | | `blogDescription` | `string` | `'Blog'` | Blog page meta description for better SEO. | @@ -61,10 +61,10 @@ Accepted fields: | `beforeDefaultRehypePlugins` | `any[]` | `[]` | Custom Rehype plugins passed to MDX before the default Docusaurus Rehype plugins. | | `truncateMarker` | `RegExp` | `//` | Truncate marker marking where the summary ends. | | `showReadingTime` | `boolean` | `true` | Show estimated reading time for the blog post. | -| `readingTime` | `ReadingTimeFunctionOption` | The default reading time | A callback to customize the reading time number displayed. | +| `readingTime` | `ReadingTimeFn` | The default reading time | A callback to customize the reading time number displayed. | | `authorsMapPath` | `string` | `'authors.yml'` | Path to the authors map file, relative to the blog content directory. | | `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. | -| `feedOptions.type` | FeedType \| FeedType[] \| 'all' \| null | **Required** | Type of feed to be generated. Use `null` to disable generation. | +| `feedOptions.type` | FeedType \| FeedType[] \| 'all' \| null | **Required** | Type of feed to be generated. Use `null` to disable generation. | | `feedOptions.title` | `string` | `siteConfig.title` | Title of the feed. | | `feedOptions.description` | `string` | \`${siteConfig.title} Blog\` | Description of the feed. | | `feedOptions.copyright` | `string` | `undefined` | Copyright message. | @@ -73,6 +73,10 @@ Accepted fields: +### Types {#types} + +#### `EditUrlFn` {#EditUrlFn} + ```ts type EditUrlFunction = (params: { blogDirPath: string; @@ -80,24 +84,32 @@ type EditUrlFunction = (params: { permalink: string; locale: string; }) => string | undefined; +``` + +#### `ReadingTimeFn` {#ReadingTimeFn} +```ts type ReadingTimeOptions = { wordsPerMinute: number; wordBound: (char: string) => boolean; }; -type ReadingTimeFunction = (params: { +type ReadingTimeCalculator = (params: { content: string; frontMatter?: BlogPostFrontMatter & Record; options?: ReadingTimeOptions; }) => number; -type ReadingTimeFunctionOption = (params: { +type ReadingTimeFn = (params: { content: string; frontMatter: BlogPostFrontMatter & Record; - defaultReadingTime: ReadingTimeFunction; + defaultReadingTime: ReadingTimeCalculator; }) => number | undefined; +``` +#### `FeedType` {#FeedType} + +```ts type FeedType = 'rss' | 'atom' | 'json'; ``` diff --git a/website/docs/api/plugins/plugin-content-docs.md b/website/docs/api/plugins/plugin-content-docs.md index 331c7cb0a9f9..a44ce3ca1a5a 100644 --- a/website/docs/api/plugins/plugin-content-docs.md +++ b/website/docs/api/plugins/plugin-content-docs.md @@ -32,7 +32,7 @@ Accepted fields: | Name | Type | Default | Description | | --- | --- | --- | --- | | `path` | `string` | `'docs'` | Path to the docs content directory on the file system, relative to site directory. | -| `editUrl` | string \| EditUrlFunction | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. | +| `editUrl` | string \| EditUrlFunction | `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativeDocPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. | | `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. | | `editCurrentVersion` | `boolean` | `false` | The edit URL will always target the current version doc instead of older versions. Ignored when `editUrl` is a function. | | `routeBasePath` | `string` | `'docs'` | URL route for the docs section of your site. **DO NOT** include a trailing slash. Use `/` for shipping docs without base path. | @@ -42,8 +42,8 @@ Accepted fields: | `sidebarPath` | false \| string | `undefined` | Path to sidebar configuration. Use `false` to disable sidebars, or `undefined` to create a fully autogenerated sidebar. | | `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. See also [Collapsible categories](/docs/sidebar#collapsible-categories) | | `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. See also [Expanded categories by default](/docs/sidebar#expanded-categories-by-default) | -| `sidebarItemsGenerator` | `SidebarGenerator` | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) | -| `numberPrefixParser` | boolean \| PrefixParser | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar#using-number-prefixes) | +| `sidebarItemsGenerator` | SidebarGenerator | _Omitted_ | Function used to replace the sidebar items of type `'autogenerated'` with real sidebar items (docs, categories, links...). See also [Customize the sidebar items generator](/docs/sidebar#customize-the-sidebar-items-generator) | +| `numberPrefixParser` | boolean \| PrefixParser | _Omitted_ | Custom parsing logic to extract number prefixes from file names. Use `false` to disable this behavior and leave the docs untouched, and `true` to use the default parser. See also [Using number prefixes](/docs/sidebar#using-number-prefixes) | | `docLayoutComponent` | `string` | `'@theme/DocPage'` | Root layout component of each doc page. Provides the version data context, and is not unmounted when switching docs. | | `docItemComponent` | `string` | `'@theme/DocItem'` | Main doc container, with TOC, pagination, etc. | | `docTagsListComponent` | `string` | `'@theme/DocTagsListPage'` | Root component of the tags list page | @@ -60,10 +60,14 @@ Accepted fields: | `includeCurrentVersion` | `boolean` | `true` | Include the current version of your docs. | | `lastVersion` | `string` | First version in `versions.json` | The version navigated to in priority and displayed by default for docs navbar items. | | `onlyIncludeVersions` | `string[]` | All versions available | Only include a subset of all available versions. | -| `versions` | `VersionsConfig` | `{}` | Independent customization of each version's properties. | +| `versions` | VersionsConfig | `{}` | Independent customization of each version's properties. | +### Types {#types} + +#### `EditUrlFunction` {#EditUrlFunction} + ```ts type EditUrlFunction = (params: { version: string; @@ -72,24 +76,20 @@ type EditUrlFunction = (params: { permalink: string; locale: string; }) => string | undefined; +``` +#### `PrefixParser` {#PrefixParser} + +```ts type PrefixParser = (filename: string) => { filename: string; numberPrefix?: number; }; +``` -type CategoryIndexMatcher = (param: { - /** The file name, without extension */ - fileName: string; - /** - * The list of directories, from lowest level to highest. - * If there's no dir name, directories is ['.'] - */ - directories: string[]; - /** The extension, with a leading dot */ - extension: string; -}) => boolean; +#### `SidebarGenerator` {#SidebarGenerator} +```ts type SidebarGenerator = (generatorArgs: { /** The sidebar item with type "autogenerated" to be transformed. */ item: {type: 'autogenerated'; dirName: string}; @@ -118,8 +118,26 @@ type SidebarGenerator = (generatorArgs: { * Docusaurus. */ defaultSidebarItemsGenerator: SidebarGenerator; + // Returns an array of sidebar items — same as what you can declare in + // sidebars.js, except for shorthands. See https://docusaurus.io/docs/sidebar/items }) => Promise; +type CategoryIndexMatcher = (param: { + /** The file name, without extension */ + fileName: string; + /** + * The list of directories, from lowest level to highest. + * If there's no dir name, directories is ['.'] + */ + directories: string[]; + /** The extension, with a leading dot */ + extension: string; +}) => boolean; +``` + +#### `VersionsConfig` {#VersionsConfig} + +```ts type VersionsConfig = { [versionName: string]: { /** From 47a2cca17df1c83638b421da6b77c3b9faa4dbef Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 26 May 2022 17:44:18 +0800 Subject: [PATCH 07/16] chore: require Node 16.14 (#7501) --- .github/workflows/tests-e2e.yml | 2 +- .github/workflows/tests-windows.yml | 2 +- .github/workflows/tests.yml | 2 +- .nvmrc | 2 +- packages/create-docusaurus/package.json | 2 +- packages/docusaurus-cssnano-preset/package.json | 3 +++ packages/docusaurus-logger/package.json | 2 +- packages/docusaurus-mdx-loader/package.json | 2 +- packages/docusaurus-migrate/package.json | 2 +- packages/docusaurus-plugin-client-redirects/package.json | 2 +- packages/docusaurus-plugin-content-blog/package.json | 2 +- packages/docusaurus-plugin-content-docs/package.json | 2 +- packages/docusaurus-plugin-content-pages/package.json | 2 +- packages/docusaurus-plugin-debug/package.json | 2 +- packages/docusaurus-plugin-google-analytics/package.json | 2 +- packages/docusaurus-plugin-google-gtag/package.json | 2 +- packages/docusaurus-plugin-ideal-image/package.json | 2 +- packages/docusaurus-plugin-pwa/package.json | 3 +++ packages/docusaurus-plugin-sitemap/package.json | 2 +- packages/docusaurus-preset-classic/package.json | 2 +- packages/docusaurus-remark-plugin-npm2yarn/package.json | 2 +- packages/docusaurus-theme-classic/package.json | 2 +- packages/docusaurus-theme-common/package.json | 2 +- packages/docusaurus-theme-live-codeblock/package.json | 2 +- packages/docusaurus-theme-search-algolia/package.json | 2 +- packages/docusaurus-theme-translations/package.json | 2 +- packages/docusaurus-utils-common/package.json | 2 +- packages/docusaurus-utils-validation/package.json | 2 +- packages/docusaurus-utils/package.json | 2 +- packages/docusaurus/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/lqip-loader/package.json | 2 +- website/docs/installation.md | 2 +- 33 files changed, 37 insertions(+), 31 deletions(-) diff --git a/.github/workflows/tests-e2e.yml b/.github/workflows/tests-e2e.yml index f10f08f65786..92b9f5319f84 100644 --- a/.github/workflows/tests-e2e.yml +++ b/.github/workflows/tests-e2e.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: ['14', '16', '18'] + node: ['16.14', '16', '18'] steps: - name: Checkout uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3 diff --git a/.github/workflows/tests-windows.yml b/.github/workflows/tests-windows.yml index 186833e7d080..d4dbaef8da9f 100644 --- a/.github/workflows/tests-windows.yml +++ b/.github/workflows/tests-windows.yml @@ -22,7 +22,7 @@ jobs: runs-on: windows-latest strategy: matrix: - node: ['14', '16', '18'] + node: ['16.14', '16', '18'] steps: - name: Support longpaths run: git config --system core.longpaths true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a078a2bf3639..502a4812fd64 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: ['14', '16', '18'] + node: ['16.14', '16', '18'] steps: - name: Checkout uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3 diff --git a/.nvmrc b/.nvmrc index 832d38506443..3c032078a4a2 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16.14.0 +18 diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json index d7a60dba1c13..46ae2253e1b4 100755 --- a/packages/create-docusaurus/package.json +++ b/packages/create-docusaurus/package.json @@ -36,6 +36,6 @@ "@types/supports-color": "^8.1.1" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-cssnano-preset/package.json b/packages/docusaurus-cssnano-preset/package.json index 6469eba2405a..aec575bf1c3b 100644 --- a/packages/docusaurus-cssnano-preset/package.json +++ b/packages/docusaurus-cssnano-preset/package.json @@ -24,5 +24,8 @@ }, "devDependencies": { "to-vfile": "^6.1.0" + }, + "engines": { + "node": ">=16.14" } } diff --git a/packages/docusaurus-logger/package.json b/packages/docusaurus-logger/package.json index 6c91e0d029ec..2c6dcab1b1c8 100644 --- a/packages/docusaurus-logger/package.json +++ b/packages/docusaurus-logger/package.json @@ -24,7 +24,7 @@ "tslib": "^2.4.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" }, "devDependencies": { "@types/supports-color": "^8.1.1" diff --git a/packages/docusaurus-mdx-loader/package.json b/packages/docusaurus-mdx-loader/package.json index b071b9732ba3..36e190295f02 100644 --- a/packages/docusaurus-mdx-loader/package.json +++ b/packages/docusaurus-mdx-loader/package.json @@ -52,6 +52,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-migrate/package.json b/packages/docusaurus-migrate/package.json index 9d43bdcf7a73..2102cac885c8 100644 --- a/packages/docusaurus-migrate/package.json +++ b/packages/docusaurus-migrate/package.json @@ -4,7 +4,7 @@ "description": "A CLI tool to migrate from older versions of Docusaurus.", "license": "MIT", "engines": { - "node": ">=14" + "node": ">=16.14" }, "scripts": { "build": "tsc --build", diff --git a/packages/docusaurus-plugin-client-redirects/package.json b/packages/docusaurus-plugin-client-redirects/package.json index 426d13b139d2..b0a378708339 100644 --- a/packages/docusaurus-plugin-client-redirects/package.json +++ b/packages/docusaurus-plugin-client-redirects/package.json @@ -36,6 +36,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json index 5d0dbade229e..85ce797f5e6e 100644 --- a/packages/docusaurus-plugin-content-blog/package.json +++ b/packages/docusaurus-plugin-content-blog/package.json @@ -44,6 +44,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index bf59cd020096..0a49a06e77ec 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -56,6 +56,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index 4e8e2eb7edf5..4ec059c3cfef 100644 --- a/packages/docusaurus-plugin-content-pages/package.json +++ b/packages/docusaurus-plugin-content-pages/package.json @@ -35,6 +35,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-debug/package.json b/packages/docusaurus-plugin-debug/package.json index 3382fcab737a..98f9c72f08cf 100644 --- a/packages/docusaurus-plugin-debug/package.json +++ b/packages/docusaurus-plugin-debug/package.json @@ -34,6 +34,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-google-analytics/package.json b/packages/docusaurus-plugin-google-analytics/package.json index f62db432005c..d97f66f979a6 100644 --- a/packages/docusaurus-plugin-google-analytics/package.json +++ b/packages/docusaurus-plugin-google-analytics/package.json @@ -30,6 +30,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-google-gtag/package.json b/packages/docusaurus-plugin-google-gtag/package.json index c353d7a1a28c..146b913d71da 100644 --- a/packages/docusaurus-plugin-google-gtag/package.json +++ b/packages/docusaurus-plugin-google-gtag/package.json @@ -30,6 +30,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-ideal-image/package.json b/packages/docusaurus-plugin-ideal-image/package.json index 5bda29fd0203..582127cb4bc9 100644 --- a/packages/docusaurus-plugin-ideal-image/package.json +++ b/packages/docusaurus-plugin-ideal-image/package.json @@ -47,6 +47,6 @@ } }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-pwa/package.json b/packages/docusaurus-plugin-pwa/package.json index f47075267b29..429ae3f1b186 100644 --- a/packages/docusaurus-plugin-pwa/package.json +++ b/packages/docusaurus-plugin-pwa/package.json @@ -45,5 +45,8 @@ "peerDependencies": { "react": "^16.8.4 || ^17.0.0", "react-dom": "^16.8.4 || ^17.0.0" + }, + "engines": { + "node": ">=16.14" } } diff --git a/packages/docusaurus-plugin-sitemap/package.json b/packages/docusaurus-plugin-sitemap/package.json index deabe52f3741..f6fd11b8921b 100644 --- a/packages/docusaurus-plugin-sitemap/package.json +++ b/packages/docusaurus-plugin-sitemap/package.json @@ -35,6 +35,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-preset-classic/package.json b/packages/docusaurus-preset-classic/package.json index 310a920bf4db..40a209675956 100644 --- a/packages/docusaurus-preset-classic/package.json +++ b/packages/docusaurus-preset-classic/package.json @@ -35,6 +35,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-remark-plugin-npm2yarn/package.json b/packages/docusaurus-remark-plugin-npm2yarn/package.json index a47e1de9c9e0..0c9c44fdc3a2 100644 --- a/packages/docusaurus-remark-plugin-npm2yarn/package.json +++ b/packages/docusaurus-remark-plugin-npm2yarn/package.json @@ -28,6 +28,6 @@ "to-vfile": "^6.1.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 577babee2892..9439db4a2c40 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -58,6 +58,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json index ff097aa08e95..9e0208c32eb4 100644 --- a/packages/docusaurus-theme-common/package.json +++ b/packages/docusaurus-theme-common/package.json @@ -49,6 +49,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-theme-live-codeblock/package.json b/packages/docusaurus-theme-live-codeblock/package.json index f107b6b8b302..4454d741c479 100644 --- a/packages/docusaurus-theme-live-codeblock/package.json +++ b/packages/docusaurus-theme-live-codeblock/package.json @@ -42,6 +42,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-theme-search-algolia/package.json b/packages/docusaurus-theme-search-algolia/package.json index 6ec7ab36203a..518e0836e599 100644 --- a/packages/docusaurus-theme-search-algolia/package.json +++ b/packages/docusaurus-theme-search-algolia/package.json @@ -52,6 +52,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-theme-translations/package.json b/packages/docusaurus-theme-translations/package.json index a296a446f3eb..5b10cbf18e24 100644 --- a/packages/docusaurus-theme-translations/package.json +++ b/packages/docusaurus-theme-translations/package.json @@ -28,6 +28,6 @@ "lodash": "^4.17.21" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-utils-common/package.json b/packages/docusaurus-utils-common/package.json index 31f9a3fcd0c8..9bdb0b8d122c 100644 --- a/packages/docusaurus-utils-common/package.json +++ b/packages/docusaurus-utils-common/package.json @@ -25,6 +25,6 @@ "@docusaurus/types": "2.0.0-beta.20" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-utils-validation/package.json b/packages/docusaurus-utils-validation/package.json index a112ef5797c4..9059249d9b04 100644 --- a/packages/docusaurus-utils-validation/package.json +++ b/packages/docusaurus-utils-validation/package.json @@ -25,6 +25,6 @@ "tslib": "^2.4.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json index 36dd648ff13d..4a460a57d648 100644 --- a/packages/docusaurus-utils/package.json +++ b/packages/docusaurus-utils/package.json @@ -35,7 +35,7 @@ "webpack": "^5.72.1" }, "engines": { - "node": ">=14" + "node": ">=16.14" }, "devDependencies": { "@docusaurus/types": "2.0.0-beta.20", diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index 9c2ead275092..664fd9977dbd 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -126,6 +126,6 @@ "react-dom": "^16.8.4 || ^17.0.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 8bd7a9494539..8dca637d064b 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -31,6 +31,6 @@ "eslint": ">=6" }, "engines": { - "node": ">=14" + "node": ">=16.14" } } diff --git a/packages/lqip-loader/package.json b/packages/lqip-loader/package.json index 5e96bac253fe..1311e978db16 100644 --- a/packages/lqip-loader/package.json +++ b/packages/lqip-loader/package.json @@ -24,7 +24,7 @@ "tslib": "^2.4.0" }, "engines": { - "node": ">=14" + "node": ">=16.14" }, "devDependencies": { "@types/file-loader": "^5.0.1", diff --git a/website/docs/installation.md b/website/docs/installation.md index 90c16645303a..92576624eec1 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -20,7 +20,7 @@ Use **[docusaurus.new](https://docusaurus.new)** to test Docusaurus immediately ## Requirements {#requirements} -- [Node.js](https://nodejs.org/en/download/) version 14.13 or above (which can be checked by running `node -v`). You can use [nvm](https://github.com/nvm-sh/nvm) for managing multiple Node versions on a single machine installed. +- [Node.js](https://nodejs.org/en/download/) version 16.14 or above (which can be checked by running `node -v`). You can use [nvm](https://github.com/nvm-sh/nvm) for managing multiple Node versions on a single machine installed. - When installing Node.js, you are recommended to check all checkboxes related to dependencies. ## Scaffold project website {#scaffold-project-website} From 309a7e8bd4bd46d8b6aa99a39b091df6ee3fd071 Mon Sep 17 00:00:00 2001 From: Massoud Maboudi Date: Thu, 26 May 2022 18:38:14 +0800 Subject: [PATCH 08/16] docs: add Massoud Maboudi's portfolio to showcase (#7412) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: add Massoud Maboudi's portfolio to showcase * optimize image * Update website/src/data/users.tsx Co-authored-by: Joshua Chen Co-authored-by: Sébastien Lorber --- website/src/data/showcase/iammassoud.png | Bin 0 -> 18166 bytes website/src/data/users.tsx | 8 ++++++++ 2 files changed, 8 insertions(+) create mode 100644 website/src/data/showcase/iammassoud.png diff --git a/website/src/data/showcase/iammassoud.png b/website/src/data/showcase/iammassoud.png new file mode 100644 index 0000000000000000000000000000000000000000..e31b3126ed60886aa9fe76a0ae13e6f11084f31a GIT binary patch literal 18166 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 literal 0 HcmV?d00001 diff --git a/website/src/data/users.tsx b/website/src/data/users.tsx index 88e6dffe9df8..2e78d627d001 100644 --- a/website/src/data/users.tsx +++ b/website/src/data/users.tsx @@ -886,6 +886,14 @@ const Users: User[] = [ source: 'https://github.com/ggicci/httpin/tree/documentation/docs', tags: ['opensource'], }, + { + title: 'I am Massoud', + description: 'The portfolio of Massoud Maboudi, Full Stack Developer', + preview: require('./showcase/iammassoud.png'), + website: 'https://iammassoud.ir/', + source: null, + tags: ['personal', 'rtl'], + }, { title: 'icodex', description: 'Front end engineer personal website', From e955ae472da3264db45980c0cfd6a943651cce17 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 26 May 2022 18:41:23 +0800 Subject: [PATCH 09/16] fix(theme-classic): allow nested task lists to preserve the indent (#7438) * fix(theme-classic): allow nested task lists to preserve the indent * add Ul back --- .../MDXComponents/{Ul.tsx => Ul/index.tsx} | 6 ++-- .../theme/MDXComponents/Ul/styles.module.css | 14 ++++++++ .../_pages tests/markdownPageTests.md | 32 +++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) rename packages/docusaurus-theme-classic/src/theme/MDXComponents/{Ul.tsx => Ul/index.tsx} (78%) create mode 100644 packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul/styles.module.css diff --git a/packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul.tsx b/packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul/index.tsx similarity index 78% rename from packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul.tsx rename to packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul/index.tsx index 080ecaac2a1a..d426298f6a8d 100644 --- a/packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul.tsx +++ b/packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul/index.tsx @@ -9,13 +9,15 @@ import React from 'react'; import clsx from 'clsx'; import type {Props} from '@theme/MDXComponents/Ul'; +import styles from './styles.module.css'; + function transformUlClassName(className?: string): string { return clsx( className, // This class is set globally by GitHub/MDX. We keep the global class, and - // add another Infima class to get list without styling + // add another class to get a task list without the default ul styling // See https://github.com/syntax-tree/mdast-util-to-hast/issues/28 - className?.includes('contains-task-list') && 'clean-list', + className?.includes('contains-task-list') && styles.containsTaskList, ); } diff --git a/packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul/styles.module.css b/packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul/styles.module.css new file mode 100644 index 000000000000..c1d9c4f95dbd --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/MDXComponents/Ul/styles.module.css @@ -0,0 +1,14 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.containsTaskList { + list-style: none; +} + +:not(.containsTaskList > li) > .containsTaskList { + padding-left: 0; +} diff --git a/website/_dogfooding/_pages tests/markdownPageTests.md b/website/_dogfooding/_pages tests/markdownPageTests.md index ca7e9fcff7d2..dc8695b11179 100644 --- a/website/_dogfooding/_pages tests/markdownPageTests.md +++ b/website/_dogfooding/_pages tests/markdownPageTests.md @@ -189,3 +189,35 @@ This is a fragment: <>Hello It should work :) + +## Task list + +A list: + +- [ ] Simple +- [x] Tasks +- [ ] Has simple +- [ ] Styles + +Another list: + +- Nested + - [ ] Tasks + - [ ] Should be well-formatted +- [ ] No matter +- [ ] How weird + +Can be arbitrarily nested: + +- Level + - [ ] Task + - [ ] Task + - Another level + - [ ] Task + - [ ] Task + - Deeper + - [ ] Task + - [ ] Task + - [ ] Task + - [ ] Task +- [ ] Task From 9cf2bf11997eb6341af5fc5c7031ade849c42235 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Thu, 26 May 2022 19:05:03 +0800 Subject: [PATCH 10/16] fix(core): always treat error boundary fallback as a callback (#7492) Co-authored-by: sebastienlorber --- .../src/index.d.ts | 23 +++++++++---------- .../src/theme/Layout/index.tsx | 4 +++- packages/docusaurus/src/client/App.tsx | 4 +--- .../src/client/exports/ErrorBoundary.tsx | 22 +++++++++++++----- website/docs/docusaurus-core.md | 8 ++++++- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 3a900c907d77..c8f2c995f012 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -77,14 +77,9 @@ declare module '@theme-original/*'; declare module '@theme-init/*'; declare module '@theme/Error' { - import type {ComponentProps} from 'react'; - import type ErrorBoundary from '@docusaurus/ErrorBoundary'; + import type {FallbackParams} from '@docusaurus/ErrorBoundary'; - type ErrorProps = ComponentProps< - NonNullable['fallback']> - >; - - export interface Props extends ErrorProps {} + export interface Props extends FallbackParams {} export default function Error(props: Props): JSX.Element; } @@ -125,13 +120,17 @@ declare module '@docusaurus/constants' { } declare module '@docusaurus/ErrorBoundary' { - import type {ReactNode, ComponentType} from 'react'; + import type {ReactNode} from 'react'; + + export type FallbackParams = { + readonly error: Error; + readonly tryAgain: () => void; + }; + + export type FallbackFunction = (params: FallbackParams) => JSX.Element; export interface Props { - readonly fallback?: ComponentType<{ - readonly error: Error; - readonly tryAgain: () => void; - }>; + readonly fallback?: FallbackFunction; readonly children: ReactNode; } export default function ErrorBoundary(props: Props): JSX.Element; diff --git a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx index c5503edcaaa2..7f58712af95c 100644 --- a/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Layout/index.tsx @@ -45,7 +45,9 @@ export default function Layout(props: Props): JSX.Element {
- {children} + }> + {children} +
{!noFooter &&