@rasenganjs/mdx 1.0.0
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/CODE_OF_CONDUCT.md +38 -0
- package/CONTRIBUTING.md +0 -0
- package/LICENSE +21 -0
- package/README.md +107 -0
- package/lib/components/index.d.ts +35 -0
- package/lib/components/index.js +92 -0
- package/lib/components/index.js.map +1 -0
- package/lib/index.d.ts +35 -0
- package/lib/index.js +72 -0
- package/lib/index.js.map +1 -0
- package/lib/types/index.d.ts +15 -0
- package/lib/types/index.js +2 -0
- package/lib/types/index.js.map +1 -0
- package/lib/utils/generate-page.d.ts +10 -0
- package/lib/utils/generate-page.js +18 -0
- package/lib/utils/generate-page.js.map +1 -0
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +3 -0
- package/lib/utils/index.js.map +1 -0
- package/package.json +49 -0
- package/src/components/index.tsx +219 -0
- package/src/index.ts +82 -0
- package/src/types/index.ts +15 -0
- package/src/utils/generate-page.tsx +24 -0
- package/src/utils/index.ts +3 -0
- package/tsconfig.json +37 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability or other physical appearance.
|
|
6
|
+
|
|
7
|
+
## Our Standards
|
|
8
|
+
|
|
9
|
+
Examples of behavior that contributes to creating a positive environment include:
|
|
10
|
+
|
|
11
|
+
- Using welcoming and inclusive language
|
|
12
|
+
- Being respectful of differing viewpoints and experiences
|
|
13
|
+
- Gracefully accepting constructive criticism
|
|
14
|
+
- Focusing on what is best for the community
|
|
15
|
+
- Showing empathy towards other community members
|
|
16
|
+
- Be kind and courteous
|
|
17
|
+
|
|
18
|
+
Examples of unacceptable behavior by participants include:
|
|
19
|
+
|
|
20
|
+
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
|
21
|
+
- Trolling, insulting/derogatory comments, and personal or political attacks
|
|
22
|
+
- Public or private harassment
|
|
23
|
+
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
|
24
|
+
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
25
|
+
|
|
26
|
+
## Our Responsibilities
|
|
27
|
+
|
|
28
|
+
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
|
29
|
+
|
|
30
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
|
31
|
+
|
|
32
|
+
## Scope
|
|
33
|
+
|
|
34
|
+
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
|
35
|
+
|
|
36
|
+
## Enforcement
|
|
37
|
+
|
|
38
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [reactgx@gmail.com](mailto:reactgx@gmail.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
package/CONTRIBUTING.md
ADDED
|
File without changes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-Present Dilane Kombou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Rasengan MDX Plugin
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/@rasenganjs%mdx)
|
|
4
|
+

