react-router-markdown 0.9.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/LICENSE.md +18 -0
- package/README.md +70 -0
- package/dist/index.d.mts +19 -0
- package/dist/index.mjs +25 -0
- package/dist/index.mjs.map +1 -0
- package/dist/references.d.ts +12 -0
- package/dist/vite.d.mts +39 -0
- package/dist/vite.mjs +47 -0
- package/dist/vite.mjs.map +1 -0
- package/package.json +75 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Javier Aguilar (itsjavi.com)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
6
|
+
associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
7
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
8
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
12
|
+
portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
|
15
|
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
|
17
|
+
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# react-router-markdown
|
|
2
|
+
|
|
3
|
+
Vite plugin to parse Markdown files as React Router pages. It supports defining React Router's meta
|
|
4
|
+
function returned data, as frontmatter.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pnpm add react-router-markdown
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
### Vite config
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
// vite.config.ts
|
|
18
|
+
|
|
19
|
+
import { defineConfig } from 'vite'
|
|
20
|
+
import markdown from 'react-router-markdown/vite'
|
|
21
|
+
|
|
22
|
+
export default defineConfig({
|
|
23
|
+
plugins: [
|
|
24
|
+
markdown({
|
|
25
|
+
parseHtml: true,
|
|
26
|
+
wrapperModule: '@/components/markdown-wrapper',
|
|
27
|
+
handleData: (mdContent, frontmatter) => ({
|
|
28
|
+
layoutClass: 'mx-auto max-w-5xl lg:p-4',
|
|
29
|
+
title: frontmatter.title,
|
|
30
|
+
contentLength: mdContent.length,
|
|
31
|
+
}),
|
|
32
|
+
beforeTransform: (rawFileContent) =>
|
|
33
|
+
rawFileContent.replaceAll('%YEAR%', new Date().getFullYear().toString()),
|
|
34
|
+
afterTransform: (mdContent, frontmatter) => [mdContent, frontmatter],
|
|
35
|
+
}),
|
|
36
|
+
],
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Plugin options
|
|
41
|
+
|
|
42
|
+
- `parseHtml?: boolean` - Parse HTML tags in markdown as HTML (default: `false`).
|
|
43
|
+
- `wrapperModule?: string` - Module specifier of a default-exported React wrapper component.
|
|
44
|
+
- `beforeTransform?: (content: string) => string` - Transform raw markdown before frontmatter
|
|
45
|
+
parsing.
|
|
46
|
+
- `afterTransform?: (content: string, frontmatter: Record<string, any>) => [string, Record<string, any>]` -
|
|
47
|
+
Transform parsed content/frontmatter.
|
|
48
|
+
- `handleData?: (content: string, frontmatter: Record<string, any>) => Record<string, any>` - Return
|
|
49
|
+
React Router `handle` export data.
|
|
50
|
+
|
|
51
|
+
### Imports and TypeScript support
|
|
52
|
+
|
|
53
|
+
In order to TypeScript import `.md` files with type hints, add the following to your `vite.d.ts`
|
|
54
|
+
file:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
/// <reference types="react-router-markdown/references" />
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Optionally, you can also add the following to your `tsconfig.json` file:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"compilerOptions": {
|
|
65
|
+
"types": ["react-router-markdown/references"]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Now you can use any `.md` file as a React Router page.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/lib/markdow-page.d.ts
|
|
2
|
+
type MarkdownPageProps = {
|
|
3
|
+
parseHtml: boolean;
|
|
4
|
+
rawContent: string;
|
|
5
|
+
frontmatter: Record<string, unknown>;
|
|
6
|
+
Wrapper: React.ComponentType<{
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
frontmatter: Record<string, unknown>;
|
|
9
|
+
}> | null;
|
|
10
|
+
};
|
|
11
|
+
declare function MarkdownPage({
|
|
12
|
+
parseHtml,
|
|
13
|
+
rawContent,
|
|
14
|
+
frontmatter,
|
|
15
|
+
Wrapper
|
|
16
|
+
}: MarkdownPageProps): React.ReactElement;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { MarkdownPage };
|
|
19
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { raw } from "hast-util-raw";
|
|
2
|
+
import ReactMarkdown from "react-markdown";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/lib/markdow-page.ts
|
|
5
|
+
function rehypeRaw(options) {
|
|
6
|
+
return (tree, file) => raw(tree, {
|
|
7
|
+
...options,
|
|
8
|
+
file
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function MarkdownPage({ parseHtml, rawContent, frontmatter, Wrapper }) {
|
|
12
|
+
const mdElement = jsx(ReactMarkdown, {
|
|
13
|
+
children: rawContent,
|
|
14
|
+
rehypePlugins: parseHtml ? [rehypeRaw] : []
|
|
15
|
+
});
|
|
16
|
+
if (!Wrapper) return mdElement;
|
|
17
|
+
return jsx(Wrapper, {
|
|
18
|
+
children: mdElement,
|
|
19
|
+
frontmatter
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { MarkdownPage };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/markdow-page.ts"],"sourcesContent":["import { raw } from 'hast-util-raw'\nimport ReactMarkdown from 'react-markdown'\nimport { jsx } from 'react/jsx-runtime'\n\ntype HastNodes = Parameters<typeof raw>[0]\ntype HastOptions = NonNullable<Parameters<typeof raw>[1]>\ntype MarkdownPageProps = {\n parseHtml: boolean\n rawContent: string\n frontmatter: Record<string, unknown>\n Wrapper: React.ComponentType<{\n children: React.ReactNode\n frontmatter: Record<string, unknown>\n }> | null\n}\n\nfunction rehypeRaw(options: HastOptions) {\n return (tree: HastNodes, file: HastOptions['file']) => raw(tree, { ...options, file })\n}\n\nexport function MarkdownPage({\n parseHtml,\n rawContent,\n frontmatter,\n Wrapper,\n}: MarkdownPageProps): React.ReactElement {\n const rehypePlugins = parseHtml ? [rehypeRaw] : []\n const mdElement = jsx(ReactMarkdown, { children: rawContent, rehypePlugins: rehypePlugins })\n\n if (!Wrapper) {\n return mdElement\n }\n\n return jsx(Wrapper, {\n children: mdElement,\n frontmatter: frontmatter,\n })\n}\n"],"mappings":";;;;AAgBA,SAAS,UAAU,SAAsB;AACvC,SAAQ,MAAiB,SAA8B,IAAI,MAAM;EAAE,GAAG;EAAS;EAAM,CAAC;;AAGxF,SAAgB,aAAa,EAC3B,WACA,YACA,aACA,WACwC;CAExC,MAAM,YAAY,IAAI,eAAe;EAAE,UAAU;EAAY,eADvC,YAAY,CAAC,UAAU,GAAG,EAAE;EACyC,CAAC;AAE5F,KAAI,CAAC,QACH,QAAO;AAGT,QAAO,IAAI,SAAS;EAClB,UAAU;EACG;EACd,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// allows importing md files
|
|
2
|
+
// Add this to your vite.d.ts file: /// <reference types="react-router-markdown/references" />
|
|
3
|
+
declare module '*.md' {
|
|
4
|
+
export const frontmatter: Record<string, any>
|
|
5
|
+
export const rawContent: string
|
|
6
|
+
export const meta: () => any[]
|
|
7
|
+
export const handle: any
|
|
8
|
+
|
|
9
|
+
const Page: () => JSX.Element
|
|
10
|
+
|
|
11
|
+
export default Page
|
|
12
|
+
}
|
package/dist/vite.d.mts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/vite-plugin.d.ts
|
|
4
|
+
type ReactRouterMarkdownOptions<D = Record<string, any>> = {
|
|
5
|
+
/**
|
|
6
|
+
* Module specifier to import a wrapper component from.
|
|
7
|
+
* Must default-export a React component.
|
|
8
|
+
*
|
|
9
|
+
* Example: '#/components/markdown/wrapper'
|
|
10
|
+
* @default undefined
|
|
11
|
+
*/
|
|
12
|
+
wrapperModule?: string;
|
|
13
|
+
/**
|
|
14
|
+
* If true, any HTML tags in the markdown content will be parsed as HTML instead of escaped.
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
parseHtml?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* A function to return the handle data to be used for each page.
|
|
20
|
+
* It accepts the post-processed content and frontmatter as arguments.
|
|
21
|
+
* @default undefined
|
|
22
|
+
*/
|
|
23
|
+
handleData?: (content: string, frontmatter: Record<string, any>) => Partial<D>;
|
|
24
|
+
/**
|
|
25
|
+
* A function to transform the raw MD file content before it is parsed.
|
|
26
|
+
* @default undefined
|
|
27
|
+
*/
|
|
28
|
+
beforeTransform?: (content: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* A function to transform the parsed MD content and/or frontmatter after they are parsed.
|
|
31
|
+
* It should return back the transformed content and frontmatter.
|
|
32
|
+
* @default undefined
|
|
33
|
+
*/
|
|
34
|
+
afterTransform?: (content: string, frontmatter: Record<string, any>) => [string, Record<string, any>];
|
|
35
|
+
};
|
|
36
|
+
declare function reactRouterMarkdown<D = Record<string, any>>(options?: ReactRouterMarkdownOptions<D>): Plugin;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { type ReactRouterMarkdownOptions, reactRouterMarkdown as default };
|
|
39
|
+
//# sourceMappingURL=vite.d.mts.map
|
package/dist/vite.mjs
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import matter from "gray-matter";
|
|
2
|
+
import "vite";
|
|
3
|
+
//#region src/lib/vite-plugin.ts
|
|
4
|
+
function reactRouterMarkdown(options = {}) {
|
|
5
|
+
const { wrapperModule, parseHtml = false, handleData: handleDataFn = () => ({}), beforeTransform = (content) => content, afterTransform = (content, frontmatter) => [content, frontmatter] } = options;
|
|
6
|
+
return {
|
|
7
|
+
name: "react-router-markdown",
|
|
8
|
+
enforce: "pre",
|
|
9
|
+
transform(code, id) {
|
|
10
|
+
if (!(id.split("?", 1)[0] ?? id).endsWith(".md")) return null;
|
|
11
|
+
const { data, content } = matter(beforeTransform(code));
|
|
12
|
+
const [transformedContent, transformedFrontmatter] = afterTransform(content, data || {});
|
|
13
|
+
const handleData = handleDataFn(transformedContent, transformedFrontmatter);
|
|
14
|
+
return {
|
|
15
|
+
code: [
|
|
16
|
+
`import { MarkdownPage } from 'react-router-markdown';`,
|
|
17
|
+
wrapperModule ? `import Wrapper from ${JSON.stringify(wrapperModule)};` : "const Wrapper = null;",
|
|
18
|
+
"",
|
|
19
|
+
`export const frontmatter = ${JSON.stringify(transformedFrontmatter || {})};`,
|
|
20
|
+
`export const rawContent = ${JSON.stringify(transformedContent || "")};`,
|
|
21
|
+
"",
|
|
22
|
+
"export const meta = () => frontmatter.meta || [];",
|
|
23
|
+
`export const handle = ${JSON.stringify(handleData)};`,
|
|
24
|
+
"",
|
|
25
|
+
`function Page() {
|
|
26
|
+
return _jsx(MarkdownPage, {
|
|
27
|
+
Wrapper,
|
|
28
|
+
parseHtml: ${parseHtml ? "true" : "false"},
|
|
29
|
+
rawContent: rawContent,
|
|
30
|
+
frontmatter: frontmatter,
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
export default Page;
|
|
34
|
+
`
|
|
35
|
+
].join("\n"),
|
|
36
|
+
map: null
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/vite.ts
|
|
43
|
+
var vite_default = reactRouterMarkdown;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { vite_default as default };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=vite.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite.mjs","names":[],"sources":["../src/lib/vite-plugin.ts","../src/vite.ts"],"sourcesContent":["import matter from 'gray-matter'\nimport { type Plugin } from 'vite'\n\nexport type ReactRouterMarkdownOptions<D = Record<string, any>> = {\n /**\n * Module specifier to import a wrapper component from.\n * Must default-export a React component.\n *\n * Example: '#/components/markdown/wrapper'\n * @default undefined\n */\n wrapperModule?: string\n /**\n * If true, any HTML tags in the markdown content will be parsed as HTML instead of escaped.\n * @default false\n */\n parseHtml?: boolean\n /**\n * A function to return the handle data to be used for each page.\n * It accepts the post-processed content and frontmatter as arguments.\n * @default undefined\n */\n handleData?: (content: string, frontmatter: Record<string, any>) => Partial<D>\n\n /**\n * A function to transform the raw MD file content before it is parsed.\n * @default undefined\n */\n beforeTransform?: (content: string) => string\n\n /**\n * A function to transform the parsed MD content and/or frontmatter after they are parsed.\n * It should return back the transformed content and frontmatter.\n * @default undefined\n */\n afterTransform?: (\n content: string,\n frontmatter: Record<string, any>,\n ) => [string, Record<string, any>]\n}\n\nexport function reactRouterMarkdown<D = Record<string, any>>(\n options: ReactRouterMarkdownOptions<D> = {},\n): Plugin {\n const {\n wrapperModule,\n parseHtml = false,\n handleData: handleDataFn = () => ({}) as Partial<D>,\n beforeTransform = (content) => content,\n afterTransform = (content, frontmatter) => [content, frontmatter],\n }: ReactRouterMarkdownOptions<D> = options\n\n return {\n name: 'react-router-markdown',\n enforce: 'pre',\n\n transform(code, id) {\n const filePath = id.split('?', 1)[0] ?? id\n if (!filePath.endsWith('.md')) return null\n\n const transformedCode = beforeTransform(code)\n const { data, content } = matter(transformedCode)\n const [transformedContent, transformedFrontmatter] = afterTransform(content, data || {})\n const handleData = handleDataFn(transformedContent, transformedFrontmatter)\n\n return {\n code: [\n `import { MarkdownPage } from 'react-router-markdown';`,\n wrapperModule\n ? `import Wrapper from ${JSON.stringify(wrapperModule)};`\n : 'const Wrapper = null;',\n '',\n `export const frontmatter = ${JSON.stringify(transformedFrontmatter || {})};`,\n `export const rawContent = ${JSON.stringify(transformedContent || '')};`,\n '',\n 'export const meta = () => frontmatter.meta || [];',\n `export const handle = ${JSON.stringify(handleData)};`,\n '',\n `function Page() {\n return _jsx(MarkdownPage, {\n Wrapper,\n parseHtml: ${parseHtml ? 'true' : 'false'},\n rawContent: rawContent,\n frontmatter: frontmatter,\n })\n }\n export default Page;\n `,\n ].join('\\n'),\n map: null,\n }\n },\n }\n}\n","export { type ReactRouterMarkdownOptions } from './lib/vite-plugin'\n\nimport { reactRouterMarkdown } from './lib/vite-plugin'\n\nexport default reactRouterMarkdown\n"],"mappings":";;;AAyCA,SAAgB,oBACd,UAAyC,EAAE,EACnC;CACR,MAAM,EACJ,eACA,YAAY,OACZ,YAAY,sBAAsB,EAAE,GACpC,mBAAmB,YAAY,SAC/B,kBAAkB,SAAS,gBAAgB,CAAC,SAAS,YAAY,KAChC;AAEnC,QAAO;EACL,MAAM;EACN,SAAS;EAET,UAAU,MAAM,IAAI;AAElB,OAAI,EADa,GAAG,MAAM,KAAK,EAAE,CAAC,MAAM,IAC1B,SAAS,MAAM,CAAE,QAAO;GAGtC,MAAM,EAAE,MAAM,YAAY,OADF,gBAAgB,KAAK,CACI;GACjD,MAAM,CAAC,oBAAoB,0BAA0B,eAAe,SAAS,QAAQ,EAAE,CAAC;GACxF,MAAM,aAAa,aAAa,oBAAoB,uBAAuB;AAE3E,UAAO;IACL,MAAM;KACJ;KACA,gBACI,uBAAuB,KAAK,UAAU,cAAc,CAAC,KACrD;KACJ;KACA,8BAA8B,KAAK,UAAU,0BAA0B,EAAE,CAAC,CAAC;KAC3E,6BAA6B,KAAK,UAAU,sBAAsB,GAAG,CAAC;KACtE;KACA;KACA,yBAAyB,KAAK,UAAU,WAAW,CAAC;KACpD;KACA;;;2BAGiB,YAAY,SAAS,QAAQ;;;;;;;KAO/C,CAAC,KAAK,KAAK;IACZ,KAAK;IACN;;EAEJ;;;;ACxFH,IAAA,eAAe"}
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-router-markdown",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Vite plugin to parse and use markdown files as React Router pages, including frontmatter support.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"markdown",
|
|
7
|
+
"react-router",
|
|
8
|
+
"vite-plugin"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://github.com/itsjavi/react-router-markdown#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/itsjavi/react-router-markdown/issues"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Javier Aguilar",
|
|
17
|
+
"url": "https://itsjavi.com"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/itsjavi/react-router-markdown.git"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"LICENSE.md",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.mts",
|
|
33
|
+
"import": "./dist/index.mjs"
|
|
34
|
+
},
|
|
35
|
+
"./vite": {
|
|
36
|
+
"types": "./dist/vite.d.mts",
|
|
37
|
+
"import": "./dist/vite.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./references": "./dist/references.d.ts"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsdown",
|
|
43
|
+
"dev": "tsdown --watch",
|
|
44
|
+
"format": "oxfmt --write .",
|
|
45
|
+
"format:check": "oxfmt --check .",
|
|
46
|
+
"lint": "pnpm typecheck && pnpm publint",
|
|
47
|
+
"publint": "publint",
|
|
48
|
+
"test": "vitest --run",
|
|
49
|
+
"test:coverage": "vitest --run --coverage",
|
|
50
|
+
"test:watch": "vitest --watch",
|
|
51
|
+
"typecheck": "tsc --noEmit"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"gray-matter": "^4.0.3",
|
|
55
|
+
"hast-util-raw": "^9.1.0",
|
|
56
|
+
"react-markdown": "^10.1.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/node": "^25.5.0",
|
|
60
|
+
"@types/react": "^19.2.14",
|
|
61
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
62
|
+
"oxfmt": "^0.42.0",
|
|
63
|
+
"publint": "^0.3.18",
|
|
64
|
+
"react": "^19.2.4",
|
|
65
|
+
"tsdown": "^0.21.7",
|
|
66
|
+
"typescript": "^6.0.2",
|
|
67
|
+
"vite": "^8.0.3",
|
|
68
|
+
"vitest": "^4.1.2"
|
|
69
|
+
},
|
|
70
|
+
"peerDependencies": {
|
|
71
|
+
"react": "^19.2.4",
|
|
72
|
+
"vite": "^7.0.0 || ^8.0.0"
|
|
73
|
+
},
|
|
74
|
+
"packageManager": "pnpm@10.33.0"
|
|
75
|
+
}
|