@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 CHANGED
@@ -1,8 +1,14 @@
1
1
  # @quietmind/mdx-docs
2
2
 
3
- 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.
3
+ > A lightweight React framework for MDX documentation sites.
4
4
 
5
- **Demo:** https://mdxdocs.com/
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
+ ![mdx-docs documentation site](./docs/screenshot.png)
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
- ## Installation
21
+ ## Quick Start
22
+
23
+ Create a new documentation site:
16
24
 
17
25
  ```sh
18
- npm install @quietmind/mdx-docs
26
+ npx create-mdx-docs@latest my-docs
19
27
  ```
20
28
 
21
- ### Peer dependencies
29
+ Create an MDX file in `pages/`:
22
30
 
23
- ```sh
24
- npm install react react-dom react-router-dom \
25
- @emotion/react @emotion/styled \
26
- @mui/material @mui/icons-material \
27
- @mdx-js/react @mdx-js/rollup \
28
- prism-react-renderer prismjs \
29
- vite @vitejs/plugin-react
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
- ## Quick Start
47
+ Register your page in `config/pages.js`:
33
48
 
34
- ### 1. Site structure
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
- my-site/
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
- ### 2. `config/site.js`
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
- ### 3. `config/pages.js`
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
- ### 4. `main.jsx`
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
- ### 6. `index.html`
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
- <title>My Site</title>
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quietmind/mdx-docs",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "homepage": "https://mdxdocs.com",
6
6
  "exports": {
@@ -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: {