@rspress/plugin-api-docgen 2.0.0-beta.9 → 2.0.0-rc.1

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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { CompilerOptions } from 'typescript';
2
2
  import type { ParserOptions } from 'react-docgen-typescript';
3
- import type { RspressPlugin } from '@rspress/shared';
3
+ import type { RspressPlugin } from '@rspress/core';
4
4
 
5
5
  declare type ApiParseTool = 'documentation' | 'react-docgen-typescript';
6
6
 
package/dist/index.js CHANGED
@@ -1,27 +1,26 @@
1
- import * as __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__ from "node:fs";
2
- import * as __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__ from "node:path";
3
- import * as __WEBPACK_EXTERNAL_MODULE__rspress_shared_logger_4374e44a__ from "@rspress/shared/logger";
4
- import * as __WEBPACK_EXTERNAL_MODULE__rspress_shared_baa012d0__ from "@rspress/shared";
5
- import * as __WEBPACK_EXTERNAL_MODULE_chokidar__ from "chokidar";
6
- import * as __WEBPACK_EXTERNAL_MODULE_react_docgen_typescript_e816f54f__ from "react-docgen-typescript";
7
- __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(__dirname, '..');
1
+ import node_fs from "node:fs";
2
+ import node_path from "node:path";
3
+ import { RSPRESS_TEMP_DIR, logger } from "@rspress/core";
4
+ import chokidar from "chokidar";
5
+ import { withCompilerOptions, withCustomConfig, withDefaultConfig } from "react-docgen-typescript";
6
+ node_path.join(__dirname, '..');
8
7
  const apiDocMap = {};
