@rspress/plugin-llms 2.0.0-beta.3 → 2.0.0-beta.30
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/README.md +1 -1
- package/dist/index.d.ts +34 -11
- package/dist/index.js +154 -186
- package/dist/runtime/index.css +168 -0
- package/dist/runtime/index.d.ts +66 -0
- package/dist/runtime/index.js +357 -0
- package/dist/runtime/index.js.LICENSE.txt +5 -0
- package/package.json +25 -14
- package/dist/index.js.LICENSE.txt +0 -10
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
import type { PageIndexInfo } from '@rspress/
|
|
2
|
-
import type {
|
|
1
|
+
import type { PageIndexInfo } from '@rspress/core';
|
|
2
|
+
import type { PluggableList } from 'unified';
|
|
3
|
+
import type { RspressPlugin } from '@rspress/core';
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @default { name: 'llms-full.txt' }
|
|
7
|
+
*/
|
|
8
|
+
declare interface LlmsFullTxt {
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @default { name: "llms.txt" }
|
|
14
|
+
*/
|
|
4
15
|
export declare interface LlmsTxt {
|
|
16
|
+
name: string;
|
|
5
17
|
onTitleGenerate?: (context: {
|
|
6
18
|
title: string | undefined;
|
|
7
19
|
description: string | undefined;
|
|
@@ -10,26 +22,35 @@ export declare interface LlmsTxt {
|
|
|
10
22
|
onAfterLlmsTxtGenerate?: (llmsTxtContent: string) => string;
|
|
11
23
|
}
|
|
12
24
|
|
|
25
|
+
declare interface MdFiles {
|
|
26
|
+
/**
|
|
27
|
+
* Whether to convert mdx to md.
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
mdxToMd?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Allow users to customize remarkPlugins and edit the content of generated md files.
|
|
33
|
+
* @default []
|
|
34
|
+
*/
|
|
35
|
+
remarkPlugins?: PluggableList;
|
|
36
|
+
}
|
|
37
|
+
|
|
13
38
|
export declare interface Options {
|
|
14
39
|
/**
|
|
15
40
|
* Whether to generate llms.txt.
|
|
16
|
-
* @default true
|
|
17
41
|
*/
|
|
18
|
-
llmsTxt?:
|
|
42
|
+
llmsTxt?: false | LlmsTxt;
|
|
19
43
|
/**
|
|
20
44
|
* Whether to generate llms.txt related md files for each route.
|
|
21
|
-
* @default true
|
|
22
45
|
*/
|
|
23
|
-
mdFiles?:
|
|
46
|
+
mdFiles?: false | MdFiles;
|
|
24
47
|
/**
|
|
25
48
|
* Whether to generate llms-full.txt.
|
|
26
|
-
* @default true
|
|
27
49
|
*/
|
|
28
|
-
llmsFullTxt?:
|
|
50
|
+
llmsFullTxt?: false | LlmsFullTxt;
|
|
29
51
|
/**
|
|
30
52
|
* Whether to include some routes from llms.txt.
|
|
31
|
-
* @
|
|
32
|
-
* @default (context) => context.page.lang === config.lang
|
|
53
|
+
* @default undefined
|
|
33
54
|
*/
|
|
34
55
|
include?: (context: {
|
|
35
56
|
page: PageIndexInfo;
|
|
@@ -47,6 +68,8 @@ export declare interface Options {
|
|
|
47
68
|
/**
|
|
48
69
|
* A plugin for rspress to generate llms.txt, llms-full.txt, md files to let llm understand your website.
|
|
49
70
|
*/
|
|
50
|
-
export declare function pluginLlms(options?:
|
|
71
|
+
export declare function pluginLlms(options?: RspressPluginLlmsOptions): RspressPlugin;
|
|
72
|
+
|
|
73
|
+
declare type RspressPluginLlmsOptions = Options | Options[];
|
|
51
74
|
|
|
52
75
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,130 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
import * as __WEBPACK_EXTERNAL_MODULE_unified__ from "unified";
|
|
10
|
-
import * as __WEBPACK_EXTERNAL_MODULE_unist_util_visit_555e002a__ from "unist-util-visit";
|
|
11
|
-
var router_Action;
|
|
12
|
-
(function(Action) {
|
|
13
|
-
Action["Pop"] = "POP";
|
|
14
|
-
Action["Push"] = "PUSH";
|
|
15
|
-
Action["Replace"] = "REPLACE";
|
|
16
|
-
})(router_Action || (router_Action = {}));
|
|
17
|
-
function warning(cond, message) {
|
|
18
|
-
if (!cond) {
|
|
19
|
-
if ("undefined" != typeof console) console.warn(message);
|
|
20
|
-
try {
|
|
21
|
-
throw new Error(message);
|
|
22
|
-
} catch (e) {}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
var router_ResultType;
|
|
26
|
-
(function(ResultType) {
|
|
27
|
-
ResultType["data"] = "data";
|
|
28
|
-
ResultType["deferred"] = "deferred";
|
|
29
|
-
ResultType["redirect"] = "redirect";
|
|
30
|
-
ResultType["error"] = "error";
|
|
31
|
-
})(router_ResultType || (router_ResultType = {}));
|
|
32
|
-
new Set([
|
|
33
|
-
"lazy",
|
|
34
|
-
"caseSensitive",
|
|
35
|
-
"path",
|
|
36
|
-
"id",
|
|
37
|
-
"index",
|
|
38
|
-
"children"
|
|
39
|
-
]);
|
|
40
|
-
function matchPath(pattern, pathname) {
|
|
41
|
-
if ("string" == typeof pattern) pattern = {
|
|
42
|
-
path: pattern,
|
|
43
|
-
caseSensitive: false,
|
|
44
|
-
end: true
|
|
45
|
-
};
|
|
46
|
-
let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
|
|
47
|
-
let match = pathname.match(matcher);
|
|
48
|
-
if (!match) return null;
|
|
49
|
-
let matchedPathname = match[0];
|
|
50
|
-
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
|
51
|
-
let captureGroups = match.slice(1);
|
|
52
|
-
let params = compiledParams.reduce((memo, _ref, index)=>{
|
|
53
|
-
let { paramName, isOptional } = _ref;
|
|
54
|
-
if ("*" === paramName) {
|
|
55
|
-
let splatValue = captureGroups[index] || "";
|
|
56
|
-
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
|
57
|
-
}
|
|
58
|
-
const value = captureGroups[index];
|
|
59
|
-
if (isOptional && !value) memo[paramName] = void 0;
|
|
60
|
-
else memo[paramName] = (value || "").replace(/%2F/g, "/");
|
|
61
|
-
return memo;
|
|
62
|
-
}, {});
|
|
63
|
-
return {
|
|
64
|
-
params,
|
|
65
|
-
pathname: matchedPathname,
|
|
66
|
-
pathnameBase,
|
|
67
|
-
pattern
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
function compilePath(path, caseSensitive, end) {
|
|
71
|
-
if (void 0 === caseSensitive) caseSensitive = false;
|
|
72
|
-
if (void 0 === end) end = true;
|
|
73
|
-
warning("*" === path || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + '" will be treated as if it were "' + path.replace(/\*$/, "/*") + '" because the `*` character must always follow a `/` in the pattern. To get rid of this warning, please change the route path to "' + path.replace(/\*$/, "/*") + "\".");
|
|
74
|
-
let params = [];
|
|
75
|
-
let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(/\/:([\w-]+)(\?)?/g, (_, paramName, isOptional)=>{
|
|
76
|
-
params.push({
|
|
77
|
-
paramName,
|
|
78
|
-
isOptional: null != isOptional
|
|
79
|
-
});
|
|
80
|
-
return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
|
|
81
|
-
});
|
|
82
|
-
if (path.endsWith("*")) {
|
|
83
|
-
params.push({
|
|
84
|
-
paramName: "*"
|
|
85
|
-
});
|
|
86
|
-
regexpSource += "*" === path || "/*" === path ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
|
|
87
|
-
} else if (end) regexpSource += "\\/*$";
|
|
88
|
-
else if ("" !== path && "/" !== path) regexpSource += "(?:(?=\\/|$))";
|
|
89
|
-
let matcher = new RegExp(regexpSource, caseSensitive ? void 0 : "i");
|
|
90
|
-
return [
|
|
91
|
-
matcher,
|
|
92
|
-
params
|
|
93
|
-
];
|
|
94
|
-
}
|
|
95
|
-
const validMutationMethodsArr = [
|
|
96
|
-
"post",
|
|
97
|
-
"put",
|
|
98
|
-
"patch",
|
|
99
|
-
"delete"
|
|
100
|
-
];
|
|
101
|
-
new Set(validMutationMethodsArr);
|
|
102
|
-
const validRequestMethodsArr = [
|
|
103
|
-
"get",
|
|
104
|
-
...validMutationMethodsArr
|
|
105
|
-
];
|
|
106
|
-
new Set(validRequestMethodsArr);
|
|
107
|
-
new Set([
|
|
108
|
-
301,
|
|
109
|
-
302,
|
|
110
|
-
303,
|
|
111
|
-
307,
|
|
112
|
-
308
|
|
113
|
-
]);
|
|
114
|
-
new Set([
|
|
115
|
-
307,
|
|
116
|
-
308
|
|
117
|
-
]);
|
|
118
|
-
Symbol("deferred");
|
|
119
|
-
function routePathToMdPath(routePath) {
|
|
1
|
+
import node_path from "node:path";
|
|
2
|
+
import { getSidebarDataGroup, logger, matchPath, normalizeHref, remarkFileCodeBlock, remarkLink, withBase } from "@rspress/core";
|
|
3
|
+
import remark_mdx from "remark-mdx";
|
|
4
|
+
import remark_parse from "remark-parse";
|
|
5
|
+
import remark_stringify from "remark-stringify";
|
|
6
|
+
import { unified } from "unified";
|
|
7
|
+
import { SKIP, visit } from "unist-util-visit";
|
|
8
|
+
function routePathToMdPath(routePath, base) {
|
|
120
9
|
let url = routePath;
|
|
121
|
-
url =
|
|
10
|
+
url = normalizeHref(url, false);
|
|
122
11
|
url = url.replace(/\.html$/, '.md');
|
|
123
|
-
return url;
|
|
12
|
+
return withBase(url, base);
|
|
124
13
|
}
|
|
125
|
-
function generateLlmsTxt(pageDataArray, navList, others, llmsTxtOptions, title, description) {
|
|
14
|
+
function generateLlmsTxt(pageDataArray, navList, others, llmsTxtOptions, title, description, base) {
|
|
126
15
|
const lines = [];
|
|
127
|
-
const { onAfterLlmsTxtGenerate, onLineGenerate, onTitleGenerate } =
|
|
16
|
+
const { onAfterLlmsTxtGenerate, onLineGenerate, onTitleGenerate } = llmsTxtOptions;
|
|
128
17
|
const summary = onTitleGenerate ? onTitleGenerate({
|
|
129
18
|
title,
|
|
130
19
|
description
|
|
@@ -139,7 +28,7 @@ function generateLlmsTxt(pageDataArray, navList, others, llmsTxtOptions, title,
|
|
|
139
28
|
for (const page of pages){
|
|
140
29
|
const { routePath, lang, title, frontmatter } = page;
|
|
141
30
|
if ('/' === routePath || routePath === `/${lang}/`) continue;
|
|
142
|
-
const line = onLineGenerate ? onLineGenerate(page) : `- [${title}](${routePathToMdPath(routePath)})${frontmatter.description ? `: ${frontmatter.description}` : ''}`;
|
|
31
|
+
const line = onLineGenerate ? onLineGenerate(page) : `- [${title}](${routePathToMdPath(routePath, base)})${frontmatter.description ? `: ${frontmatter.description}` : ''}`;
|
|
143
32
|
lines.push(line);
|
|
144
33
|
}
|
|
145
34
|
}
|
|
@@ -149,7 +38,7 @@ function generateLlmsTxt(pageDataArray, navList, others, llmsTxtOptions, title,
|
|
|
149
38
|
for (const page of others){
|
|
150
39
|
const { routePath, lang, title, frontmatter } = page;
|
|
151
40
|
if ('/' === routePath || routePath === `/${lang}/`) continue;
|
|
152
|
-
const line = onLineGenerate ? onLineGenerate(page) : `- [${title}](${routePathToMdPath(routePath)})${frontmatter.description ? `: ${frontmatter.description}` : ''}`;
|
|
41
|
+
const line = onLineGenerate ? onLineGenerate(page) : `- [${title}](${routePathToMdPath(routePath, base)})${frontmatter.description ? `: ${frontmatter.description}` : ''}`;
|
|
153
42
|
otherLines.push(line);
|
|
154
43
|
hasOthers = true;
|
|
155
44
|
}
|
|
@@ -157,13 +46,13 @@ function generateLlmsTxt(pageDataArray, navList, others, llmsTxtOptions, title,
|
|
|
157
46
|
const llmsTxt = `${summary}\n${lines.join('\n')}`;
|
|
158
47
|
return onAfterLlmsTxtGenerate ? onAfterLlmsTxtGenerate(llmsTxt) : llmsTxt;
|
|
159
48
|
}
|
|
160
|
-
function generateLlmsFullTxt(pageDataArray, navList, others) {
|
|
49
|
+
function generateLlmsFullTxt(pageDataArray, navList, others, base) {
|
|
161
50
|
const lines = [];
|
|
162
51
|
for(let i = 0; i < navList.length; i++){
|
|
163
52
|
const pages = pageDataArray[i];
|
|
164
53
|
if (0 !== pages.length) for (const page of pages){
|
|
165
54
|
lines.push(`---
|
|
166
|
-
url: ${routePathToMdPath(page.routePath)}
|
|
55
|
+
url: ${routePathToMdPath(page.routePath, base)}
|
|
167
56
|
---
|
|
168
57
|
`);
|
|
169
58
|
lines.push(page.mdContent ?? page._flattenContent ?? page.content);
|
|
@@ -172,7 +61,7 @@ url: ${routePathToMdPath(page.routePath)}
|
|
|
172
61
|
}
|
|
173
62
|
for (const page of others){
|
|
174
63
|
lines.push(`---
|
|
175
|
-
url: ${routePathToMdPath(page.routePath)}
|
|
64
|
+
url: ${routePathToMdPath(page.routePath, base)}
|
|
176
65
|
---
|
|
177
66
|
`);
|
|
178
67
|
lines.push(page.mdContent ?? page._flattenContent ?? page.content);
|
|
@@ -181,42 +70,56 @@ url: ${routePathToMdPath(page.routePath)}
|
|
|
181
70
|
return lines.join('\n');
|
|
182
71
|
}
|
|
183
72
|
const mdxToMdPlugin = ()=>(tree)=>{
|
|
184
|
-
|
|
73
|
+
visit(tree, 'mdxjsEsm', (node)=>{
|
|
185
74
|
if (node.data?.estree?.body[0].type === 'ImportDeclaration') {
|
|
186
75
|
node.value = '';
|
|
187
|
-
return
|
|
76
|
+
return SKIP;
|
|
188
77
|
}
|
|
189
78
|
});
|
|
190
|
-
|
|
79
|
+
visit(tree, 'mdxJsxFlowElement', (node, index, parent)=>{
|
|
191
80
|
if (parent && void 0 !== index && Array.isArray(parent.children)) {
|
|
192
81
|
parent.children.splice(index, 1, ...node.children);
|
|
193
82
|
return index - 1;
|
|
194
83
|
}
|
|
195
84
|
});
|
|
196
|
-
|
|
85
|
+
visit(tree, 'mdxJsxTextElement', (node, index, parent)=>{
|
|
197
86
|
if (parent && void 0 !== index && Array.isArray(parent.children)) {
|
|
198
87
|
parent.children.splice(index, 1, ...node.children);
|
|
199
88
|
return index - 1;
|
|
200
89
|
}
|
|
201
90
|
});
|
|
202
91
|
};
|
|
203
|
-
function
|
|
204
|
-
|
|
92
|
+
function noopPlugin() {}
|
|
93
|
+
function normalizeMdFile(content, filepath, routeService, base, mdxToMd, isMd, remarkPlugins) {
|
|
94
|
+
const compiler = unified().use(remark_parse).use(isMd ? noopPlugin : remark_mdx).use(remarkFileCodeBlock, {
|
|
95
|
+
filepath
|
|
96
|
+
}).use(!isMd && mdxToMd ? mdxToMdPlugin : noopPlugin).use(remarkLink, {
|
|
205
97
|
cleanUrls: '.md',
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
98
|
+
routeService,
|
|
99
|
+
remarkLinkOptions: {
|
|
100
|
+
checkDeadLinks: false,
|
|
101
|
+
autoPrefix: true
|
|
102
|
+
},
|
|
103
|
+
__base: base
|
|
104
|
+
}).use(remarkPlugins).use(remark_stringify);
|
|
105
|
+
return compiler.process({
|
|
209
106
|
value: content,
|
|
210
107
|
path: filepath
|
|
211
108
|
});
|
|
212
109
|
}
|
|
213
|
-
const rsbuildPluginLlms = ({ pageDataList, routes, titleRef, descriptionRef, langRef, sidebar,
|
|
214
|
-
name:
|
|
110
|
+
const rsbuildPluginLlms = ({ disableSSGRef, baseRef, pageDataList, routes, titleRef, descriptionRef, langRef, sidebar, routeServiceRef, nav, rspressPluginOptions, index = 0 })=>({
|
|
111
|
+
name: `rsbuild-plugin-llms-${index}`,
|
|
215
112
|
async setup (api) {
|
|
216
|
-
const { llmsTxt =
|
|
113
|
+
const { llmsTxt = {
|
|
114
|
+
name: 'llms.txt'
|
|
115
|
+
}, mdFiles = {
|
|
116
|
+
mdxToMd: false,
|
|
117
|
+
remarkPlugins: []
|
|
118
|
+
}, llmsFullTxt = {
|
|
119
|
+
name: 'llms-full.txt'
|
|
120
|
+
}, include, exclude } = rspressPluginOptions;
|
|
217
121
|
api.onBeforeBuild(async ()=>{
|
|
218
|
-
const
|
|
219
|
-
const docDirectory = docDirectoryRef.current;
|
|
122
|
+
const disableSSG = disableSSGRef.current;
|
|
220
123
|
const newPageDataList = mergeRouteMetaWithPageData(routes, pageDataList, langRef.current, include, exclude);
|
|
221
124
|
const navList = Array.isArray(nav) ? nav.map((i)=>{
|
|
222
125
|
const nav = i.nav.default;
|
|
@@ -233,21 +136,24 @@ const rsbuildPluginLlms = ({ pageDataList, routes, titleRef, descriptionRef, lan
|
|
|
233
136
|
for(let i = 0; i < pageArray.length; i++){
|
|
234
137
|
const pageArrayItem = pageArray[i];
|
|
235
138
|
const navItem = navList[i];
|
|
236
|
-
if (lang === navItem.lang && new RegExp(navItem.activeMatch ?? navItem.link).test(
|
|
139
|
+
if (lang === navItem.lang && new RegExp(navItem.activeMatch ?? navItem.link).test(routePath)) return void pageArrayItem.push(pageData);
|
|
237
140
|
}
|
|
238
141
|
others.push(pageData);
|
|
239
142
|
});
|
|
240
|
-
for (const array of pageArray)organizeBySidebar(sidebar, array
|
|
143
|
+
for (const array of pageArray)organizeBySidebar(sidebar, array);
|
|
241
144
|
if (llmsTxt) {
|
|
242
|
-
const
|
|
145
|
+
const { name } = llmsTxt;
|
|
146
|
+
const llmsTxtContent = generateLlmsTxt(pageArray, navList, others, llmsTxt, titleRef.current, descriptionRef.current, baseRef.current);
|
|
243
147
|
api.processAssets({
|
|
244
|
-
|
|
148
|
+
environments: disableSSG ? [
|
|
149
|
+
'web'
|
|
150
|
+
] : [
|
|
245
151
|
'node'
|
|
246
152
|
],
|
|
247
153
|
stage: 'additional'
|
|
248
154
|
}, async ({ compilation, sources })=>{
|
|
249
155
|
const source = new sources.RawSource(llmsTxtContent);
|
|
250
|
-
compilation.emitAsset(
|
|
156
|
+
compilation.emitAsset(name, source);
|
|
251
157
|
});
|
|
252
158
|
}
|
|
253
159
|
const mdContents = {};
|
|
@@ -256,22 +162,21 @@ const rsbuildPluginLlms = ({ pageDataList, routes, titleRef, descriptionRef, lan
|
|
|
256
162
|
].map(async (pageData)=>{
|
|
257
163
|
const content = pageData._flattenContent ?? pageData.content;
|
|
258
164
|
const filepath = pageData._filepath;
|
|
259
|
-
const isMD = 'mdx' !==
|
|
165
|
+
const isMD = 'mdx' !== node_path.extname(filepath).slice(1);
|
|
260
166
|
let mdContent;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
mdContent = (await mdxToMd(content, filepath, docDirectory, routeServiceRef.current)).toString();
|
|
167
|
+
try {
|
|
168
|
+
mdContent = (await normalizeMdFile(content, filepath, routeServiceRef.current, baseRef.current, 'boolean' != typeof mdFiles ? mdFiles?.mdxToMd ?? false : false, isMD, 'boolean' != typeof mdFiles ? mdFiles?.remarkPlugins ?? [] : [])).toString();
|
|
264
169
|
} catch (e) {
|
|
265
|
-
|
|
170
|
+
logger.debug('normalizeMdFile failed', pageData.routePath, e);
|
|
266
171
|
mdContent = content;
|
|
267
|
-
return;
|
|
268
172
|
}
|
|
269
|
-
pageData.
|
|
270
|
-
const outFilePath = `${pageData.routePath.endsWith('/') ? `${pageData.routePath}index` : pageData.routePath}.md`;
|
|
173
|
+
const outFilePath = routePathToMdPath(pageData.routePath, '');
|
|
271
174
|
mdContents[outFilePath] = mdContent.toString();
|
|
272
175
|
}) ?? []);
|
|
273
176
|
if (mdFiles) api.processAssets({
|
|
274
|
-
|
|
177
|
+
environments: disableSSG ? [
|
|
178
|
+
'web'
|
|
179
|
+
] : [
|
|
275
180
|
'node'
|
|
276
181
|
],
|
|
277
182
|
stage: 'additional'
|
|
@@ -282,15 +187,18 @@ const rsbuildPluginLlms = ({ pageDataList, routes, titleRef, descriptionRef, lan
|
|
|
282
187
|
});
|
|
283
188
|
});
|
|
284
189
|
if (llmsFullTxt) {
|
|
285
|
-
const
|
|
190
|
+
const { name } = llmsFullTxt;
|
|
191
|
+
const llmsFullTxtContent = generateLlmsFullTxt(pageArray, navList, others, baseRef.current);
|
|
286
192
|
api.processAssets({
|
|
287
|
-
targets: [
|
|
193
|
+
targets: disableSSG ? [
|
|
194
|
+
'web'
|
|
195
|
+
] : [
|
|
288
196
|
'node'
|
|
289
197
|
],
|
|
290
198
|
stage: 'additional'
|
|
291
199
|
}, async ({ compilation, sources })=>{
|
|
292
200
|
const source = new sources.RawSource(llmsFullTxtContent);
|
|
293
|
-
compilation.emitAsset(
|
|
201
|
+
compilation.emitAsset(name, source);
|
|
294
202
|
});
|
|
295
203
|
}
|
|
296
204
|
});
|
|
@@ -330,19 +238,45 @@ function flatSidebar(sidebar) {
|
|
|
330
238
|
if ('items' in i && Array.isArray(i.items)) return flatSidebar(i.items);
|
|
331
239
|
}).filter(Boolean);
|
|
332
240
|
}
|
|
333
|
-
function organizeBySidebar(sidebar, pages
|
|
241
|
+
function organizeBySidebar(sidebar, pages) {
|
|
334
242
|
if (0 === pages.length) return;
|
|
335
243
|
const pageItem = pages[0];
|
|
336
|
-
const currSidebar =
|
|
244
|
+
const currSidebar = getSidebarDataGroup(sidebar, pageItem.routePath);
|
|
337
245
|
if (0 === currSidebar.length) return;
|
|
338
246
|
const orderList = flatSidebar(currSidebar);
|
|
339
247
|
pages.sort((a, b)=>{
|
|
340
|
-
|
|
341
|
-
|
|
248
|
+
let aIndex = orderList.findIndex((order)=>matchPath(order, a.routePath));
|
|
249
|
+
if (-1 === aIndex) aIndex = Number.MAX_SAFE_INTEGER;
|
|
250
|
+
let bIndex = orderList.findIndex((order)=>matchPath(order, b.routePath));
|
|
251
|
+
if (-1 === bIndex) bIndex = Number.MAX_SAFE_INTEGER;
|
|
342
252
|
return aIndex - bIndex;
|
|
343
253
|
});
|
|
344
254
|
}
|
|
345
|
-
function
|
|
255
|
+
function getDefaultOptions(lang, langs) {
|
|
256
|
+
if (!lang || 0 === langs.length) return {};
|
|
257
|
+
return langs.map((l)=>{
|
|
258
|
+
if (l === lang) return {
|
|
259
|
+
llmsTxt: {
|
|
260
|
+
name: 'llms.txt'
|
|
261
|
+
},
|
|
262
|
+
llmsFullTxt: {
|
|
263
|
+
name: 'llms-full.txt'
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
return {
|
|
267
|
+
llmsTxt: {
|
|
268
|
+
name: `${l}/llms.txt`
|
|
269
|
+
},
|
|
270
|
+
llmsFullTxt: {
|
|
271
|
+
name: `${l}/llms-full.txt`
|
|
272
|
+
},
|
|
273
|
+
include ({ page }) {
|
|
274
|
+
return page.lang === l;
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
function pluginLlms(options) {
|
|
346
280
|
const baseRef = {
|
|
347
281
|
current: ''
|
|
348
282
|
};
|
|
@@ -361,6 +295,9 @@ function pluginLlms(options = {}) {
|
|
|
361
295
|
const pageDataList = [];
|
|
362
296
|
const routes = [];
|
|
363
297
|
const sidebar = {};
|
|
298
|
+
const disableSSGRef = {
|
|
299
|
+
current: false
|
|
300
|
+
};
|
|
364
301
|
const nav = [];
|
|
365
302
|
const routeServiceRef = {
|
|
366
303
|
current: void 0
|
|
@@ -376,40 +313,71 @@ function pluginLlms(options = {}) {
|
|
|
376
313
|
routeGenerated (_routes, isProd) {
|
|
377
314
|
if (isProd) routes.push(..._routes);
|
|
378
315
|
},
|
|
316
|
+
config (config) {
|
|
317
|
+
config.themeConfig = config.themeConfig || {};
|
|
318
|
+
config.themeConfig.locales = config.themeConfig.locales || config.locales || [];
|
|
319
|
+
const langs = config.themeConfig.locales.map((locale)=>locale.lang);
|
|
320
|
+
let mergedOptions;
|
|
321
|
+
mergedOptions = void 0 === options ? getDefaultOptions(config.lang, langs) : options;
|
|
322
|
+
if (!config.builderConfig) config.builderConfig = {};
|
|
323
|
+
if (!config.builderConfig.plugins) config.builderConfig.plugins = [];
|
|
324
|
+
config.builderConfig.plugins.push(...Array.isArray(mergedOptions) ? mergedOptions.map((item, index)=>rsbuildPluginLlms({
|
|
325
|
+
pageDataList,
|
|
326
|
+
routes,
|
|
327
|
+
titleRef,
|
|
328
|
+
descriptionRef,
|
|
329
|
+
langRef,
|
|
330
|
+
sidebar,
|
|
331
|
+
routeServiceRef,
|
|
332
|
+
nav,
|
|
333
|
+
baseRef,
|
|
334
|
+
disableSSGRef,
|
|
335
|
+
rspressPluginOptions: item,
|
|
336
|
+
index
|
|
337
|
+
})) : [
|
|
338
|
+
rsbuildPluginLlms({
|
|
339
|
+
pageDataList,
|
|
340
|
+
routes,
|
|
341
|
+
titleRef,
|
|
342
|
+
descriptionRef,
|
|
343
|
+
langRef,
|
|
344
|
+
sidebar,
|
|
345
|
+
routeServiceRef,
|
|
346
|
+
nav,
|
|
347
|
+
baseRef,
|
|
348
|
+
disableSSGRef,
|
|
349
|
+
rspressPluginOptions: mergedOptions
|
|
350
|
+
})
|
|
351
|
+
]);
|
|
352
|
+
return config;
|
|
353
|
+
},
|
|
379
354
|
beforeBuild (config) {
|
|
380
|
-
|
|
355
|
+
disableSSGRef.current = false === config.ssg;
|
|
356
|
+
const locales = config.themeConfig?.locales;
|
|
357
|
+
const isMultiLang = locales && locales.length > 0;
|
|
358
|
+
const sidebars = isMultiLang ? locales.map((i)=>i.sidebar) : [
|
|
359
|
+
config.themeConfig?.sidebar
|
|
360
|
+
];
|
|
361
|
+
const configSidebar = sidebars.reduce((prev, curr)=>{
|
|
381
362
|
Object.assign(prev, curr);
|
|
382
363
|
return prev;
|
|
383
364
|
}, {});
|
|
384
365
|
Object.assign(sidebar, configSidebar);
|
|
385
|
-
const configNav =
|
|
366
|
+
const configNav = isMultiLang ? locales.filter((i)=>Boolean(i.nav)).map((i)=>({
|
|
386
367
|
nav: i.nav,
|
|
387
368
|
lang: i.lang
|
|
388
|
-
}))
|
|
369
|
+
})) : [
|
|
370
|
+
{
|
|
371
|
+
nav: config.themeConfig?.nav,
|
|
372
|
+
lang: config.lang ?? ''
|
|
373
|
+
}
|
|
374
|
+
];
|
|
389
375
|
nav.push(...configNav);
|
|
390
376
|
titleRef.current = config.title;
|
|
391
377
|
descriptionRef.current = config.description;
|
|
392
|
-
langRef.current = config.lang;
|
|
378
|
+
langRef.current = config.lang ?? '';
|
|
393
379
|
baseRef.current = config.base ?? '/';
|
|
394
380
|
docDirectoryRef.current = config.root ?? 'docs';
|
|
395
|
-
},
|
|
396
|
-
builderConfig: {
|
|
397
|
-
plugins: [
|
|
398
|
-
rsbuildPluginLlms({
|
|
399
|
-
...options,
|
|
400
|
-
pageDataList,
|
|
401
|
-
routes,
|
|
402
|
-
titleRef,
|
|
403
|
-
descriptionRef,
|
|
404
|
-
langRef,
|
|
405
|
-
sidebar,
|
|
406
|
-
docDirectoryRef,
|
|
407
|
-
routeServiceRef,
|
|
408
|
-
nav,
|
|
409
|
-
baseRef,
|
|
410
|
-
rspressPluginOptions: options
|
|
411
|
-
})
|
|
412
|
-
]
|
|
413
381
|
}
|
|
414
382
|
};
|
|
415
383
|
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
.llmsContainer-glE3L4 {
|
|
2
|
+
align-items: center;
|
|
3
|
+
gap: 8px;
|
|
4
|
+
margin-bottom: 20px;
|
|
5
|
+
display: flex;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.llmsCopyButtonContainer-osHvFn {
|
|
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);
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
border-radius: 8px;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
align-items: center;
|
|
17
|
+
gap: 8px;
|
|
18
|
+
padding: 8px 12px;
|
|
19
|
+
font-size: 14px;
|
|
20
|
+
font-style: normal;
|
|
21
|
+
font-weight: 400;
|
|
22
|
+
transition: background .3s, border .3s, opacity .3s;
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.llmsCopyButtonContainer-osHvFn:hover {
|
|
27
|
+
background: var(--rp-c-bg-mute);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.llmsCopyButtonContainer-osHvFn.loading-p5nEhg {
|
|
31
|
+
background: var(--rp-c-bg-mute);
|
|
32
|
+
opacity: .5;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.llmsCopyButtonContainer-osHvFn.success-F4Qj8u .iconCopy-g1n4MZ {
|
|
36
|
+
display: none;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.llmsCopyButtonContainer-osHvFn.success-F4Qj8u .iconSuccess-PId4Mj {
|
|
40
|
+
opacity: 1;
|
|
41
|
+
visibility: inherit;
|
|
42
|
+
transition-delay: 75ms;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.iconContainer-G_2NC6 {
|
|
46
|
+
width: 16px;
|
|
47
|
+
height: 16px;
|
|
48
|
+
position: relative;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.iconCopy-g1n4MZ {
|
|
52
|
+
width: 16px;
|
|
53
|
+
height: 16px;
|
|
54
|
+
position: absolute;
|
|
55
|
+
top: 50%;
|
|
56
|
+
left: 50%;
|
|
57
|
+
transform: translate(-50%, -50%);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.iconSuccess-PId4Mj {
|
|
61
|
+
visibility: hidden;
|
|
62
|
+
opacity: 0;
|
|
63
|
+
width: 16px;
|
|
64
|
+
height: 16px;
|
|
65
|
+
transition: opacity .2s, transform .2s;
|
|
66
|
+
position: absolute;
|
|
67
|
+
top: 50%;
|
|
68
|
+
left: 50%;
|
|
69
|
+
transform: translate(-50%, -50%);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.dropdownButton-Mj4g7p {
|
|
73
|
+
border: 1px solid var(--rp-c-divider-light);
|
|
74
|
+
background: var(--rp-c-bg);
|
|
75
|
+
height: 40px;
|
|
76
|
+
color: var(--rp-c-text-1);
|
|
77
|
+
cursor: pointer;
|
|
78
|
+
border-radius: 8px;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: 8px;
|
|
82
|
+
padding: 8px 12px;
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
font-style: normal;
|
|
85
|
+
font-weight: 400;
|
|
86
|
+
line-height: 22px;
|
|
87
|
+
transition: background .3s, border .3s;
|
|
88
|
+
display: inline-flex;
|
|
89
|
+
position: relative;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.dropdownButton-Mj4g7p:hover, .dropdownButton-Mj4g7p.active-SacMuO {
|
|
93
|
+
background: var(--rp-c-bg-mute);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.dropdownArrow-UjqrjW {
|
|
97
|
+
transition: transform .2s;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.dropdownArrow-UjqrjW.rotated-YGs7Vp {
|
|
101
|
+
transform: rotate(180deg);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.dropdownMenu-_ggfjT {
|
|
105
|
+
z-index: 2;
|
|
106
|
+
border: 1px solid var(--rp-c-divider-light);
|
|
107
|
+
background: var(--rp-c-bg);
|
|
108
|
+
width: 250px;
|
|
109
|
+
color: var(--rp-c-text-1);
|
|
110
|
+
border-radius: 8px;
|
|
111
|
+
flex-direction: column;
|
|
112
|
+
align-items: flex-start;
|
|
113
|
+
margin-top: 4px;
|
|
114
|
+
padding: 8px;
|
|
115
|
+
animation: .15s ease-in-out fadeIn-_SWLWZ;
|
|
116
|
+
display: inline-flex;
|
|
117
|
+
position: absolute;
|
|
118
|
+
top: 100%;
|
|
119
|
+
left: -10%;
|
|
120
|
+
box-shadow: 0 4px 16px #0000000a;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@keyframes fadeIn-_SWLWZ {
|
|
124
|
+
0% {
|
|
125
|
+
opacity: 0;
|
|
126
|
+
transform: translateY(-4px);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
100% {
|
|
130
|
+
opacity: 1;
|
|
131
|
+
transform: translateY(0);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.dropdownItem-taWikf {
|
|
136
|
+
text-align: left;
|
|
137
|
+
cursor: pointer;
|
|
138
|
+
background: none;
|
|
139
|
+
border: none;
|
|
140
|
+
border-radius: 8px;
|
|
141
|
+
align-items: center;
|
|
142
|
+
gap: 8px;
|
|
143
|
+
width: 100%;
|
|
144
|
+
padding: 8px 12px;
|
|
145
|
+
font-size: 14px;
|
|
146
|
+
display: flex;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.dropdownItem-taWikf:hover {
|
|
150
|
+
background: var(--rp-c-bg-mute);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.leftIcon-JI6iFK {
|
|
154
|
+
justify-content: center;
|
|
155
|
+
align-items: center;
|
|
156
|
+
width: 16px;
|
|
157
|
+
height: 16px;
|
|
158
|
+
font-size: 16px;
|
|
159
|
+
display: inline-flex;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.externalIcon-r8tMpa {
|
|
163
|
+
width: 16px;
|
|
164
|
+
height: 16px;
|
|
165
|
+
margin-left: auto;
|
|
166
|
+
font-size: 16px;
|
|
167
|
+
}
|
|
168
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { JSX } from 'react/jsx-runtime';
|
|
2
|
+
import type { default as React_2 } from 'react';
|
|
3
|
+
|
|
4
|
+
export declare function LlmsContainer(props: LlmsContainerProps): JSX.Element;
|
|
5
|
+
|
|
6
|
+
export declare interface LlmsContainerProps extends React_2.HTMLAttributes<HTMLDivElement> {
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export declare function LlmsCopyButton(props: LlmsCopyButtonProps): JSX.Element;
|
|
10
|
+
|
|
11
|
+
export declare interface LlmsCopyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
12
|
+
/**
|
|
13
|
+
* Text by language, used with `useLang`.
|
|
14
|
+
* @default en: 'Copy Markdown', zh: '复制 Markdown'
|
|
15
|
+
*/
|
|
16
|
+
textByLang?: Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Priority is higher than textByLang
|
|
19
|
+
* @default ''
|
|
20
|
+
*/
|
|
21
|
+
text?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Overrides the default click handler.
|
|
24
|
+
* If provided, the default copy to clipboard functionality will not be executed.
|
|
25
|
+
*/
|
|
26
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare const LlmsViewOptions: ({ options, text, textByLang, }: LlmsViewOptionsProps) => JSX.Element;
|
|
30
|
+
|
|
31
|
+
export declare interface LlmsViewOptionsProps extends React_2.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
32
|
+
/**
|
|
33
|
+
* Default options for the dropdown.
|
|
34
|
+
* @default ['markdownLink', 'chatgpt', 'claude']
|
|
35
|
+
* - 'chatgpt': Open in ChatGPT
|
|
36
|
+
* - 'claude': Open in Claude
|
|
37
|
+
*/
|
|
38
|
+
options?: Option_2[];
|
|
39
|
+
/**
|
|
40
|
+
* Button text by language, used with `useLang`.
|
|
41
|
+
* @default en: 'Open', zh: '打开'
|
|
42
|
+
*/
|
|
43
|
+
textByLang?: Record<string, string>;
|
|
44
|
+
/**
|
|
45
|
+
* Button text.
|
|
46
|
+
* Priority is higher than textByLang
|
|
47
|
+
* @default ''
|
|
48
|
+
*/
|
|
49
|
+
text?: string;
|
|
50
|
+
}
|
|
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
|
+
|
|
62
|
+
export declare function useMdUrl(): {
|
|
63
|
+
pathname: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { }
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import "./index.css"
|
|
2
|
+
/*! For license information please see index.js.LICENSE.txt */
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { normalizeHref, useLang, usePageData, withBase } from "@rspress/core/runtime";
|
|
5
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
var _1 = "llmsContainer-glE3L4";
|
|
7
|
+
function LlmsContainer(props) {
|
|
8
|
+
return /*#__PURE__*/ jsx("div", {
|
|
9
|
+
...props,
|
|
10
|
+
className: _1
|
|
11
|
+
});
|
|
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
|
+
}
|
|
38
|
+
var LlmsCopyButton_module_1 = "iconContainer-G_2NC6";
|
|
39
|
+
var _2 = "iconCopy-g1n4MZ";
|
|
40
|
+
var _3 = "iconSuccess-PId4Mj";
|
|
41
|
+
var _4 = "llmsCopyButtonContainer-osHvFn";
|
|
42
|
+
var _5 = "loading-p5nEhg";
|
|
43
|
+
var _6 = "success-F4Qj8u";
|
|
44
|
+
function routePathToMdPath(routePath) {
|
|
45
|
+
let url = routePath;
|
|
46
|
+
url = normalizeHref(url, false);
|
|
47
|
+
url = url.replace(/\.html$/, '.md');
|
|
48
|
+
return withBase(url);
|
|
49
|
+
}
|
|
50
|
+
function useMdUrl() {
|
|
51
|
+
const { page } = usePageData();
|
|
52
|
+
const mdPath = useMemo(()=>{
|
|
53
|
+
const pathname = routePathToMdPath(page.routePath);
|
|
54
|
+
return {
|
|
55
|
+
pathname
|
|
56
|
+
};
|
|
57
|
+
}, [
|
|
58
|
+
page.routePath
|
|
59
|
+
]);
|
|
60
|
+
return mdPath;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Inspired from fumadocs docsite
|
|
64
|
+
* @from https://github.com/fuma-nama/fumadocs/blob/5723bbe58ef805a5421a780abf235a10b251be2f/apps/docs/app/docs/%5B...slug%5D/page.client.tsx#L11
|
|
65
|
+
* @license MIT
|
|
66
|
+
*/ function IconSuccess({ className }) {
|
|
67
|
+
return /*#__PURE__*/ jsx("svg", {
|
|
68
|
+
width: "32",
|
|
69
|
+
height: "32",
|
|
70
|
+
viewBox: "0 0 30 30",
|
|
71
|
+
className: className,
|
|
72
|
+
children: /*#__PURE__*/ jsx("path", {
|
|
73
|
+
fill: "#49cd37",
|
|
74
|
+
d: "m13 24l-9-9l1.414-1.414L13 21.171L26.586 7.586L28 9L13 24z"
|
|
75
|
+
})
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const cache = new Map();
|
|
79
|
+
function LlmsCopyButton(props) {
|
|
80
|
+
const { onClick, text, textByLang = {
|
|
81
|
+
zh: "\u590D\u5236 Markdown",
|
|
82
|
+
en: 'Copy Markdown'
|
|
83
|
+
}, ...otherProps } = props;
|
|
84
|
+
const lang = useLang();
|
|
85
|
+
const { pathname } = useMdUrl();
|
|
86
|
+
const [isLoading, setLoading] = useState(false);
|
|
87
|
+
const [isFinished, setFinished] = useState(false);
|
|
88
|
+
const timer = useRef(null);
|
|
89
|
+
const handleClick = useCallback(async ()=>{
|
|
90
|
+
setLoading(true);
|
|
91
|
+
const url = pathname;
|
|
92
|
+
try {
|
|
93
|
+
const content = cache.get(url) ?? await fetch(url).then((res)=>res.text());
|
|
94
|
+
cache.set(url, content);
|
|
95
|
+
await navigator.clipboard.writeText(content);
|
|
96
|
+
} finally{
|
|
97
|
+
setLoading(false);
|
|
98
|
+
setFinished(true);
|
|
99
|
+
if (timer.current) {
|
|
100
|
+
clearTimeout(timer.current);
|
|
101
|
+
timer.current = null;
|
|
102
|
+
}
|
|
103
|
+
timer.current = window.setTimeout(()=>{
|
|
104
|
+
setFinished(false);
|
|
105
|
+
timer.current = null;
|
|
106
|
+
}, 500);
|
|
107
|
+
}
|
|
108
|
+
}, [
|
|
109
|
+
pathname
|
|
110
|
+
]);
|
|
111
|
+
if (!pathname) return /*#__PURE__*/ jsx(Fragment, {});
|
|
112
|
+
return /*#__PURE__*/ jsxs("button", {
|
|
113
|
+
...otherProps,
|
|
114
|
+
disabled: isLoading,
|
|
115
|
+
className: [
|
|
116
|
+
_4,
|
|
117
|
+
isLoading ? _5 : '',
|
|
118
|
+
isFinished ? _6 : ''
|
|
119
|
+
].filter(Boolean).join(' '),
|
|
120
|
+
onClick: onClick ?? handleClick,
|
|
121
|
+
children: [
|
|
122
|
+
/*#__PURE__*/ jsxs("div", {
|
|
123
|
+
className: LlmsCopyButton_module_1,
|
|
124
|
+
children: [
|
|
125
|
+
/*#__PURE__*/ jsx(IconSuccess, {
|
|
126
|
+
className: _3
|
|
127
|
+
}),
|
|
128
|
+
/*#__PURE__*/ jsx(IconCopy, {
|
|
129
|
+
className: _2
|
|
130
|
+
})
|
|
131
|
+
]
|
|
132
|
+
}),
|
|
133
|
+
/*#__PURE__*/ jsx("span", {
|
|
134
|
+
children: text ?? textByLang?.[lang] ?? 'Copy Markdown'
|
|
135
|
+
})
|
|
136
|
+
]
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
var LlmsViewOptions_module_1 = "active-SacMuO";
|
|
140
|
+
var LlmsViewOptions_module_2 = "dropdownArrow-UjqrjW";
|
|
141
|
+
var LlmsViewOptions_module_3 = "dropdownButton-Mj4g7p";
|
|
142
|
+
var LlmsViewOptions_module_4 = "dropdownItem-taWikf";
|
|
143
|
+
var LlmsViewOptions_module_5 = "dropdownMenu-_ggfjT";
|
|
144
|
+
var LlmsViewOptions_module_6 = "externalIcon-r8tMpa";
|
|
145
|
+
var _8 = "leftIcon-JI6iFK";
|
|
146
|
+
var _9 = "rotated-YGs7Vp";
|
|
147
|
+
/**
|
|
148
|
+
* Inspired from fumadocs docsite
|
|
149
|
+
* @from https://github.com/fuma-nama/fumadocs/blob/5723bbe58ef805a5421a780abf235a10b251be2f/apps/docs/app/docs/%5B...slug%5D/page.client.tsx#L11
|
|
150
|
+
* @license MIT
|
|
151
|
+
*/ const IconArrow = ({ className })=>/*#__PURE__*/ jsx("svg", {
|
|
152
|
+
className: className,
|
|
153
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
154
|
+
width: "16",
|
|
155
|
+
height: "16",
|
|
156
|
+
viewBox: "0 0 15 16",
|
|
157
|
+
fill: "none",
|
|
158
|
+
children: /*#__PURE__*/ jsx("path", {
|
|
159
|
+
d: "M11.125 5.27885L7 9.72115L2.875 5.27885",
|
|
160
|
+
stroke: "#4E5969",
|
|
161
|
+
strokeWidth: "1.125",
|
|
162
|
+
strokeLinecap: "round",
|
|
163
|
+
strokeLinejoin: "round"
|
|
164
|
+
})
|
|
165
|
+
});
|
|
166
|
+
const IconExternalLink = ()=>/*#__PURE__*/ jsxs("svg", {
|
|
167
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
168
|
+
width: "16",
|
|
169
|
+
height: "16",
|
|
170
|
+
viewBox: "0 0 16 16",
|
|
171
|
+
fill: "none",
|
|
172
|
+
children: [
|
|
173
|
+
/*#__PURE__*/ jsx("path", {
|
|
174
|
+
d: "M9.33301 2H13.9997V6.66667",
|
|
175
|
+
stroke: "#808080",
|
|
176
|
+
strokeWidth: "1.33333",
|
|
177
|
+
strokeLinecap: "round",
|
|
178
|
+
strokeLinejoin: "round"
|
|
179
|
+
}),
|
|
180
|
+
/*#__PURE__*/ jsx("path", {
|
|
181
|
+
d: "M14 9.82457V13C14 13.5523 13.5523 14 13 14H3C2.44772 14 2 13.5523 2 13V3C2 2.44772 2.44772 2 3 2H6",
|
|
182
|
+
stroke: "#808080",
|
|
183
|
+
strokeWidth: "1.33333",
|
|
184
|
+
strokeLinecap: "round",
|
|
185
|
+
strokeLinejoin: "round"
|
|
186
|
+
}),
|
|
187
|
+
/*#__PURE__*/ jsx("path", {
|
|
188
|
+
d: "M8.59961 7.39996L13.6996 2.29996",
|
|
189
|
+
stroke: "#808080",
|
|
190
|
+
strokeWidth: "1.33333",
|
|
191
|
+
strokeLinecap: "round",
|
|
192
|
+
strokeLinejoin: "round"
|
|
193
|
+
})
|
|
194
|
+
]
|
|
195
|
+
});
|
|
196
|
+
const LlmsViewOptions = ({ options = [
|
|
197
|
+
'markdownLink',
|
|
198
|
+
'chatgpt',
|
|
199
|
+
'claude'
|
|
200
|
+
], text, textByLang = {
|
|
201
|
+
en: 'Open',
|
|
202
|
+
zh: "\u6253\u5F00"
|
|
203
|
+
} })=>{
|
|
204
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
205
|
+
const dropdownRef = useRef(null);
|
|
206
|
+
useEffect(()=>{
|
|
207
|
+
const handleClickOutside = (event)=>{
|
|
208
|
+
if (dropdownRef.current && event.target && !dropdownRef.current.contains(event.target)) setIsOpen(false);
|
|
209
|
+
};
|
|
210
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
211
|
+
return ()=>{
|
|
212
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
213
|
+
};
|
|
214
|
+
}, []);
|
|
215
|
+
const toggleDropdown = ()=>{
|
|
216
|
+
setIsOpen(!isOpen);
|
|
217
|
+
};
|
|
218
|
+
const { pathname } = useMdUrl();
|
|
219
|
+
const lang = useLang();
|
|
220
|
+
const isEn = !lang || 'en' === lang;
|
|
221
|
+
const items = useMemo(()=>{
|
|
222
|
+
const fullMarkdownUrl = 'undefined' != typeof window ? new URL(pathname, window.location.origin).toString() : 'loading';
|
|
223
|
+
const q = `Read ${fullMarkdownUrl}, I want to ask questions about it.`;
|
|
224
|
+
return {
|
|
225
|
+
markdownLink: {
|
|
226
|
+
title: isEn ? 'Copy Markdown link' : "\u590D\u5236 Markdown \u94FE\u63A5",
|
|
227
|
+
icon: /*#__PURE__*/ jsx("svg", {
|
|
228
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
229
|
+
viewBox: "0 0 24 24",
|
|
230
|
+
width: "24",
|
|
231
|
+
height: "24",
|
|
232
|
+
children: /*#__PURE__*/ jsxs("g", {
|
|
233
|
+
fill: "none",
|
|
234
|
+
stroke: "currentColor",
|
|
235
|
+
strokeLinecap: "round",
|
|
236
|
+
strokeLinejoin: "round",
|
|
237
|
+
strokeWidth: "2",
|
|
238
|
+
children: [
|
|
239
|
+
/*#__PURE__*/ jsx("path", {
|
|
240
|
+
d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
|
|
241
|
+
}),
|
|
242
|
+
/*#__PURE__*/ jsx("path", {
|
|
243
|
+
d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
|
|
244
|
+
})
|
|
245
|
+
]
|
|
246
|
+
})
|
|
247
|
+
}),
|
|
248
|
+
onClick: ()=>{
|
|
249
|
+
navigator.clipboard.writeText(fullMarkdownUrl);
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
chatgpt: {
|
|
253
|
+
title: isEn ? 'Open in ChatGPT' : "\u5728 ChatGPT \u4E2D\u6253\u5F00",
|
|
254
|
+
href: `https://chatgpt.com/?${new URLSearchParams({
|
|
255
|
+
hints: 'search',
|
|
256
|
+
q
|
|
257
|
+
})}`,
|
|
258
|
+
icon: /*#__PURE__*/ jsxs("svg", {
|
|
259
|
+
role: "img",
|
|
260
|
+
viewBox: "0 0 24 24",
|
|
261
|
+
fill: "currentColor",
|
|
262
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
263
|
+
children: [
|
|
264
|
+
/*#__PURE__*/ jsx("title", {
|
|
265
|
+
children: "OpenAI"
|
|
266
|
+
}),
|
|
267
|
+
/*#__PURE__*/ jsx("path", {
|
|
268
|
+
d: "M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"
|
|
269
|
+
})
|
|
270
|
+
]
|
|
271
|
+
})
|
|
272
|
+
},
|
|
273
|
+
claude: {
|
|
274
|
+
title: isEn ? 'Open in Claude' : "\u5728 Claude \u4E2D\u6253\u5F00",
|
|
275
|
+
href: `https://claude.ai/new?${new URLSearchParams({
|
|
276
|
+
q
|
|
277
|
+
})}`,
|
|
278
|
+
icon: /*#__PURE__*/ jsxs("svg", {
|
|
279
|
+
fill: "currentColor",
|
|
280
|
+
role: "img",
|
|
281
|
+
viewBox: "0 0 24 24",
|
|
282
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
283
|
+
children: [
|
|
284
|
+
/*#__PURE__*/ jsx("title", {
|
|
285
|
+
children: "Anthropic"
|
|
286
|
+
}),
|
|
287
|
+
/*#__PURE__*/ jsx("path", {
|
|
288
|
+
d: "M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z"
|
|
289
|
+
})
|
|
290
|
+
]
|
|
291
|
+
})
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
}, [
|
|
295
|
+
pathname,
|
|
296
|
+
isEn
|
|
297
|
+
]);
|
|
298
|
+
return /*#__PURE__*/ jsx(Fragment, {
|
|
299
|
+
children: /*#__PURE__*/ jsxs("button", {
|
|
300
|
+
ref: dropdownRef,
|
|
301
|
+
className: [
|
|
302
|
+
LlmsViewOptions_module_3,
|
|
303
|
+
isOpen ? LlmsViewOptions_module_1 : ''
|
|
304
|
+
].filter(Boolean).join(' '),
|
|
305
|
+
type: "button",
|
|
306
|
+
onClick: toggleDropdown,
|
|
307
|
+
children: [
|
|
308
|
+
text ?? textByLang[lang] ?? 'Open',
|
|
309
|
+
/*#__PURE__*/ jsx(IconArrow, {
|
|
310
|
+
className: `${LlmsViewOptions_module_2} ${isOpen ? _9 : ''}`
|
|
311
|
+
}),
|
|
312
|
+
isOpen && /*#__PURE__*/ jsx("div", {
|
|
313
|
+
className: LlmsViewOptions_module_5,
|
|
314
|
+
children: options.map((item)=>{
|
|
315
|
+
let displayItem = item;
|
|
316
|
+
if ('markdownLink' === item) displayItem = items.markdownLink;
|
|
317
|
+
else if ('chatgpt' === item) displayItem = items.chatgpt;
|
|
318
|
+
else if ('claude' === item) displayItem = items.claude;
|
|
319
|
+
if (displayItem.href) return /*#__PURE__*/ jsxs("a", {
|
|
320
|
+
className: LlmsViewOptions_module_4,
|
|
321
|
+
href: displayItem.href,
|
|
322
|
+
target: "_blank",
|
|
323
|
+
rel: "noopener noreferrer",
|
|
324
|
+
children: [
|
|
325
|
+
/*#__PURE__*/ jsx("span", {
|
|
326
|
+
className: _8,
|
|
327
|
+
children: displayItem.icon
|
|
328
|
+
}),
|
|
329
|
+
/*#__PURE__*/ jsx("span", {
|
|
330
|
+
children: displayItem.title
|
|
331
|
+
}),
|
|
332
|
+
/*#__PURE__*/ jsx("span", {
|
|
333
|
+
className: LlmsViewOptions_module_6,
|
|
334
|
+
children: /*#__PURE__*/ jsx(IconExternalLink, {})
|
|
335
|
+
})
|
|
336
|
+
]
|
|
337
|
+
}, displayItem.title);
|
|
338
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
339
|
+
className: LlmsViewOptions_module_4,
|
|
340
|
+
onClick: displayItem.onClick,
|
|
341
|
+
children: [
|
|
342
|
+
/*#__PURE__*/ jsx("span", {
|
|
343
|
+
className: _8,
|
|
344
|
+
children: displayItem.icon
|
|
345
|
+
}),
|
|
346
|
+
/*#__PURE__*/ jsx("span", {
|
|
347
|
+
children: displayItem.title
|
|
348
|
+
})
|
|
349
|
+
]
|
|
350
|
+
}, displayItem.title);
|
|
351
|
+
})
|
|
352
|
+
})
|
|
353
|
+
]
|
|
354
|
+
})
|
|
355
|
+
});
|
|
356
|
+
};
|
|
357
|
+
export { LlmsContainer, LlmsCopyButton, LlmsViewOptions, useMdUrl };
|
package/package.json
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rspress/plugin-llms",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.30",
|
|
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": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/web-infra-dev/rspress",
|
|
8
|
+
"url": "git+https://github.com/web-infra-dev/rspress.git",
|
|
9
9
|
"directory": "packages/plugin-llm"
|
|
10
10
|
},
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"type": "module",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./runtime": {
|
|
19
|
+
"types": "./dist/runtime/index.d.ts",
|
|
20
|
+
"default": "./dist/runtime/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
13
23
|
"main": "./dist/index.js",
|
|
14
24
|
"module": "./dist/index.js",
|
|
15
25
|
"types": "./dist/index.d.ts",
|
|
@@ -18,34 +28,35 @@
|
|
|
18
28
|
"static"
|
|
19
29
|
],
|
|
20
30
|
"dependencies": {
|
|
21
|
-
"remark-mdx": "^3.1.
|
|
31
|
+
"remark-mdx": "^3.1.1",
|
|
22
32
|
"remark-parse": "^11.0.0",
|
|
23
33
|
"remark-stringify": "^11.0.0",
|
|
24
34
|
"unified": "^11.0.5",
|
|
25
|
-
"unist-util-visit": "^5.0.0"
|
|
26
|
-
"unist-util-visit-children": "^3.0.0",
|
|
27
|
-
"@rspress/shared": "2.0.0-beta.3"
|
|
35
|
+
"unist-util-visit": "^5.0.0"
|
|
28
36
|
},
|
|
29
37
|
"devDependencies": {
|
|
30
|
-
"@microsoft/api-extractor": "^7.52.
|
|
31
|
-
"@rsbuild/core": "1.3
|
|
32
|
-
"@
|
|
38
|
+
"@microsoft/api-extractor": "^7.52.11",
|
|
39
|
+
"@rsbuild/core": "~1.5.3",
|
|
40
|
+
"@rsbuild/plugin-react": "~1.4.0",
|
|
41
|
+
"@rsbuild/plugin-sass": "~1.4.0",
|
|
42
|
+
"@rslib/core": "0.12.4",
|
|
33
43
|
"@types/hast": "^3.0.4",
|
|
34
|
-
"@types/node": "^
|
|
44
|
+
"@types/node": "^22.8.1",
|
|
45
|
+
"@types/react": "^19.1.12",
|
|
46
|
+
"react": "^19.1.1",
|
|
47
|
+
"rsbuild-plugin-publint": "^0.3.3",
|
|
35
48
|
"typescript": "^5.8.2",
|
|
36
49
|
"vfile": "^6.0.3",
|
|
37
|
-
"@rspress/config": "1.0.0"
|
|
38
|
-
"@rspress/runtime": "2.0.0-beta.3"
|
|
50
|
+
"@rspress/config": "1.0.0"
|
|
39
51
|
},
|
|
40
52
|
"peerDependencies": {
|
|
41
|
-
"@rspress/core": "^2.0.0-beta.
|
|
53
|
+
"@rspress/core": "^2.0.0-beta.30"
|
|
42
54
|
},
|
|
43
55
|
"engines": {
|
|
44
56
|
"node": ">=18.0.0"
|
|
45
57
|
},
|
|
46
58
|
"publishConfig": {
|
|
47
59
|
"access": "public",
|
|
48
|
-
"provenance": true,
|
|
49
60
|
"registry": "https://registry.npmjs.org/"
|
|
50
61
|
},
|
|
51
62
|
"scripts": {
|