vitepress-plugin-md-api 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 vitepress-plugin-md-api contributors
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,181 @@
1
+ # vitepress-plugin-md-api
2
+
3
+ > 在 VitePress 的 Markdown 中使用 `@API('类型文件', '接口名')`,自动把 TypeScript interface / type 渲染为接口说明表格。
4
+
5
+ 生成的表格支持 **必填、默认值、废弃标记、readonly、方法签名、索引签名、JSDoc 注释**,并内置 **多语言(zh-CN / en-US)**,可扩展任意语言。
6
+
7
+ ## ✨ 特性
8
+
9
+ - 🧩 一行指令 `@API('../types/user.ts', 'User')` 即生成 API 表格
10
+ - 🔍 基于 TypeScript 编译器 API 解析 AST,类型/方法/索引签名准确还原
11
+ - 📝 自动提取 JSDoc:说明、`@default` 默认值、`@deprecated` 废弃原因
12
+ - 🌐 内置 zh-CN / en-US 界面文案,JSDoc 用 `@locale` 标签做多语言注释
13
+ - 🗂️ 与 VitePress `locales` 目录结构联动,按路径自动切换语言
14
+ - ⚠️ 解析失败时输出警告块,不中断构建
15
+ - 🔥 通过 `addWatchFile` 监听类型文件,修改后文档热更新
16
+ - 🛡️ 代码块内的 `@API(...)` 示例自动遮蔽,不会被误替换
17
+
18
+ ## 📦 安装
19
+
20
+ ```bash
21
+ npm i -D vitepress-plugin-md-api
22
+ # pnpm add -D vitepress-plugin-md-api
23
+ # yarn add -D vitepress-plugin-md-api
24
+ ```
25
+
26
+ ## 🚀 快速开始
27
+
28
+ ### 1. 注册插件
29
+
30
+ 在 `.vitepress/config.mts` 中挂载:
31
+
32
+ ```ts
33
+ import { defineConfig } from 'vitepress'
34
+ import { mdApiPlugin } from 'vitepress-plugin-md-api'
35
+
36
+ export default defineConfig({
37
+ vite: {
38
+ plugins: [mdApiPlugin()]
39
+ }
40
+ })
41
+ ```
42
+
43
+ ### 2. 准备类型文件
44
+
45
+ ```ts
46
+ // types/user.ts
47
+ export interface User {
48
+ /** 用户名 */
49
+ name: string
50
+ /** 年龄 @default 18 */
51
+ age?: number
52
+ /** @deprecated 请使用 name */
53
+ oldName?: string
54
+ readonly id: string
55
+ /** 打招呼 */
56
+ greet(greeting: string, loud?: boolean): string
57
+ [key: string]: any
58
+ }
59
+ ```
60
+
61
+ ### 3. 在 Markdown 中使用
62
+
63
+ ```md
64
+ @API('../types/user.ts', 'User')
65
+ ```
66
+
67
+ 渲染结果:
68
+
69
+ | 属性名 | 类型 | 必填 | 默认值 | 说明 |
70
+ | --- | --- | --- | --- | --- |
71
+ | `name` | `string` | 是 | - | 用户名 |
72
+ | `age` | `number` | 否 | `18` | 年龄 |
73
+ | `oldName` | `string` | 否 | - | **(已废弃:请使用 name)** |
74
+ | `id` _(readonly)_ | `string` | 是 | - | - |
75
+ | `greet(greeting: string, loud?: boolean)` | `string` | 是 | - | 打招呼 |
76
+ | `[key: string]` | `any` | 是 | - | - |
77
+
78
+ 类型文件路径相对当前 markdown 文件解析,省略扩展名时会自动尝试 `.ts` / `.d.ts` / `.tsx` / `.mts` / `.cts`。
79
+
80
+ ## 🌐 多语言支持
81
+
82
+ ### 指令显式指定
83
+
84
+ 第三个参数为语言代码:
85
+
86
+ ```md
87
+ @API('../types/user.ts', 'User', 'en-US')
88
+ ```
89
+
90
+ ### JSDoc 多语言注释
91
+
92
+ 在类型文件中用 `@locale <语言代码> <说明>` 提供翻译,未命中的语言回退到默认注释:
93
+
94
+ ```ts
95
+ export interface Book {
96
+ /**
97
+ * 书名
98
+ * @locale en-US Book title
99
+ * @locale ja-JP 書名
100
+ */
101
+ title: string
102
+ }
103
+ ```
104
+
105
+ 废弃原因同理:`@deprecatedLocale en-US Use name instead`。
106
+
107
+ ### 语言判定优先级
108
+
109
+ 1. 指令第三参数(支持前缀匹配,`en` 可命中 `en-US`)
110
+ 2. Markdown 文件路径前缀检测(VitePress `locales` 目录如 `doc/en/`)
111
+ 3. 插件选项 `defaultLocale`(默认 `zh-CN`)
112
+
113
+ ### 自定义语言包
114
+
115
+ 通过 `locales` 选项扩展或覆盖语言包,只写需要覆盖的字段,其余回退内置文案:
116
+
117
+ ```ts
118
+ mdApiPlugin({
119
+ defaultLocale: 'zh-CN',
120
+ locales: {
121
+ 'ja-JP': {
122
+ columnName: 'プロパティ',
123
+ columnType: '型',
124
+ columnRequired: '必須',
125
+ columnDefault: 'デフォルト',
126
+ columnDescription: '説明',
127
+ yes: 'はい',
128
+ no: 'いいえ',
129
+ readonlyLabel: 'readonly',
130
+ deprecated: (r) => `**(非推奨${r ? `:${r}` : ''})**`,
131
+ noProperties: (n) => `\`${n}\` にプロパティがありません`,
132
+ parseFailed: '解析失敗:'
133
+ }
134
+ }
135
+ })
136
+ ```
137
+
138
+ `LocaleMessages` 完整字段:
139
+
140
+ | 字段 | 类型 | 说明 |
141
+ | --- | --- | --- |
142
+ | `columnName` | string | 表头「属性名」 |
143
+ | `columnType` | string | 表头「类型」 |
144
+ | `columnRequired` | string | 表头「必填」 |
145
+ | `columnDefault` | string | 表头「默认值」 |
146
+ | `columnDescription` | string | 表头「说明」 |
147
+ | `yes` / `no` | string | 是 / 否 |
148
+ | `readonlyLabel` | string | readonly 标记文本 |
149
+ | `deprecated` | `(reason?: string) => string` | 废弃标记 |
150
+ | `noProperties` | `(name: string) => string` | 空接口提示 |
151
+ | `parseFailed` | string | 解析失败警告块标题 |
152
+
153
+ ## ⚙️ 插件选项
154
+
155
+ ```ts
156
+ interface MdApiPluginOptions {
157
+ /** 类型文件解析基准目录(绝对路径),默认先相对当前 md 目录再回退到此目录 */
158
+ baseDir?: string
159
+ /** 默认界面语言代码,默认 `zh-CN` */
160
+ defaultLocale?: string
161
+ /** 自定义 / 覆盖语言包,key 为语言代码,value 为部分或完整 LocaleMessages */
162
+ locales?: Record<string, Partial<LocaleMessages>>
163
+ }
164
+ ```
165
+
166
+ ## 🏗️ 开发 & 发布
167
+
168
+ ```bash
169
+ # 构建
170
+ npm run build # tsc 输出到 dist/
171
+
172
+ # 本地测试发布
173
+ npm pack
174
+
175
+ # 发布到 npm
176
+ npm publish
177
+ ```
178
+
179
+ ## 📄 License
180
+
181
+ MIT
@@ -0,0 +1,10 @@
1
+ import type { InterfaceInfo } from './parser.js';
2
+ import { type LocaleMessages } from './locales.js';
3
+ /**
4
+ * 将接口信息生成为 GFM Markdown 表格。
5
+ * 表头与界面文案由 `t`(LocaleMessages)提供,属性说明按 `localeCode` 选取。
6
+ */
7
+ export declare function generateTable(info: InterfaceInfo, localeCode: string, t: LocaleMessages): string;
8
+ /** 解析失败时生成警告块,避免静默失效 */
9
+ export declare function generateWarning(fileArg: string, name: string, t: LocaleMessages, message: string): string;
10
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAyC9D;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,MAAM,EAClB,CAAC,EAAE,cAAc,GAChB,MAAM,CAmBR;AAED,wBAAwB;AACxB,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,cAAc,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAMR"}
@@ -0,0 +1,61 @@
1
+ import { pickLocale } from './locales.js';
2
+ /** 转义表格单元格中的管道符与换行 */
3
+ function escapeCell(text) {
4
+ return text
5
+ .replace(/\r?\n/g, ' ')
6
+ .replace(/\|/g, '\\|')
7
+ .trim();
8
+ }
9
+ /** 行内代码单元格:类型里的反引号替换为单引号,换行转为 <br> */
10
+ function codeCell(code) {
11
+ const safe = code
12
+ .replace(/`/g, "'")
13
+ .replace(/\s*\n\s*/g, '<br>')
14
+ .trim();
15
+ return '`' + safe + '`';
16
+ }
17
+ /** 选取当前语言的说明文本,未命中时回退到默认 description */
18
+ function localizeDescription(member, localeCode) {
19
+ return pickLocale(member.descriptions, localeCode) ?? member.description;
20
+ }
21
+ function descriptionCell(member, localeCode, t) {
22
+ const parts = [];
23
+ if (member.deprecated) {
24
+ const reason = pickLocale(member.deprecatedReasons, localeCode) ??
25
+ (typeof member.deprecated === 'string' ? member.deprecated : undefined);
26
+ parts.push(t.deprecated(reason));
27
+ }
28
+ const description = localizeDescription(member, localeCode);
29
+ if (description)
30
+ parts.push(escapeCell(description));
31
+ return parts.length ? parts.join(' ') : '-';
32
+ }
33
+ /**
34
+ * 将接口信息生成为 GFM Markdown 表格。
35
+ * 表头与界面文案由 `t`(LocaleMessages)提供,属性说明按 `localeCode` 选取。
36
+ */
37
+ export function generateTable(info, localeCode, t) {
38
+ const header = `| ${t.columnName} | ${t.columnType} | ${t.columnRequired} | ${t.columnDefault} | ${t.columnDescription} |\n` +
39
+ '| --- | --- | --- | --- | --- |';
40
+ if (info.members.length === 0) {
41
+ return `${header}\n| - | - | - | - | ${t.noProperties(info.name)} |`;
42
+ }
43
+ const rows = info.members.map((m) => {
44
+ const name = codeCell(m.name) + (m.readonly ? ` _(${t.readonlyLabel})_` : '');
45
+ const type = codeCell(m.type);
46
+ const required = m.required ? t.yes : t.no;
47
+ const defaultValue = m.default ? codeCell(m.default) : '-';
48
+ const description = descriptionCell(m, localeCode, t);
49
+ return `| ${name} | ${type} | ${required} | ${defaultValue} | ${description} |`;
50
+ });
51
+ return [header, ...rows].join('\n');
52
+ }
53
+ /** 解析失败时生成警告块,避免静默失效 */
54
+ export function generateWarning(fileArg, name, t, message) {
55
+ return [
56
+ '> [!WARNING]',
57
+ `> \`@API('${fileArg}', '${name}')\` ${t.parseFailed}`,
58
+ `> ${message.split('\n').join('\n> ')}`
59
+ ].join('\n');
60
+ }
61
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import type { Plugin } from 'vite';
2
+ import { type LocaleMessages } from './locales.js';
3
+ export { parseInterface, resolveTypeFile } from './parser.js';
4
+ export type { ApiMember, InterfaceInfo } from './parser.js';
5
+ export { generateTable, generateWarning } from './generator.js';
6
+ export { BUILTIN_LOCALES, detectLocaleFromPath, normalizeLocale, pickLocale, resolveLocaleCode, resolveLocaleMessages } from './locales.js';
7
+ export type { LocaleMessages } from './locales.js';
8
+ export interface MdApiPluginOptions {
9
+ /**
10
+ * 解析类型文件的基准目录(绝对路径)。
11
+ * 默认先相对当前 markdown 文件所在目录解析,再回退到该目录。
12
+ */
13
+ baseDir?: string;
14
+ /**
15
+ * 默认界面语言代码,默认 `zh-CN`。
16
+ * 内置支持 `zh-CN`、`en-US`,可通过 locales 选项扩展或覆盖。
17
+ */
18
+ defaultLocale?: string;
19
+ /**
20
+ * 自定义 / 覆盖界面文案。key 为语言代码,value 为部分或完整 LocaleMessages。
21
+ * 未提供的字段回退到内置语言包;未知语言则需提供完整字段。
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * mdApiPlugin({
26
+ * locales: {
27
+ * 'ja-JP': {
28
+ * columnName: 'プロパティ',
29
+ * columnType: '型',
30
+ * // ...
31
+ * },
32
+ * 'en-US': { yes: 'Y' } // 仅覆盖部分字段
33
+ * }
34
+ * })
35
+ * ```
36
+ */
37
+ locales?: Record<string, Partial<LocaleMessages>>;
38
+ }
39
+ /**
40
+ * VitePress 插件:在 markdown 中使用
41
+ * `@API('类型文件地址', 'InterfaceName', '语言代码?')`
42
+ * 自动生成 TypeScript 接口说明表格。
43
+ *
44
+ * 语言解析优先级:指令第三参数 > markdown 路径前缀(VitePress locales 目录)
45
+ * > defaultLocale 选项(默认 zh-CN)。
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * // .vitepress/config.mts
50
+ * import { defineConfig } from 'vitepress'
51
+ * import { mdApiPlugin } from 'vitepress-plugin-md-api'
52
+ *
53
+ * export default defineConfig({
54
+ * vite: {
55
+ * plugins: [
56
+ * mdApiPlugin({
57
+ * defaultLocale: 'zh-CN',
58
+ * locales: {
59
+ * 'ja-JP': { columnName: 'プロパティ' } // 其余字段需补全
60
+ * }
61
+ * })
62
+ * ]
63
+ * }
64
+ * })
65
+ * ```
66
+ *
67
+ * ```md
68
+ * @API('../types/Module.d.ts', 'Book')
69
+ * @API('../types/Module.d.ts', 'Book', 'en-US')
70
+ * ```
71
+ *
72
+ * 类型文件中用 JSDoc 标签提供多语言说明:
73
+ * ```ts
74
+ * /**
75
+ * * 书名
76
+ * * @locale en-US Book title
77
+ * *\/
78
+ * title: string
79
+ * ```
80
+ */
81
+ export declare function mdApiPlugin(options?: MdApiPluginOptions): Plugin;
82
+ export default mdApiPlugin;
83
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAGlC,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7D,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAA;CAClD;AAyCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,MAAM,CA4DpE;AAED,eAAe,WAAW,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,124 @@
1
+ import path from 'node:path';
2
+ import { parseInterface, resolveTypeFile } from './parser.js';
3
+ import { generateTable, generateWarning } from './generator.js';
4
+ import { BUILTIN_LOCALES, pickLocale, resolveLocaleCode, resolveLocaleMessages } from './locales.js';
5
+ export { parseInterface, resolveTypeFile } from './parser.js';
6
+ export { generateTable, generateWarning } from './generator.js';
7
+ export { BUILTIN_LOCALES, detectLocaleFromPath, normalizeLocale, pickLocale, resolveLocaleCode, resolveLocaleMessages } from './locales.js';
8
+ /**
9
+ * 匹配 @API('path/to/file', 'InterfaceName'),
10
+ * 第三参数为可选语言代码:@API('file', 'User', 'en-US')。
11
+ * 兼容单/双引号与多余空白。
12
+ */
13
+ const DIRECTIVE_RE = /@API\(\s*(['"])([^'"]+)\1\s*,\s*(['"])([^'"]+)\3(?:\s*,\s*(['"])([^'"]+)\5)?\s*\)/g;
14
+ /** 围栏代码块(``` / ~~~) */
15
+ const FENCED_CODE_RE = /(^|\n)([ \t]*)(`{3,}|~{3,})[^\n]*\n[\s\S]*?\n[ \t]*\3[ \t]*(?=\n|$)/g;
16
+ /** 行内代码 `...` */
17
+ const INLINE_CODE_RE = /`[^`\n]*`/g;
18
+ const PLACEHOLDER = '\u0000MDAPI_CODE_%s\u0000';
19
+ /**
20
+ * 遮蔽代码块/行内代码,避免示例代码中的 @API(...) 被误替换。
21
+ * 返回替换后的文本与还原函数。
22
+ */
23
+ function maskCode(source) {
24
+ const blocks = [];
25
+ const stash = (code) => {
26
+ blocks.push(code);
27
+ return PLACEHOLDER.replace('%s', String(blocks.length - 1));
28
+ };
29
+ const text = source
30
+ .replace(FENCED_CODE_RE, (m) => stash(m))
31
+ .replace(INLINE_CODE_RE, (m) => stash(m));
32
+ const restore = (s) => s.replace(new RegExp(`\u0000MDAPI_CODE_(\\d+)\u0000`, 'g'), (_, i) => blocks[Number(i)]);
33
+ return { text, restore };
34
+ }
35
+ /**
36
+ * VitePress 插件:在 markdown 中使用
37
+ * `@API('类型文件地址', 'InterfaceName', '语言代码?')`
38
+ * 自动生成 TypeScript 接口说明表格。
39
+ *
40
+ * 语言解析优先级:指令第三参数 > markdown 路径前缀(VitePress locales 目录)
41
+ * > defaultLocale 选项(默认 zh-CN)。
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * // .vitepress/config.mts
46
+ * import { defineConfig } from 'vitepress'
47
+ * import { mdApiPlugin } from 'vitepress-plugin-md-api'
48
+ *
49
+ * export default defineConfig({
50
+ * vite: {
51
+ * plugins: [
52
+ * mdApiPlugin({
53
+ * defaultLocale: 'zh-CN',
54
+ * locales: {
55
+ * 'ja-JP': { columnName: 'プロパティ' } // 其余字段需补全
56
+ * }
57
+ * })
58
+ * ]
59
+ * }
60
+ * })
61
+ * ```
62
+ *
63
+ * ```md
64
+ * @API('../types/Module.d.ts', 'Book')
65
+ * @API('../types/Module.d.ts', 'Book', 'en-US')
66
+ * ```
67
+ *
68
+ * 类型文件中用 JSDoc 标签提供多语言说明:
69
+ * ```ts
70
+ * /**
71
+ * * 书名
72
+ * * @locale en-US Book title
73
+ * *\/
74
+ * title: string
75
+ * ```
76
+ */
77
+ export function mdApiPlugin(options = {}) {
78
+ const messagesMap = resolveLocaleMessages(options.locales);
79
+ const localeKeys = Object.keys(messagesMap);
80
+ const defaultLocale = options.defaultLocale ?? 'zh-CN';
81
+ return {
82
+ name: 'vitepress-plugin-md-api',
83
+ enforce: 'pre',
84
+ transform(code, id) {
85
+ const cleanId = id.replace(/[?#].*$/, '');
86
+ if (!cleanId.endsWith('.md'))
87
+ return null;
88
+ if (!code.includes('@API('))
89
+ return null;
90
+ const markdownDir = path.dirname(cleanId);
91
+ const { text, restore } = maskCode(code);
92
+ let changed = false;
93
+ const replaced = text.replace(DIRECTIVE_RE, (_match, _q1, fileArg, _q2, nameArg, _q3, localeArg) => {
94
+ changed = true;
95
+ try {
96
+ const typeFile = resolveTypeFile(fileArg, markdownDir, options.baseDir);
97
+ this.addWatchFile(typeFile);
98
+ const info = parseInterface(typeFile, nameArg);
99
+ const localeCode = resolveLocaleCode({
100
+ directive: localeArg,
101
+ filePath: cleanId,
102
+ localeKeys,
103
+ defaultLocale
104
+ });
105
+ const t = pickLocale(messagesMap, localeCode) ??
106
+ messagesMap[defaultLocale] ??
107
+ BUILTIN_LOCALES['zh-CN'];
108
+ return `\n\n${generateTable(info, localeCode, t)}\n\n`;
109
+ }
110
+ catch (error) {
111
+ const message = error instanceof Error ? error.message : String(error);
112
+ this.warn(`[vitepress-plugin-md-api] ${message}`);
113
+ const fallback = messagesMap[defaultLocale] ?? BUILTIN_LOCALES['zh-CN'];
114
+ return `\n\n${generateWarning(fileArg, nameArg, fallback, message)}\n\n`;
115
+ }
116
+ });
117
+ if (!changed)
118
+ return null;
119
+ return restore(replaced);
120
+ }
121
+ };
122
+ }
123
+ export default mdApiPlugin;
124
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /** 插件界面文案,可按语言自定义或覆盖 */
2
+ export interface LocaleMessages {
3
+ /** 表头:属性名 */
4
+ columnName: string;
5
+ /** 表头:类型 */
6
+ columnType: string;
7
+ /** 表头:必填 */
8
+ columnRequired: string;
9
+ /** 表头:默认值 */
10
+ columnDefault: string;
11
+ /** 表头:说明 */
12
+ columnDescription: string;
13
+ /** 必填:是 */
14
+ yes: string;
15
+ /** 必填:否 */
16
+ no: string;
17
+ /** readonly 标记文本 */
18
+ readonlyLabel: string;
19
+ /** 废弃标记,reason 为废弃原因(可能为空字符串) */
20
+ deprecated: (reason?: string) => string;
21
+ /** 接口无属性时的提示文本 */
22
+ noProperties: (interfaceName: string) => string;
23
+ /** 警告块标题:解析失败 */
24
+ parseFailed: string;
25
+ }
26
+ /** 内置语言包 */
27
+ export declare const BUILTIN_LOCALES: Record<string, LocaleMessages>;
28
+ /** 归一化语言代码:小写、下划线转连字符(zh_CN -> zh-cn) */
29
+ export declare function normalizeLocale(code: string): string;
30
+ /**
31
+ * 按语言代码从映射中取值。
32
+ * 匹配顺序:精确 → 大小写不敏感 → 前缀(en 匹配 en-US,zh-CN 匹配 zh)。
33
+ */
34
+ export declare function pickLocale<T>(map: Record<string, T> | undefined, code: string): T | undefined;
35
+ /**
36
+ * 合并内置语言包与用户自定义语言包。
37
+ * 用户只需提供部分字段,其余回退到内置文案;全新语言则需提供完整字段。
38
+ */
39
+ export declare function resolveLocaleMessages(custom?: Record<string, Partial<LocaleMessages>>): Record<string, LocaleMessages>;
40
+ /**
41
+ * 从 markdown 文件路径中检测语言:
42
+ * 路径段与 locale key 匹配,如 `doc/en/guide.md` → en-US、`doc/zh-CN/` → zh-CN。
43
+ * 适配 VitePress locales 的目录结构(根目录为默认语言,子目录为其他语言)。
44
+ */
45
+ export declare function detectLocaleFromPath(filePath: string, localeKeys: string[]): string | undefined;
46
+ /**
47
+ * 解析最终使用的语言代码,优先级:
48
+ * 1. 指令第三参数 `@API('file', 'Interface', 'en-US')`
49
+ * 2. markdown 文件路径前缀自动检测(VitePress locales 目录)
50
+ * 3. 插件选项 defaultLocale
51
+ */
52
+ export declare function resolveLocaleCode(options: {
53
+ directive?: string;
54
+ filePath: string;
55
+ localeKeys: string[];
56
+ defaultLocale: string;
57
+ }): string;
58
+ //# sourceMappingURL=locales.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../src/locales.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,MAAM,WAAW,cAAc;IAC7B,aAAa;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY;IACZ,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa;IACb,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY;IACZ,iBAAiB,EAAE,MAAM,CAAA;IACzB,WAAW;IACX,GAAG,EAAE,MAAM,CAAA;IACX,WAAW;IACX,EAAE,EAAE,MAAM,CAAA;IACV,oBAAoB;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,iCAAiC;IACjC,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC,kBAAkB;IAClB,YAAY,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/C,iBAAiB;IACjB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,YAAY;AACZ,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CA2B1D,CAAA;AAED,yCAAyC;AACzC,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,EAClC,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,SAAS,CAef;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,GAC/C,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAShC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAAE,GACnB,MAAM,GAAG,SAAS,CAUpB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;CACtB,GAAG,MAAM,CAST"}
@@ -0,0 +1,100 @@
1
+ /** 内置语言包 */
2
+ export const BUILTIN_LOCALES = {
3
+ 'zh-CN': {
4
+ columnName: '属性名',
5
+ columnType: '类型',
6
+ columnRequired: '必填',
7
+ columnDefault: '默认值',
8
+ columnDescription: '说明',
9
+ yes: '是',
10
+ no: '否',
11
+ readonlyLabel: 'readonly',
12
+ deprecated: (reason) => `**(已废弃${reason ? `:${reason}` : ''})**`,
13
+ noProperties: (name) => `\`${name}\` 暂无属性`,
14
+ parseFailed: '解析失败:'
15
+ },
16
+ 'en-US': {
17
+ columnName: 'Property',
18
+ columnType: 'Type',
19
+ columnRequired: 'Required',
20
+ columnDefault: 'Default',
21
+ columnDescription: 'Description',
22
+ yes: 'Yes',
23
+ no: 'No',
24
+ readonlyLabel: 'readonly',
25
+ deprecated: (reason) => `**(Deprecated${reason ? `: ${reason}` : ''})**`,
26
+ noProperties: (name) => `\`${name}\` has no properties`,
27
+ parseFailed: 'failed to parse:'
28
+ }
29
+ };
30
+ /** 归一化语言代码:小写、下划线转连字符(zh_CN -> zh-cn) */
31
+ export function normalizeLocale(code) {
32
+ return code.trim().toLowerCase().replace(/_/g, '-');
33
+ }
34
+ /**
35
+ * 按语言代码从映射中取值。
36
+ * 匹配顺序:精确 → 大小写不敏感 → 前缀(en 匹配 en-US,zh-CN 匹配 zh)。
37
+ */
38
+ export function pickLocale(map, code) {
39
+ if (!map)
40
+ return undefined;
41
+ if (map[code])
42
+ return map[code];
43
+ const target = normalizeLocale(code);
44
+ for (const [key, value] of Object.entries(map)) {
45
+ if (normalizeLocale(key) === target)
46
+ return value;
47
+ }
48
+ const short = target.split('-')[0];
49
+ for (const [key, value] of Object.entries(map)) {
50
+ const keyLower = normalizeLocale(key);
51
+ if (keyLower === short || keyLower.startsWith(short + '-'))
52
+ return value;
53
+ }
54
+ return undefined;
55
+ }
56
+ /**
57
+ * 合并内置语言包与用户自定义语言包。
58
+ * 用户只需提供部分字段,其余回退到内置文案;全新语言则需提供完整字段。
59
+ */
60
+ export function resolveLocaleMessages(custom) {
61
+ const result = { ...BUILTIN_LOCALES };
62
+ if (!custom)
63
+ return result;
64
+ for (const [code, partial] of Object.entries(custom)) {
65
+ const base = pickLocale(BUILTIN_LOCALES, code) ?? {};
66
+ result[code] = { ...base, ...partial };
67
+ }
68
+ return result;
69
+ }
70
+ /**
71
+ * 从 markdown 文件路径中检测语言:
72
+ * 路径段与 locale key 匹配,如 `doc/en/guide.md` → en-US、`doc/zh-CN/` → zh-CN。
73
+ * 适配 VitePress locales 的目录结构(根目录为默认语言,子目录为其他语言)。
74
+ */
75
+ export function detectLocaleFromPath(filePath, localeKeys) {
76
+ const segments = filePath.split(/[\\/]/).map(normalizeLocale);
77
+ for (const key of localeKeys) {
78
+ const keyLower = normalizeLocale(key);
79
+ const short = keyLower.split('-')[0];
80
+ if (segments.some((seg) => seg === keyLower || seg === short)) {
81
+ return key;
82
+ }
83
+ }
84
+ return undefined;
85
+ }
86
+ /**
87
+ * 解析最终使用的语言代码,优先级:
88
+ * 1. 指令第三参数 `@API('file', 'Interface', 'en-US')`
89
+ * 2. markdown 文件路径前缀自动检测(VitePress locales 目录)
90
+ * 3. 插件选项 defaultLocale
91
+ */
92
+ export function resolveLocaleCode(options) {
93
+ if (options.directive) {
94
+ const keyMap = Object.fromEntries(options.localeKeys.map((k) => [k, k]));
95
+ return pickLocale(keyMap, options.directive) ?? options.directive;
96
+ }
97
+ return (detectLocaleFromPath(options.filePath, options.localeKeys) ??
98
+ options.defaultLocale);
99
+ }
100
+ //# sourceMappingURL=locales.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locales.js","sourceRoot":"","sources":["../src/locales.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /** 接口成员(属性 / 方法 / 索引签名)解析结果 */
2
+ export interface ApiMember {
3
+ /** 成员名称,方法会带参数列表,索引签名形如 [key: string] */
4
+ name: string;
5
+ /** 类型文本(属性为类型,方法为返回值类型) */
6
+ type: string;
7
+ /** 是否必填(没有 ? 修饰) */
8
+ required: boolean;
9
+ /** 是否 readonly */
10
+ readonly: boolean;
11
+ /** JSDoc 默认说明(未命中多语言标签时回退使用) */
12
+ description: string;
13
+ /**
14
+ * 多语言说明,来自 `@locale <code> <text>` 标签。
15
+ * @example
16
+ * ```ts
17
+ * /**
18
+ * * 书名
19
+ * * @locale en-US Book title
20
+ * *\/
21
+ * title: string
22
+ * ```
23
+ */
24
+ descriptions?: Record<string, string>;
25
+ /** @default 标签内容 */
26
+ default?: string;
27
+ /** 是否标记 @deprecated,字符串为默认废弃原因 */
28
+ deprecated?: boolean | string;
29
+ /** 多语言废弃原因,来自 `@deprecatedLocale <code> <text>` 标签 */
30
+ deprecatedReasons?: Record<string, string>;
31
+ }
32
+ export interface InterfaceInfo {
33
+ /** 接口 / 类型名 */
34
+ name: string;
35
+ /** 解析来源文件绝对路径 */
36
+ sourceFile: string;
37
+ members: ApiMember[];
38
+ }
39
+ /**
40
+ * 解析 TypeScript 文件中指定的 interface 或对象类型别名。
41
+ * @param filePath .ts / .d.ts 文件绝对路径
42
+ * @param name interface 或 type 名称
43
+ */
44
+ export declare function parseInterface(filePath: string, name: string): InterfaceInfo;
45
+ /**
46
+ * 解析类型文件路径:优先相对当前 markdown 文件目录,其次相对 baseDir。
47
+ * 省略扩展名时自动尝试 .ts / .d.ts 等。
48
+ */
49
+ export declare function resolveTypeFile(fileArg: string, markdownDir: string, baseDir?: string): string;
50
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAIA,+BAA+B;AAC/B,MAAM,WAAW,SAAS;IACxB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,oBAAoB;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,kBAAkB;IAClB,QAAQ,EAAE,OAAO,CAAA;IACjB,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,kCAAkC;IAClC,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IAC7B,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC3C;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,iBAAiB;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB;AAmJD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CA+C5E;AAKD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAoBR"}
package/dist/parser.js ADDED
@@ -0,0 +1,195 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import ts from 'typescript';
4
+ /** 解析单个成员上的 JSDoc 正文 */
5
+ function getJsDocDescription(node) {
6
+ const docs = node.jsDoc;
7
+ if (!docs || docs.length === 0)
8
+ return '';
9
+ const doc = docs[docs.length - 1];
10
+ return jsDocTextToString(doc.comment);
11
+ }
12
+ /** 读取指定 @tag 的文本内容 */
13
+ function getJsDocTagText(node, tagName) {
14
+ const docs = node.jsDoc;
15
+ if (!docs)
16
+ return undefined;
17
+ for (const doc of docs) {
18
+ const tag = doc.tags?.find((t) => t.tagName.text === tagName);
19
+ if (tag) {
20
+ const text = jsDocTextToString(tag.comment);
21
+ return text || '';
22
+ }
23
+ }
24
+ return undefined;
25
+ }
26
+ function hasJsDocTag(node, tagName) {
27
+ return getJsDocTagText(node, tagName) !== undefined;
28
+ }
29
+ /**
30
+ * 读取 `@tag <语言代码> <文本>` 形式的多语言标签,如:
31
+ * `@locale en-US Book title`、`@deprecatedLocale ja-JP xxx`
32
+ */
33
+ function getLocaleTaggedTexts(node, tagName) {
34
+ const docs = node.jsDoc;
35
+ if (!docs)
36
+ return undefined;
37
+ const map = {};
38
+ for (const doc of docs) {
39
+ for (const tag of doc.tags ?? []) {
40
+ if (tag.tagName.text !== tagName)
41
+ continue;
42
+ const text = jsDocTextToString(tag.comment);
43
+ const match = /^(\S+)\s+([\s\S]+)$/.exec(text);
44
+ if (match)
45
+ map[match[1]] = match[2].trim();
46
+ }
47
+ }
48
+ return Object.keys(map).length > 0 ? map : undefined;
49
+ }
50
+ /** JSDoc comment 可能是 string,也可能是 NodeArray(TS 4.7+) */
51
+ function jsDocTextToString(comment) {
52
+ if (!comment)
53
+ return '';
54
+ if (typeof comment === 'string')
55
+ return comment.trim();
56
+ return comment
57
+ .map((c) => ('text' in c ? c.text : ''))
58
+ .join('')
59
+ .trim();
60
+ }
61
+ function isReadonly(node) {
62
+ return (ts.canHaveModifiers(node) &&
63
+ !!ts.getModifiers(node)?.some((m) => m.kind === ts.SyntaxKind.ReadonlyKeyword));
64
+ }
65
+ /** 提取成员上的 JSDoc 公共字段(说明 / 默认值 / 废弃 / 多语言文案) */
66
+ function docFields(node) {
67
+ const deprecatedReason = getJsDocTagText(node, 'deprecated');
68
+ return {
69
+ description: getJsDocDescription(node),
70
+ descriptions: getLocaleTaggedTexts(node, 'locale'),
71
+ default: getJsDocTagText(node, 'default'),
72
+ deprecated: hasJsDocTag(node, 'deprecated')
73
+ ? deprecatedReason || true
74
+ : undefined,
75
+ deprecatedReasons: getLocaleTaggedTexts(node, 'deprecatedLocale')
76
+ };
77
+ }
78
+ /** 将属性/方法/索引签名节点转换为 ApiMember */
79
+ function memberToApi(member, sourceFile) {
80
+ if (ts.isPropertySignature(member) && member.name) {
81
+ const name = member.name.getText(sourceFile);
82
+ const type = member.type ? member.type.getText(sourceFile) : 'any';
83
+ return {
84
+ name,
85
+ type: normalizeType(type),
86
+ required: !member.questionToken,
87
+ readonly: isReadonly(member),
88
+ ...docFields(member)
89
+ };
90
+ }
91
+ if (ts.isMethodSignature(member) && member.name) {
92
+ const params = member.parameters
93
+ .map((p) => {
94
+ const pName = p.name.getText(sourceFile) + (p.questionToken ? '?' : '');
95
+ const pType = p.type ? p.type.getText(sourceFile) : 'any';
96
+ return `${pName}: ${normalizeType(pType)}`;
97
+ })
98
+ .join(', ');
99
+ const name = `${member.name.getText(sourceFile)}(${params})`;
100
+ const type = member.type ? member.type.getText(sourceFile) : 'void';
101
+ return {
102
+ name,
103
+ type: normalizeType(type),
104
+ required: !member.questionToken,
105
+ readonly: false,
106
+ ...docFields(member)
107
+ };
108
+ }
109
+ if (ts.isIndexSignatureDeclaration(member)) {
110
+ const params = member.parameters
111
+ .map((p) => {
112
+ const pType = p.type ? p.type.getText(sourceFile) : 'string';
113
+ return `[${p.name.getText(sourceFile)}: ${normalizeType(pType)}]`;
114
+ })
115
+ .join('');
116
+ return {
117
+ name: params,
118
+ type: normalizeType(member.type.getText(sourceFile)),
119
+ required: true,
120
+ readonly: isReadonly(member),
121
+ description: getJsDocDescription(member)
122
+ };
123
+ }
124
+ return null;
125
+ }
126
+ /** 折叠类型文本中的多余空白与换行 */
127
+ function normalizeType(text) {
128
+ return text.replace(/\s*\n\s*/g, ' ').replace(/\s{2,}/g, ' ').trim();
129
+ }
130
+ /**
131
+ * 解析 TypeScript 文件中指定的 interface 或对象类型别名。
132
+ * @param filePath .ts / .d.ts 文件绝对路径
133
+ * @param name interface 或 type 名称
134
+ */
135
+ export function parseInterface(filePath, name) {
136
+ if (!fs.existsSync(filePath)) {
137
+ throw new Error(`类型文件不存在: ${filePath}`);
138
+ }
139
+ const sourceText = fs.readFileSync(filePath, 'utf-8');
140
+ const sourceFile = ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true, filePath.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
141
+ let members;
142
+ const visit = (node) => {
143
+ if (members)
144
+ return;
145
+ if (ts.isInterfaceDeclaration(node) && node.name.text === name) {
146
+ members = node.members;
147
+ return;
148
+ }
149
+ if (ts.isTypeAliasDeclaration(node) &&
150
+ node.name.text === name &&
151
+ ts.isTypeLiteralNode(node.type)) {
152
+ members = node.type.members;
153
+ return;
154
+ }
155
+ ts.forEachChild(node, visit);
156
+ };
157
+ visit(sourceFile);
158
+ if (!members) {
159
+ throw new Error(`在 ${path.basename(filePath)} 中未找到 interface/type "${name}"`);
160
+ }
161
+ const apiMembers = members
162
+ .map((m) => memberToApi(m, sourceFile))
163
+ .filter((m) => m !== null);
164
+ return {
165
+ name,
166
+ sourceFile: filePath,
167
+ members: apiMembers
168
+ };
169
+ }
170
+ /** 支持的类型文件扩展名 */
171
+ const TYPE_EXTENSIONS = ['.ts', '.d.ts', '.tsx', '.mts', '.cts'];
172
+ /**
173
+ * 解析类型文件路径:优先相对当前 markdown 文件目录,其次相对 baseDir。
174
+ * 省略扩展名时自动尝试 .ts / .d.ts 等。
175
+ */
176
+ export function resolveTypeFile(fileArg, markdownDir, baseDir) {
177
+ const bases = [markdownDir];
178
+ if (baseDir)
179
+ bases.push(baseDir);
180
+ const candidates = [];
181
+ for (const base of bases) {
182
+ const direct = path.resolve(base, fileArg);
183
+ candidates.push(direct);
184
+ if (!path.extname(fileArg)) {
185
+ for (const ext of TYPE_EXTENSIONS)
186
+ candidates.push(direct + ext);
187
+ }
188
+ }
189
+ const found = candidates.find((c) => fs.existsSync(c) && fs.statSync(c).isFile());
190
+ if (!found) {
191
+ throw new Error(`无法解析类型文件 "${fileArg}",已尝试:\n${candidates.map((c) => ` - ${c}`).join('\n')}`);
192
+ }
193
+ return found;
194
+ }
195
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "vitepress-plugin-md-api",
3
+ "version": "0.1.0",
4
+ "description": "VitePress plugin: use @API('file', 'Interface') in markdown to generate TypeScript interface API tables",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "keywords": [
21
+ "vitepress",
22
+ "vitepress-plugin",
23
+ "markdown",
24
+ "typescript",
25
+ "interface",
26
+ "api-table"
27
+ ],
28
+ "license": "MIT",
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "dev": "tsc --watch"
32
+ },
33
+ "dependencies": {
34
+ "typescript": "^5.5.0"
35
+ },
36
+ "peerDependencies": {
37
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
38
+ "vitepress": "^1.0.0 || ^2.0.0-alpha.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^20.14.0",
42
+ "typescript": "^5.5.0",
43
+ "vite": "^7.0.0",
44
+ "vitepress": "^2.0.0-alpha.20"
45
+ }
46
+ }