mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-01 03:08:17 +02:00
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 <lex61rus@gmail.com>
This commit is contained in:
parent
9cbca49ecf
commit
dc31dad1de
5 changed files with 58 additions and 8 deletions
|
@ -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'`.
|
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
|
## Provided Components
|
||||||
|
|
||||||
Docusaurus provides the following components in `CompLibrary`:
|
Docusaurus provides the following components in `CompLibrary`:
|
||||||
|
|
|
@ -13,7 +13,7 @@ describe('themeAlias', () => {
|
||||||
test('valid themePath 1 with components', () => {
|
test('valid themePath 1 with components', () => {
|
||||||
const fixtures = path.join(__dirname, '__fixtures__');
|
const fixtures = path.join(__dirname, '__fixtures__');
|
||||||
const themePath = path.join(fixtures, 'theme-1');
|
const themePath = path.join(fixtures, 'theme-1');
|
||||||
const alias = themeAlias(themePath);
|
const alias = themeAlias(themePath, true);
|
||||||
expect(alias).toEqual({
|
expect(alias).toEqual({
|
||||||
'@theme/Footer': path.join(themePath, 'Footer/index.js'),
|
'@theme/Footer': path.join(themePath, 'Footer/index.js'),
|
||||||
'@theme-original/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', () => {
|
test('valid themePath 2 with components', () => {
|
||||||
const fixtures = path.join(__dirname, '__fixtures__');
|
const fixtures = path.join(__dirname, '__fixtures__');
|
||||||
const themePath = path.join(fixtures, 'theme-2');
|
const themePath = path.join(fixtures, 'theme-2');
|
||||||
const alias = themeAlias(themePath);
|
const alias = themeAlias(themePath, true);
|
||||||
expect(alias).toEqual({
|
expect(alias).toEqual({
|
||||||
'@theme/Navbar': path.join(themePath, 'Navbar.js'),
|
'@theme/Navbar': path.join(themePath, 'Navbar.js'),
|
||||||
'@theme-original/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 fixtures = path.join(__dirname, '__fixtures__');
|
||||||
const themePath = path.join(fixtures, 'empty-theme');
|
const themePath = path.join(fixtures, 'empty-theme');
|
||||||
fs.ensureDirSync(themePath);
|
fs.ensureDirSync(themePath);
|
||||||
const alias = themeAlias(themePath);
|
const alias = themeAlias(themePath, true);
|
||||||
expect(alias).toEqual({});
|
expect(alias).toEqual({});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ describe('themeAlias', () => {
|
||||||
test('invalid themePath that does not exist', () => {
|
test('invalid themePath that does not exist', () => {
|
||||||
const fixtures = path.join(__dirname, '__fixtures__');
|
const fixtures = path.join(__dirname, '__fixtures__');
|
||||||
const themePath = path.join(fixtures, '__noExist__');
|
const themePath = path.join(fixtures, '__noExist__');
|
||||||
const alias = themeAlias(themePath);
|
const alias = themeAlias(themePath, true);
|
||||||
expect(alias).toEqual({});
|
expect(alias).toEqual({});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {ThemeAlias} from '@docusaurus/types';
|
||||||
|
|
||||||
export default function themeAlias(
|
export default function themeAlias(
|
||||||
themePath: string,
|
themePath: string,
|
||||||
addOriginalAlias: boolean = true,
|
addOriginalAlias: boolean,
|
||||||
): ThemeAlias {
|
): ThemeAlias {
|
||||||
if (!fs.pathExistsSync(themePath)) {
|
if (!fs.pathExistsSync(themePath)) {
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -31,7 +31,7 @@ export default function loadThemeAlias(
|
||||||
let aliases = {};
|
let aliases = {};
|
||||||
|
|
||||||
themePaths.forEach((themePath) => {
|
themePaths.forEach((themePath) => {
|
||||||
const themeAliases = themeAlias(themePath);
|
const themeAliases = themeAlias(themePath, true);
|
||||||
aliases = {...aliases, ...buildThemeAliases(themeAliases, aliases)};
|
aliases = {...aliases, ...buildThemeAliases(themeAliases, aliases)};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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.
|
**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 (
|
||||||
|
<>
|
||||||
|
<div>Before footer</div>
|
||||||
|
<OriginalFooter {...props} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 ? (
|
||||||
|
<ReactLivePlayground {...props} />
|
||||||
|
) : (
|
||||||
|
<InitialCodeBlock {...props} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
## Official themes by Docusaurus
|
||||||
|
|
||||||
### `@docusaurus/theme-classic`
|
### `@docusaurus/theme-classic`
|
||||||
|
|
Loading…
Add table
Reference in a new issue