|
|
5
|
+
[](https://github.com/rasengan-dev/rasengan-mdx-plugin/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
MDX plugin for Rasengan.Js
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
You can install the `@rasenganjs/mdx` package using the following command:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @rasenganjs/mdx
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
or
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
yarn add @rasenganjs/mdx
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Here is an example of how you can use the `@rasenganjs/mdx` package:
|
|
26
|
+
|
|
27
|
+
### Basic Usage
|
|
28
|
+
|
|
29
|
+
1. Setup the `rasengan.config.js` file
|
|
30
|
+
|
|
31
|
+
Import the `mdx` plugin into the `rasengan.config.js` file.
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
import { defineConfig } from "rasengan";
|
|
35
|
+
import mdx from "@rasenganjs/mdx";
|
|
36
|
+
|
|
37
|
+
export default defineConfig({
|
|
38
|
+
reactStrictMode: true,
|
|
39
|
+
|
|
40
|
+
// Define aliases
|
|
41
|
+
vite: {
|
|
42
|
+
plugins: [
|
|
43
|
+
mdx(),
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
2. Create your `markdown` file.
|
|
50
|
+
|
|
51
|
+
Create a `markdown` file inside the `app` folder with the pattern `[name].page.mdx` or `[name].page.md`
|
|
52
|
+
|
|
53
|
+
```mdx
|
|
54
|
+
---
|
|
55
|
+
path: /blog
|
|
56
|
+
metadata:
|
|
57
|
+
title: Blog page
|
|
58
|
+
description: Discover our new blog posts
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
import Button from "@/components/Button";
|
|
62
|
+
|
|
63
|
+
# Blog page
|
|
64
|
+
|
|
65
|
+
This is a `blog` page.
|
|
66
|
+
|
|
67
|
+
<Button>Click Me</Button>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
3. Use your `markdown` file.
|
|
71
|
+
|
|
72
|
+
Inside the `app.router.ts` file, import your Markdown Component and the `generatePage` function from `@rasenganjs/mdx`
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { RouterComponent, defineRouter } from "rasengan";
|
|
76
|
+
import AppLayout from "@app/app.layout";
|
|
77
|
+
import Blog from "@app/blog.page.mdx";
|
|
78
|
+
import { generatePage } from "@rasenganjs/mdx";
|
|
79
|
+
|
|
80
|
+
const BlogPage = generatePage(Blog);
|
|
81
|
+
|
|
82
|
+
class AppRouter extends RouterComponent {}
|
|
83
|
+
|
|
84
|
+
export default defineRouter({
|
|
85
|
+
imports: [],
|
|
86
|
+
layout: AppLayout,
|
|
87
|
+
pages: [BlogPage],
|
|
88
|
+
})(AppRouter);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Now visit [http://localhost:5320/blog](http://localhost:5320/blog)
|
|
92
|
+
|
|
93
|
+
## Community
|
|
94
|
+
|
|
95
|
+
The Rasengan.js community can be found on [GitHub Discussions](https://github.com/rasengan-dev/rasenganjs/discussions) where you can ask questions, voice ideas, and share your projects with other people.
|
|
96
|
+
|
|
97
|
+
We also have a [Twitter](https://twitter.com/rasenganjs) account where you can follow us to get the latest news about Rasengan.js.
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
Rasengan.js is [MIT licensed](https://github.com/rasengan-dev/rasengan-image/blob/main/LICENSE).
|
|
102
|
+
|
|
103
|
+
## Authors
|
|
104
|
+
|
|
105
|
+
Here is the authors list:
|
|
106
|
+
|
|
107
|
+
- Dilane Kombou ([**@dilanekombou**](https://twitter.com/dilanekombou))
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { MDXPageComponent } from "../types/index.js";
|
|
3
|
+
type ComponentWithTextChildrenProps = {
|
|
4
|
+
children: string;
|
|
5
|
+
};
|
|
6
|
+
type MDXRendererProps = {
|
|
7
|
+
children: MDXPageComponent;
|
|
8
|
+
className?: string;
|
|
9
|
+
};
|
|
10
|
+
type CodeBlockProps = ComponentWithTextChildrenProps & {
|
|
11
|
+
className?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A React component that renders a code block with syntax highlighting and a copy button.
|
|
15
|
+
*
|
|
16
|
+
* The component uses the `prism-react-renderer` library to provide syntax highlighting for the code block.
|
|
17
|
+
* It also includes a copy button that allows the user to copy the code to their clipboard.
|
|
18
|
+
*
|
|
19
|
+
* @param {object} props - The component props.
|
|
20
|
+
* @param {string} props.children - The code content to be displayed in the code block.
|
|
21
|
+
* @param {string} [props.className] - The CSS class name to apply to the code block.
|
|
22
|
+
* @returns {React.ReactElement} - The rendered code block component.
|
|
23
|
+
*/
|
|
24
|
+
declare const CodeBlock: ({ children, className }: CodeBlockProps) => React.ReactElement;
|
|
25
|
+
declare const SimpleBlock: ({ children }: ComponentWithTextChildrenProps) => React.ReactElement;
|
|
26
|
+
/**
|
|
27
|
+
* Renders an MDX content component with a custom code block component.
|
|
28
|
+
*
|
|
29
|
+
* @param {MDXRendererProps} props - The props for the MDX renderer.
|
|
30
|
+
* @param {React.ReactNode} props.children - The MDX content to render.
|
|
31
|
+
* @param {string} [props.className] - An optional CSS class name to apply to the rendered section.
|
|
32
|
+
* @returns {React.ReactElement} - The rendered MDX content with the custom code block component.
|
|
33
|
+
*/
|
|
34
|
+
declare const MDXRenderer: ({ children: MDXContent, className }: MDXRendererProps) => React.ReactElement;
|
|
35
|
+
export { MDXRenderer, CodeBlock, SimpleBlock };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { themes, Highlight } from "prism-react-renderer";
|
|
3
|
+
import React from "react";
|
|
4
|
+
/**
|
|
5
|
+
* A React component that renders a code block with syntax highlighting and a copy button.
|
|
6
|
+
*
|
|
7
|
+
* The component uses the `prism-react-renderer` library to provide syntax highlighting for the code block.
|
|
8
|
+
* It also includes a copy button that allows the user to copy the code to their clipboard.
|
|
9
|
+
*
|
|
10
|
+
* @param {object} props - The component props.
|
|
11
|
+
* @param {string} props.children - The code content to be displayed in the code block.
|
|
12
|
+
* @param {string} [props.className] - The CSS class name to apply to the code block.
|
|
13
|
+
* @returns {React.ReactElement} - The rendered code block component.
|
|
14
|
+
*/
|
|
15
|
+
const CodeBlock = ({ children, className = "" }) => {
|
|
16
|
+
const language = className.replace(/language-/, "");
|
|
17
|
+
if (!language) {
|
|
18
|
+
return _jsx(SimpleBlock, { children: children });
|
|
19
|
+
}
|
|
20
|
+
return (_jsx(Highlight, { theme: themes.oneDark, code: children.trim(), language: language, children: ({ className, tokens, getLineProps, getTokenProps }) => {
|
|
21
|
+
const [copied, setCopied] = React.useState(false);
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
/**
|
|
24
|
+
* Sets the `copied` state to `false` after 2 seconds, effectively hiding the "copied" indicator.
|
|
25
|
+
* This function is called after the user's clipboard is updated with the code content.
|
|
26
|
+
*/
|
|
27
|
+
const timer = setTimeout(() => {
|
|
28
|
+
setCopied(false);
|
|
29
|
+
}, 2000);
|
|
30
|
+
return () => clearTimeout(timer);
|
|
31
|
+
}, [copied]);
|
|
32
|
+
/**
|
|
33
|
+
* Copies the trimmed text content of the `children` prop to the user's clipboard.
|
|
34
|
+
* This function is called when the "Copy" button is clicked in the code block component.
|
|
35
|
+
* It sets the `copied` state to `true` for 2 seconds to display a "copied" indicator.
|
|
36
|
+
*/
|
|
37
|
+
const handleCopy = () => {
|
|
38
|
+
navigator.clipboard.writeText(children.trim());
|
|
39
|
+
setCopied(true);
|
|
40
|
+
};
|
|
41
|
+
return (_jsxs("pre", { className: className, style: {
|
|
42
|
+
color: "#fff",
|
|
43
|
+
backgroundColor: "#1d2529",
|
|
44
|
+
borderRadius: "20px",
|
|
45
|
+
overflow: "hidden",
|
|
46
|
+
padding: "0px",
|
|
47
|
+
}, children: [_jsxs("div", { style: {
|
|
48
|
+
width: "100%",
|
|
49
|
+
height: "50px",
|
|
50
|
+
backgroundColor: "#28373f",
|
|
51
|
+
display: "flex",
|
|
52
|
+
justifyContent: "space-between",
|
|
53
|
+
alignItems: "center",
|
|
54
|
+
paddingLeft: "20px",
|
|
55
|
+
paddingRight: "20px",
|
|
56
|
+
}, children: [_jsx("span", { children: "Filename" }), _jsx("button", { className: 'copy-button', onClick: handleCopy, children: copied ? (_jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', width: '24', height: '24', color: '#f0f0f0', fill: 'none', children: [_jsx("path", { d: 'M22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12Z', stroke: 'currentColor', strokeWidth: '1.5' }), _jsx("path", { d: 'M8 12.5L10.5 15L16 9', stroke: 'currentColor', strokeWidth: '1.5', strokeLinecap: 'round', strokeLinejoin: 'round' })] })) : (_jsxs("svg", { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24', width: '24', height: '24', color: '#f0f0f0', fill: 'none', children: [_jsx("path", { d: 'M9 15C9 12.1716 9 10.7574 9.87868 9.87868C10.7574 9 12.1716 9 15 9L16 9C18.8284 9 20.2426 9 21.1213 9.87868C22 10.7574 22 12.1716 22 15V16C22 18.8284 22 20.2426 21.1213 21.1213C20.2426 22 18.8284 22 16 22H15C12.1716 22 10.7574 22 9.87868 21.1213C9 20.2426 9 18.8284 9 16L9 15Z', stroke: 'currentColor', strokeWidth: '1.5', strokeLinecap: 'round', strokeLinejoin: 'round' }), _jsx("path", { d: 'M16.9999 9C16.9975 6.04291 16.9528 4.51121 16.092 3.46243C15.9258 3.25989 15.7401 3.07418 15.5376 2.90796C14.4312 2 12.7875 2 9.5 2C6.21252 2 4.56878 2 3.46243 2.90796C3.25989 3.07417 3.07418 3.25989 2.90796 3.46243C2 4.56878 2 6.21252 2 9.5C2 12.7875 2 14.4312 2.90796 15.5376C3.07417 15.7401 3.25989 15.9258 3.46243 16.092C4.51121 16.9528 6.04291 16.9975 9 16.9999', stroke: 'currentColor', strokeWidth: '1.5', strokeLinecap: 'round', strokeLinejoin: 'round' })] })) })] }), _jsx("div", { style: {
|
|
57
|
+
padding: "20px",
|
|
58
|
+
fontSize: "14px",
|
|
59
|
+
}, children: _jsx("code", { children: tokens.map((line, i) => (_jsxs("div", { ...getLineProps({ line }), children: [_jsx("span", { style: {
|
|
60
|
+
opacity: 0.6,
|
|
61
|
+
marginRight: "5px",
|
|
62
|
+
}, children: i + 1 }), _jsx("span", { children: " " }), line.map((token, key) => (_jsx("span", { ...getTokenProps({ token }) }, key)))] }, i))) }) })] }));
|
|
63
|
+
} }));
|
|
64
|
+
};
|
|
65
|
+
const SimpleBlock = ({ children }) => {
|
|
66
|
+
return (_jsx("span", { className: "simple-block", style: {
|
|
67
|
+
fontSize: "14px",
|
|
68
|
+
borderRadius: "5px",
|
|
69
|
+
paddingLeft: "3.6px",
|
|
70
|
+
paddingRight: "3.6px",
|
|
71
|
+
paddingTop: "2px",
|
|
72
|
+
paddingBottom: "2px",
|
|
73
|
+
marginInline: "0px",
|
|
74
|
+
backgroundColor: "#f7f7f7",
|
|
75
|
+
border: "1px solid #f0f0f0",
|
|
76
|
+
}, children: children }));
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Renders an MDX content component with a custom code block component.
|
|
80
|
+
*
|
|
81
|
+
* @param {MDXRendererProps} props - The props for the MDX renderer.
|
|
82
|
+
* @param {React.ReactNode} props.children - The MDX content to render.
|
|
83
|
+
* @param {string} [props.className] - An optional CSS class name to apply to the rendered section.
|
|
84
|
+
* @returns {React.ReactElement} - The rendered MDX content with the custom code block component.
|
|
85
|
+
*/
|
|
86
|
+
const MDXRenderer = ({ children: MDXContent, className }) => {
|
|
87
|
+
return (_jsx("section", { className: "rasengan-markdown-body " + className, children: _jsx(MDXContent, { components: {
|
|
88
|
+
code: CodeBlock,
|
|
89
|
+
} }) }));
|
|
90
|
+
};
|
|
91
|
+
export { MDXRenderer, CodeBlock, SimpleBlock };
|
|
92
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.tsx"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export * from './types/index.js';
|
|
2
|
+
export * from "./utils/index.js";
|
|
3
|
+
export * from './components/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* A Vite plugin that transforms MDX files into a format that can be used in a RasenganJs application.
|
|
6
|
+
*
|
|
7
|
+
* The plugin performs the following tasks:
|
|
8
|
+
* - Resolves the Vite configuration and stores it for later use.
|
|
9
|
+
* - Transforms MDX files by applying the `@mdx-js/rollup` transformation.
|
|
10
|
+
* - Extracts frontmatter data from the MDX files and creates a `metadata` object.
|
|
11
|
+
* - Appends the `metadata` object to the transformed MDX content.
|
|
12
|
+
*
|
|
13
|
+
* The transformed MDX content can then be used in the RasenganJs application, with the `metadata` object providing additional information about the content.
|
|
14
|
+
*/
|
|
15
|
+
export default function rasengan(): {
|
|
16
|
+
name: string;
|
|
17
|
+
enforce: string;
|
|
18
|
+
/**
|
|
19
|
+
* Stores the resolved Vite configuration for later use.
|
|
20
|
+
*
|
|
21
|
+
* @param resolvedConfig - The resolved Vite configuration object.
|
|
22
|
+
*/
|
|
23
|
+
configResolved(resolvedConfig: unknown): void;
|
|
24
|
+
/**
|
|
25
|
+
* Transforms an MDX file by applying the `@mdx-js/rollup` transformation, extracting frontmatter data, and appending a `metadata` object to the transformed content.
|
|
26
|
+
*
|
|
27
|
+
* @param code - The content of the MDX file.
|
|
28
|
+
* @param id - The ID of the MDX file.
|
|
29
|
+
* @returns An object containing the transformed MDX code and a source map, or `null` if the file is not an MDX file.
|
|
30
|
+
*/
|
|
31
|
+
transform(code: string, id: string): Promise<{
|
|
32
|
+
code: string;
|
|
33
|
+
map: import("rollup").SourceMapInput;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import mdx from '@mdx-js/rollup';
|
|
2
|
+
import { createFilter } from "@rollup/pluginutils";
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
export * from './types/index.js';
|
|
5
|
+
export * from "./utils/index.js";
|
|
6
|
+
export * from './components/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* A Vite plugin that transforms MDX files into a format that can be used in a RasenganJs application.
|
|
9
|
+
*
|
|
10
|
+
* The plugin performs the following tasks:
|
|
11
|
+
* - Resolves the Vite configuration and stores it for later use.
|
|
12
|
+
* - Transforms MDX files by applying the `@mdx-js/rollup` transformation.
|
|
13
|
+
* - Extracts frontmatter data from the MDX files and creates a `metadata` object.
|
|
14
|
+
* - Appends the `metadata` object to the transformed MDX content.
|
|
15
|
+
*
|
|
16
|
+
* The transformed MDX content can then be used in the RasenganJs application, with the `metadata` object providing additional information about the content.
|
|
17
|
+
*/
|
|
18
|
+
export default function rasengan() {
|
|
19
|
+
let config;
|
|
20
|
+
const filter = createFilter(/\.mdx?$/);
|
|
21
|
+
return {
|
|
22
|
+
name: "vite-plugin-rasengan-mdx",
|
|
23
|
+
// Apply transformation of the mdx file before other plugins
|
|
24
|
+
enforce: 'pre',
|
|
25
|
+
/**
|
|
26
|
+
* Stores the resolved Vite configuration for later use.
|
|
27
|
+
*
|
|
28
|
+
* @param resolvedConfig - The resolved Vite configuration object.
|
|
29
|
+
*/
|
|
30
|
+
configResolved(resolvedConfig) {
|
|
31
|
+
// store the resolved config
|
|
32
|
+
config = resolvedConfig;
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Transforms an MDX file by applying the `@mdx-js/rollup` transformation, extracting frontmatter data, and appending a `metadata` object to the transformed content.
|
|
36
|
+
*
|
|
37
|
+
* @param code - The content of the MDX file.
|
|
38
|
+
* @param id - The ID of the MDX file.
|
|
39
|
+
* @returns An object containing the transformed MDX code and a source map, or `null` if the file is not an MDX file.
|
|
40
|
+
*/
|
|
41
|
+
async transform(code, id) {
|
|
42
|
+
if (!filter(id)) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const { content, data: frontmatter } = matter(code);
|
|
46
|
+
// Apply transformation of the mdx file
|
|
47
|
+
const result = await mdx().transform(content, id);
|
|
48
|
+
// Extract the file name from the path
|
|
49
|
+
const fileName = id
|
|
50
|
+
.split("/")
|
|
51
|
+
.pop()
|
|
52
|
+
.replace(/.page.mdx?$/, "");
|
|
53
|
+
// TODO: Consider other params of metadata from frontmatter
|
|
54
|
+
const metadata = {
|
|
55
|
+
path: frontmatter.path || `/${fileName}`,
|
|
56
|
+
metadata: frontmatter.metadata || {
|
|
57
|
+
title: fileName,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
code: `
|
|
62
|
+
${result.code}
|
|
63
|
+
const metadata = ${JSON.stringify(metadata)};
|
|
64
|
+
|
|
65
|
+
MDXContent.metadata = metadata;
|
|
66
|
+
`,
|
|
67
|
+
map: result.map,
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,gBAAgB,CAAA;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ;IAC/B,IAAI,MAAe,CAAC;IACpB,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IAEvC,OAAO;QACN,IAAI,EAAE,0BAA0B;QAEhC,4DAA4D;QAC5D,OAAO,EAAE,KAAK;QAEd;;;;WAIG;QACH,cAAc,CAAC,cAAuB;YACrC,4BAA4B;YAC5B,MAAM,GAAG,cAAc,CAAC;QACzB,CAAC;QAED;;;;;;WAMG;QACH,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,EAAU;YACvC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;gBACjB,OAAO,IAAI,CAAC;YACb,CAAC;YAED,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAEpD,uCAAuC;YACvC,MAAM,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAElD,sCAAsC;YACtC,MAAM,QAAQ,GAAG,EAAE;iBACjB,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,EAAE;iBACL,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YAE7B,2DAA2D;YAC3D,MAAM,QAAQ,GAAG;gBAChB,IAAI,EAAE,WAAW,CAAC,IAAI,IAAI,IAAI,QAAQ,EAAE;gBACxC,QAAQ,EAAE,WAAW,CAAC,QAAQ,IAAI;oBACjC,KAAK,EAAE,QAAQ;iBACf;aACD,CAAC;YAEF,OAAO;gBACN,IAAI,EAAE;YACE,MAAM,CAAC,IAAI;6BACM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;;SAG5C;gBACL,GAAG,EAAE,MAAM,CAAC,GAAG;aACf,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { type Metadata } from "rasengan";
|
|
3
|
+
/**
|
|
4
|
+
* A React functional component that represents an MDX page.
|
|
5
|
+
*
|
|
6
|
+
* The `MDXPageComponent` type extends the `React.FC<ReactComponentProps>` type, which means it is a React functional component that accepts the standard props for a React component.
|
|
7
|
+
*
|
|
8
|
+
* The `MDXPageComponent` type also has an optional `metadata` property of type `Metadata`, which can be used to store metadata about the page.
|
|
9
|
+
*/
|
|
10
|
+
export type MDXPageComponent = React.FC<any> & {
|
|
11
|
+
metadata?: {
|
|
12
|
+
path: string;
|
|
13
|
+
metadata: Metadata;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type PageComponent } from "rasengan";
|
|
2
|
+
import { MDXPageComponent } from "../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generates a React component from an MDXPageComponent.
|
|
5
|
+
*
|
|
6
|
+
* @param MDXPage - The MDXPageComponent to generate the React component from.
|
|
7
|
+
* @param className - An optional CSS class name to apply to the MDXRenderer component.
|
|
8
|
+
* @returns A React component that renders the MDXPage content using the MDXRenderer.
|
|
9
|
+
*/
|
|
10
|
+
export default function generatePage(MDXPage: MDXPageComponent, className?: string): PageComponent;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { MDXRenderer } from "../components/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generates a React component from an MDXPageComponent.
|
|
5
|
+
*
|
|
6
|
+
* @param MDXPage - The MDXPageComponent to generate the React component from.
|
|
7
|
+
* @param className - An optional CSS class name to apply to the MDXRenderer component.
|
|
8
|
+
* @returns A React component that renders the MDXPage content using the MDXRenderer.
|
|
9
|
+
*/
|
|
10
|
+
export default function generatePage(MDXPage, className = "") {
|
|
11
|
+
const Page = () => {
|
|
12
|
+
return _jsx(MDXRenderer, { className: className, children: MDXPage });
|
|
13
|
+
};
|
|
14
|
+
Page.path = MDXPage.metadata.path;
|
|
15
|
+
Page.metadata = MDXPage.metadata.metadata;
|
|
16
|
+
return Page;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=generate-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-page.js","sourceRoot":"","sources":["../../src/utils/generate-page.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CACnC,OAAyB,EACzB,SAAS,GAAG,EAAE;IAEd,MAAM,IAAI,GAAkB,GAAG,EAAE;QAChC,OAAO,KAAC,WAAW,IAAC,SAAS,EAAE,SAAS,YAAG,OAAO,GAAe,CAAC;IACnE,CAAC,CAAC;IAEF,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IAClC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAE1C,OAAO,IAAI,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rasenganjs/mdx",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "RasenganJS plugin for MDX support",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "lib/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./lib/index.js",
|
|
11
|
+
"require": "./lib/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "dilane3",
|
|
16
|
+
"email": "komboudilane125@gmail.com",
|
|
17
|
+
"url": "https://dilane3.com",
|
|
18
|
+
"twitter": "https://twitter.com/dilanekombou",
|
|
19
|
+
"github": "https://github.com/dilane3"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/rasengan-dev/rasengan-mdx-plugin.git",
|
|
24
|
+
"issues": "https://github.com/rasengan-dev/rasengan-mdx-plugin/issues"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build:clean": "rm -rf ./lib",
|
|
29
|
+
"build": "npm run build:clean && tsc",
|
|
30
|
+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
31
|
+
"pack": "npm pack --pack-destination ./../../packages/@rasenganjs/mdx",
|
|
32
|
+
"deploy": "npm publish --access public"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/react": "^18.0.0",
|
|
36
|
+
"typescript": "^5.2.2"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@mdx-js/rollup": "^3.0.1",
|
|
40
|
+
"@rollup/pluginutils": "^5.1.0",
|
|
41
|
+
"gray-matter": "^4.0.3",
|
|
42
|
+
"prism-react-renderer": "^2.3.1",
|
|
43
|
+
"prismjs": "^1.29.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"rasengan": "^1.0.0-beta.35",
|
|
47
|
+
"react": "^18.3.1"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { themes, Highlight } from "prism-react-renderer";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { MDXPageComponent } from "../types/index.js";
|
|
4
|
+
|
|
5
|
+
type ComponentWithTextChildrenProps = {
|
|
6
|
+
children: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type MDXRendererProps = {
|
|
10
|
+
children: MDXPageComponent;
|
|
11
|
+
className?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type CodeBlockProps = ComponentWithTextChildrenProps & {
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A React component that renders a code block with syntax highlighting and a copy button.
|
|
21
|
+
*
|
|
22
|
+
* The component uses the `prism-react-renderer` library to provide syntax highlighting for the code block.
|
|
23
|
+
* It also includes a copy button that allows the user to copy the code to their clipboard.
|
|
24
|
+
*
|
|
25
|
+
* @param {object} props - The component props.
|
|
26
|
+
* @param {string} props.children - The code content to be displayed in the code block.
|
|
27
|
+
* @param {string} [props.className] - The CSS class name to apply to the code block.
|
|
28
|
+
* @returns {React.ReactElement} - The rendered code block component.
|
|
29
|
+
*/
|
|
30
|
+
const CodeBlock = ({ children, className = "" }: CodeBlockProps): React.ReactElement => {
|
|
31
|
+
const language = className.replace(/language-/, "");
|
|
32
|
+
|
|
33
|
+
if (!language) {
|
|
34
|
+
return <SimpleBlock>{children}</SimpleBlock>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Highlight
|
|
39
|
+
theme={themes.oneDark}
|
|
40
|
+
code={children.trim()}
|
|
41
|
+
language={language}
|
|
42
|
+
>
|
|
43
|
+
{({ className, tokens, getLineProps, getTokenProps }: any) => {
|
|
44
|
+
const [copied, setCopied] = React.useState(false);
|
|
45
|
+
|
|
46
|
+
React.useEffect(() => {
|
|
47
|
+
/**
|
|
48
|
+
* Sets the `copied` state to `false` after 2 seconds, effectively hiding the "copied" indicator.
|
|
49
|
+
* This function is called after the user's clipboard is updated with the code content.
|
|
50
|
+
*/
|
|
51
|
+
const timer = setTimeout(() => {
|
|
52
|
+
setCopied(false);
|
|
53
|
+
}, 2000);
|
|
54
|
+
|
|
55
|
+
return () => clearTimeout(timer);
|
|
56
|
+
}, [copied]);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Copies the trimmed text content of the `children` prop to the user's clipboard.
|
|
60
|
+
* This function is called when the "Copy" button is clicked in the code block component.
|
|
61
|
+
* It sets the `copied` state to `true` for 2 seconds to display a "copied" indicator.
|
|
62
|
+
*/
|
|
63
|
+
const handleCopy = () => {
|
|
64
|
+
navigator.clipboard.writeText(children.trim());
|
|
65
|
+
setCopied(true);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<pre
|
|
70
|
+
className={className}
|
|
71
|
+
style={{
|
|
72
|
+
color: "#fff",
|
|
73
|
+
backgroundColor: "#1d2529",
|
|
74
|
+
borderRadius: "20px",
|
|
75
|
+
overflow: "hidden",
|
|
76
|
+
padding: "0px",
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
<div
|
|
80
|
+
style={{
|
|
81
|
+
width: "100%",
|
|
82
|
+
height: "50px",
|
|
83
|
+
backgroundColor: "#28373f",
|
|
84
|
+
display: "flex",
|
|
85
|
+
justifyContent: "space-between",
|
|
86
|
+
alignItems: "center",
|
|
87
|
+
paddingLeft: "20px",
|
|
88
|
+
paddingRight: "20px",
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
<span>Filename</span>
|
|
92
|
+
|
|
93
|
+
<button className='copy-button' onClick={handleCopy}>
|
|
94
|
+
{copied ? (
|
|
95
|
+
<svg
|
|
96
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
97
|
+
viewBox='0 0 24 24'
|
|
98
|
+
width='24'
|
|
99
|
+
height='24'
|
|
100
|
+
color='#f0f0f0'
|
|
101
|
+
fill='none'
|
|
102
|
+
>
|
|
103
|
+
<path
|
|
104
|
+
d='M22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12Z'
|
|
105
|
+
stroke='currentColor'
|
|
106
|
+
strokeWidth='1.5'
|
|
107
|
+
/>
|
|
108
|
+
<path
|
|
109
|
+
d='M8 12.5L10.5 15L16 9'
|
|
110
|
+
stroke='currentColor'
|
|
111
|
+
strokeWidth='1.5'
|
|
112
|
+
strokeLinecap='round'
|
|
113
|
+
strokeLinejoin='round'
|
|
114
|
+
/>
|
|
115
|
+
</svg>
|
|
116
|
+
) : (
|
|
117
|
+
<svg
|
|
118
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
119
|
+
viewBox='0 0 24 24'
|
|
120
|
+
width='24'
|
|
121
|
+
height='24'
|
|
122
|
+
color='#f0f0f0'
|
|
123
|
+
fill='none'
|
|
124
|
+
>
|
|
125
|
+
<path
|
|
126
|
+
d='M9 15C9 12.1716 9 10.7574 9.87868 9.87868C10.7574 9 12.1716 9 15 9L16 9C18.8284 9 20.2426 9 21.1213 9.87868C22 10.7574 22 12.1716 22 15V16C22 18.8284 22 20.2426 21.1213 21.1213C20.2426 22 18.8284 22 16 22H15C12.1716 22 10.7574 22 9.87868 21.1213C9 20.2426 9 18.8284 9 16L9 15Z'
|
|
127
|
+
stroke='currentColor'
|
|
128
|
+
strokeWidth='1.5'
|
|
129
|
+
strokeLinecap='round'
|
|
130
|
+
strokeLinejoin='round'
|
|
131
|
+
/>
|
|
132
|
+
<path
|
|
133
|
+
d='M16.9999 9C16.9975 6.04291 16.9528 4.51121 16.092 3.46243C15.9258 3.25989 15.7401 3.07418 15.5376 2.90796C14.4312 2 12.7875 2 9.5 2C6.21252 2 4.56878 2 3.46243 2.90796C3.25989 3.07417 3.07418 3.25989 2.90796 3.46243C2 4.56878 2 6.21252 2 9.5C2 12.7875 2 14.4312 2.90796 15.5376C3.07417 15.7401 3.25989 15.9258 3.46243 16.092C4.51121 16.9528 6.04291 16.9975 9 16.9999'
|
|
134
|
+
stroke='currentColor'
|
|
135
|
+
strokeWidth='1.5'
|
|
136
|
+
strokeLinecap='round'
|
|
137
|
+
strokeLinejoin='round'
|
|
138
|
+
/>
|
|
139
|
+
</svg>
|
|
140
|
+
)}
|
|
141
|
+
</button>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<div
|
|
145
|
+
style={{
|
|
146
|
+
padding: "20px",
|
|
147
|
+
fontSize: "14px",
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
150
|
+
<code>
|
|
151
|
+
{tokens.map((line: any, i: number) => (
|
|
152
|
+
<div key={i} {...getLineProps({ line })}>
|
|
153
|
+
<span
|
|
154
|
+
style={{
|
|
155
|
+
opacity: 0.6,
|
|
156
|
+
marginRight: "5px",
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
{i + 1}
|
|
160
|
+
</span>
|
|
161
|
+
<span> </span>
|
|
162
|
+
{line.map((token: any, key: number) => (
|
|
163
|
+
<span key={key} {...getTokenProps({ token })} />
|
|
164
|
+
))}
|
|
165
|
+
</div>
|
|
166
|
+
))}
|
|
167
|
+
</code>
|
|
168
|
+
</div>
|
|
169
|
+
</pre>
|
|
170
|
+
);
|
|
171
|
+
}}
|
|
172
|
+
</Highlight>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const SimpleBlock = ({ children }: ComponentWithTextChildrenProps): React.ReactElement => {
|
|
177
|
+
return (
|
|
178
|
+
<span
|
|
179
|
+
className="simple-block"
|
|
180
|
+
style={{
|
|
181
|
+
fontSize: "14px",
|
|
182
|
+
borderRadius: "5px",
|
|
183
|
+
paddingLeft: "3.6px",
|
|
184
|
+
paddingRight: "3.6px",
|
|
185
|
+
paddingTop: "2px",
|
|
186
|
+
paddingBottom: "2px",
|
|
187
|
+
marginInline: "0px",
|
|
188
|
+
backgroundColor: "#f7f7f7",
|
|
189
|
+
border: "1px solid #f0f0f0",
|
|
190
|
+
}}
|
|
191
|
+
>{children}</span>
|
|
192
|
+
);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Renders an MDX content component with a custom code block component.
|
|
197
|
+
*
|
|
198
|
+
* @param {MDXRendererProps} props - The props for the MDX renderer.
|
|
199
|
+
* @param {React.ReactNode} props.children - The MDX content to render.
|
|
200
|
+
* @param {string} [props.className] - An optional CSS class name to apply to the rendered section.
|
|
201
|
+
* @returns {React.ReactElement} - The rendered MDX content with the custom code block component.
|
|
202
|
+
*/
|
|
203
|
+
const MDXRenderer = ({ children: MDXContent, className }: MDXRendererProps): React.ReactElement => {
|
|
204
|
+
return (
|
|
205
|
+
<section className={"rasengan-markdown-body " + className}>
|
|
206
|
+
<MDXContent
|
|
207
|
+
components={{
|
|
208
|
+
code: CodeBlock,
|
|
209
|
+
}}
|
|
210
|
+
/>
|
|
211
|
+
</section>
|
|
212
|
+
);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export {
|
|
216
|
+
MDXRenderer,
|
|
217
|
+
CodeBlock,
|
|
218
|
+
SimpleBlock
|
|
219
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import mdx from '@mdx-js/rollup'
|
|
2
|
+
import { createFilter } from "@rollup/pluginutils";
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
|
|
5
|
+
export * from './types/index.js';
|
|
6
|
+
export * from "./utils/index.js";
|
|
7
|
+
export * from './components/index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A Vite plugin that transforms MDX files into a format that can be used in a RasenganJs application.
|
|
11
|
+
*
|
|
12
|
+
* The plugin performs the following tasks:
|
|
13
|
+
* - Resolves the Vite configuration and stores it for later use.
|
|
14
|
+
* - Transforms MDX files by applying the `@mdx-js/rollup` transformation.
|
|
15
|
+
* - Extracts frontmatter data from the MDX files and creates a `metadata` object.
|
|
16
|
+
* - Appends the `metadata` object to the transformed MDX content.
|
|
17
|
+
*
|
|
18
|
+
* The transformed MDX content can then be used in the RasenganJs application, with the `metadata` object providing additional information about the content.
|
|
19
|
+
*/
|
|
20
|
+
export default function rasengan() {
|
|
21
|
+
let config: unknown;
|
|
22
|
+
const filter = createFilter(/\.mdx?$/);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
name: "vite-plugin-rasengan-mdx",
|
|
26
|
+
|
|
27
|
+
// Apply transformation of the mdx file before other plugins
|
|
28
|
+
enforce: 'pre',
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Stores the resolved Vite configuration for later use.
|
|
32
|
+
*
|
|
33
|
+
* @param resolvedConfig - The resolved Vite configuration object.
|
|
34
|
+
*/
|
|
35
|
+
configResolved(resolvedConfig: unknown) {
|
|
36
|
+
// store the resolved config
|
|
37
|
+
config = resolvedConfig;
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Transforms an MDX file by applying the `@mdx-js/rollup` transformation, extracting frontmatter data, and appending a `metadata` object to the transformed content.
|
|
42
|
+
*
|
|
43
|
+
* @param code - The content of the MDX file.
|
|
44
|
+
* @param id - The ID of the MDX file.
|
|
45
|
+
* @returns An object containing the transformed MDX code and a source map, or `null` if the file is not an MDX file.
|
|
46
|
+
*/
|
|
47
|
+
async transform(code: string, id: string) {
|
|
48
|
+
if (!filter(id)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { content, data: frontmatter } = matter(code);
|
|
53
|
+
|
|
54
|
+
// Apply transformation of the mdx file
|
|
55
|
+
const result = await mdx().transform(content, id);
|
|
56
|
+
|
|
57
|
+
// Extract the file name from the path
|
|
58
|
+
const fileName = id
|
|
59
|
+
.split("/")
|
|
60
|
+
.pop()
|
|
61
|
+
.replace(/.page.mdx?$/, "");
|
|
62
|
+
|
|
63
|
+
// TODO: Consider other params of metadata from frontmatter
|
|
64
|
+
const metadata = {
|
|
65
|
+
path: frontmatter.path || `/${fileName}`,
|
|
66
|
+
metadata: frontmatter.metadata || {
|
|
67
|
+
title: fileName,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
code: `
|
|
73
|
+
${result.code}
|
|
74
|
+
const metadata = ${JSON.stringify(metadata)};
|
|
75
|
+
|
|
76
|
+
MDXContent.metadata = metadata;
|
|
77
|
+
`,
|
|
78
|
+
map: result.map,
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {type Metadata } from "rasengan";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A React functional component that represents an MDX page.
|
|
5
|
+
*
|
|
6
|
+
* The `MDXPageComponent` type extends the `React.FC<ReactComponentProps>` type, which means it is a React functional component that accepts the standard props for a React component.
|
|
7
|
+
*
|
|
8
|
+
* The `MDXPageComponent` type also has an optional `metadata` property of type `Metadata`, which can be used to store metadata about the page.
|
|
9
|
+
*/
|
|
10
|
+
export type MDXPageComponent = React.FC<any> & {
|
|
11
|
+
metadata?: {
|
|
12
|
+
path: string;
|
|
13
|
+
metadata: Metadata;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type PageComponent } from "rasengan";
|
|
2
|
+
import { MDXPageComponent } from "../types/index.js";
|
|
3
|
+
import { MDXRenderer } from "../components/index.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates a React component from an MDXPageComponent.
|
|
7
|
+
*
|
|
8
|
+
* @param MDXPage - The MDXPageComponent to generate the React component from.
|
|
9
|
+
* @param className - An optional CSS class name to apply to the MDXRenderer component.
|
|
10
|
+
* @returns A React component that renders the MDXPage content using the MDXRenderer.
|
|
11
|
+
*/
|
|
12
|
+
export default function generatePage(
|
|
13
|
+
MDXPage: MDXPageComponent,
|
|
14
|
+
className = ""
|
|
15
|
+
): PageComponent {
|
|
16
|
+
const Page: PageComponent = () => {
|
|
17
|
+
return <MDXRenderer className={className}>{MDXPage}</MDXRenderer>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
Page.path = MDXPage.metadata.path;
|
|
21
|
+
Page.metadata = MDXPage.metadata.metadata;
|
|
22
|
+
|
|
23
|
+
return Page;
|
|
24
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"outDir": "lib",
|
|
4
|
+
"rootDir": "src",
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"lib": [
|
|
7
|
+
"ES2015",
|
|
8
|
+
"ESNext",
|
|
9
|
+
"dom",
|
|
10
|
+
"dom.iterable",
|
|
11
|
+
"esnext"
|
|
12
|
+
],
|
|
13
|
+
"allowJs": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"esModuleInterop": true,
|
|
16
|
+
"allowSyntheticDefaultImports": true,
|
|
17
|
+
"strict": false,
|
|
18
|
+
"forceConsistentCasingInFileNames": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"module": "ESNext",
|
|
21
|
+
"moduleResolution": "bundler",
|
|
22
|
+
"resolveJsonModule": true,
|
|
23
|
+
"isolatedModules": true,
|
|
24
|
+
"jsx": "react-jsx",
|
|
25
|
+
"noEmit": false,
|
|
26
|
+
"declaration": true,
|
|
27
|
+
"sourceMap": true,
|
|
28
|
+
|
|
29
|
+
/* Types */
|
|
30
|
+
"typeRoots": ["node_modules/@types", "src/types"]
|
|
31
|
+
},
|
|
32
|
+
"include": [
|
|
33
|
+
"src",
|
|
34
|
+
"src/types",
|
|
35
|
+
],
|
|
36
|
+
"exclude": ["node_modules", "lib"]
|
|
37
|
+
}
|