Skip to content

Commit 52ba95c

Browse files
authored
Tables in docs (#4835)
* Automtically transpose tables with empty heads * Extract Vite config * Do not mark headlines in plugins as code * Use tables in plugin docs * Use tables in options docs
1 parent 141039a commit 52ba95c

8 files changed

Lines changed: 847 additions & 300 deletions

File tree

docs/.vitepress/config.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
import alias from '@rollup/plugin-alias';
12
import { defineConfig } from 'vitepress';
23
import { withMermaid } from 'vitepress-plugin-mermaid';
4+
import { moduleAliases } from '../../build-plugins/aliases';
5+
import { resolutions } from '../../build-plugins/replace-browser-modules';
36
import '../declarations.d';
7+
import { examplesPlugin } from './create-examples';
8+
import { transposeTables } from './transpose-tables';
49
import { buildEnd, callback, transformPageData } from './verify-anchors';
510

611
export default withMermaid(
@@ -26,6 +31,9 @@ export default withMermaid(
2631
callback,
2732
level: 2
2833
},
34+
config(md) {
35+
transposeTables(md);
36+
},
2937
linkify: false,
3038
toc: {
3139
level: [2, 3, 4]
@@ -117,6 +125,41 @@ export default withMermaid(
117125
socialLinks: [{ icon: 'github', link: 'https://github.com/rollup/rollup' }]
118126
},
119127
title: 'Rollup',
120-
transformPageData
128+
transformPageData,
129+
vite: {
130+
optimizeDeps: { include: ['moment-mini', '@braintree/sanitize-url'] },
131+
plugins: [
132+
{
133+
apply: 'serve',
134+
enforce: 'pre',
135+
name: 'replace-browser-modules',
136+
resolveId(source, importer) {
137+
if (importer && source.startsWith('/@fs')) {
138+
const resolved = source.slice(4);
139+
if (resolutions[resolved]) {
140+
return resolutions[resolved];
141+
}
142+
}
143+
},
144+
transformIndexHtml(html) {
145+
// Unfortunately, picomatch sneaks as a dedendency into the dev bundle.
146+
// This fixes an error.
147+
return html.replace('</head>', '<script>window.process={}</script></head>');
148+
}
149+
},
150+
{
151+
apply: 'build',
152+
enforce: 'pre',
153+
name: 'replace-local-rollup',
154+
resolveId(source) {
155+
if (source.includes('/browser-entry')) {
156+
return false;
157+
}
158+
}
159+
},
160+
examplesPlugin(),
161+
alias(moduleAliases)
162+
]
163+
}
121164
})
122165
);

docs/.vitepress/create-examples.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { readFile } from 'node:fs/promises';
2+
import type { Plugin } from 'vite';
3+
import type { RollupOptions } from '../../src/rollup/types';
4+
import type { Example, Module } from '../types';
5+
import { getFilesInDirectory } from './helpers';
6+
7+
const examplesDirectory = new URL('../repl/examples', import.meta.url);
8+
9+
export function examplesPlugin(): Plugin {
10+
return {
11+
async load(id) {
12+
if (id === 'examples.json') {
13+
const exampleFiles = await getFilesInDirectory(examplesDirectory);
14+
const examples: Example[] = await Promise.all(
15+
exampleFiles.map(async id => {
16+
const {
17+
entryModules = ['main.js'],
18+
options = {},
19+
title
20+
}: {
21+
entryModules?: string[];
22+
options?: RollupOptions;
23+
title: string;
24+
} = JSON.parse(
25+
await readFile(new URL(`examples/${id}/example.json`, examplesDirectory), 'utf8')
26+
);
27+
const moduleFiles = await getFilesInDirectory(
28+
new URL(`examples/${id}/modules`, examplesDirectory)
29+
);
30+
const modules: Module[] = await Promise.all(
31+
moduleFiles.map(async name => {
32+
const code = (
33+
await readFile(
34+
new URL(`examples/${id}/modules/${name}`, examplesDirectory),
35+
'utf8'
36+
)
37+
).trim();
38+
return { code, isEntry: entryModules.includes(name), name };
39+
})
40+
);
41+
42+
modules.sort((a, b) => {
43+
if (a.name === 'main.js') return -1;
44+
if (b.name === 'main.js') return 1;
45+
if (a.isEntry) return -1;
46+
if (b.isEntry) return 1;
47+
return a.name < b.name ? -1 : 1;
48+
});
49+
50+
return { id, modules, options, title };
51+
})
52+
);
53+
const examplesById: Record<string, Example> = {};
54+
for (const example of examples) {
55+
examplesById[example.id] = example;
56+
}
57+
return JSON.stringify(examplesById);
58+
}
59+
},
60+
name: 'examples',
61+
resolveId(source) {
62+
if (source === 'examples.json') {
63+
return source;
64+
}
65+
}
66+
};
67+
}

docs/.vitepress/helpers.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { readdir } from 'node:fs/promises';
2+
3+
export async function getFilesInDirectory(directory: URL): Promise<string[]> {
4+
return (await readdir(directory)).filter(file => file[0] !== '.');
5+
}

docs/.vitepress/theme/custom.css

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,17 @@
3838
}
3939

4040
.vp-doc h4 {
41-
margin: 8px 0 -16px;
41+
margin-top: 24px;
42+
}
43+
44+
.vp-doc tr.transposed-table:nth-child(2n) {
45+
background: transparent;
46+
}
47+
48+
.vp-doc tr.transposed-table:nth-child(2n+1) {
49+
background: var(--vp-c-bg-soft);
50+
}
51+
52+
.vp-doc tr.transposed-table > th {
53+
white-space:nowrap;
4254
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import type { UserConfig } from 'vitepress';
2+
3+
export const transposeTables: NonNullable<
4+
NonNullable<UserConfig<any>['markdown']>['config']
5+
> = md => {
6+
const render = md.renderer.render.bind(md.renderer);
7+
md.renderer.render = (tokens, options, environment) => {
8+
const filteredTokens: typeof tokens = [];
9+
let inEmptyThead = false;
10+
let inTransposedTable = false;
11+
let inFirstTableRowElement = false;
12+
for (const [index, token] of tokens.entries()) {
13+
const { type } = token;
14+
if (inEmptyThead) {
15+
if (type === 'thead_close') {
16+
inEmptyThead = false;
17+
}
18+
continue;
19+
}
20+
if (type === 'thead_open' && tokens[index + 3].content === '') {
21+
inEmptyThead = true;
22+
inTransposedTable = true;
23+
continue;
24+
}
25+
if (inTransposedTable) {
26+
if (type === 'tr_open') {
27+
inFirstTableRowElement = true;
28+
token.attrPush(['class', 'transposed-table']);
29+
}
30+
if (inFirstTableRowElement) {
31+
if (type === 'td_open') {
32+
token.type = 'th_open';
33+
token.tag = 'th';
34+
} else if (type === 'td_close') {
35+
token.type = 'th_close';
36+
token.tag = 'th';
37+
inFirstTableRowElement = false;
38+
}
39+
}
40+
if (type === 'table_close') {
41+
inTransposedTable = false;
42+
}
43+
}
44+
filteredTokens.push(token);
45+
}
46+
return render(filteredTokens, options, environment);
47+
};
48+
};

0 commit comments

Comments
 (0)