From 29d19a688458eac5fa5b291604722901d586b232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 10 Apr 2025 15:55:02 +0200 Subject: [PATCH 1/8] refactor(live-codeblock): refactor live code block theme components (#11077) --- .../src/remark/mdx1Compat/codeCompatPlugin.ts | 1 + .../src/utils/useThemeConfig.ts | 1 + .../src/theme-live-codeblock.d.ts | 66 +++++++++ .../src/theme/CodeBlock/index.tsx | 35 +++-- .../src/theme/LiveCodeBlock/index.tsx | 15 ++ .../src/theme/Playground/Container/index.tsx | 16 +++ .../Playground/Container/styles.module.css | 13 ++ .../src/theme/Playground/Editor/index.tsx | 35 +++++ .../theme/Playground/Editor/styles.module.css | 17 +++ .../src/theme/Playground/Header/index.tsx | 19 +++ .../Playground/{ => Header}/styles.module.css | 23 --- .../src/theme/Playground/Layout/index.tsx | 37 +++++ .../src/theme/Playground/Preview/index.tsx | 59 ++++++++ .../Playground/Preview/styles.module.css | 11 ++ .../src/theme/Playground/Provider/index.tsx | 35 +++++ .../src/theme/Playground/index.tsx | 131 ++---------------- .../src/types.d.ts | 20 --- 17 files changed, 354 insertions(+), 180 deletions(-) create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/LiveCodeBlock/index.tsx create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Container/index.tsx create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Container/styles.module.css create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Editor/index.tsx create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Editor/styles.module.css create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Header/index.tsx rename packages/docusaurus-theme-live-codeblock/src/theme/Playground/{ => Header}/styles.module.css (53%) create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Layout/index.tsx create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Preview/index.tsx create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Preview/styles.module.css create mode 100644 packages/docusaurus-theme-live-codeblock/src/theme/Playground/Provider/index.tsx delete mode 100644 packages/docusaurus-theme-live-codeblock/src/types.d.ts diff --git a/packages/docusaurus-mdx-loader/src/remark/mdx1Compat/codeCompatPlugin.ts b/packages/docusaurus-mdx-loader/src/remark/mdx1Compat/codeCompatPlugin.ts index f71dca66ee..6078ee6987 100644 --- a/packages/docusaurus-mdx-loader/src/remark/mdx1Compat/codeCompatPlugin.ts +++ b/packages/docusaurus-mdx-loader/src/remark/mdx1Compat/codeCompatPlugin.ts @@ -25,6 +25,7 @@ const plugin: Plugin = function plugin(): Transformer { node.data.hProperties = node.data.hProperties || {}; node.data.hProperties.metastring = node.meta; + // TODO Docusaurus v4: remove special case // Retrocompatible support for live codeblock metastring // Not really the appropriate place to handle that :s node.data.hProperties.live = node.meta?.split(' ').includes('live'); diff --git a/packages/docusaurus-theme-common/src/utils/useThemeConfig.ts b/packages/docusaurus-theme-common/src/utils/useThemeConfig.ts index 4d0b08fa94..a1d095387e 100644 --- a/packages/docusaurus-theme-common/src/utils/useThemeConfig.ts +++ b/packages/docusaurus-theme-common/src/utils/useThemeConfig.ts @@ -104,6 +104,7 @@ export type TableOfContents = { maxHeadingLevel: number; }; +// TODO Docusaurus v4: use interface + declaration merging to enhance // Theme config after validation/normalization export type ThemeConfig = { docs: { diff --git a/packages/docusaurus-theme-live-codeblock/src/theme-live-codeblock.d.ts b/packages/docusaurus-theme-live-codeblock/src/theme-live-codeblock.d.ts index e3854a0681..3e6c8e971c 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme-live-codeblock.d.ts +++ b/packages/docusaurus-theme-live-codeblock/src/theme-live-codeblock.d.ts @@ -16,6 +16,14 @@ declare module '@docusaurus/theme-live-codeblock' { }; } +declare module '@theme/LiveCodeBlock' { + import type {Props as BaseProps} from '@theme/CodeBlock'; + + export interface Props extends BaseProps {} + + export default function LiveCodeBlock(props: Props): ReactNode; +} + declare module '@theme/Playground' { import type {ReactNode} from 'react'; import type {Props as BaseProps} from '@theme/CodeBlock'; @@ -31,6 +39,64 @@ declare module '@theme/Playground' { export default function Playground(props: LiveProviderProps): ReactNode; } +declare module '@theme/Playground/Provider' { + import type {ReactNode} from 'react'; + import type {Props as PlaygroundProps} from '@theme/Playground'; + + export interface Props extends Omit { + code: string | undefined; + children: ReactNode; + } + + export default function PlaygroundProvider(props: Props): ReactNode; +} + +declare module '@theme/Playground/Container' { + import type {ReactNode} from 'react'; + + export interface Props { + children: ReactNode; + } + + export default function PlaygroundContainer(props: Props): ReactNode; +} + +declare module '@theme/Playground/Layout' { + import type {ReactNode} from 'react'; + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface Props {} + + export default function PlaygroundLayout(props: Props): ReactNode; +} + +declare module '@theme/Playground/Preview' { + import type {ReactNode} from 'react'; + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface Props {} + + export default function PlaygroundPreview(props: Props): ReactNode; +} + +declare module '@theme/Playground/Editor' { + import type {ReactNode} from 'react'; + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface Props {} + + export default function PlaygroundEditor(props: Props): ReactNode; +} + +declare module '@theme/Playground/Header' { + import type {ReactNode} from 'react'; + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface Props {} + + export default function PlaygroundHeader(props: Props): ReactNode; +} + declare module '@theme/ReactLiveScope' { type Scope = { [key: string]: unknown; diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/index.tsx index 225073c0ee..a7290ad768 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/index.tsx +++ b/packages/docusaurus-theme-live-codeblock/src/theme/CodeBlock/index.tsx @@ -5,21 +5,28 @@ * LICENSE file in the root directory of this source tree. */ -import React from 'react'; -import Playground from '@theme/Playground'; -import ReactLiveScope from '@theme/ReactLiveScope'; -import CodeBlock, {type Props} from '@theme-init/CodeBlock'; +import React, {type ReactNode} from 'react'; +import type {Props as CodeBlockProps} from '@theme/CodeBlock'; +import OriginalCodeBlock from '@theme-init/CodeBlock'; +import LiveCodeBlock from '@theme/LiveCodeBlock'; -const withLiveEditor = (Component: typeof CodeBlock) => { - function WrappedComponent(props: Props) { - if (props.live) { - return ; - } - - return ; +// TODO Docusaurus v4: remove special case +// see packages/docusaurus-mdx-loader/src/remark/mdx1Compat/codeCompatPlugin.ts +// we can just use the metastring instead +declare module '@theme/CodeBlock' { + interface Props { + live?: boolean; } +} - return WrappedComponent; -}; +function isLiveCodeBlock(props: CodeBlockProps): boolean { + return !!props.live; +} -export default withLiveEditor(CodeBlock); +export default function CodeBlockEnhancer(props: CodeBlockProps): ReactNode { + return isLiveCodeBlock(props) ? ( + + ) : ( + + ); +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/LiveCodeBlock/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/LiveCodeBlock/index.tsx new file mode 100644 index 0000000000..5beb7ca277 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/LiveCodeBlock/index.tsx @@ -0,0 +1,15 @@ +/** + * 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. + */ + +import React, {type ReactNode} from 'react'; +import Playground from '@theme/Playground'; +import ReactLiveScope from '@theme/ReactLiveScope'; +import type {Props} from '@theme/LiveCodeBlock'; + +export default function LiveCodeBlock(props: Props): ReactNode { + return ; +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Container/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Container/index.tsx new file mode 100644 index 0000000000..4dd77725bb --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Container/index.tsx @@ -0,0 +1,16 @@ +/** + * 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. + */ + +import React, {type ReactNode} from 'react'; + +import type {Props} from '@theme/Playground/Container'; + +import styles from './styles.module.css'; + +export default function PlaygroundContainer({children}: Props): ReactNode { + return
{children}
; +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Container/styles.module.css b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Container/styles.module.css new file mode 100644 index 0000000000..e5690b0fe6 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Container/styles.module.css @@ -0,0 +1,13 @@ +/** + * 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. + */ + +.playgroundContainer { + margin-bottom: var(--ifm-leading); + border-radius: var(--ifm-global-radius); + box-shadow: var(--ifm-global-shadow-lw); + overflow: hidden; +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Editor/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Editor/index.tsx new file mode 100644 index 0000000000..e807f85706 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Editor/index.tsx @@ -0,0 +1,35 @@ +/** + * 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. + */ + +import React, {type ReactNode} from 'react'; +import {LiveEditor} from 'react-live'; +import useIsBrowser from '@docusaurus/useIsBrowser'; +import Translate from '@docusaurus/Translate'; +import PlaygroundHeader from '@theme/Playground/Header'; + +import styles from './styles.module.css'; + +export default function PlaygroundEditor(): ReactNode { + const isBrowser = useIsBrowser(); + return ( + <> + + + Live Editor + + + + + ); +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Editor/styles.module.css b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Editor/styles.module.css new file mode 100644 index 0000000000..3b5165baf9 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Editor/styles.module.css @@ -0,0 +1,17 @@ +/** + * 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. + */ + +.playgroundEditor { + font: var(--ifm-code-font-size) / var(--ifm-pre-line-height) + var(--ifm-font-family-monospace) !important; + /* rtl:ignore */ + direction: ltr; +} + +.playgroundEditor pre { + border-radius: 0; +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Header/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Header/index.tsx new file mode 100644 index 0000000000..5d1e4d2499 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Header/index.tsx @@ -0,0 +1,19 @@ +/** + * 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. + */ + +import React, {type ReactNode} from 'react'; +import clsx from 'clsx'; + +import styles from './styles.module.css'; + +export default function PlaygroundHeader({ + children, +}: { + children: ReactNode; +}): ReactNode { + return
{children}
; +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/styles.module.css b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Header/styles.module.css similarity index 53% rename from packages/docusaurus-theme-live-codeblock/src/theme/Playground/styles.module.css rename to packages/docusaurus-theme-live-codeblock/src/theme/Playground/Header/styles.module.css index 6696d31335..092af7825d 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/styles.module.css +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Header/styles.module.css @@ -5,13 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -.playgroundContainer { - margin-bottom: var(--ifm-leading); - border-radius: var(--ifm-global-radius); - box-shadow: var(--ifm-global-shadow-lw); - overflow: hidden; -} - .playgroundHeader { letter-spacing: 0.08rem; padding: 0.75rem; @@ -26,19 +19,3 @@ background: var(--ifm-color-emphasis-600); color: var(--ifm-color-content-inverse); } - -.playgroundEditor { - font: var(--ifm-code-font-size) / var(--ifm-pre-line-height) - var(--ifm-font-family-monospace) !important; - /* rtl:ignore */ - direction: ltr; -} - -.playgroundEditor pre { - border-radius: 0; -} - -.playgroundPreview { - padding: 1rem; - background-color: var(--ifm-pre-background); -} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Layout/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Layout/index.tsx new file mode 100644 index 0000000000..63b209ace8 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Layout/index.tsx @@ -0,0 +1,37 @@ +/** + * 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. + */ + +import React, {type ReactNode} from 'react'; +import {useThemeConfig} from '@docusaurus/theme-common'; +import PlaygroundPreview from '@theme/Playground/Preview'; +import PlaygroundEditor from '@theme/Playground/Editor'; + +import type {ThemeConfig} from '@docusaurus/theme-live-codeblock'; + +function useLiveCodeBlockThemeConfig() { + const themeConfig = useThemeConfig() as unknown as ThemeConfig; + return themeConfig.liveCodeBlock; +} + +export default function PlaygroundLayout(): ReactNode { + const {playgroundPosition} = useLiveCodeBlockThemeConfig(); + return ( + <> + {playgroundPosition === 'top' ? ( + <> + + + + ) : ( + <> + + + + )} + + ); +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Preview/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Preview/index.tsx new file mode 100644 index 0000000000..b4f6e1ef88 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Preview/index.tsx @@ -0,0 +1,59 @@ +/** + * 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. + */ + +import React, {type ReactNode} from 'react'; +import {LiveError, LivePreview} from 'react-live'; +import BrowserOnly from '@docusaurus/BrowserOnly'; +import {ErrorBoundaryErrorMessageFallback} from '@docusaurus/theme-common'; +import ErrorBoundary from '@docusaurus/ErrorBoundary'; +import Translate from '@docusaurus/Translate'; +import PlaygroundHeader from '@theme/Playground/Header'; + +import styles from './styles.module.css'; + +function Loader() { + // Is it worth improving/translating? + // eslint-disable-next-line @docusaurus/no-untranslated-text + return
Loading...
; +} + +function PlaygroundLivePreview(): ReactNode { + // No SSR for the live preview + // See https://github.com/facebook/docusaurus/issues/5747 + return ( + }> + {() => ( + <> + ( + + )}> + + + + + )} + + ); +} + +export default function PlaygroundPreview(): ReactNode { + return ( + <> + + + Result + + +
+ +
+ + ); +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Preview/styles.module.css b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Preview/styles.module.css new file mode 100644 index 0000000000..b22c113f10 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Preview/styles.module.css @@ -0,0 +1,11 @@ +/** + * 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. + */ + +.playgroundPreview { + padding: 1rem; + background-color: var(--ifm-pre-background); +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Provider/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Provider/index.tsx new file mode 100644 index 0000000000..6664b59d23 --- /dev/null +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/Provider/index.tsx @@ -0,0 +1,35 @@ +/** + * 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. + */ + +import React, {type ReactNode} from 'react'; +import {LiveProvider} from 'react-live'; +import {usePrismTheme} from '@docusaurus/theme-common'; + +import type {Props} from '@theme/Playground/Provider'; + +// this should rather be a stable function +// see https://github.com/facebook/docusaurus/issues/9630#issuecomment-1855682643 +const DEFAULT_TRANSFORM_CODE = (code: string) => `${code};`; + +export default function PlaygroundProvider({ + code, + children, + ...props +}: Props): ReactNode { + const prismTheme = usePrismTheme(); + const noInline = props.metastring?.includes('noInline') ?? false; + return ( + + {children} + + ); +} diff --git a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx index 37cda3ee02..61463314d4 100644 --- a/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx +++ b/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx @@ -6,137 +6,22 @@ */ import React, {type ReactNode} from 'react'; -import clsx from 'clsx'; -import useIsBrowser from '@docusaurus/useIsBrowser'; -import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live'; -import Translate from '@docusaurus/Translate'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import BrowserOnly from '@docusaurus/BrowserOnly'; -import { - ErrorBoundaryErrorMessageFallback, - usePrismTheme, -} from '@docusaurus/theme-common'; -import ErrorBoundary from '@docusaurus/ErrorBoundary'; +import PlaygroundProvider from '@theme/Playground/Provider'; +import PlaygroundContainer from '@theme/Playground/Container'; +import PlaygroundLayout from '@theme/Playground/Layout'; import type {Props} from '@theme/Playground'; -import type {ThemeConfig} from '@docusaurus/theme-live-codeblock'; - -import styles from './styles.module.css'; - -function Header({children}: {children: ReactNode}) { - return
{children}
; -} - -function LivePreviewLoader() { - // Is it worth improving/translating? - // eslint-disable-next-line @docusaurus/no-untranslated-text - return
Loading...
; -} - -function Preview() { - // No SSR for the live preview - // See https://github.com/facebook/docusaurus/issues/5747 - return ( - }> - {() => ( - <> - ( - - )}> - - - - - )} - - ); -} - -function ResultWithHeader() { - return ( - <> -
- - Result - -
- {/* https://github.com/facebook/docusaurus/issues/5747 */} -
- -
- - ); -} - -function ThemedLiveEditor() { - const isBrowser = useIsBrowser(); - return ( - - ); -} - -function EditorWithHeader() { - return ( - <> -
- - Live Editor - -
- - - ); -} - -// this should rather be a stable function -// see https://github.com/facebook/docusaurus/issues/9630#issuecomment-1855682643 -const DEFAULT_TRANSFORM_CODE = (code: string) => `${code};`; export default function Playground({ children, transformCode, ...props }: Props): ReactNode { - const { - siteConfig: {themeConfig}, - } = useDocusaurusContext(); - const { - liveCodeBlock: {playgroundPosition}, - } = themeConfig as ThemeConfig; - const prismTheme = usePrismTheme(); - - const noInline = props.metastring?.includes('noInline') ?? false; - return ( -
- - {playgroundPosition === 'top' ? ( - <> - - - - ) : ( - <> - - - - )} - -
+ + + + + ); } diff --git a/packages/docusaurus-theme-live-codeblock/src/types.d.ts b/packages/docusaurus-theme-live-codeblock/src/types.d.ts deleted file mode 100644 index 47200c50ab..0000000000 --- a/packages/docusaurus-theme-live-codeblock/src/types.d.ts +++ /dev/null @@ -1,20 +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. - */ - -/// -/// - -declare module '@theme-init/CodeBlock' { - import type CodeBlock from '@theme/CodeBlock'; - import type {Props as BaseProps} from '@theme/CodeBlock'; - - export interface Props extends BaseProps { - live?: boolean; - } - const CodeBlockComp: typeof CodeBlock; - export default CodeBlockComp; -} From 535c1c9835719cef462560764bb499319d2f840a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 11 Apr 2025 11:05:44 +0200 Subject: [PATCH 2/8] docs: remove ref to Docusaurus v2 (#11084) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- project-words.txt | 20 -------------------- website/docs/blog.mdx | 4 ++-- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/project-words.txt b/project-words.txt index 7c109ead9f..2151d48837 100644 --- a/project-words.txt +++ b/project-words.txt @@ -25,9 +25,6 @@ beforeinstallprompt Bhatt Blockquotes blockquotes -BLUESKY -Bluesky -bluesky Bokmål bunx caabernathy @@ -36,14 +33,12 @@ cdabcdab cdpath Cena cena -changefreq Chedeau chedeau Clément Codegen codegen codesandbox -Codespaces commonmark contravariance corejs @@ -61,9 +56,6 @@ dedup devto dingers Dmitry -Docsearch -docsearch -Docsify Docu docu docusuarus @@ -117,8 +109,6 @@ Héctor héllô IANAD Infima -infima -Infima's inlines interactiveness Interpolatable @@ -140,14 +130,11 @@ Knapen Koyeb Koyeb's Lamana -Lastmod -lastmod Lifecycles lifecycles lightningcss Linkify linkify -lockb Lorber lorber Lorber's @@ -196,7 +183,6 @@ navigations navlink netrc newtab -Nextra ngryman Nisarag noflash @@ -230,16 +216,12 @@ paraiso pathinfo paularmstrong philpl -Photoshop -photoshop Pipeable playbtn Plushie plushie plushies posthog -Precache -precache precached precaching preconfigured @@ -310,11 +292,9 @@ stackoverflow Stormkit Strikethrough strikethroughs -stylelintrc sublabel sublicensable sublist -subpage subsetting subsubcategory subsubfolder diff --git a/website/docs/blog.mdx b/website/docs/blog.mdx index 468e42f3b9..8c9b0dc0ef 100644 --- a/website/docs/blog.mdx +++ b/website/docs/blog.mdx @@ -67,11 +67,11 @@ image: https://i.imgur.com/mErPwqL.png hide_table_of_contents: false --- -Welcome to this blog. This blog is created with [**Docusaurus 2**](https://docusaurus.io/). +Welcome to this blog. This blog is created with [**Docusaurus**](https://docusaurus.io/). -This is my first post on Docusaurus 2. +This is my first post on Docusaurus. A whole bunch of exploration to follow. ``` From 72b8621515f155e3d4089b0b45486cc7c9073d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 11 Apr 2025 11:44:12 +0200 Subject: [PATCH 3/8] fix(theme): add missing `rel="tag"` attribute for docs/blog tags (#11085) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- packages/docusaurus-theme-classic/src/theme/Tag/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docusaurus-theme-classic/src/theme/Tag/index.tsx b/packages/docusaurus-theme-classic/src/theme/Tag/index.tsx index 174ef66842..3011c5c841 100644 --- a/packages/docusaurus-theme-classic/src/theme/Tag/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Tag/index.tsx @@ -20,6 +20,7 @@ export default function Tag({ }: Props): ReactNode { return ( Date: Fri, 11 Apr 2025 12:51:42 +0200 Subject: [PATCH 4/8] chore: add `pr: translations` GitHub + lerna changelog label (#11087) Co-authored-by: slorber <749374+slorber@users.noreply.github.com> --- lerna.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 522fca1495..d5d76a7c99 100644 --- a/lerna.json +++ b/lerna.json @@ -13,7 +13,8 @@ "pr: polish": ":nail_care: Polish", "pr: documentation": ":memo: Documentation", "pr: dependencies": ":robot: Dependencies", - "pr: maintenance": ":wrench: Maintenance" + "pr: maintenance": ":wrench: Maintenance", + "pr: translations": ":globe_with_meridians: Translations" }, "cacheDir": ".changelog" } From 5b944d6b64c56cbf5438bc2e8f37d452cc16dc91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 11 Apr 2025 14:44:19 +0200 Subject: [PATCH 5/8] feat(pages): Support `frontMatter.slug` like docs and blog plugins (#11088) --- .../website/src/pages/hello/mdxPage.mdx | 2 ++ .../src/__tests__/__snapshots__/index.test.ts.snap | 9 ++++++--- .../docusaurus-plugin-content-pages/src/content.ts | 14 +++++++++----- .../src/frontMatter.ts | 1 + .../src/plugin-content-pages.d.ts | 1 + website/_dogfooding/_pages tests/index.mdx | 2 +- website/_dogfooding/_pages tests/unlisted.mdx | 1 + website/docs/api/plugins/plugin-content-pages.mdx | 2 ++ 8 files changed, 23 insertions(+), 9 deletions(-) diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/mdxPage.mdx b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/mdxPage.mdx index 27b0b9f9be..79a1fc5af9 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/mdxPage.mdx +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/mdxPage.mdx @@ -1,5 +1,7 @@ --- title: MDX page description: my MDX page +slug: /custom-mdx/slug --- + MDX page diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap index bc9b5308c3..ecb51dba22 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__snapshots__/index.test.ts.snap @@ -32,11 +32,12 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = ` "frontMatter": { "custom_frontMatter": "added by parseFrontMatter", "description": "my MDX page", + "slug": "/custom-mdx/slug", "title": "MDX page", }, "lastUpdatedAt": undefined, "lastUpdatedBy": undefined, - "permalink": "/hello/mdxPage", + "permalink": "/custom-mdx/slug", "source": "@site/src/pages/hello/mdxPage.mdx", "title": "MDX page", "type": "mdx", @@ -101,11 +102,12 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat "frontMatter": { "custom_frontMatter": "added by parseFrontMatter", "description": "my MDX page", + "slug": "/custom-mdx/slug", "title": "MDX page", }, "lastUpdatedAt": undefined, "lastUpdatedBy": undefined, - "permalink": "/fr/hello/mdxPage", + "permalink": "/fr/custom-mdx/slug", "source": "@site/src/pages/hello/mdxPage.mdx", "title": "MDX page", "type": "mdx", @@ -170,11 +172,12 @@ exports[`docusaurus-plugin-content-pages loads simple pages with last update 1`] "frontMatter": { "custom_frontMatter": "added by parseFrontMatter", "description": "my MDX page", + "slug": "/custom-mdx/slug", "title": "MDX page", }, "lastUpdatedAt": 1539502055000, "lastUpdatedBy": "Author", - "permalink": "/hello/mdxPage", + "permalink": "/custom-mdx/slug", "source": "@site/src/pages/hello/mdxPage.mdx", "title": "MDX page", "type": "mdx", diff --git a/packages/docusaurus-plugin-content-pages/src/content.ts b/packages/docusaurus-plugin-content-pages/src/content.ts index 769adbf459..97806bfb67 100644 --- a/packages/docusaurus-plugin-content-pages/src/content.ts +++ b/packages/docusaurus-plugin-content-pages/src/content.ts @@ -106,12 +106,13 @@ async function processPageSourceFile( const source = path.join(contentPath, relativeSource); const aliasedSourcePath = aliasedSitePath(source, siteDir); - const permalink = normalizeUrl([ - baseUrl, - options.routeBasePath, - encodePath(fileToPath(relativeSource)), - ]); + + const filenameSlug = encodePath(fileToPath(relativeSource)); + if (!isMarkdownSource(relativeSource)) { + // For now, slug can't be customized for JSX pages + const slug = filenameSlug; + const permalink = normalizeUrl([baseUrl, options.routeBasePath, slug]); return { type: 'jsx', permalink, @@ -131,6 +132,9 @@ async function processPageSourceFile( }); const frontMatter = validatePageFrontMatter(unsafeFrontMatter); + const slug = frontMatter.slug ?? filenameSlug; + const permalink = normalizeUrl([baseUrl, options.routeBasePath, slug]); + const pagesDirPath = await getFolderContainingFile( getContentPathList(contentPaths), relativeSource, diff --git a/packages/docusaurus-plugin-content-pages/src/frontMatter.ts b/packages/docusaurus-plugin-content-pages/src/frontMatter.ts index 5a87b1a221..d68923d89e 100644 --- a/packages/docusaurus-plugin-content-pages/src/frontMatter.ts +++ b/packages/docusaurus-plugin-content-pages/src/frontMatter.ts @@ -22,6 +22,7 @@ const PageFrontMatterSchema = Joi.object({ description: Joi.string().allow(''), keywords: Joi.array().items(Joi.string().required()), image: URISchema, + slug: Joi.string(), wrapperClassName: Joi.string(), hide_table_of_contents: Joi.boolean(), ...FrontMatterTOCHeadingLevels, diff --git a/packages/docusaurus-plugin-content-pages/src/plugin-content-pages.d.ts b/packages/docusaurus-plugin-content-pages/src/plugin-content-pages.d.ts index d9045fd3f4..c0e02f40ae 100644 --- a/packages/docusaurus-plugin-content-pages/src/plugin-content-pages.d.ts +++ b/packages/docusaurus-plugin-content-pages/src/plugin-content-pages.d.ts @@ -37,6 +37,7 @@ declare module '@docusaurus/plugin-content-pages' { readonly title?: string; readonly description?: string; readonly image?: string; + readonly slug?: string; readonly keywords?: string[]; readonly wrapperClassName?: string; readonly hide_table_of_contents?: string; diff --git a/website/_dogfooding/_pages tests/index.mdx b/website/_dogfooding/_pages tests/index.mdx index 6ed5de6daf..38f13ae9ae 100644 --- a/website/_dogfooding/_pages tests/index.mdx +++ b/website/_dogfooding/_pages tests/index.mdx @@ -37,7 +37,7 @@ import Readme from "../README.mdx" - [Tabs tests](/tests/pages/tabs-tests) - [z-index tests](/tests/pages/z-index-tests) - [Head metadata tests](/tests/pages/head-metadata) -- [Unlisted page](/tests/pages/unlisted) +- [Unlisted page](/tests/pages/my-custom/unlisted/slug) - [Analytics](/tests/pages/analytics) - [History tests](/tests/pages/history-tests) - [Embeds](/tests/pages/embeds) diff --git a/website/_dogfooding/_pages tests/unlisted.mdx b/website/_dogfooding/_pages tests/unlisted.mdx index 0e34391496..f1a0134320 100644 --- a/website/_dogfooding/_pages tests/unlisted.mdx +++ b/website/_dogfooding/_pages tests/unlisted.mdx @@ -1,5 +1,6 @@ --- unlisted: true +slug: /my-custom/unlisted/slug --- # Unlisted page diff --git a/website/docs/api/plugins/plugin-content-pages.mdx b/website/docs/api/plugins/plugin-content-pages.mdx index 03db1f4f1b..b71ef05500 100644 --- a/website/docs/api/plugins/plugin-content-pages.mdx +++ b/website/docs/api/plugins/plugin-content-pages.mdx @@ -113,6 +113,7 @@ Accepted fields: | `description` | `string` | The first line of Markdown content | The description of your page, which will become the `` and `` in ``, used by search engines. | | `keywords` | `string[]` | `undefined` | Keywords meta tag, which will become the `` in ``, used by search engines. | | `image` | `string` | `undefined` | Cover or thumbnail image that will be used as the `` in the ``, enhancing link previews on social media and messaging platforms. | +| `slug` | `string` | File path | Allows to customize the page URL (`//`). Support multiple patterns: `slug: my-page`, `slug: /my/page`, slug: `/`. | | `wrapperClassName` | `string` | | Class name to be added to the wrapper element to allow targeting specific page content. | | `hide_table_of_contents` | `boolean` | `false` | Whether to hide the table of contents to the right. | | `draft` | `boolean` | `false` | Draft pages will only be available during development. | @@ -131,6 +132,7 @@ description: Markdown page SEO description wrapperClassName: markdown-page hide_table_of_contents: false draft: true +slug: /markdown-page --- Markdown page content From 730ce485ba71dd4a8bab16dbb2375db8d5619279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 11 Apr 2025 19:16:17 +0200 Subject: [PATCH 6/8] feat(theme): make it possible to provide your own page title formatter (#11090) --- .../src/index.d.ts | 9 ++ .../website/build-snap/blog/atom.xsl | 2 +- .../src/theme-classic.d.ts | 11 ++ .../ThemeProvider/TitleFormatter/index.tsx | 27 ++++ .../src/theme/ThemeProvider/index.tsx | 14 ++ .../docusaurus-theme-common/src/internal.ts | 5 +- .../src/utils/__tests__/generalUtils.test.tsx | 33 ----- .../__tests__/titleFormatterUtils.test.tsx | 43 ++++++ .../src/utils/generalUtils.ts | 19 --- .../src/utils/metadataUtils.tsx | 84 ++++++++---- .../src/utils/titleFormatterUtils.tsx | 122 ++++++++++++++++++ .../src/theme/SearchPage/index.tsx | 47 +++---- packages/docusaurus/src/client/App.tsx | 11 +- .../theme-fallback/ThemeProvider/index.tsx | 20 +++ .../__tests__/__snapshots__/base.test.ts.snap | 2 + .../__snapshots__/index.test.ts.snap | 8 ++ .../ThemeProvider/TitleFormatter/index.tsx | 36 ++++++ 17 files changed, 386 insertions(+), 107 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/theme/ThemeProvider/TitleFormatter/index.tsx create mode 100644 packages/docusaurus-theme-classic/src/theme/ThemeProvider/index.tsx delete mode 100644 packages/docusaurus-theme-common/src/utils/__tests__/generalUtils.test.tsx create mode 100644 packages/docusaurus-theme-common/src/utils/__tests__/titleFormatterUtils.test.tsx delete mode 100644 packages/docusaurus-theme-common/src/utils/generalUtils.ts create mode 100644 packages/docusaurus-theme-common/src/utils/titleFormatterUtils.tsx create mode 100644 packages/docusaurus/src/client/theme-fallback/ThemeProvider/index.tsx create mode 100644 website/src/theme/ThemeProvider/TitleFormatter/index.tsx diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 176ca2ec52..5876e36484 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -122,6 +122,15 @@ declare module '@theme/Root' { export default function Root({children}: Props): ReactNode; } +declare module '@theme/ThemeProvider' { + import type {ReactNode} from 'react'; + + export interface Props { + readonly children: ReactNode; + } + export default function ThemeProvider({children}: Props): ReactNode; +} + declare module '@theme/SiteMetadata' { import type {ReactNode} from 'react'; diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/atom.xsl b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/atom.xsl index 271895cf77..b4b2d9619c 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/atom.xsl +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/build-snap/blog/atom.xsl @@ -71,7 +71,7 @@
-