diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap index 7e67c5144d..12d628cea5 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap @@ -514,7 +514,7 @@ Object { \\"pluginId\\": \\"default\\", \\"version\\": \\"current\\", \\"label\\": \\"Next\\", - \\"banner\\": \\"none\\", + \\"banner\\": null, \\"badge\\": false, \\"className\\": \\"docs-version-current\\", \\"isLast\\": true, @@ -1025,7 +1025,7 @@ Object { \\"pluginId\\": \\"community\\", \\"version\\": \\"1.0.0\\", \\"label\\": \\"1.0.0\\", - \\"banner\\": \\"none\\", + \\"banner\\": null, \\"badge\\": true, \\"className\\": \\"docs-version-1.0.0\\", \\"isLast\\": true, @@ -1722,7 +1722,7 @@ Object { \\"pluginId\\": \\"default\\", \\"version\\": \\"1.0.1\\", \\"label\\": \\"1.0.1\\", - \\"banner\\": \\"none\\", + \\"banner\\": null, \\"badge\\": true, \\"className\\": \\"docs-version-1.0.1\\", \\"isLast\\": true, diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/versions.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/versions.test.ts index 0fad9a9217..fbf427889e 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/versions.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/versions.test.ts @@ -81,7 +81,7 @@ describe('simple site', () => { versionLabel: 'Next', versionName: 'current', versionPath: '/docs', - versionBanner: 'none', + versionBanner: null, versionBadge: false, versionClassName: 'docs-version-current', }; @@ -262,7 +262,7 @@ describe('versioned site, pluginId=default', () => { versionLabel: '1.0.1', versionName: '1.0.1', versionPath: '/docs', - versionBanner: 'none', + versionBanner: null, versionBadge: true, versionClassName: 'docs-version-1.0.1', }; @@ -554,7 +554,7 @@ describe('versioned site, pluginId=default', () => { routePriority: -1, tagsPath: '/docs/tags', versionPath: '/docs', - versionBanner: 'none', + versionBanner: null, versionBadge: false, }, ]); @@ -702,7 +702,7 @@ describe('versioned site, pluginId=community', () => { versionLabel: '1.0.0', versionName: '1.0.0', versionPath: '/communityBasePath', - versionBanner: 'none', + versionBanner: null, versionBadge: true, versionClassName: 'docs-version-1.0.0', }; @@ -750,7 +750,7 @@ describe('versioned site, pluginId=community', () => { routePriority: -1, tagsPath: '/communityBasePath/tags', versionPath: '/communityBasePath', - versionBanner: 'none', + versionBanner: null, versionBadge: false, }, ]); diff --git a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts index 9972e6a96b..4c0495de73 100644 --- a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts +++ b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts @@ -11,7 +11,7 @@ declare module '@docusaurus/plugin-content-docs' { // TODO public api surface types should rather be exposed as "@docusaurus/plugin-content-docs" declare module '@docusaurus/plugin-content-docs-types' { - type VersionBanner = import('./types').VersionBanner; + export type VersionBanner = import('./types').VersionBanner; type GlobalDataVersion = import('./types').GlobalVersion; type GlobalDataDoc = import('./types').GlobalDoc; type VersionTag = import('./types').VersionTag; @@ -22,7 +22,7 @@ declare module '@docusaurus/plugin-content-docs-types' { pluginId: string; version: string; label: string; - banner: VersionBanner; + banner: VersionBanner | null; badge: boolean; className: string; isLast: boolean; diff --git a/packages/docusaurus-plugin-content-docs/src/types.ts b/packages/docusaurus-plugin-content-docs/src/types.ts index 089b5bf84c..16f977883c 100644 --- a/packages/docusaurus-plugin-content-docs/src/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/types.ts @@ -32,7 +32,7 @@ export type VersionMetadata = ContentPaths & { tagsPath: string; versionEditUrl?: string | undefined; versionEditUrlLocalized?: string | undefined; - versionBanner: VersionBanner; + versionBanner: VersionBanner | null; versionBadge: boolean; versionClassName: string; isLast: boolean; @@ -65,12 +65,12 @@ export type PathOptions = { }; // TODO support custom version banner? {type: "error", content: "html content"} -export type VersionBanner = 'none' | 'unreleased' | 'unmaintained'; +export type VersionBanner = 'unreleased' | 'unmaintained'; export type VersionOptions = { path?: string; label?: string; - banner?: VersionBanner; + banner?: 'none' | VersionBanner; badge?: boolean; className?: string; }; diff --git a/packages/docusaurus-plugin-content-docs/src/versions.ts b/packages/docusaurus-plugin-content-docs/src/versions.ts index d73b26faf5..b4de0af428 100644 --- a/packages/docusaurus-plugin-content-docs/src/versions.ts +++ b/packages/docusaurus-plugin-content-docs/src/versions.ts @@ -264,10 +264,10 @@ function getDefaultVersionBanner({ versionName: string; versionNames: string[]; lastVersionName: string; -}): VersionBanner { +}): VersionBanner | null { // Current version: good, no banner if (versionName === lastVersionName) { - return 'none'; + return null; } // Upcoming versions: unreleased banner else if ( @@ -291,17 +291,16 @@ function getVersionBanner({ versionNames: string[]; lastVersionName: string; options: Pick; -}): VersionBanner { - const versionOptionBanner = options.versions[versionName]?.banner; - - return ( - versionOptionBanner ?? - getDefaultVersionBanner({ - versionName, - versionNames, - lastVersionName, - }) - ); +}): VersionBanner | null { + const versionBannerOption = options.versions[versionName]?.banner; + if (versionBannerOption) { + return versionBannerOption === 'none' ? null : versionBannerOption; + } + return getDefaultVersionBanner({ + versionName, + versionNames, + lastVersionName, + }); } function getVersionBadge({ diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 0f3cf69a75..17b7d1c135 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -51,7 +51,9 @@ }, "devDependencies": { "@docusaurus/module-type-aliases": "2.0.0-beta.5", + "@types/mdx-js__react": "^1.5.4", "@types/parse-numeric-range": "^0.0.1", + "@types/rtlcss": "^3.1.1", "utility-types": "^3.10.0" }, "peerDependencies": { diff --git a/packages/docusaurus-theme-classic/src/index.ts b/packages/docusaurus-theme-classic/src/index.ts index 7bf65db0f2..3097fe6cfa 100644 --- a/packages/docusaurus-theme-classic/src/index.ts +++ b/packages/docusaurus-theme-classic/src/index.ts @@ -10,7 +10,7 @@ import type {ThemeConfig} from '@docusaurus/theme-common'; import {getTranslationFiles, translateThemeConfig} from './translations'; import path from 'path'; import Module from 'module'; -import type {AcceptedPlugin, Result, Plugin as PostCssPlugin} from 'postcss'; +import type {AcceptedPlugin, Plugin as PostCssPlugin} from 'postcss'; import rtlcss from 'rtlcss'; import {readDefaultCodeTranslationMessages} from '@docusaurus/utils'; @@ -25,7 +25,10 @@ const ContextReplacementPlugin = requireFromDocusaurusCore( // Need to be inlined to prevent dark mode FOUC // Make sure that the 'storageKey' is the same as the one in `/theme/hooks/useTheme.js` const ThemeStorageKey = 'theme'; -const noFlashColorMode = ({defaultMode, respectPrefersColorScheme}) => { +const noFlashColorMode = ({ + defaultMode, + respectPrefersColorScheme, +}: ThemeConfig['colorMode']) => { return `(function() { var defaultMode = '${defaultMode}'; var respectPrefersColorScheme = ${respectPrefersColorScheme}; @@ -83,7 +86,7 @@ const AnnouncementBarInlineJavaScript = ` document.documentElement.setAttribute('${AnnouncementBarDismissDataAttribute}', isDismissed()); })();`; -function getInfimaCSSFile(direction) { +function getInfimaCSSFile(direction: string) { return `infima/dist/css/default/default${ direction === 'rtl' ? '-rtl' : '' }.css`; @@ -183,13 +186,13 @@ export default function docusaurusThemeClassic( const resolvedInfimaFile = require.resolve(getInfimaCSSFile(direction)); const plugin: PostCssPlugin = { postcssPlugin: 'RtlCssPlugin', - prepare: (result: Result) => { + prepare: (result) => { const file = result.root?.source?.input?.file; // Skip Infima as we are using the its RTL version. if (file === resolvedInfimaFile) { return {}; } - return rtlcss(result.root); + return rtlcss((result.root as unknown) as rtlcss.ConfigOptions); }, }; postCssOptions.plugins.push(plugin); diff --git a/packages/docusaurus-theme-classic/src/prism-include-languages.js b/packages/docusaurus-theme-classic/src/prism-include-languages.ts similarity index 100% rename from packages/docusaurus-theme-classic/src/prism-include-languages.js rename to packages/docusaurus-theme-classic/src/prism-include-languages.ts diff --git a/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx b/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx index 086186bb8b..65383d93e3 100644 --- a/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/CodeBlock/index.tsx @@ -18,49 +18,61 @@ import styles from './styles.module.css'; import {useThemeConfig, parseCodeBlockTitle} from '@docusaurus/theme-common'; -const highlightLinesRangeRegex = /{([\d,-]+)}/; +const HighlightLinesRangeRegex = /{([\d,-]+)}/; + +const HighlightLanguages = ['js', 'jsBlock', 'jsx', 'python', 'html'] as const; +type HighlightLanguage = typeof HighlightLanguages[number]; + +type HighlightLanguageConfig = { + start: string; + end: string; +}; + +// Supported types of highlight comments +const HighlightComments: Record = { + js: { + start: '\\/\\/', + end: '', + }, + jsBlock: { + start: '\\/\\*', + end: '\\*\\/', + }, + jsx: { + start: '\\{\\s*\\/\\*', + end: '\\*\\/\\s*\\}', + }, + python: { + start: '#', + end: '', + }, + html: { + start: '', + }, +}; + +// Supported highlight directives +const HighlightDirectives = [ + 'highlight-next-line', + 'highlight-start', + 'highlight-end', +]; + const getHighlightDirectiveRegex = ( - languages = ['js', 'jsBlock', 'jsx', 'python', 'html'], + languages: readonly HighlightLanguage[] = HighlightLanguages, ) => { - // supported types of comments - const comments = { - js: { - start: '\\/\\/', - end: '', - }, - jsBlock: { - start: '\\/\\*', - end: '\\*\\/', - }, - jsx: { - start: '\\{\\s*\\/\\*', - end: '\\*\\/\\s*\\}', - }, - python: { - start: '#', - end: '', - }, - html: { - start: '', - }, - }; - // supported directives - const directives = [ - 'highlight-next-line', - 'highlight-start', - 'highlight-end', - ].join('|'); // to be more reliable, the opening and closing comment must match const commentPattern = languages - .map( - (lang) => - `(?:${comments[lang].start}\\s*(${directives})\\s*${comments[lang].end})`, - ) + .map((lang) => { + const {start, end} = HighlightComments[lang]; + return `(?:${start}\\s*(${HighlightDirectives.join('|')})\\s*${end})`; + }) .join('|'); // white space is allowed, but otherwise it should be on it's own line return new RegExp(`^\\s*(?:${commentPattern})\\s*$`); }; + // select comment styles based on language const highlightDirectiveRegex = (lang: string) => { switch (lang) { @@ -123,9 +135,9 @@ export default function CodeBlock({ ? children.join('') : (children as string); - if (metastring && highlightLinesRangeRegex.test(metastring)) { + if (metastring && HighlightLinesRangeRegex.test(metastring)) { // Tested above - const highlightLinesRange = metastring.match(highlightLinesRangeRegex)![1]; + const highlightLinesRange = metastring.match(HighlightLinesRangeRegex)![1]; highlightLines = rangeParser(highlightLinesRange).filter((n) => n > 0); } diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx index 702e7a54ca..fd5f3fe331 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx @@ -35,7 +35,7 @@ function useShowAnnouncementBar() { return showAnnouncementBar; } -function HideableSidebarButton({onClick}) { +function HideableSidebarButton({onClick}: {onClick: React.MouseEventHandler}) { return (