Skip to content

Commit ee9ab9e

Browse files
committed
Add ability specify tabs in codeblock metadata
1 parent db2a8e8 commit ee9ab9e

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

docusaurus.config.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,10 @@ export default {
128128
sidebarCollapsed: false,
129129
remarkPlugins: [[remarkNpm2Yarn, { sync: true }]],
130130
rehypePlugins: [
131-
[rehypeCodeblockMeta, { match: { snack: true, lang: true } }],
131+
[
132+
rehypeCodeblockMeta,
133+
{ match: { snack: true, lang: true, tabs: true } },
134+
],
132135
],
133136
},
134137
blog: {

src/components/Pre.js

+66
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,22 @@ import { useColorMode } from '@docusaurus/theme-common';
33
import { usePluginData } from '@docusaurus/useGlobalData';
44
import MDXPre from '@theme-original/MDXComponents/Pre';
55
import React from 'react';
6+
import Tabs from '@theme/Tabs';
7+
import TabItem from '@theme/TabItem';
8+
9+
const SUPPORTED_TABS = {
10+
config: [
11+
{ value: 'static', label: 'Static', default: true },
12+
{ value: 'dynamic', label: 'Dynamic' },
13+
],
14+
};
615

716
export default function Pre({
817
children,
918
'data-name': name,
1019
'data-snack': snack,
1120
'data-dependencies': deps,
21+
'data-tabs': tabs,
1222
'data-lang': lang,
1323
...rest
1424
}) {
@@ -18,6 +28,62 @@ export default function Pre({
1828

1929
const child = React.Children.only(children);
2030

31+
// If we encounter tabs, we need to render 2 code blocks
32+
if (tabs && tabs in SUPPORTED_TABS) {
33+
return (
34+
<Tabs groupId="config" queryString="config">
35+
{SUPPORTED_TABS[tabs].map((tab) => {
36+
const code = child.props.children;
37+
38+
if (typeof code !== 'string') {
39+
throw new Error(
40+
'Code to display in tabs must be a string, but received ' +
41+
typeof code
42+
);
43+
}
44+
45+
const lines = code.split('\n');
46+
47+
let content = '';
48+
let exclude = false;
49+
let indent;
50+
51+
for (const line of lines) {
52+
if (line.trim().startsWith('// codeblock-tabs=')) {
53+
exclude = line.trim() !== `// codeblock-tabs=${tab.value}`;
54+
} else if (line.trim() === '// codeblock-tabs-end') {
55+
exclude = false;
56+
} else if (!exclude) {
57+
content += line + '\n';
58+
}
59+
}
60+
61+
return (
62+
<TabItem
63+
key={tab.value}
64+
value={tab.value}
65+
label={tab.label}
66+
default={tab.default}
67+
>
68+
<Pre
69+
{...rest}
70+
data-name={name}
71+
data-snack={snack}
72+
data-dependencies={deps}
73+
data-lang={lang}
74+
>
75+
{React.cloneElement(children, {
76+
...child.props,
77+
children: content.trim(),
78+
})}
79+
</Pre>
80+
</TabItem>
81+
);
82+
})}
83+
</Tabs>
84+
);
85+
}
86+
2187
// Handle diffs with language
2288
if (child.props.className === 'language-diff' && lang) {
2389
const code = child.props.children;

0 commit comments

Comments
 (0)