Skip to content

Commit 5eb5533

Browse files
authored
Add tabbed content support in documentation and implement conversion to Docusaurus Tabs components (#124)
* Add tabbed content support in documentation and implement conversion to Docusaurus Tabs components - Introduced a new section in README.md detailing how to create tabbed content using HTML comment markers for Docusaurus. - Implemented a function in repo-transforms.js to convert GitHub-style tab markers into Docusaurus Tabs components, enhancing documentation interactivity. Signed-off-by: Pete Cheslock <[email protected]> * Enhance documentation with GitHub callouts support and refine tab conversion Signed-off-by: Pete Cheslock <[email protected]> --------- Signed-off-by: Pete Cheslock <[email protected]>
1 parent b01a8a0 commit 5eb5533

File tree

2 files changed

+122
-3
lines changed

2 files changed

+122
-3
lines changed

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,64 @@ To add other remote content (non-component):
161161
**For local website content:**
162162
- Follow the standard pull request process below
163163

164+
### Creating Tabs in Remote Content
165+
166+
When writing documentation in source repositories (like llm-d/llm-d) that will be synced to this Docusaurus site, you can create tabbed content using HTML comment markers. These are invisible in GitHub but will be transformed into Docusaurus tabs during the build.
167+
168+
**In your GitHub README:**
169+
```markdown
170+
### Deploy Model Servers
171+
172+
<!-- TABS:START -->
173+
<!-- TAB:GKE (H200):default -->
174+
kubectl apply -k ./manifests/modelserver/gke -n ${NAMESPACE}
175+
176+
<!-- TAB:GKE (B200) -->
177+
kubectl apply -k ./manifests/modelserver/gke-a4 -n ${NAMESPACE}
178+
179+
<!-- TAB:CoreWeave -->
180+
kubectl apply -k ./manifests/modelserver/coreweave -n ${NAMESPACE}
181+
182+
<!-- TABS:END -->
183+
```
184+
185+
**Key points:**
186+
- Use `<!-- TABS:START -->` and `<!-- TABS:END -->` to wrap the entire tabbed section
187+
- Use `<!-- TAB:Label -->` before each tab's content
188+
- Add `:default` after the label to make it the default selected tab (e.g., `<!-- TAB:GKE:default -->`)
189+
- **No imports needed** - the transformation automatically adds them
190+
- On GitHub, the HTML comments are invisible, showing clean markdown
191+
- On Docusaurus, these are transformed into proper `<Tabs>` components
192+
193+
**Result on Docusaurus:**
194+
The content will automatically be transformed with the proper Tabs imports and components, creating an interactive tabbed interface.
195+
196+
### GitHub Callouts Support
197+
198+
The transformation system also automatically converts GitHub-style callouts to Docusaurus admonitions:
199+
200+
```markdown
201+
> [!NOTE]
202+
> This is a note
203+
204+
> [!TIP]
205+
> This is a tip
206+
207+
> [!IMPORTANT]
208+
> This is important
209+
210+
> [!WARNING]
211+
> This is a warning
212+
213+
> [!CAUTION]
214+
> This is dangerous
215+
216+
> [!REQUIREMENTS]
217+
> These are requirements
218+
```
219+
220+
These will be automatically converted to the appropriate Docusaurus `:::note`, `:::tip`, `:::info`, `:::warning`, and `:::danger` admonitions during the build.
221+
164222
### Troubleshooting
165223

166224
| Problem | Solution |
@@ -170,6 +228,7 @@ To add other remote content (non-component):
170228
| Links broken | Make sure you're using `createStandardTransform()` |
171229
| Component not showing | Check `components-data.yaml` and repository accessibility |
172230
| Wrong sidebar order | Adjust `sidebarPosition` numbers in configuration |
231+
| Tabs not rendering | Check that you have both `TABS:START` and `TABS:END` markers |
173232

174233
## BEFORE DOING A PULL REQUEST
175234

remote-content/remote-sources/repo-transforms.js

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,81 @@ function getInternalGuidePath(githubUrl) {
5555
return null;
5656
}
5757

58+
/**
59+
* Convert GitHub-friendly tab markers to Docusaurus Tabs components
60+
*/
61+
function convertTabsToDocusaurus(content) {
62+
// Check if there are any tab blocks
63+
const hasTabBlocks = /<!-- TABS:START -->/.test(content);
64+
if (!hasTabBlocks) return content;
65+
66+
// Pattern to match tab blocks
67+
const tabBlockRegex = /<!-- TABS:START -->\n([\s\S]*?)<!-- TABS:END -->/g;
68+
69+
const transformedContent = content.replace(tabBlockRegex, (match, tabsContent) => {
70+
// Split content by TAB markers to extract individual tabs
71+
const tabSections = tabsContent.split(/<!-- TAB:/);
72+
const tabs = [];
73+
74+
// Skip first element (empty or content before first tab)
75+
for (let i = 1; i < tabSections.length; i++) {
76+
const section = tabSections[i];
77+
78+
// Extract label and check for :default marker
79+
const labelMatch = section.match(/^([^:]+?)(?::default)?\s*-->\n([\s\S]*?)$/);
80+
if (labelMatch) {
81+
const label = labelMatch[1].trim();
82+
const content = labelMatch[2].trim();
83+
const isDefault = section.includes(':default -->');
84+
tabs.push({ label, content, isDefault });
85+
}
86+
}
87+
88+
if (tabs.length === 0) return match;
89+
90+
// Generate Docusaurus Tabs component (without imports here)
91+
let result = `<Tabs>\n`;
92+
93+
tabs.forEach(tab => {
94+
const defaultAttr = tab.isDefault ? ' default' : '';
95+
result += ` <TabItem value="${tab.label.toLowerCase().replace(/[^a-z0-9]/g, '-')}" label="${tab.label}"${defaultAttr}>\n\n`;
96+
result += `${tab.content}\n\n`;
97+
result += ` </TabItem>\n`;
98+
});
99+
100+
result += `</Tabs>`;
101+
102+
return result;
103+
});
104+
105+
// Add imports at the top of the file if tabs were found
106+
if (transformedContent !== content) {
107+
return `import Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n${transformedContent}`;
108+
}
109+
110+
return transformedContent;
111+
}
112+
58113
/**
59114
* Apply essential MDX compatibility fixes and content transformations
60115
* Combines all content-only transformations that don't require repository information
61116
*/
62117
function applyBasicMdxFixes(content) {
63-
return content
118+
// First convert tabs to Docusaurus format
119+
let transformed = convertTabsToDocusaurus(content);
120+
121+
// Then apply other MDX fixes
122+
return transformed
64123
// Convert GitHub-style callouts to Docusaurus admonitions
65-
.replace(/^> \[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*\n((?:> .*\n?)*)/gm, (match, type, content) => {
124+
.replace(/^> \[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION|REQUIREMENTS)\]\s*\n((?:> .*\n?)*)/gm, (match, type, content) => {
66125
// Map GitHub callout types to Docusaurus admonition types
67126
const typeMap = {
68127
'NOTE': 'note',
69128
'TIP': 'tip',
70129
'IMPORTANT': 'info',
71130
'WARNING': 'warning',
72-
'CAUTION': 'danger'
131+
'CAUTION': 'danger',
132+
'REQUIREMENTS': 'info' // Map to info admonition
73133
};
74134

75135
const docusaurusType = typeMap[type] || type.toLowerCase();

0 commit comments

Comments
 (0)