9
8
  const locales = {
10
9
  zh: {
11
- copy: "\u590D\u5236",
12
- copied: "\u590D\u5236\u6210\u529F",
13
- expand: "\u5C55\u5F00\u4EE3\u7801",
14
- collapse: "\u6536\u8D77\u4EE3\u7801",
15
- className: "\u8282\u70B9\u7C7B\u540D",
16
- style: "\u8282\u70B9\u6837\u5F0F",
17
- children: "\u5B50\u8282\u70B9",
18
- disabled: "\u662F\u5426\u7981\u7528",
19
- required: "\u5FC5\u586B",
20
- property: "\u5C5E\u6027",
21
- description: "\u8BF4\u660E",
22
- type: "\u7C7B\u578B",
23
- defaultValue: "\u9ED8\u8BA4\u503C",
24
- overview: "\u6982\u89C8"
10
+ copy: '复制',
11
+ copied: '复制成功',
12
+ expand: '展开代码',
13
+ collapse: '收起代码',
14
+ className: '节点类名',
15
+ style: '节点样式',
16
+ children: '子节点',
17
+ disabled: '是否禁用',
18
+ required: '必填',
19
+ property: '属性',
20
+ description: '说明',
21
+ type: '类型',
22
+ defaultValue: '默认值',
23
+ overview: '概览'
25
24
  },
26
25
  en: {
27
26
  copy: 'Copy',
@@ -40,20 +39,20 @@ const locales = {
40
39
  overview: 'Overview'
41
40
  },
42
41
  ru: {
43
- copy: "\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
44
- copied: "\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u043D\u043E \u0443\u0441\u043F\u0435\u0448\u043D\u043E",
45
- expand: "\u0420\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u043A\u043E\u0434",
46
- collapse: "\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C \u043A\u043E\u0434",
47
- className: "\u0418\u043C\u044F \u043A\u043B\u0430\u0441\u0441\u0430 \u0443\u0437\u043B\u0430",
48
- style: "\u0421\u0442\u0438\u043B\u044C \u0443\u0437\u043B\u0430",
49
- children: "\u0414\u043E\u0447\u0435\u0440\u043D\u0438\u0435 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u044B",
50
- disabled: "\u041E\u0442\u043A\u043B\u044E\u0447\u0435\u043D\u043E",
51
- required: "\u041E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E",
52
- property: "\u0421\u0432\u043E\u0439\u0441\u0442\u0432\u043E",
53
- description: "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435",
54
- type: "\u0422\u0438\u043F",
55
- defaultValue: "\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E",
56
- overview: "\u041E\u0431\u0437\u043E\u0440"
42
+ copy: 'Копировать',
43
+ copied: 'Скопировано успешно',
44
+ expand: 'Развернуть код',
45
+ collapse: 'Свернуть код',
46
+ className: 'Имя класса узла',
47
+ style: 'Стиль узла',
48
+ children: 'Дочерние элементы',
49
+ disabled: 'Отключено',
50
+ required: 'Обязательно',
51
+ property: 'Свойство',
52
+ description: 'Описание',
53
+ type: 'Тип',
54
+ defaultValue: 'Значение по умолчанию',
55
+ overview: 'Обзор'
57
56
  }
58
57
  };
59
58
  const isToolEntries = (obj)=>!!obj.documentation || !!obj["react-docgen-typescript"];
@@ -62,7 +61,7 @@ const docgen = async ({ entries, languages, apiParseTool, appDir, parseToolOptio
62
61
  const genApiDoc = async (entry, tool)=>{
63
62
  if (0 === Object.keys(entry).length) return;
64
63
  await Promise.all(Object.entries(entry).map(async ([key, value])=>{
65
- const moduleSourceFilePath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].resolve(appDir, value);
64
+ const moduleSourceFilePath = node_path.resolve(appDir, value);
66
65
  watchFileMap[moduleSourceFilePath] = {
67
66
  apiParseTool,
68
67
  moduleName: key
@@ -91,22 +90,21 @@ const docgen = async ({ entries, languages, apiParseTool, appDir, parseToolOptio
91
90
  },
92
91
  ...restOptions
93
92
  };
94
- let fileParser = (0, __WEBPACK_EXTERNAL_MODULE_react_docgen_typescript_e816f54f__.withDefaultConfig)(parserOpts);
95
- if (tsconfigPath?.[key]) fileParser = (0, __WEBPACK_EXTERNAL_MODULE_react_docgen_typescript_e816f54f__.withCustomConfig)(tsconfigPath[key], parserOpts);
96
- else if (compilerOptions?.[key]) fileParser = (0, __WEBPACK_EXTERNAL_MODULE_react_docgen_typescript_e816f54f__.withCompilerOptions)(compilerOptions[key], parserOpts);
93
+ let fileParser = withDefaultConfig(parserOpts);
94
+ if (tsconfigPath?.[key]) fileParser = withCustomConfig(tsconfigPath[key], parserOpts);
95
+ else if (compilerOptions?.[key]) fileParser = withCompilerOptions(compilerOptions[key], parserOpts);
97
96
  const componentDoc = fileParser.parse(moduleSourceFilePath);
98
- if (0 === componentDoc.length) __WEBPACK_EXTERNAL_MODULE__rspress_shared_logger_4374e44a__.logger.warn('[module-doc-plugin]', `Unable to parse API document in ${moduleSourceFilePath}`);
99
- if (languages.length > 0) languages.forEach((language)=>{
97
+ if (0 === componentDoc.length) logger.warn('[module-doc-plugin]', `Unable to parse API document in ${moduleSourceFilePath}`);
98
+ languages.forEach((language)=>{
100
99
  apiDocMap[`${key}-${language}`] = generateTable(componentDoc, language);
101
100
  });
102
- else apiDocMap[key] = generateTable(componentDoc, 'en');
103
101
  }
104
102
  } catch (e) {
105
- if (e instanceof Error) __WEBPACK_EXTERNAL_MODULE__rspress_shared_logger_4374e44a__.logger.error('[module-doc-plugin]', 'Generate API table error:\n', e);
103
+ if (e instanceof Error) logger.error('[module-doc-plugin]', 'Generate API table error:\n', e);
106
104
  }
107
105
  }));
108
106
  };
109
- __WEBPACK_EXTERNAL_MODULE__rspress_shared_logger_4374e44a__.logger.info('[module-doc-plugin]', 'Start to generate API table...');
107
+ logger.info('[module-doc-plugin]', 'Start to generate API table...');
110
108
  if (isToolEntries(entries)) {
111
109
  const reactEntries = entries["react-docgen-typescript"];
112
110
  const documentationEntries = entries.documentation;
@@ -116,7 +114,7 @@ const docgen = async ({ entries, languages, apiParseTool, appDir, parseToolOptio
116
114
  ]);
117
115
  } else await genApiDoc(entries, apiParseTool);
118
116
  if (!isProd) {
119
- const watcher = __WEBPACK_EXTERNAL_MODULE_chokidar__["default"].watch(Object.keys(watchFileMap), {
117
+ const watcher = chokidar.watch(Object.keys(watchFileMap), {
120
118
  ignoreInitial: true,
121
119
  ignorePermissionErrors: true,
122
120
  ignored: [
@@ -127,12 +125,12 @@ const docgen = async ({ entries, languages, apiParseTool, appDir, parseToolOptio
127
125
  watcher.on('change', (changed)=>{
128
126
  if (isUpdate) return;
129
127
  isUpdate = true;
130
- __WEBPACK_EXTERNAL_MODULE__rspress_shared_logger_4374e44a__.logger.info('[module-doc-plugin]', 'updating API');
128
+ logger.info('[module-doc-plugin]', 'updating API');
131
129
  const watchFileInfo = watchFileMap[changed];
132
130
  if (watchFileInfo) {
133
131
  const { apiParseTool, moduleName } = watchFileInfo;
134
132
  const updateSiteData = ()=>{
135
- const siteDataPath = __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(process.cwd(), 'node_modules', __WEBPACK_EXTERNAL_MODULE__rspress_shared_baa012d0__.RSPRESS_TEMP_DIR, 'runtime', 'virtual-site-data.mjs');
133
+ const siteDataPath = node_path.join(process.cwd(), 'node_modules', RSPRESS_TEMP_DIR, 'runtime', 'virtual-site-data.mjs');
136
134
  import(siteDataPath).then((siteData)=>{
137
135
  const data = {
138
136
  ...siteData.default
@@ -140,7 +138,7 @@ const docgen = async ({ entries, languages, apiParseTool, appDir, parseToolOptio
140
138
  data.pages.forEach((page)=>{
141
139
  page.apiDocMap = apiDocMap;
142
140
  });
143
- __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].writeFileSync(siteDataPath, `export default ${JSON.stringify(data)}`);
141
+ node_fs.writeFileSync(siteDataPath, `export default ${JSON.stringify(data)}`);
144
142
  isUpdate = false;
145
143
  });
146
144
  };
@@ -150,12 +148,12 @@ const docgen = async ({ entries, languages, apiParseTool, appDir, parseToolOptio
150
148
  }
151
149
  });
152
150
  }
153
- __WEBPACK_EXTERNAL_MODULE__rspress_shared_logger_4374e44a__.logger.success('[module-doc-plugin]', 'Generate API table successfully!');
151
+ logger.success('[module-doc-plugin]', 'Generate API table successfully!');
154
152
  };
155
153
  function generateTable(componentDoc, language) {
156
154
  return componentDoc.map((param)=>{
157
155
  const { props } = param;
158
- const t = locales[language];
156
+ const t = locales[language] ?? locales.en;
159
157
  const PROP_TABLE_HEADER = `|${t.property}|${t.description}|${t.type}|${t.defaultValue}|\n|:---:|:---:|:---:|:---:|`;
160
158
  const tableContent = Object.keys(props).filter((propName)=>{
161
159
  const { name, description } = props[propName];
@@ -208,11 +206,15 @@ function pluginApiDocgen(options) {
208
206
  return config;
209
207
  },
210
208
  async beforeBuild (config, isProd) {
211
- const languages = (config.themeConfig?.locales?.map((locale)=>locale.lang) || config.locales?.map((locale)=>locale.lang) || []).filter((lang)=>[
209
+ let languages = (config.themeConfig?.locales?.map((locale)=>locale.lang) || config.locales?.map((locale)=>locale.lang) || []).filter((lang)=>[
212
210
  'zh',
213
211
  'en',
214
212
  'ru'
215
213
  ].includes(lang));
214
+ const defaultLang = config.lang || 'en';
215
+ if (0 === languages.length) languages = [
216
+ defaultLang
217
+ ];
216
218
  await docgen({
217
219
  entries,
218
220
  apiParseTool,
@@ -221,33 +223,34 @@ function pluginApiDocgen(options) {
221
223
  parseToolOptions,
222
224
  isProd
223
225
  });
226
+ config.builderConfig = config.builderConfig || {};
227
+ config.builderConfig.source = config.builderConfig.source || {};
228
+ config.builderConfig.source.define = {
229
+ ...config.builderConfig.source.define,
230
+ RSPRESS_PLUGIN_API_DOCGEN_MAP: JSON.stringify(apiDocMap)
231
+ };
224
232
  },
225
233
  async modifySearchIndexData (pages) {
226
234
  const apiCompRegExp = /(<API\s+moduleName=['"](\S+)['"]\s*(.*)?\/>)|(<API\s+moduleName=['"](\S+)['"]\s*(.*)?>(.*)?<\/API>)/;
227
235
  await Promise.all(pages.map(async (page)=>{
228
236
  const { _filepath, lang } = page;
229
- let content = await __WEBPACK_EXTERNAL_MODULE_node_fs_5ea92f0c__["default"].promises.readFile(_filepath, 'utf-8');
237
+ let content = await node_fs.promises.readFile(_filepath, 'utf-8');
230
238
  let matchResult = apiCompRegExp.exec(content);
231
239
  if (!matchResult) return;
232
240
  while(null !== matchResult){
233
241
  const matchContent = matchResult[0];
234
242
  const moduleName = matchResult[2] ?? matchResult[5] ?? '';
235
- const apiDoc = apiDocMap[moduleName] ?? apiDocMap[`${moduleName}-${lang ? lang : 'en'}`] ?? '';
236
- if (matchContent && !apiDoc) __WEBPACK_EXTERNAL_MODULE__rspress_shared_logger_4374e44a__.logger.warn(`No api doc found for module: ${moduleName} in lang: ${lang ?? 'en'}`);
243
+ const apiDoc = apiDocMap[`${moduleName}-${lang ? lang : 'en'}`] ?? '';
244
+ if (matchContent && !apiDoc) logger.warn(`No api doc found for module: ${moduleName} in lang: ${lang ?? 'en'}`);
237
245
  content = content.replace(matchContent, apiDoc);
238
246
  matchResult = apiCompRegExp.exec(content);
239
247
  }
240
248
  page.content = content;
241
249
  }));
242
250
  },
243
- extendPageData (pageData) {
244
- pageData.apiDocMap = {
245
- ...apiDocMap
246
- };
247
- },
248
251
  markdown: {
249
252
  globalComponents: [
250
- __WEBPACK_EXTERNAL_MODULE_node_path_c5b9b54f__["default"].join(__dirname, '..', 'static', 'global-components', 'API.tsx')
253
+ node_path.join(__dirname, '..', 'static', 'global-components', 'API.tsx')
251
254
  ]
252
255
  }
253
256
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rspress/plugin-api-docgen",
3
- "version": "2.0.0-beta.9",
3
+ "version": "2.0.0-rc.1",
4
4
  "description": "A plugin for rspress to generate api doc.",
5
5
  "bugs": "https://github.com/web-infra-dev/rspress/issues",
6
6
  "repository": {
@@ -12,43 +12,41 @@
12
12
  "type": "module",
13
13
  "exports": {
14
14
  ".": {
15
- "types": "./index.d.ts",
15
+ "types": "./dist/index.d.ts",
16
16
  "default": "./dist/index.js"
17
17
  }
18
18
  },
19
- "types": "./index.d.ts",
19
+ "types": "./dist/index.d.ts",
20
20
  "files": [
21
21
  "dist",
22
- "static",
23
- "index.d.ts"
22
+ "static"
24
23
  ],
25
24
  "dependencies": {
26
25
  "chokidar": "^3.6.0",
27
26
  "documentation": "14.0.3",
28
27
  "github-slugger": "^2.0.0",
29
- "react-docgen-typescript": "2.2.2",
28
+ "react-docgen-typescript": "2.4.0",
30
29
  "react-markdown": "^10.1.0",
31
30
  "remark-gfm": "^4.0.1",
32
31
  "unified": "^11.0.5",
33
- "unist-util-visit": "^5.0.0",
34
- "@rspress/shared": "2.0.0-beta.9"
32
+ "unist-util-visit": "^5.0.0"
35
33
  },
36
34
  "devDependencies": {
37
- "@microsoft/api-extractor": "^7.52.8",
38
- "@rslib/core": "0.8.0",
35
+ "@microsoft/api-extractor": "^7.55.0",
36
+ "@rslib/core": "0.17.2",
39
37
  "@types/hast": "^3.0.4",
40
38
  "@types/mdast": "^4.0.4",
41
39
  "@types/node": "^22.8.1",
42
- "@types/react": "^18.3.22",
43
- "@types/react-dom": "^18.3.7",
44
- "react": "^19.1.0",
45
- "react-dom": "^19.1.0",
46
- "react-router-dom": "^6.29.0",
47
- "rsbuild-plugin-publint": "^0.3.2",
40
+ "@types/react": "^19.2.5",
41
+ "@types/react-dom": "^19.2.3",
42
+ "react": "^19.2.0",
43
+ "react-dom": "^19.2.0",
44
+ "react-router-dom": "^6.30.2",
45
+ "rsbuild-plugin-publint": "^0.3.3",
48
46
  "typescript": "^5.8.2"
49
47
  },
50
48
  "peerDependencies": {
51
- "@rspress/core": "^2.0.0-beta.9",
49
+ "@rspress/core": "^2.0.0-rc.1",
52
50
  "typescript": "^5.8.2"
53
51
  },
54
52
  "peerDependenciesMeta": {
@@ -61,7 +59,6 @@
61
59
  },
62
60
  "publishConfig": {
63
61
  "access": "public",
64
- "provenance": true,
65
62
  "registry": "https://registry.npmjs.org/"
66
63
  },
67
64
  "scripts": {
@@ -1,17 +1,20 @@
1
- /// <reference path="../../index.d.ts" />
2
-
3
- import { useLang, usePageData } from '@rspress/core/runtime';
4
- import { getCustomMDXComponent } from '@rspress/core/theme';
1
+ import { useLang } from '@rspress/core/runtime';
2
+ // @ts-expect-error @theme is overridden by alias in @rspress/core
3
+ import { getCustomMDXComponent } from '@theme';
4
+ import GithubSlugger from 'github-slugger';
5
+ import type { Content, Element, Root } from 'hast';
5
6
  import ReactMarkdown from 'react-markdown';
6
7
  import remarkGfm from 'remark-gfm';
7
8
  import './API.css';
8
- import GithubSlugger from 'github-slugger';
9
- import type { Content, Element, Root } from 'hast';
10
9
  // biome-ignore lint/style/useImportType: <exact>
11
10
  import React from 'react';
12
11
  import type { Plugin } from 'unified';
13
12
  import { visit } from 'unist-util-visit';
14
13
 
14
+ declare global {
15
+ var RSPRESS_PLUGIN_API_DOCGEN_MAP: Record<string, string>;
16
+ }
17
+
15
18
  function headingRank(node: Root | Content): number | null {
16
19
  const name =
17
20
  (node && node.type === 'element' && node.tagName.toLowerCase()) || '';
@@ -36,7 +39,7 @@ const rehypeHeaderAnchor: Plugin<[], Root> = () => {
36
39
  if (!node.properties?.id) {
37
40
  const text = collectHeaderText(node);
38
41
  node.properties ??= {};
39
- node.properties.id = slugger.slug(text);
42
+ node.properties.id = slugger.slug(text.trim());
40
43
  }
41
44
  // apply to headings
42
45
  node.children.unshift(create(node));
@@ -57,7 +60,7 @@ function create(node: Element): Element {
57
60
  type: 'element',
58
61
  tagName: 'a',
59
62
  properties: {
60
- class: 'header-anchor',
63
+ class: 'rp-header-anchor',
61
64
  ariaHidden: 'true',
62
65
  href: `#${node.properties!.id}`,
63
66
  },
@@ -97,15 +100,13 @@ const collectHeaderText = (node: Element): string => {
97
100
  return text;
98
101
  };
99
102
 
100
- export default (props: { moduleName: string }) => {
103
+ const API = (props: { moduleName: string }) => {
101
104
  const lang = useLang();
102
- const { page } = usePageData();
103
105
  const { moduleName } = props;
104
106
  // some api doc have two languages.
105
- const apiDocMap = page.apiDocMap;
107
+ const apiDocMap = RSPRESS_PLUGIN_API_DOCGEN_MAP;
106
108
  // avoid error when no page data
107
- const apiDoc =
108
- apiDocMap?.[moduleName] || apiDocMap?.[`${moduleName}-${lang}`] || '';
109
+ const apiDoc = apiDocMap?.[`${moduleName}-${lang}`] || '';
109
110
  return (
110
111
  <div className="rspress-plugin-api-docgen">
111
112
  <ReactMarkdown
@@ -121,3 +122,5 @@ export default (props: { moduleName: string }) => {
121
122
  </div>
122
123
  );
123
124
  };
125
+
126
+ export default API;
package/index.d.ts DELETED
@@ -1,7 +0,0 @@
1
- declare module '@rspress/shared' {
2
- interface PageIndexInfo {
3
- apiDocMap?: Record<string, string>;
4
- }
5
- }
6
-
7
- export * from './dist'