@rspress/plugin-llms 2.0.0-beta.24 → 2.0.0-beta.26

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,17 +1,17 @@
1
1
  import type { PageIndexInfo } from '@rspress/core';
2
2
  import type { RspressPlugin } from '@rspress/core';
3
3
 
4
+ /**
5
+ * @default { name: 'llms-full.txt' }
6
+ */
4
7
  declare interface LlmsFullTxt {
5
- /**
6
- * @default "llms-full.txt"
7
- */
8
8
  name: string;
9
9
  }
10
10
 
11
+ /**
12
+ * @default { name: "llms.txt" }
13
+ */
11
14
  export declare interface LlmsTxt {
12
- /**
13
- * @default "llms.txt"
14
- */
15
15
  name: string;
16
16
  onTitleGenerate?: (context: {
17
17
  title: string | undefined;
@@ -23,7 +23,7 @@ export declare interface LlmsTxt {
23
23
 
24
24
  declare interface MdFiles {
25
25
  /**
26
- * @default true
26
+ * @default false
27
27
  */
28
28
  mdxToMd: boolean;
29
29
  }
package/dist/index.js CHANGED
@@ -165,12 +165,10 @@ const rsbuildPluginLlms = ({ disableSSGRef, baseRef, pageDataList, routes, title
165
165
  try {
166
166
  mdContent = (await normalizeMdFile(content, filepath, routeServiceRef.current, baseRef.current, 'boolean' != typeof mdFiles ? mdFiles?.mdxToMd : false, isMD)).toString();
167
167
  } catch (e) {
168
- logger.debug(e);
168
+ logger.debug('normalizeMdFile failed', pageData.routePath, e);
169
169
  mdContent = content;
170
- return;
171
170
  }
172
- pageData.mdContent = mdContent;
173
- const outFilePath = `${pageData.routePath.endsWith('/') ? `${pageData.routePath}index` : pageData.routePath}.md`;
171
+ const outFilePath = routePathToMdPath(pageData.routePath, '');
174
172
  mdContents[outFilePath] = mdContent.toString();
175
173
  }) ?? []);
176
174
  if (mdFiles) api.processAssets({
@@ -250,7 +248,34 @@ function organizeBySidebar(sidebar, pages) {
250
248
  return aIndex - bIndex;
251
249
  });
252
250
  }
253
- function pluginLlms(options = {}) {
251
+ function getDefaultOptions(lang, langs) {
252
+ if (!lang || 0 === langs.length) return {};
253
+ return langs.map((l)=>{
254
+ if (l === lang) return {
255
+ llmsTxt: {
256
+ name: 'llms.txt'
257
+ },
258
+ llmsFullTxt: {
259
+ name: 'llms-full.txt'
260
+ },
261
+ include ({ page }) {
262
+ return page.lang === l;
263
+ }
264
+ };
265
+ return {
266
+ llmsTxt: {
267
+ name: `${l}/llms.txt`
268
+ },
269
+ llmsFullTxt: {
270
+ name: `${l}/llms-full.txt`
271
+ },
272
+ include ({ page }) {
273
+ return page.lang === l;
274
+ }
275
+ };
276
+ });
277
+ }
278
+ function pluginLlms(options) {
254
279
  const baseRef = {
255
280
  current: ''
256
281
  };
@@ -287,6 +312,44 @@ function pluginLlms(options = {}) {
287
312
  routeGenerated (_routes, isProd) {
288
313
  if (isProd) routes.push(..._routes);
289
314
  },
315
+ config (config) {
316
+ config.themeConfig = config.themeConfig || {};
317
+ config.themeConfig.locales = config.themeConfig.locales || config.locales || [];
318
+ const langs = config.themeConfig.locales.map((locale)=>locale.lang);
319
+ let mergedOptions;
320
+ mergedOptions = void 0 === options ? getDefaultOptions(config.lang, langs) : options;
321
+ if (!config.builderConfig) config.builderConfig = {};
322
+ if (!config.builderConfig.plugins) config.builderConfig.plugins = [];
323
+ config.builderConfig.plugins.push(...Array.isArray(mergedOptions) ? mergedOptions.map((item, index)=>rsbuildPluginLlms({
324
+ pageDataList,
325
+ routes,
326
+ titleRef,
327
+ descriptionRef,
328
+ langRef,
329
+ sidebar,
330
+ routeServiceRef,
331
+ nav,
332
+ baseRef,
333
+ disableSSGRef,
334
+ rspressPluginOptions: item,
335
+ index
336
+ })) : [
337
+ rsbuildPluginLlms({
338
+ pageDataList,
339
+ routes,
340
+ titleRef,
341
+ descriptionRef,
342
+ langRef,
343
+ sidebar,
344
+ routeServiceRef,
345
+ nav,
346
+ baseRef,
347
+ disableSSGRef,
348
+ rspressPluginOptions: mergedOptions
349
+ })
350
+ ]);
351
+ return config;
352
+ },
290
353
  beforeBuild (config) {
291
354
  disableSSGRef.current = false === config.ssg;
292
355
  const locales = config.themeConfig?.locales;
@@ -314,36 +377,6 @@ function pluginLlms(options = {}) {
314
377
  langRef.current = config.lang ?? '';
315
378
  baseRef.current = config.base ?? '/';
316
379
  docDirectoryRef.current = config.root ?? 'docs';
317
- },
318
- builderConfig: {
319
- plugins: [
320
- Array.isArray(options) ? options.map((item, index)=>rsbuildPluginLlms({
321
- pageDataList,
322
- routes,
323
- titleRef,
324
- descriptionRef,
325
- langRef,
326
- sidebar,
327
- routeServiceRef,
328
- nav,
329
- baseRef,
330
- disableSSGRef,
331
- rspressPluginOptions: item,
332
- index
333
- })) : rsbuildPluginLlms({
334
- pageDataList,
335
- routes,
336
- titleRef,
337
- descriptionRef,
338
- langRef,
339
- sidebar,
340
- routeServiceRef,
341
- nav,
342
- baseRef,
343
- disableSSGRef,
344
- rspressPluginOptions: options
345
- })
346
- ]
347
380
  }
348
381
  };
349
382
  }
@@ -6,14 +6,14 @@
6
6
  }
7
7
 
8
8
  .llmsCopyButtonContainer-osHvFn {
9
- color: #000000e6;
10
- background: #fff;
11
- border: 1px solid #e5e6eb;
9
+ border: 1px solid var(--rp-c-divider-light);
10
+ background: var(--rp-c-bg);
11
+ height: 40px;
12
+ color: var(--rp-c-text-1);
12
13
  border-radius: 8px;
13
14
  justify-content: center;
14
15
  align-items: center;
15
16
  gap: 8px;
16
- height: 40px;
17
17
  padding: 8px 12px;
18
18
  font-size: 14px;
19
19
  font-style: normal;
@@ -23,14 +23,12 @@
23
23
  }
24
24
 
25
25
  .llmsCopyButtonContainer-osHvFn:hover {
26
- background: #f5f5f5;
27
- border: 1px solid #e5e6eb;
26
+ background: var(--rp-c-bg-mute);
28
27
  }
29
28
 
30
29
  .llmsCopyButtonContainer-osHvFn.loading-p5nEhg {
30
+ background: var(--rp-c-bg-mute);
31
31
  opacity: .5;
32
- background: #f5f5f5;
33
- border: 1px solid #e5e6eb;
34
32
  }
35
33
 
36
34
  .llmsCopyButtonContainer-osHvFn.success-F4Qj8u .iconCopy-g1n4MZ {
@@ -71,14 +69,14 @@
71
69
  }
72
70
 
73
71
  .llmsViewOptionsContainer-EuqmUT {
74
- color: #000000e6;
75
- background: #fff;
76
- border: 1px solid #e5e6eb;
72
+ border: 1px solid var(--rp-c-divider-light);
73
+ background: var(--rp-c-bg);
74
+ height: 40px;
75
+ color: var(--rp-c-text-1);
77
76
  border-radius: 8px;
78
77
  justify-content: center;
79
78
  align-items: center;
80
79
  gap: 8px;
81
- height: 40px;
82
80
  padding: 8px 12px;
83
81
  font-size: 14px;
84
82
  font-style: normal;
@@ -89,7 +87,7 @@
89
87
  }
90
88
 
91
89
  .llmsViewOptionsContainer-EuqmUT:hover, .llmsViewOptionsContainer-EuqmUT.active-SacMuO {
92
- background: #f5f5f5;
90
+ background: var(--rp-c-bg-mute);
93
91
  }
94
92
 
95
93
  .dropdownButton-Mj4g7p {
@@ -107,12 +105,13 @@
107
105
 
108
106
  .dropdownMenu-_ggfjT {
109
107
  z-index: 2;
110
- background: #fff;
111
- border: 1px solid #e5e6eb;
108
+ border: 1px solid var(--rp-c-divider-light);
109
+ background: var(--rp-c-bg);
110
+ width: 250px;
111
+ color: var(--rp-c-text-1);
112
112
  border-radius: 8px;
113
113
  flex-direction: column;
114
114
  align-items: flex-start;
115
- width: 250px;
116
115
  margin-top: 4px;
117
116
  padding: 8px;
118
117
  display: inline-flex;
@@ -137,10 +136,10 @@
137
136
  }
138
137
 
139
138
  .dropdownItem-taWikf:hover {
140
- background: #f5f5f5;
139
+ background: var(--rp-c-bg-mute);
141
140
  }
142
141
 
143
- .githubIcon-lJkbbr {
142
+ .leftIcon-JI6iFK {
144
143
  justify-content: center;
145
144
  align-items: center;
146
145
  width: 16px;
@@ -31,15 +31,11 @@ export declare const LlmsViewOptions: ({ options, text, textByLang, }: LlmsViewO
31
31
  export declare interface LlmsViewOptionsProps extends React_2.ButtonHTMLAttributes<HTMLButtonElement> {
32
32
  /**
33
33
  * Default options for the dropdown.
34
- * @default ['chatgpt', 'claude']
34
+ * @default ['markdownLink', 'chatgpt', 'claude']
35
35
  * - 'chatgpt': Open in ChatGPT
36
36
  * - 'claude': Open in Claude
37
37
  */
38
- options?: Array<{
39
- title: string;
40
- href: string;
41
- icon: React_2.ReactNode;
42
- } | 'claude' | 'chatgpt'>;
38
+ options?: Option_2[];
43
39
  /**
44
40
  * Button text by language, used with `useLang`.
45
41
  * @default en: 'Open', zh: '打开'
@@ -53,6 +49,16 @@ export declare interface LlmsViewOptionsProps extends React_2.ButtonHTMLAttribut
53
49
  text?: string;
54
50
  }
55
51
 
52
+ declare type Option_2 = {
53
+ title: string;
54
+ icon?: React_2.ReactNode;
55
+ onClick?: () => void;
56
+ } | {
57
+ title: string;
58
+ href: string;
59
+ icon?: React_2.ReactNode;
60
+ } | 'markdownLink' | 'chatgpt' | 'claude';
61
+
56
62
  export declare function useMdUrl(): {
57
63
  pathname: string;
58
64
  };
@@ -10,6 +10,31 @@ function LlmsContainer(props) {
10
10
  className: _1
11
11
  });
12
12
  }
13
+ function IconCopy({ className }) {
14
+ return /*#__PURE__*/ jsxs("svg", {
15
+ xmlns: "http://www.w3.org/2000/svg",
16
+ width: "16",
17
+ height: "16",
18
+ viewBox: "0 0 16 16",
19
+ className: className,
20
+ fill: "none",
21
+ children: [
22
+ /*#__PURE__*/ jsx("path", {
23
+ d: "M4.33301 4.14386V2.60416C4.33301 2.08639 4.75274 1.66666 5.27051 1.66666H13.3955C13.9133 1.66666 14.333 2.08639 14.333 2.60416V10.7292C14.333 11.2469 13.9133 11.6667 13.3955 11.6667H11.8384",
24
+ stroke: "#808080",
25
+ strokeWidth: "1.33333",
26
+ strokeLinecap: "round",
27
+ strokeLinejoin: "round"
28
+ }),
29
+ /*#__PURE__*/ jsx("path", {
30
+ d: "M10.7295 4.33334H2.60449C2.08673 4.33334 1.66699 4.75308 1.66699 5.27084V13.3958C1.66699 13.9136 2.08673 14.3333 2.60449 14.3333H10.7295C11.2473 14.3333 11.667 13.9136 11.667 13.3958V5.27084C11.667 4.75308 11.2473 4.33334 10.7295 4.33334Z",
31
+ stroke: "#808080",
32
+ strokeWidth: "1.33333",
33
+ strokeLinejoin: "round"
34
+ })
35
+ ]
36
+ });
37
+ }
13
38
  var LlmsCopyButton_module_1 = "iconContainer-G_2NC6";
14
39
  var _2 = "iconCopy-g1n4MZ";
15
40
  var _3 = "iconSuccess-PId4Mj";
@@ -38,37 +63,12 @@ function useMdUrl() {
38
63
  * Inspired from fumadocs docsite
39
64
  * @from https://github.com/fuma-nama/fumadocs/blob/5723bbe58ef805a5421a780abf235a10b251be2f/apps/docs/app/docs/%5B...slug%5D/page.client.tsx#L11
40
65
  * @license MIT
41
- */ function IconCopy() {
42
- return /*#__PURE__*/ jsxs("svg", {
43
- xmlns: "http://www.w3.org/2000/svg",
44
- width: "16",
45
- height: "16",
46
- viewBox: "0 0 16 16",
47
- className: _2,
48
- fill: "none",
49
- children: [
50
- /*#__PURE__*/ jsx("path", {
51
- d: "M4.33301 4.14386V2.60416C4.33301 2.08639 4.75274 1.66666 5.27051 1.66666H13.3955C13.9133 1.66666 14.333 2.08639 14.333 2.60416V10.7292C14.333 11.2469 13.9133 11.6667 13.3955 11.6667H11.8384",
52
- stroke: "#808080",
53
- strokeWidth: "1.33333",
54
- strokeLinecap: "round",
55
- strokeLinejoin: "round"
56
- }),
57
- /*#__PURE__*/ jsx("path", {
58
- d: "M10.7295 4.33334H2.60449C2.08673 4.33334 1.66699 4.75308 1.66699 5.27084V13.3958C1.66699 13.9136 2.08673 14.3333 2.60449 14.3333H10.7295C11.2473 14.3333 11.667 13.9136 11.667 13.3958V5.27084C11.667 4.75308 11.2473 4.33334 10.7295 4.33334Z",
59
- stroke: "#808080",
60
- strokeWidth: "1.33333",
61
- strokeLinejoin: "round"
62
- })
63
- ]
64
- });
65
- }
66
- function IconSuccess() {
66
+ */ function IconSuccess({ className }) {
67
67
  return /*#__PURE__*/ jsx("svg", {
68
68
  width: "32",
69
69
  height: "32",
70
70
  viewBox: "0 0 30 30",
71
- className: _3,
71
+ className: className,
72
72
  children: /*#__PURE__*/ jsx("path", {
73
73
  fill: "#49cd37",
74
74
  d: "m13 24l-9-9l1.414-1.414L13 21.171L26.586 7.586L28 9L13 24z"
@@ -122,8 +122,12 @@ function LlmsCopyButton(props) {
122
122
  /*#__PURE__*/ jsxs("div", {
123
123
  className: LlmsCopyButton_module_1,
124
124
  children: [
125
- /*#__PURE__*/ jsx(IconSuccess, {}),
126
- /*#__PURE__*/ jsx(IconCopy, {})
125
+ /*#__PURE__*/ jsx(IconSuccess, {
126
+ className: _3
127
+ }),
128
+ /*#__PURE__*/ jsx(IconCopy, {
129
+ className: _2
130
+ })
127
131
  ]
128
132
  }),
129
133
  /*#__PURE__*/ jsx("span", {
@@ -138,7 +142,7 @@ var LlmsViewOptions_module_3 = "dropdownButton-Mj4g7p";
138
142
  var LlmsViewOptions_module_4 = "dropdownItem-taWikf";
139
143
  var LlmsViewOptions_module_5 = "dropdownMenu-_ggfjT";
140
144
  var LlmsViewOptions_module_6 = "externalIcon-r8tMpa";
141
- var _7 = "githubIcon-lJkbbr";
145
+ var _7 = "leftIcon-JI6iFK";
142
146
  var _8 = "llmsViewOptionsContainer-EuqmUT";
143
147
  var _9 = "rotated-YGs7Vp";
144
148
  /**
@@ -191,6 +195,7 @@ const IconExternalLink = ()=>/*#__PURE__*/ jsxs("svg", {
191
195
  ]
192
196
  });
193
197
  const LlmsViewOptions = ({ options = [
198
+ 'markdownLink',
194
199
  'chatgpt',
195
200
  'claude'
196
201
  ], text, textByLang = {
@@ -215,9 +220,36 @@ const LlmsViewOptions = ({ options = [
215
220
  const lang = useLang();
216
221
  const isEn = !lang || 'en' === lang;
217
222
  const items = useMemo(()=>{
218
- const fullMarkdownUrl = 'undefined' != typeof window ? new URL(pathname, window.location.origin) : 'loading';
223
+ const fullMarkdownUrl = 'undefined' != typeof window ? new URL(pathname, window.location.origin).toString() : 'loading';
219
224
  const q = `Read ${fullMarkdownUrl}, I want to ask questions about it.`;
220
225
  return {
226
+ markdownLink: {
227
+ title: isEn ? 'Copy Markdown link' : "\u590D\u5236 Markdown \u94FE\u63A5",
228
+ icon: /*#__PURE__*/ jsx("svg", {
229
+ xmlns: "http://www.w3.org/2000/svg",
230
+ viewBox: "0 0 24 24",
231
+ width: "24",
232
+ height: "24",
233
+ children: /*#__PURE__*/ jsxs("g", {
234
+ fill: "none",
235
+ stroke: "currentColor",
236
+ strokeLinecap: "round",
237
+ strokeLinejoin: "round",
238
+ strokeWidth: "2",
239
+ children: [
240
+ /*#__PURE__*/ jsx("path", {
241
+ d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
242
+ }),
243
+ /*#__PURE__*/ jsx("path", {
244
+ d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
245
+ })
246
+ ]
247
+ })
248
+ }),
249
+ onClick: ()=>{
250
+ navigator.clipboard.writeText(fullMarkdownUrl);
251
+ }
252
+ },
221
253
  chatgpt: {
222
254
  title: isEn ? 'Open in ChatGPT' : "\u5728 ChatGPT \u4E2D\u6253\u5F00",
223
255
  href: `https://chatgpt.com/?${new URLSearchParams({
@@ -283,9 +315,10 @@ const LlmsViewOptions = ({ options = [
283
315
  className: LlmsViewOptions_module_5,
284
316
  children: options.map((item)=>{
285
317
  let displayItem = item;
286
- if ('chatgpt' === item) displayItem = items.chatgpt;
318
+ if ('markdownLink' === item) displayItem = items.markdownLink;
319
+ else if ('chatgpt' === item) displayItem = items.chatgpt;
287
320
  else if ('claude' === item) displayItem = items.claude;
288
- return /*#__PURE__*/ jsxs("a", {
321
+ if (displayItem.href) return /*#__PURE__*/ jsxs("a", {
289
322
  className: LlmsViewOptions_module_4,
290
323
  href: displayItem.href,
291
324
  target: "_blank",
@@ -304,6 +337,19 @@ const LlmsViewOptions = ({ options = [
304
337
  })
305
338
  ]
306
339
  }, displayItem.title);
340
+ return /*#__PURE__*/ jsxs("div", {
341
+ className: LlmsViewOptions_module_4,
342
+ onClick: displayItem.onClick,
343
+ children: [
344
+ /*#__PURE__*/ jsx("span", {
345
+ className: _7,
346
+ children: displayItem.icon
347
+ }),
348
+ /*#__PURE__*/ jsx("span", {
349
+ children: displayItem.title
350
+ })
351
+ ]
352
+ }, displayItem.title);
307
353
  })
308
354
  })
309
355
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rspress/plugin-llms",
3
- "version": "2.0.0-beta.24",
3
+ "version": "2.0.0-beta.26",
4
4
  "description": "A plugin for rspress to generate llms.txt, llms-full.txt, md files to let llm understand your website.",
5
5
  "bugs": "https://github.com/web-infra-dev/rspress/issues",
6
6
  "repository": {
@@ -36,29 +36,28 @@
36
36
  "unist-util-visit-children": "^3.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@microsoft/api-extractor": "^7.52.9",
40
- "@rsbuild/core": "~1.4.12",
41
- "@rsbuild/plugin-react": "~1.3.4",
42
- "@rsbuild/plugin-sass": "~1.3.3",
43
- "@rslib/core": "0.11.0",
39
+ "@microsoft/api-extractor": "^7.52.10",
40
+ "@rsbuild/core": "~1.4.15",
41
+ "@rsbuild/plugin-react": "~1.3.5",
42
+ "@rsbuild/plugin-sass": "~1.3.5",
43
+ "@rslib/core": "0.11.2",
44
44
  "@types/hast": "^3.0.4",
45
45
  "@types/node": "^22.8.1",
46
- "@types/react": "^19.1.8",
47
- "react": "^19.1.0",
48
- "rsbuild-plugin-publint": "^0.3.2",
46
+ "@types/react": "^19.1.9",
47
+ "react": "^19.1.1",
48
+ "rsbuild-plugin-publint": "^0.3.3",
49
49
  "typescript": "^5.8.2",
50
50
  "vfile": "^6.0.3",
51
51
  "@rspress/config": "1.0.0"
52
52
  },
53
53
  "peerDependencies": {
54
- "@rspress/core": "^2.0.0-beta.24"
54
+ "@rspress/core": "^2.0.0-beta.26"
55
55
  },
56
56
  "engines": {
57
57
  "node": ">=18.0.0"
58
58
  },
59
59
  "publishConfig": {
60
60
  "access": "public",
61
- "provenance": true,
62
61
  "registry": "https://registry.npmjs.org/"
63
62
  },
64
63
  "scripts": {