reallysimpledocs 1.0.0-beta.4 → 1.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -35
- package/package.json +10 -13
- package/src/astro/index.js +46 -98
- package/src/astro/preview-source.js +90 -0
- package/src/components/index.js +1 -0
- package/src/css/custom.css +252 -33
- package/src/css/styles/luma.css +11 -0
- package/src/css/styles/lyra.css +11 -0
- package/src/css/styles/maia.css +11 -0
- package/src/css/styles/mira.css +11 -0
- package/src/css/styles/nova.css +11 -0
- package/src/css/styles/rhea.css +11 -0
- package/src/css/styles/sera.css +11 -0
- package/src/css/styles/vega.css +11 -0
- package/src/runtime/components/BaseLayout.astro +20 -27
- package/src/runtime/components/CommandDialog.astro +30 -32
- package/src/runtime/components/DefaultContentHeader.astro +0 -17
- package/src/runtime/components/DefaultHead.astro +120 -0
- package/src/runtime/components/DefaultHeadContent.astro +2 -0
- package/src/runtime/components/DefaultSidebarHeader.astro +1 -1
- package/src/runtime/components/DocsLayout.astro +114 -165
- package/src/runtime/components/DropdownMenu.astro +1 -1
- package/src/runtime/components/ThemeToggle.astro +21 -0
- package/src/runtime/components/mdx/Callout.astro +2 -32
- package/src/runtime/components/mdx/Card.astro +3 -8
- package/src/runtime/components/mdx/CardGrid.astro +1 -1
- package/src/runtime/components/mdx/Code.astro +2 -16
- package/src/runtime/components/mdx/CodeGroup.astro +7 -11
- package/src/runtime/components/mdx/Preview.astro +7 -13
- package/src/runtime/components/mdx/Steps.astro +1 -5
- package/src/runtime/components/mdx/Tab.astro +6 -0
- package/src/runtime/components/mdx/Tabs.astro +7 -7
- package/src/runtime/lib/docs.js +130 -102
- package/src/runtime/lib/highlight.js +1 -14
- package/src/runtime/lib/macros.js +10 -5
- package/src/runtime/lib/markdown-export.js +134 -171
- package/src/runtime/pages/doc.astro +1 -3
- package/src/runtime/pages/llms-full.txt.ts +2 -2
- package/src/runtime/pages/llms.txt.ts +2 -2
- package/src/runtime/pages/markdown.ts +2 -2
- package/src/runtime/pages/search-index.ts +12 -3
- package/CHANGELOG.md +0 -35
- package/src/css/overrides.css +0 -1
- package/src/css/sources.css +0 -1
- package/src/runtime/lib/markdown-exporters/index.js +0 -144
- package/src/runtime/lib/mdx-source.js +0 -19
- package/src/runtime/lib/preview-source-plugin.js +0 -33
- package/src/runtime/scripts/copy-code.js +0 -130
- package/src/site/ContentHeader.astro +0 -33
package/README.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
A simple documentation system for Astro, built with **Basecoat** and **Tailwind CSS**.
|
|
4
4
|
|
|
5
|
-
ReallySimpleDocs
|
|
6
|
-
|
|
7
|
-
Docs stay portable: content lives in `docs/`, navigation lives in `docs/docs.json`, and the Astro integration owns the docs UI.
|
|
5
|
+
ReallySimpleDocs keeps docs portable: content lives in `docs/`, navigation lives in `docs/docs.json`, and the Astro integration owns the docs UI.
|
|
8
6
|
|
|
9
7
|
## Add to an Astro site
|
|
10
8
|
|
|
9
|
+
ReallySimpleDocs is an Astro integration. Add it to an existing Astro site, or create one first with `npm create astro@latest`.
|
|
10
|
+
|
|
11
11
|
```bash
|
|
12
|
-
npm install reallysimpledocs
|
|
12
|
+
npm install reallysimpledocs basecoat-css tailwindcss
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Add the integration:
|
|
@@ -63,47 +63,39 @@ Welcome to the docs.
|
|
|
63
63
|
|
|
64
64
|
ReallySimpleDocs injects docs pages, Lunr search, per-page Markdown exports, `llms.txt`, and `llms-full.txt`.
|
|
65
65
|
|
|
66
|
-
Use
|
|
67
|
-
|
|
68
|
-
```mdx
|
|
69
|
-
# Button
|
|
66
|
+
Use component overrides for layout chrome such as sidebar branding, extra head tags, or header controls between search and the built-in theme toggle:
|
|
70
67
|
|
|
71
|
-
|
|
68
|
+
```js
|
|
69
|
+
reallySimpleDocs({
|
|
70
|
+
components: {
|
|
71
|
+
ContentHeader: "./src/components/ContentHeader.astro",
|
|
72
|
+
},
|
|
73
|
+
});
|
|
72
74
|
```
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
For example, put only the GitHub button in `ContentHeader`; the theme toggle stays built in.
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
Use `.mdx` when a page needs ReallySimpleDocs components. Common components are available by default, so you do not need to import them in each page:
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
```mdx
|
|
81
|
+
# Button
|
|
79
82
|
|
|
80
|
-
|
|
81
|
-
npm install reallysimpledocs@beta basecoat-css@beta tailwindcss
|
|
83
|
+
<Callout title="MDX works">MDX is optional. Plain Markdown stays the default.</Callout>
|
|
82
84
|
```
|
|
83
85
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
```css
|
|
87
|
-
/* src/styles/site.css */
|
|
88
|
-
@import "tailwindcss";
|
|
89
|
-
@import "basecoat-css/base";
|
|
90
|
-
@import "basecoat-css/styles/vega";
|
|
86
|
+
## Use Basecoat outside the docs
|
|
91
87
|
|
|
92
|
-
|
|
93
|
-
```
|
|
88
|
+
By default, ReallySimpleDocs manages one Tailwind/Basecoat stylesheet for the app. It scans `src/`, `docs/`, and the ReallySimpleDocs runtime, so Basecoat and Tailwind classes used by custom Astro pages outside the docs route are included in the same CSS build.
|
|
94
89
|
|
|
95
|
-
|
|
90
|
+
Disable managed CSS only when you want to provide the full stylesheet pipeline yourself:
|
|
96
91
|
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
<slot />
|
|
92
|
+
```js
|
|
93
|
+
reallySimpleDocs({
|
|
94
|
+
css: false,
|
|
95
|
+
});
|
|
104
96
|
```
|
|
105
97
|
|
|
106
|
-
Use
|
|
98
|
+
Use `css: false` when you bring your own Tailwind/Basecoat/RSD stylesheet. ReallySimpleDocs still provides its managed JavaScript.
|
|
107
99
|
|
|
108
100
|
## Local development (this repo)
|
|
109
101
|
|
|
@@ -112,17 +104,25 @@ npm install
|
|
|
112
104
|
npm run dev
|
|
113
105
|
```
|
|
114
106
|
|
|
107
|
+
Useful checks before publishing changes:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm run build
|
|
111
|
+
npm pack --dry-run
|
|
112
|
+
npm run smoke:consumer
|
|
113
|
+
```
|
|
114
|
+
|
|
115
115
|
## Documentation
|
|
116
116
|
|
|
117
117
|
Go to [ReallySimpleDocs.com](https://reallysimpledocs.com).
|
|
118
118
|
|
|
119
|
-
## Support the project
|
|
119
|
+
## Support the project
|
|
120
120
|
|
|
121
|
-
- [Contribute code](
|
|
121
|
+
- [Contribute code](/CONTRIBUTING.md)
|
|
122
122
|
- [Report issues](https://github.com/hunvreus/reallysimpledocs/issues)
|
|
123
123
|
- [Sponsor me](https://github.com/sponsors/hunvreus)
|
|
124
124
|
- [Star the project on GitHub](https://github.com/hunvreus/reallysimpledocs)
|
|
125
125
|
|
|
126
126
|
## License
|
|
127
127
|
|
|
128
|
-
[MIT](
|
|
128
|
+
[MIT](/LICENSE.md)
|
package/package.json
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reallysimpledocs",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./src/index.js",
|
|
7
7
|
"./astro": "./src/astro/index.js",
|
|
8
|
-
"./components": "./src/components/index.js"
|
|
8
|
+
"./components": "./src/components/index.js",
|
|
9
|
+
"./css": "./src/css/custom.css",
|
|
10
|
+
"./css/styles/*": "./src/css/styles/*.css",
|
|
11
|
+
"./css/styles/*.css": "./src/css/styles/*.css"
|
|
9
12
|
},
|
|
10
13
|
"files": [
|
|
11
14
|
"src",
|
|
12
15
|
"README.md",
|
|
13
|
-
"CHANGELOG.md",
|
|
14
16
|
"LICENSE.md"
|
|
15
17
|
],
|
|
16
18
|
"scripts": {
|
|
@@ -24,25 +26,20 @@
|
|
|
24
26
|
"@astrojs/markdown-remark": "^7.2.0",
|
|
25
27
|
"@astrojs/mdx": "^6.0.3",
|
|
26
28
|
"@tailwindcss/vite": "4.1.17",
|
|
27
|
-
"astro": "^6.4.6",
|
|
28
29
|
"github-slugger": "^2.0.0",
|
|
29
30
|
"lucide-static": "^0.552.0",
|
|
30
31
|
"lunr": "^2.3.9",
|
|
31
32
|
"marked": "^16.4.1",
|
|
32
|
-
"
|
|
33
|
-
"mdast-util-to-markdown": "^2.1.2",
|
|
34
|
-
"remark-gfm": "^4.0.1",
|
|
35
|
-
"remark-mdx": "^3.1.1",
|
|
36
|
-
"remark-parse": "^11.0.0",
|
|
37
|
-
"shiki": "^4.1.0",
|
|
38
|
-
"unified": "^11.0.5"
|
|
33
|
+
"shiki": "^4.1.0"
|
|
39
34
|
},
|
|
40
35
|
"peerDependencies": {
|
|
41
|
-
"
|
|
36
|
+
"astro": "^6.4.6",
|
|
37
|
+
"basecoat-css": "^1.0.0-beta.5",
|
|
42
38
|
"tailwindcss": ">=4.1.17 <5"
|
|
43
39
|
},
|
|
44
40
|
"devDependencies": {
|
|
45
|
-
"
|
|
41
|
+
"astro": "^6.4.6",
|
|
42
|
+
"basecoat-css": "^1.0.0-beta.5",
|
|
46
43
|
"tailwindcss": "4.1.17"
|
|
47
44
|
},
|
|
48
45
|
"overrides": {
|
package/src/astro/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { unified as astroMarkdown } from "@astrojs/markdown-remark";
|
|
5
4
|
import mdx from "@astrojs/mdx";
|
|
5
|
+
import { unified } from "@astrojs/markdown-remark";
|
|
6
6
|
import tailwindcss from "@tailwindcss/vite";
|
|
7
|
-
import {
|
|
7
|
+
import { remarkPreviewSource } from "./preview-source.js";
|
|
8
8
|
|
|
9
9
|
const basecoatStyles = new Set(["vega", "nova", "maia", "lyra", "mira", "luma", "sera", "rhea"]);
|
|
10
10
|
|
|
@@ -28,12 +28,7 @@ const normalizeArray = (value) => (Array.isArray(value) ? value : value ? [value
|
|
|
28
28
|
|
|
29
29
|
const normalizeImportPath = (filePath) => filePath.replaceAll(path.sep, "/");
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
const isInsideDir = (dir, file) => {
|
|
34
|
-
const relative = path.relative(dir, file);
|
|
35
|
-
return relative && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
36
|
-
};
|
|
31
|
+
const normalizeBoolean = (value, fallback = true) => (value === undefined ? fallback : Boolean(value));
|
|
37
32
|
|
|
38
33
|
const shikiConfig = {
|
|
39
34
|
themes: {
|
|
@@ -63,18 +58,6 @@ function collectMdxModules(docsDir) {
|
|
|
63
58
|
return modules;
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
function componentModuleSource(modules) {
|
|
67
|
-
const entries = Object.entries(modules);
|
|
68
|
-
const imports = entries
|
|
69
|
-
.map(([name, moduleId], index) => `import component${index} from ${JSON.stringify(moduleId)};`)
|
|
70
|
-
.join("\n");
|
|
71
|
-
return `${imports}
|
|
72
|
-
export default {
|
|
73
|
-
${entries.map(([name], index) => ` ${JSON.stringify(name)}: component${index},`).join("\n")}
|
|
74
|
-
};
|
|
75
|
-
`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
61
|
export default function reallySimpleDocs(options = {}) {
|
|
79
62
|
const style = options.style || "vega";
|
|
80
63
|
if (!basecoatStyles.has(style)) {
|
|
@@ -87,9 +70,8 @@ export default function reallySimpleDocs(options = {}) {
|
|
|
87
70
|
siteFile: options.siteFile || null,
|
|
88
71
|
style,
|
|
89
72
|
customCss: normalizeArray(options.customCss),
|
|
73
|
+
css: normalizeBoolean(options.css),
|
|
90
74
|
components: options.components || {},
|
|
91
|
-
mdxComponents: normalizeRecord(options.mdxComponents),
|
|
92
|
-
markdownSerializers: normalizeRecord(options.markdownSerializers),
|
|
93
75
|
routeBase: options.routeBase ?? "/docs",
|
|
94
76
|
assetsBase: options.assetsBase || "/assets",
|
|
95
77
|
};
|
|
@@ -97,57 +79,51 @@ export default function reallySimpleDocs(options = {}) {
|
|
|
97
79
|
return {
|
|
98
80
|
name: "reallysimpledocs",
|
|
99
81
|
hooks: {
|
|
100
|
-
"astro:config:setup": ({ injectRoute, updateConfig, config }) => {
|
|
82
|
+
"astro:config:setup": ({ injectRoute, injectScript, updateConfig, config }) => {
|
|
101
83
|
const root = fileURLToPath(config.root);
|
|
102
84
|
const generatedDir = path.join(root, ".astro", "reallysimpledocs");
|
|
103
85
|
const generatedStyles = path.join(generatedDir, "styles.css");
|
|
104
86
|
const docsDir = path.resolve(root, normalizedOptions.docsDir);
|
|
105
|
-
const resolveUserId = (id) => (id?.startsWith(".") ? path.resolve(root, id) : id);
|
|
106
|
-
const markdownSerializers = Object.fromEntries(
|
|
107
|
-
Object.entries(normalizedOptions.markdownSerializers).map(([name, moduleId]) => [
|
|
108
|
-
name,
|
|
109
|
-
normalizeImportPath(resolveUserId(moduleId)),
|
|
110
|
-
]),
|
|
111
|
-
);
|
|
112
|
-
const mdxComponents = Object.fromEntries(
|
|
113
|
-
Object.entries(normalizedOptions.mdxComponents).map(([name, moduleId]) => [
|
|
114
|
-
name,
|
|
115
|
-
normalizeImportPath(resolveUserId(moduleId)),
|
|
116
|
-
]),
|
|
117
|
-
);
|
|
118
87
|
const virtualConfig = {
|
|
119
88
|
...normalizedOptions,
|
|
120
89
|
root,
|
|
121
90
|
docsDir,
|
|
122
91
|
siteFile: normalizedOptions.siteFile ? path.resolve(root, normalizedOptions.siteFile) : null,
|
|
123
|
-
mdxComponents,
|
|
124
|
-
markdownSerializers,
|
|
125
92
|
routeBase: normalizeRouteBase(normalizedOptions.routeBase),
|
|
126
93
|
};
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
SidebarFooter:
|
|
133
|
-
|
|
94
|
+
const mdxModules = collectMdxModules(docsDir);
|
|
95
|
+
const resolveUserId = (id) => (id?.startsWith(".") ? path.resolve(root, id) : id);
|
|
96
|
+
const componentDefaults = {
|
|
97
|
+
Head: runtimePath("components/DefaultHeadContent.astro"),
|
|
98
|
+
SidebarHeader: runtimePath("components/DefaultSidebarHeader.astro"),
|
|
99
|
+
SidebarFooter: runtimePath("components/DefaultSidebarFooter.astro"),
|
|
100
|
+
ContentHeader: runtimePath("components/DefaultContentHeader.astro"),
|
|
134
101
|
};
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
'@import "basecoat-css/base";',
|
|
141
|
-
`@import "basecoat-css/styles/${style}";`,
|
|
142
|
-
`@import ${JSON.stringify(cssPath("sources.css"))};`,
|
|
143
|
-
`@import ${JSON.stringify(cssPath("custom.css"))};`,
|
|
144
|
-
`@import ${JSON.stringify(cssPath("overrides.css"))};`,
|
|
145
|
-
...normalizedOptions.customCss.map((css) => `@import ${JSON.stringify(resolveUserId(css))};`),
|
|
146
|
-
`@source ${JSON.stringify(runtimePath("**/*.{astro,js,ts}"))};`,
|
|
147
|
-
`@source ${JSON.stringify(path.join(virtualConfig.docsDir, "**/*.{md,mdx}"))};`,
|
|
148
|
-
"",
|
|
149
|
-
].join("\n"),
|
|
102
|
+
const components = Object.fromEntries(
|
|
103
|
+
Object.entries(componentDefaults).map(([name, defaultPath]) => [
|
|
104
|
+
name,
|
|
105
|
+
normalizedOptions.components[name] || defaultPath,
|
|
106
|
+
]),
|
|
150
107
|
);
|
|
108
|
+
fs.mkdirSync(generatedDir, { recursive: true });
|
|
109
|
+
const styleSource = normalizedOptions.css
|
|
110
|
+
? [
|
|
111
|
+
'@import "tailwindcss";',
|
|
112
|
+
'@import "basecoat-css/base";',
|
|
113
|
+
`@import "basecoat-css/styles/${style}";`,
|
|
114
|
+
`@import ${JSON.stringify(cssPath("custom.css"))};`,
|
|
115
|
+
`@import ${JSON.stringify(cssPath(`styles/${style}.css`))};`,
|
|
116
|
+
...normalizedOptions.customCss.map((css) => `@import ${JSON.stringify(resolveUserId(css))};`),
|
|
117
|
+
`@source ${JSON.stringify(path.join(root, "src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"))};`,
|
|
118
|
+
`@source ${JSON.stringify(runtimePath("**/*.{astro,js,ts}"))};`,
|
|
119
|
+
`@source ${JSON.stringify(path.join(virtualConfig.docsDir, "**/*.{md,mdx}"))};`,
|
|
120
|
+
"",
|
|
121
|
+
].join("\n")
|
|
122
|
+
: "/* ReallySimpleDocs CSS disabled by config. */\n";
|
|
123
|
+
fs.writeFileSync(generatedStyles, styleSource);
|
|
124
|
+
if (normalizedOptions.css) {
|
|
125
|
+
injectScript("page-ssr", 'import "virtual:reallysimpledocs/styles.css";');
|
|
126
|
+
}
|
|
151
127
|
|
|
152
128
|
injectRoute({
|
|
153
129
|
pattern: routePattern(normalizedOptions.routeBase),
|
|
@@ -178,8 +154,8 @@ export default function reallySimpleDocs(options = {}) {
|
|
|
178
154
|
}),
|
|
179
155
|
],
|
|
180
156
|
markdown: {
|
|
181
|
-
processor:
|
|
182
|
-
remarkPlugins: [
|
|
157
|
+
processor: unified({
|
|
158
|
+
remarkPlugins: [[remarkPreviewSource, { docsDir }]],
|
|
183
159
|
}),
|
|
184
160
|
shikiConfig,
|
|
185
161
|
},
|
|
@@ -191,41 +167,20 @@ export default function reallySimpleDocs(options = {}) {
|
|
|
191
167
|
tailwindcss(),
|
|
192
168
|
{
|
|
193
169
|
name: "reallysimpledocs-virtual-modules",
|
|
194
|
-
configureServer(server) {
|
|
195
|
-
const invalidateMdxPages = () => {
|
|
196
|
-
const module = server.moduleGraph.getModuleById("\0virtual:reallysimpledocs/mdx-pages");
|
|
197
|
-
if (module) server.moduleGraph.invalidateModule(module);
|
|
198
|
-
server.ws.send({ type: "full-reload" });
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
server.watcher.add(path.join(docsDir, "**/*.mdx"));
|
|
202
|
-
server.watcher.on("add", (file) => {
|
|
203
|
-
if (file.endsWith(".mdx") && isInsideDir(docsDir, file)) invalidateMdxPages();
|
|
204
|
-
});
|
|
205
|
-
server.watcher.on("unlink", (file) => {
|
|
206
|
-
if (file.endsWith(".mdx") && isInsideDir(docsDir, file)) invalidateMdxPages();
|
|
207
|
-
});
|
|
208
|
-
},
|
|
209
170
|
resolveId(id) {
|
|
210
171
|
if (id === "virtual:reallysimpledocs/config") return "\0virtual:reallysimpledocs/config";
|
|
211
172
|
if (id === "virtual:reallysimpledocs/mdx-pages") return "\0virtual:reallysimpledocs/mdx-pages";
|
|
212
|
-
if (id === "virtual:reallysimpledocs/mdx-components") return "\0virtual:reallysimpledocs/mdx-components";
|
|
213
173
|
if (id === "virtual:reallysimpledocs/styles.css") return generatedStyles;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
return "\0virtual:reallysimpledocs/components/SidebarFooter";
|
|
219
|
-
}
|
|
220
|
-
if (id === "virtual:reallysimpledocs/components/ContentHeader") {
|
|
221
|
-
return "\0virtual:reallysimpledocs/components/ContentHeader";
|
|
174
|
+
for (const name of Object.keys(components)) {
|
|
175
|
+
if (id === `virtual:reallysimpledocs/components/${name}`) {
|
|
176
|
+
return `\0virtual:reallysimpledocs/components/${name}`;
|
|
177
|
+
}
|
|
222
178
|
}
|
|
223
179
|
return null;
|
|
224
180
|
},
|
|
225
181
|
load(id) {
|
|
226
182
|
if (id === "\0virtual:reallysimpledocs/config") return `export default ${JSON.stringify(virtualConfig)};`;
|
|
227
183
|
if (id === "\0virtual:reallysimpledocs/mdx-pages") {
|
|
228
|
-
const mdxModules = collectMdxModules(docsDir);
|
|
229
184
|
const imports = Object.entries(mdxModules)
|
|
230
185
|
.map(([slug, filePath], index) => `import * as mdx${index} from ${JSON.stringify(filePath)};`)
|
|
231
186
|
.join("\n");
|
|
@@ -241,17 +196,10 @@ export async function getMdxPage(slug) {
|
|
|
241
196
|
}
|
|
242
197
|
`;
|
|
243
198
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return `export { default } from ${JSON.stringify(resolveUserId(components.SidebarHeader))};`;
|
|
249
|
-
}
|
|
250
|
-
if (id === "\0virtual:reallysimpledocs/components/SidebarFooter") {
|
|
251
|
-
return `export { default } from ${JSON.stringify(resolveUserId(components.SidebarFooter))};`;
|
|
252
|
-
}
|
|
253
|
-
if (id === "\0virtual:reallysimpledocs/components/ContentHeader") {
|
|
254
|
-
return `export { default } from ${JSON.stringify(resolveUserId(components.ContentHeader))};`;
|
|
199
|
+
for (const [name, componentPath] of Object.entries(components)) {
|
|
200
|
+
if (id === `\0virtual:reallysimpledocs/components/${name}`) {
|
|
201
|
+
return `export { default } from ${JSON.stringify(resolveUserId(componentPath))};`;
|
|
202
|
+
}
|
|
255
203
|
}
|
|
256
204
|
return null;
|
|
257
205
|
},
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { toMarkdown } from "mdast-util-to-markdown";
|
|
2
|
+
import { mdxToMarkdown } from "mdast-util-mdx";
|
|
3
|
+
|
|
4
|
+
export function remarkPreviewSource({ docsDir } = {}) {
|
|
5
|
+
const normalizedDocsDir = docsDir ? normalizePath(docsDir).replace(/\/$/, "") : "";
|
|
6
|
+
|
|
7
|
+
return (tree, file) => {
|
|
8
|
+
if (normalizedDocsDir && !isDocsFile(file?.path, normalizedDocsDir)) return;
|
|
9
|
+
|
|
10
|
+
visit(tree, (node) => {
|
|
11
|
+
if (node?.type !== "mdxJsxFlowElement") return;
|
|
12
|
+
if (node.name === "Preview") addPreviewSource(node);
|
|
13
|
+
if (node.name === "Tabs") addTabsMetadata(node);
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isDocsFile(filePath, docsDir) {
|
|
19
|
+
const normalized = normalizePath(filePath || "");
|
|
20
|
+
return normalized === docsDir || normalized.startsWith(`${docsDir}/`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function normalizePath(value) {
|
|
24
|
+
return String(value || "").replaceAll("\\", "/");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function addPreviewSource(node) {
|
|
28
|
+
node.attributes ||= [];
|
|
29
|
+
if (hasAttr(node, "code")) return;
|
|
30
|
+
|
|
31
|
+
const source = toMarkdown({ type: "root", children: node.children || [] }, { extensions: [mdxToMarkdown()] }).trim();
|
|
32
|
+
node.attributes.push({ type: "mdxJsxAttribute", name: "code", value: source });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function addTabsMetadata(node) {
|
|
36
|
+
node.attributes ||= [];
|
|
37
|
+
if (hasAttr(node, "tabs")) return;
|
|
38
|
+
|
|
39
|
+
const tabNodes = (node.children || []).filter((child) => child?.type === "mdxJsxFlowElement" && child.name === "Tab");
|
|
40
|
+
if (!tabNodes.length) return;
|
|
41
|
+
|
|
42
|
+
const seen = new Map();
|
|
43
|
+
const tabs = tabNodes.map((tab, index) => {
|
|
44
|
+
tab.attributes ||= [];
|
|
45
|
+
const title = getAttr(tab, "title") || `Tab ${index + 1}`;
|
|
46
|
+
const value = uniqueValue(slugify(title) || `tab-${index + 1}`, seen);
|
|
47
|
+
if (!hasAttr(tab, "slot")) {
|
|
48
|
+
tab.attributes.push({ type: "mdxJsxAttribute", name: "slot", value });
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
label: title,
|
|
52
|
+
slot: value,
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
node.attributes.push({
|
|
57
|
+
type: "mdxJsxAttribute",
|
|
58
|
+
name: "tabs",
|
|
59
|
+
value: JSON.stringify(tabs),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function visit(node, visitor) {
|
|
64
|
+
visitor(node);
|
|
65
|
+
if (!Array.isArray(node?.children)) return;
|
|
66
|
+
for (const child of node.children) visit(child, visitor);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getAttr(node, name) {
|
|
70
|
+
const attr = (node.attributes || []).find((item) => item.type === "mdxJsxAttribute" && item.name === name);
|
|
71
|
+
return typeof attr?.value === "string" ? attr.value : "";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function hasAttr(node, name) {
|
|
75
|
+
return (node.attributes || []).some((item) => item.type === "mdxJsxAttribute" && item.name === name);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function slugify(value) {
|
|
79
|
+
return String(value || "")
|
|
80
|
+
.trim()
|
|
81
|
+
.toLowerCase()
|
|
82
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
83
|
+
.replace(/^-+|-+$/g, "");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function uniqueValue(value, seen) {
|
|
87
|
+
const count = seen.get(value) || 0;
|
|
88
|
+
seen.set(value, count + 1);
|
|
89
|
+
return count ? `${value}-${count + 1}` : value;
|
|
90
|
+
}
|
package/src/components/index.js
CHANGED
|
@@ -10,4 +10,5 @@ export { default as CodeGroup } from "../runtime/components/mdx/CodeGroup.astro"
|
|
|
10
10
|
export { default as Preview } from "../runtime/components/mdx/Preview.astro";
|
|
11
11
|
export { default as Step } from "../runtime/components/mdx/Step.astro";
|
|
12
12
|
export { default as Steps } from "../runtime/components/mdx/Steps.astro";
|
|
13
|
+
export { default as Tab } from "../runtime/components/mdx/Tab.astro";
|
|
13
14
|
export { default as Tabs } from "../runtime/components/mdx/Tabs.astro";
|