From dc31dad1def48ac6aa0a91cbdeb55f9472a26dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Wed, 30 Sep 2020 18:15:47 +0200 Subject: [PATCH] docs(v2): add doc for wrapping theme components with @theme-original and @theme-init (#3502) * add doc for wrapping theme components * fix tests * Minor improvements Co-authored-by: Alexey Pyltsyn --- docs/api-pages.md | 2 - .../src/server/themes/__tests__/alias.test.ts | 8 +-- .../docusaurus/src/server/themes/alias.ts | 2 +- .../docusaurus/src/server/themes/index.ts | 2 +- website/docs/using-themes.md | 52 +++++++++++++++++++ 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/docs/api-pages.md b/docs/api-pages.md index 3cbc105412a1..f636c29b7652 100644 --- a/docs/api-pages.md +++ b/docs/api-pages.md @@ -83,8 +83,6 @@ What this means to the user is that if you wish to use the `CompLibrary` module, If you wish to use your own components inside the website directory, use `process.cwd()` which will refer to the `website` directory to construct require paths. For example, if you add a component to `website/core/mycomponent.js`, you can use the require path, `'process.cwd() + /core/mycomponent.js'`. -There is a special import for custom items `@theme-original`. The `theme-original` alias (just like using `theme` alias) will not get the theme component from the plugin's code. While the `init-theme` alias refers to the proper (theme) component (from the theme itself, where it is first defined). Therefore the `theme-original` is for the user and `theme-initial` is for the plugins. - ## Provided Components Docusaurus provides the following components in `CompLibrary`: diff --git a/packages/docusaurus/src/server/themes/__tests__/alias.test.ts b/packages/docusaurus/src/server/themes/__tests__/alias.test.ts index 61672780d05c..0e3a889d8240 100644 --- a/packages/docusaurus/src/server/themes/__tests__/alias.test.ts +++ b/packages/docusaurus/src/server/themes/__tests__/alias.test.ts @@ -13,7 +13,7 @@ describe('themeAlias', () => { test('valid themePath 1 with components', () => { const fixtures = path.join(__dirname, '__fixtures__'); const themePath = path.join(fixtures, 'theme-1'); - const alias = themeAlias(themePath); + const alias = themeAlias(themePath, true); expect(alias).toEqual({ '@theme/Footer': path.join(themePath, 'Footer/index.js'), '@theme-original/Footer': path.join(themePath, 'Footer/index.js'), @@ -37,7 +37,7 @@ describe('themeAlias', () => { test('valid themePath 2 with components', () => { const fixtures = path.join(__dirname, '__fixtures__'); const themePath = path.join(fixtures, 'theme-2'); - const alias = themeAlias(themePath); + const alias = themeAlias(themePath, true); expect(alias).toEqual({ '@theme/Navbar': path.join(themePath, 'Navbar.js'), '@theme-original/Navbar': path.join(themePath, 'Navbar.js'), @@ -62,7 +62,7 @@ describe('themeAlias', () => { const fixtures = path.join(__dirname, '__fixtures__'); const themePath = path.join(fixtures, 'empty-theme'); fs.ensureDirSync(themePath); - const alias = themeAlias(themePath); + const alias = themeAlias(themePath, true); expect(alias).toEqual({}); }); @@ -77,7 +77,7 @@ describe('themeAlias', () => { test('invalid themePath that does not exist', () => { const fixtures = path.join(__dirname, '__fixtures__'); const themePath = path.join(fixtures, '__noExist__'); - const alias = themeAlias(themePath); + const alias = themeAlias(themePath, true); expect(alias).toEqual({}); }); }); diff --git a/packages/docusaurus/src/server/themes/alias.ts b/packages/docusaurus/src/server/themes/alias.ts index 11a62126d25b..883d29df1c01 100644 --- a/packages/docusaurus/src/server/themes/alias.ts +++ b/packages/docusaurus/src/server/themes/alias.ts @@ -13,7 +13,7 @@ import {ThemeAlias} from '@docusaurus/types'; export default function themeAlias( themePath: string, - addOriginalAlias: boolean = true, + addOriginalAlias: boolean, ): ThemeAlias { if (!fs.pathExistsSync(themePath)) { return {}; diff --git a/packages/docusaurus/src/server/themes/index.ts b/packages/docusaurus/src/server/themes/index.ts index 574a65ab4d3d..93ab66480681 100644 --- a/packages/docusaurus/src/server/themes/index.ts +++ b/packages/docusaurus/src/server/themes/index.ts @@ -31,7 +31,7 @@ export default function loadThemeAlias( let aliases = {}; themePaths.forEach((themePath) => { - const themeAliases = themeAlias(themePath); + const themeAliases = themeAlias(themePath, true); aliases = {...aliases, ...buildThemeAliases(themeAliases, aliases)}; }); diff --git a/website/docs/using-themes.md b/website/docs/using-themes.md index 773da0e01de1..2a17fa08ab95 100644 --- a/website/docs/using-themes.md +++ b/website/docs/using-themes.md @@ -101,6 +101,58 @@ npm run swizzle @docusaurus/theme-classic **Note**: You need to restart your webpack dev server in order for Docusaurus to know about the new component. +## Wrapping theme components + +Sometimes, you just want to wrap an existing theme component with additional logic, and it can be a pain to have to maintain an almost duplicate copy of the original theme component. + +In such case, you should swizzle the component you want to wrap, but import the original theme component in your customized version to wrap it. + +### For site owners + +The `@theme-original` alias allows you to import the original theme component. + +Here is an example to display some text just above the footer, with minimal code duplication. + +```js title="src/theme/Footer.js" +// Note: importing from "@theme/Footer" would fail due to the file importing itself +import OriginalFooter from '@theme-original/Footer'; + +export default function Footer(props) { + return ( + <> +
Before footer
+ + + ); +} +``` + +### For plugin authors + +One theme can wrap a component from another theme, by importing the component from the initial theme, using the `@theme-init` import. + +Here's an example of using this feature to enhance the default theme `CodeBlock` component with a `react-live` playground feature. + +```js +import InitialCodeBlock from '@theme-init/CodeBlock'; + +export default function CodeBlock(props) { + return props.live ? ( + + ) : ( + + ); +} +``` + +Check the code of `docusaurus-theme-live-codeblock` for details. + +:::caution + +Unless you want publish to npm a "theme enhancer" (like `docusaurus-theme-live-codeblock`), you likely don't need `@theme-init`. + +::: + ## Official themes by Docusaurus ### `@docusaurus/theme-classic`