Skip to content

Commit

Permalink
docs(v2): add doc for wrapping theme components with @theme-original …
Browse files Browse the repository at this point in the history
…and @theme-init (#3502)

* add doc for wrapping theme components

* fix tests

* Minor improvements

Co-authored-by: Alexey Pyltsyn <[email protected]>
  • Loading branch information
slorber and lex111 authored Sep 30, 2020
1 parent 9cbca49 commit dc31dad
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 8 deletions.
2 changes: 0 additions & 2 deletions docs/api-pages.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
8 changes: 4 additions & 4 deletions packages/docusaurus/src/server/themes/__tests__/alias.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand All @@ -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'),
Expand All @@ -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({});
});

Expand All @@ -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({});
});
});
2 changes: 1 addition & 1 deletion packages/docusaurus/src/server/themes/alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus/src/server/themes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)};
});

Expand Down
52 changes: 52 additions & 0 deletions website/docs/using-themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<>
<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

### `@docusaurus/theme-classic`
Expand Down

0 comments on commit dc31dad

Please sign in to comment.