@quietmind/mdx-docs 0.1.8 → 0.1.10
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 +122 -76
- package/package.json +1 -1
- package/src/vite.config.helper.js +39 -1
package/README.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# @quietmind/mdx-docs
|
|
2
2
|
|
|
3
|
-
A React
|
|
3
|
+
> A lightweight React framework for MDX documentation sites.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
MDX Docs turns MDX files into routed documentation pages with a built-in layout, sidebar, and navigation.
|
|
6
|
+
|
|
7
|
+
MDX Docs is a React + Vite framework for building MDX-powered documentation sites. Write pages in Markdown with embedded React components, and get a fully-featured site with syntax highlighting, dark/light mode, and responsive navigation out of the box.
|
|
8
|
+
|
|
9
|
+
**Demo:** [https://mdxdocs.com/](https://mdxdocs.com/)
|
|
10
|
+
|
|
11
|
+

|
|
6
12
|
|
|
7
13
|
## Features
|
|
8
14
|
|
|
@@ -12,49 +18,130 @@ A React + Vite framework for building MDX-powered documentation sites. Write pag
|
|
|
12
18
|
- Responsive sidebar navigation
|
|
13
19
|
- Built on React 19, Material-UI 7, and Vite 6
|
|
14
20
|
|
|
15
|
-
##
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
Create a new documentation site:
|
|
16
24
|
|
|
17
25
|
```sh
|
|
18
|
-
|
|
26
|
+
npx create-mdx-docs@latest my-docs
|
|
19
27
|
```
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
Create an MDX file in `pages/`:
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
~~~mdx
|
|
32
|
+
import { Button } from "@mui/material";
|
|
33
|
+
|
|
34
|
+
# Button
|
|
35
|
+
|
|
36
|
+
<Button variant="contained" color="primary">
|
|
37
|
+
Primary Action
|
|
38
|
+
</Button>
|
|
39
|
+
|
|
40
|
+
```jsx
|
|
41
|
+
<Button variant="contained" color="primary">
|
|
42
|
+
Primary Action
|
|
43
|
+
</Button>
|
|
30
44
|
```
|
|
45
|
+
~~~
|
|
31
46
|
|
|
32
|
-
|
|
47
|
+
Register your page in `config/pages.js`:
|
|
33
48
|
|
|
34
|
-
|
|
49
|
+
```js
|
|
50
|
+
const GettingStartedMDX = lazy(() => import("@pages/getting-started.mdx"));
|
|
35
51
|
|
|
52
|
+
export const pages = [
|
|
53
|
+
// ...existing pages
|
|
54
|
+
{
|
|
55
|
+
name: "Getting Started",
|
|
56
|
+
route: "/getting-started",
|
|
57
|
+
component: GettingStartedMDX,
|
|
58
|
+
},
|
|
59
|
+
];
|
|
36
60
|
```
|
|
37
|
-
|
|
61
|
+
|
|
62
|
+
Pages with `isDefault: true` do not appear in the sidebar navigation.
|
|
63
|
+
|
|
64
|
+
Configure your site name and description in `config/site.js`.
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
export const site = {
|
|
68
|
+
name: "My Site",
|
|
69
|
+
description: "My site description",
|
|
70
|
+
};
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Favicon
|
|
74
|
+
|
|
75
|
+
Place your favicon in the `public/` directory and add a `<link>` tag to `index.html`:
|
|
76
|
+
|
|
77
|
+
```html
|
|
78
|
+
<head>
|
|
79
|
+
<!-- ... -->
|
|
80
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
81
|
+
</head>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Vite serves files in `public/` at the root path, so `public/favicon.svg` is accessible as `/favicon.svg`. Use `.ico`, `.png`, or `.svg` depending on your file.
|
|
85
|
+
|
|
86
|
+
## Project Structure
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
my-docs/
|
|
38
90
|
├── pages/
|
|
39
91
|
│ └── home.mdx
|
|
40
92
|
├── config/
|
|
41
93
|
│ ├── pages.js
|
|
42
94
|
│ └── site.js
|
|
95
|
+
├── public/
|
|
96
|
+
│ └── favicon.svg
|
|
43
97
|
├── index.html
|
|
44
98
|
├── main.jsx
|
|
45
99
|
├── vite.config.js
|
|
46
100
|
└── package.json
|
|
47
101
|
```
|
|
48
102
|
|
|
49
|
-
|
|
103
|
+
Vite serves files in `public/` at the root path, so `public/favicon.svg` is accessible as `/favicon.svg`. Use `.ico`, `.png`, or `.svg` depending on your file.
|
|
104
|
+
|
|
105
|
+
## Manual Installation
|
|
106
|
+
|
|
107
|
+
### 1. Install Package
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
npm install mdx-docs
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 2. Install Peer Dependencies
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
npm install react react-dom react-router-dom \
|
|
117
|
+
@emotion/react @emotion/styled \
|
|
118
|
+
@mui/material @mui/icons-material \
|
|
119
|
+
@mdx-js/react @mdx-js/rollup \
|
|
120
|
+
prism-react-renderer prismjs \
|
|
121
|
+
vite @vitejs/plugin-react
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 3. `main.jsx`
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
import "@quietmind/mdx-docs/index.css";
|
|
128
|
+
import { createApp } from "@quietmind/mdx-docs";
|
|
129
|
+
import { pages } from "./config/pages.js";
|
|
130
|
+
import { site } from "./config/site.js";
|
|
131
|
+
|
|
132
|
+
createApp({ pages, site });
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 4. `config/site.js`
|
|
50
136
|
|
|
51
137
|
```js
|
|
52
138
|
export const site = {
|
|
53
139
|
name: "My Site",
|
|
140
|
+
description: "My site description",
|
|
54
141
|
};
|
|
55
142
|
```
|
|
56
143
|
|
|
57
|
-
###
|
|
144
|
+
### 5. `config/pages.js`
|
|
58
145
|
|
|
59
146
|
```js
|
|
60
147
|
import { lazy } from "react";
|
|
@@ -71,29 +158,19 @@ export const pages = [
|
|
|
71
158
|
];
|
|
72
159
|
```
|
|
73
160
|
|
|
74
|
-
###
|
|
75
|
-
|
|
76
|
-
```js
|
|
77
|
-
import "@quietmind/mdx-docs/index.css";
|
|
78
|
-
import { createApp } from "@quietmind/mdx-docs";
|
|
79
|
-
import { pages } from "./config/pages.js";
|
|
80
|
-
import { site } from "./config/site.js";
|
|
81
|
-
|
|
82
|
-
createApp({ pages, site });
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### 5. `vite.config.js`
|
|
161
|
+
### 6. `vite.config.js`
|
|
86
162
|
|
|
87
163
|
```js
|
|
88
164
|
import { defineConfig } from "vite";
|
|
89
165
|
import { createMdxDocsConfig } from "@quietmind/mdx-docs/vite";
|
|
166
|
+
import { site } from "./config/site.js";
|
|
90
167
|
|
|
91
168
|
export default defineConfig(
|
|
92
|
-
createMdxDocsConfig({ rootDir: import.meta.dirname })
|
|
169
|
+
createMdxDocsConfig({ rootDir: import.meta.dirname, site })
|
|
93
170
|
);
|
|
94
171
|
```
|
|
95
172
|
|
|
96
|
-
###
|
|
173
|
+
### 7. `index.html`
|
|
97
174
|
|
|
98
175
|
```html
|
|
99
176
|
<!DOCTYPE html>
|
|
@@ -101,7 +178,8 @@ export default defineConfig(
|
|
|
101
178
|
<head>
|
|
102
179
|
<meta charset="UTF-8" />
|
|
103
180
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
104
|
-
<
|
|
181
|
+
<meta name="description" content="%SITE_DESCRIPTION%" />
|
|
182
|
+
<title>%SITE_NAME%</title>
|
|
105
183
|
</head>
|
|
106
184
|
<body>
|
|
107
185
|
<div id="root"></div>
|
|
@@ -110,50 +188,6 @@ export default defineConfig(
|
|
|
110
188
|
</html>
|
|
111
189
|
```
|
|
112
190
|
|
|
113
|
-
## Adding Pages
|
|
114
|
-
|
|
115
|
-
Create an MDX file in `pages/`:
|
|
116
|
-
|
|
117
|
-
~~~mdx
|
|
118
|
-
# Getting Started
|
|
119
|
-
|
|
120
|
-
This is a documentation page with **markdown** and React components.
|
|
121
|
-
|
|
122
|
-
```js
|
|
123
|
-
const hello = "world";
|
|
124
|
-
```
|
|
125
|
-
~~~
|
|
126
|
-
|
|
127
|
-
Register it in `config/pages.js`:
|
|
128
|
-
|
|
129
|
-
```js
|
|
130
|
-
const GettingStartedMDX = lazy(() => import("@pages/getting-started.mdx"));
|
|
131
|
-
|
|
132
|
-
export const pages = [
|
|
133
|
-
// ...existing pages
|
|
134
|
-
{
|
|
135
|
-
name: "Getting Started",
|
|
136
|
-
route: "/getting-started",
|
|
137
|
-
component: GettingStartedMDX,
|
|
138
|
-
},
|
|
139
|
-
];
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Pages without `isDefault: true` appear in the sidebar navigation. The page with `isDefault: true` is the fallback/home route.
|
|
143
|
-
|
|
144
|
-
## Favicon
|
|
145
|
-
|
|
146
|
-
Place your favicon in the `public/` directory and add a `<link>` tag to `index.html`:
|
|
147
|
-
|
|
148
|
-
```html
|
|
149
|
-
<head>
|
|
150
|
-
<!-- ... -->
|
|
151
|
-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
152
|
-
</head>
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
Vite serves files in `public/` at the root path, so `public/favicon.svg` is accessible as `/favicon.svg`. Use `.ico`, `.png`, or `.svg` depending on your file.
|
|
156
|
-
|
|
157
191
|
## Tech Stack
|
|
158
192
|
|
|
159
193
|
- React 19, Material-UI 7, Emotion
|
|
@@ -161,6 +195,18 @@ Vite serves files in `public/` at the root path, so `public/favicon.svg` is acce
|
|
|
161
195
|
- React Router DOM 7
|
|
162
196
|
- Prism React Renderer
|
|
163
197
|
|
|
198
|
+
## Contributing
|
|
199
|
+
|
|
200
|
+
Contributions are welcome!
|
|
201
|
+
|
|
202
|
+
1. Fork the repo
|
|
203
|
+
2. Create a branch
|
|
204
|
+
3. Submit a pull request
|
|
205
|
+
|
|
206
|
+
## Related Projects
|
|
207
|
+
|
|
208
|
+
- [https://mdxjs.com/](https://mdxjs.com/)
|
|
209
|
+
|
|
164
210
|
## License
|
|
165
211
|
|
|
166
212
|
MIT
|
package/package.json
CHANGED
|
@@ -2,12 +2,42 @@ import mdx from "@mdx-js/rollup";
|
|
|
2
2
|
import react from "@vitejs/plugin-react";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Rehype plugin that removes <p> wrappers MDX generates around text children
|
|
7
|
+
* of JSX flow elements. This happens because Prettier formats JSX text onto
|
|
8
|
+
* its own line, which MDX interprets as a paragraph. The unwrapping only
|
|
9
|
+
* applies to <p> elements whose children are all plain text nodes — explicit
|
|
10
|
+
* block content is left untouched.
|
|
11
|
+
*/
|
|
12
|
+
export function rehypeUnwrapJsxParagraphs() {
|
|
13
|
+
function processNode(node) {
|
|
14
|
+
if (!node.children) return;
|
|
15
|
+
node.children.forEach(processNode);
|
|
16
|
+
if (node.type === "mdxJsxFlowElement") {
|
|
17
|
+
node.children = node.children.flatMap((child) => {
|
|
18
|
+
if (
|
|
19
|
+
child.type === "element" &&
|
|
20
|
+
child.tagName === "p" &&
|
|
21
|
+
child.children.every((c) => c.type === "text")
|
|
22
|
+
) {
|
|
23
|
+
return child.children;
|
|
24
|
+
}
|
|
25
|
+
return [child];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return processNode;
|
|
30
|
+
}
|
|
31
|
+
|
|
5
32
|
/**
|
|
6
33
|
* Creates a base Vite config for an mdx-docs site.
|
|
7
34
|
*
|
|
8
35
|
* @param {object} options
|
|
9
36
|
* @param {string} options.rootDir - The site's root directory (pass `import.meta.dirname`)
|
|
10
37
|
* @param {string} [options.base="/"] - The base URL for the site
|
|
38
|
+
* @param {object} [options.site] - The site config object (from `config/site.js`)
|
|
39
|
+
* @param {string} [options.site.name] - Site name, replaces `%SITE_NAME%` in index.html
|
|
40
|
+
* @param {string} [options.site.description] - Site description, replaces `%SITE_DESCRIPTION%` in index.html
|
|
11
41
|
* @returns {import('vite').UserConfig}
|
|
12
42
|
*
|
|
13
43
|
* @example
|
|
@@ -19,14 +49,22 @@ import { fileURLToPath } from "url";
|
|
|
19
49
|
* createMdxDocsConfig({ rootDir: import.meta.dirname })
|
|
20
50
|
* );
|
|
21
51
|
*/
|
|
22
|
-
export function createMdxDocsConfig({ rootDir, base = "/" } = {}) {
|
|
52
|
+
export function createMdxDocsConfig({ rootDir, base = "/", site = {} } = {}) {
|
|
23
53
|
return {
|
|
24
54
|
base,
|
|
25
55
|
plugins: [
|
|
56
|
+
{
|
|
57
|
+
name: "html-site-config",
|
|
58
|
+
transformIndexHtml: (html) =>
|
|
59
|
+
html
|
|
60
|
+
.replace("%SITE_NAME%", site.name ?? "")
|
|
61
|
+
.replace("%SITE_DESCRIPTION%", site.description ?? ""),
|
|
62
|
+
},
|
|
26
63
|
react(),
|
|
27
64
|
mdx({
|
|
28
65
|
jsxImportSource: "@emotion/react",
|
|
29
66
|
providerImportSource: "@mdx-js/react",
|
|
67
|
+
rehypePlugins: [rehypeUnwrapJsxParagraphs],
|
|
30
68
|
}),
|
|
31
69
|
],
|
|
32
70
|
resolve: {
|