react-docs-ui 0.7.6 → 0.8.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.
Files changed (45) hide show
  1. package/dist/AIChatDialog-C2mEAX2T.js +407 -0
  2. package/dist/{AISelectionTrigger-SLyb8Vep.js → AISelectionTrigger-CWTJRvHo.js} +1 -1
  3. package/dist/{AISettingsPanel-Bsd_wLP4.js → AISettingsPanel-C9Bb_QtE.js} +1 -1
  4. package/dist/{DocsApp-CCFHuucK.js → DocsApp-CTh7Pa9A.js} +3797 -3560
  5. package/dist/{GlobalContextMenu-BtVjQk0v.js → GlobalContextMenu-DAIKsl1l.js} +1 -1
  6. package/dist/{MdxContent-CJydH4kW.js → MdxContent-BAm4izu3.js} +305 -317
  7. package/dist/{MdxContent.lazy-ChT4eAlU.js → MdxContent.lazy-vS9NrZj4.js} +1 -1
  8. package/dist/{SearchDialog-Dh1RvEgs.js → SearchDialog-CLbtpf7I.js} +157 -114
  9. package/dist/{SearchRuntime-wdAGDBv4.js → SearchRuntime--tjedqS6.js} +1 -1
  10. package/dist/{context-menu-BIQsQup7.js → context-menu-DwILPvwC.js} +1 -1
  11. package/dist/{dialog-D8otbqQL.js → dialog-D68sEJBe.js} +1 -1
  12. package/dist/docs-app.es.js +1 -1
  13. package/dist/{mdx-components-BLq-Umts.js → mdx-components-6beJPZgM.js} +2 -2
  14. package/dist/react-docs-ui.css +1 -1
  15. package/dist/react-docs-ui.es.js +10 -10
  16. package/dist/types/components/Breadcrumb.d.ts +14 -0
  17. package/dist/types/components/Breadcrumb.d.ts.map +1 -0
  18. package/dist/types/components/DocsLayout.d.ts.map +1 -1
  19. package/dist/types/components/MdxContent.d.ts.map +1 -1
  20. package/dist/types/components/ReadingProgressBar.d.ts +4 -0
  21. package/dist/types/components/ReadingProgressBar.d.ts.map +1 -0
  22. package/dist/types/components/ReleaseMetaBar.d.ts +1 -1
  23. package/dist/types/components/ReleaseMetaBar.d.ts.map +1 -1
  24. package/dist/types/components/ai/AIChatMessage.d.ts.map +1 -1
  25. package/dist/types/components/search/SearchItem.d.ts.map +1 -1
  26. package/dist/types/hooks/useScrollPosition.d.ts.map +1 -1
  27. package/dist/types/lib/changelog.d.ts +1 -1
  28. package/dist/types/lib/changelog.d.ts.map +1 -1
  29. package/dist/types/lib/config.d.ts +20 -0
  30. package/dist/types/lib/config.d.ts.map +1 -1
  31. package/dist/types/lib/reading-time.d.ts +7 -0
  32. package/dist/types/lib/reading-time.d.ts.map +1 -0
  33. package/dist/types/lib/search/index.d.ts +2 -1
  34. package/dist/types/lib/search/index.d.ts.map +1 -1
  35. package/dist/types/lib/search/runtime/highlighter.d.ts +10 -0
  36. package/dist/types/lib/search/runtime/highlighter.d.ts.map +1 -1
  37. package/dist/types/lib/utils.d.ts +2 -0
  38. package/dist/types/lib/utils.d.ts.map +1 -1
  39. package/dist/utils-KFBtT4Mx.js +25 -0
  40. package/package.json +147 -143
  41. package/scripts/cli.mjs +2 -0
  42. package/scripts/generate-feed.mjs +122 -0
  43. package/scripts/generate-sitemap.mjs +186 -0
  44. package/dist/AIChatDialog-BnAX3dRn.js +0 -418
  45. package/dist/utils-Ct96Mtjw.js +0 -8
@@ -1 +1 @@
1
- {"version":3,"file":"highlighter.d.ts","sourceRoot":"","sources":["../../../../../src/lib/search/runtime/highlighter.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,KAAK,CAAC;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,GAAG,EAAE,MAAM,CAAA;KACZ,CAAC,CAAA;CACH;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAAE,EACpB,GAAG,GAAE,MAAe,GACnB,MAAM,CAyCR;AAwBD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACjB,GACL,MAAM,CAyCR;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;CACR,GACL,MAAM,CAGR;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKrD"}
1
+ {"version":3,"file":"highlighter.d.ts","sourceRoot":"","sources":["../../../../../src/lib/search/runtime/highlighter.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,KAAK,CAAC;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,GAAG,EAAE,MAAM,CAAA;KACZ,CAAC,CAAA;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAAE,GACnB,gBAAgB,EAAE,CA0CpB;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAAE,EACpB,GAAG,GAAE,MAAe,GACnB,MAAM,CAyCR;AAwBD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACjB,GACL,MAAM,CAyCR;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;CACR,GACL,MAAM,CAGR;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACjB,GACL,gBAAgB,EAAE,CAGpB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKrD"}
@@ -1,4 +1,6 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  export declare function cn(...inputs: ClassValue[]): string;
3
3
  export declare function toBase64(str: string): string;
4
+ export declare function copyToClipboard(text: string): Promise<void>;
5
+ export declare function sanitizeHtml(html: string): string;
4
6
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAA;AAG5C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,UAEnC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAA;AAG5C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,UAEnC;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBjE;AAMD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD"}
@@ -0,0 +1,25 @@
1
+ import { clsx as e } from "clsx";
2
+ import { twMerge as t } from "tailwind-merge";
3
+ //#region src/lib/utils.ts
4
+ function n(...n) {
5
+ return t(e(n));
6
+ }
7
+ async function r(e) {
8
+ if (navigator.clipboard && window.isSecureContext) {
9
+ await navigator.clipboard.writeText(e);
10
+ return;
11
+ }
12
+ let t = document.createElement("textarea");
13
+ t.value = e, t.setAttribute("readonly", ""), t.style.position = "fixed", t.style.left = "-9999px", t.style.top = "-9999px", t.style.opacity = "0", document.body.appendChild(t), t.focus(), t.select();
14
+ try {
15
+ document.execCommand("copy");
16
+ } finally {
17
+ document.body.removeChild(t);
18
+ }
19
+ }
20
+ var i = /<\/?(script|iframe|object|embed|form|input|textarea|select|button|applet|meta|link|base|svg)\b[^>]*>/gi, a = /\s+on\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, o = /\s*(?:href|src|action|formaction|data)\s*=\s*(?:"javascript:[^"]*"|'javascript:[^']*')/gi;
21
+ function s(e) {
22
+ return e.replace(i, "").replace(a, "").replace(o, "");
23
+ }
24
+ //#endregion
25
+ export { r as n, s as r, n as t };
package/package.json CHANGED
@@ -1,146 +1,150 @@
1
1
  {
2
- "name": "react-docs-ui",
3
- "version": "0.7.6",
4
- "type": "module",
5
- "description": "React documentation site UI components — navigation, sidebar, search, code highlight, MDX rendering and theming to help you build docs fast.",
6
- "homepage": "https://shenjianZ.github.io/react-docs-ui",
7
- "keywords": [
8
- "react",
9
- "docs",
10
- "documentation",
11
- "ui",
12
- "component-library",
13
- "react-components",
14
- "mdx",
15
- "markdown",
16
- "documentation-site",
17
- "typescript"
18
- ],
19
- "module": "dist/react-docs-ui.es.js",
20
- "types": "dist/types/index.d.ts",
21
- "bin": {
22
- "react-docs-ui": "./scripts/cli.mjs"
23
- },
24
- "files": [
25
- "dist",
26
- "scripts/cli.mjs",
27
- "scripts/generate-changelog-index.mjs",
28
- "scripts/generate-doc-git-meta.mjs",
29
- "scripts/generate-llms-files.mjs",
30
- "scripts/generate-search-index.mjs",
31
- "scripts/generate-shiki-bundle.mjs",
32
- "README.md",
33
- "package.json"
34
- ],
35
- "exports": {
36
- ".": {
37
- "types": "./dist/types/index.d.ts",
38
- "import": "./dist/react-docs-ui.es.js"
2
+ "name": "react-docs-ui",
3
+ "version": "0.8.1",
4
+ "type": "module",
5
+ "description": "React documentation site UI components — navigation, sidebar, search, code highlight, MDX rendering and theming to help you build docs fast.",
6
+ "homepage": "https://shenjianZ.github.io/react-docs-ui",
7
+ "keywords": [
8
+ "react",
9
+ "docs",
10
+ "documentation",
11
+ "ui",
12
+ "component-library",
13
+ "react-components",
14
+ "mdx",
15
+ "markdown",
16
+ "documentation-site",
17
+ "typescript"
18
+ ],
19
+ "module": "dist/react-docs-ui.es.js",
20
+ "types": "dist/types/index.d.ts",
21
+ "bin": {
22
+ "react-docs-ui": "./scripts/cli.mjs"
39
23
  },
40
- "./docs-app": {
41
- "types": "./dist/types/docs-app.d.ts",
42
- "import": "./dist/docs-app.es.js"
24
+ "files": [
25
+ "dist",
26
+ "scripts/cli.mjs",
27
+ "scripts/generate-changelog-index.mjs",
28
+ "scripts/generate-doc-git-meta.mjs",
29
+ "scripts/generate-feed.mjs",
30
+ "scripts/generate-llms-files.mjs",
31
+ "scripts/generate-search-index.mjs",
32
+ "scripts/generate-shiki-bundle.mjs",
33
+ "scripts/generate-sitemap.mjs",
34
+ "README.md",
35
+ "package.json"
36
+ ],
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/types/index.d.ts",
40
+ "import": "./dist/react-docs-ui.es.js"
41
+ },
42
+ "./docs-app": {
43
+ "types": "./dist/types/docs-app.d.ts",
44
+ "import": "./dist/docs-app.es.js"
45
+ },
46
+ "./style.css": "./dist/react-docs-ui.css"
43
47
  },
44
- "./style.css": "./dist/react-docs-ui.css"
45
- },
46
- "dependencies": {
47
- "@mdx-js/loader": "^3.0.0",
48
- "@mdx-js/react": "^3.0.0",
49
- "@radix-ui/react-collapsible": "^1.1.11",
50
- "@radix-ui/react-context-menu": "^2.2.15",
51
- "@radix-ui/react-dialog": "^1.1.14",
52
- "@radix-ui/react-dropdown-menu": "^2.1.15",
53
- "@radix-ui/react-scroll-area": "^1.2.9",
54
- "@radix-ui/react-slot": "^1.2.3",
55
- "@radix-ui/react-toast": "^1.2.15",
56
- "@radix-ui/react-tooltip": "^1.2.7",
57
- "@shikijs/transformers": "^4.0.2",
58
- "class-variance-authority": "^0.7.1",
59
- "clsx": "^2.1.1",
60
- "cmdk": "^1.1.1",
61
- "docx": "^9.6.1",
62
- "file-saver": "^2.0.5",
63
- "flexsearch": "^0.8.212",
64
- "glob": "^13.0.6",
65
- "gray-matter": "^4.0.3",
66
- "html-to-image": "^1.11.13",
67
- "js-yaml": "^4.1.0",
68
- "jspdf": "^4.2.1",
69
- "jszip": "^3.10.1",
70
- "katex": "^0.16.42",
71
- "katex-physics": "^1.0.2",
72
- "lucide-react": "^1.6.0",
73
- "mermaid": "^11.13.0",
74
- "next-themes": "^0.4.6",
75
- "react-markdown": "^10.1.0",
76
- "rehype-autolink-headings": "^7.1.0",
77
- "rehype-katex": "^7.0.1",
78
- "rehype-raw": "^7.0.0",
79
- "rehype-slug": "^6.0.0",
80
- "remark-gfm": "^4.0.1",
81
- "remark-math": "^6.0.0",
82
- "remark-parse": "^11.0.0",
83
- "remark-rehype": "^11.1.2",
84
- "shiki": "^4.0.2",
85
- "tailwind-merge": "^3.3.1",
86
- "turndown": "^7.2.2",
87
- "unified": "^11.0.5",
88
- "unist-util-visit": "^5.1.0"
89
- },
90
- "devDependencies": {
91
- "@eslint/js": "^10.0.1",
92
- "@tailwindcss/vite": "^4.2.2",
93
- "@types/cors": "^2.8.19",
94
- "@types/express": "^5.0.6",
95
- "@types/file-saver": "^2.0.7",
96
- "@types/hast": "^3.0.4",
97
- "@types/node": "^25.5.0",
98
- "@types/react": "^19.1.9",
99
- "@types/react-dom": "^19.1.7",
100
- "@types/turndown": "^5.0.6",
101
- "@vitejs/plugin-react": "^6.0.1",
102
- "buffer": "^6.0.3",
103
- "cors": "^2.8.6",
104
- "eslint": "^10.1.0",
105
- "eslint-plugin-react-hooks": "^7.0.1",
106
- "eslint-plugin-react-refresh": "^0.5.2",
107
- "express": "^5.2.1",
108
- "globals": "^17.4.0",
109
- "puppeteer": "^24.40.0",
110
- "react": "^19.0.0",
111
- "react-dom": "^19.0.0",
112
- "react-router-dom": "^7.13.2",
113
- "tailwindcss": "^4.1.11",
114
- "tsx": "^4.21.0",
115
- "tw-animate-css": "^1.3.6",
116
- "typescript": "^6.0.2",
117
- "typescript-eslint": "^8.57.2",
118
- "vite": "^8.0.2",
119
- "vite-plugin-dts": "^4.5.4",
120
- "vite-plugin-node-polyfills": "^0.25.0",
121
- "picomatch": "^4.0.3"
122
- },
123
- "peerDependencies": {
124
- "react": ">=18",
125
- "react-dom": ">=18",
126
- "react-router-dom": "^7"
127
- },
128
- "engines": {
129
- "node": ">=20.19.0"
130
- },
131
- "publishConfig": {
132
- "access": "public"
133
- },
134
- "scripts": {
135
- "predev": "node scripts/cli.mjs generate-doc-git-meta && node scripts/cli.mjs generate-llms-files && node scripts/cli.mjs generate-changelog-index",
136
- "dev": "vite",
137
- "prebuild": "node scripts/cli.mjs generate-doc-git-meta && node scripts/cli.mjs generate-llms-files && node scripts/cli.mjs generate-changelog-index",
138
- "build": "tsc -b && vite build",
139
- "build:lib": "tsc -p tsconfig.lib.json && vite build --config vite.config.lib.ts",
140
- "build:search": "node scripts/cli.mjs generate-search-index",
141
- "preview": "vite preview",
142
- "lint": "eslint .",
143
- "pdf:server": "tsx scripts/pdf-server.ts",
144
- "pdf:generate": "tsx scripts/generate-pdf-cli.ts"
145
- }
146
- }
48
+ "scripts": {
49
+ "predev": "node scripts/cli.mjs generate-doc-git-meta && node scripts/cli.mjs generate-llms-files && node scripts/cli.mjs generate-changelog-index && node scripts/cli.mjs generate-sitemap && node scripts/cli.mjs generate-feed",
50
+ "dev": "vite",
51
+ "prebuild": "node scripts/cli.mjs generate-doc-git-meta && node scripts/cli.mjs generate-llms-files && node scripts/cli.mjs generate-changelog-index && node scripts/cli.mjs generate-sitemap && node scripts/cli.mjs generate-feed",
52
+ "build": "tsc -b && vite build",
53
+ "build:lib": "tsc -p tsconfig.lib.json && vite build --config vite.config.lib.ts",
54
+ "build:search": "node scripts/cli.mjs generate-search-index",
55
+ "preview": "vite preview",
56
+ "lint": "eslint .",
57
+ "prepublishOnly": "npm run build:lib",
58
+ "pdf:server": "tsx scripts/pdf-server.ts",
59
+ "pdf:generate": "tsx scripts/generate-pdf-cli.ts"
60
+ },
61
+ "dependencies": {
62
+ "@mdx-js/loader": "^3.0.0",
63
+ "@mdx-js/react": "^3.0.0",
64
+ "@radix-ui/react-collapsible": "^1.1.11",
65
+ "@radix-ui/react-context-menu": "^2.2.15",
66
+ "@radix-ui/react-dialog": "^1.1.14",
67
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
68
+ "@radix-ui/react-scroll-area": "^1.2.9",
69
+ "@radix-ui/react-slot": "^1.2.3",
70
+ "@radix-ui/react-toast": "^1.2.15",
71
+ "@radix-ui/react-tooltip": "^1.2.7",
72
+ "@shikijs/transformers": "^4.0.2",
73
+ "class-variance-authority": "^0.7.1",
74
+ "clsx": "^2.1.1",
75
+ "cmdk": "^1.1.1",
76
+ "docx": "^9.6.1",
77
+ "file-saver": "^2.0.5",
78
+ "flexsearch": "^0.8.212",
79
+ "glob": "^13.0.6",
80
+ "gray-matter": "^4.0.3",
81
+ "html-to-image": "^1.11.13",
82
+ "js-yaml": "^4.1.0",
83
+ "jspdf": "^4.2.1",
84
+ "jszip": "^3.10.1",
85
+ "katex": "^0.16.42",
86
+ "katex-physics": "^1.0.2",
87
+ "lucide-react": "^1.6.0",
88
+ "mermaid": "^11.13.0",
89
+ "next-themes": "^0.4.6",
90
+ "react-markdown": "^10.1.0",
91
+ "rehype-autolink-headings": "^7.1.0",
92
+ "rehype-katex": "^7.0.1",
93
+ "rehype-raw": "^7.0.0",
94
+ "rehype-slug": "^6.0.0",
95
+ "remark-gfm": "^4.0.1",
96
+ "remark-math": "^6.0.0",
97
+ "remark-parse": "^11.0.0",
98
+ "remark-rehype": "^11.1.2",
99
+ "shiki": "^4.0.2",
100
+ "tailwind-merge": "^3.3.1",
101
+ "turndown": "^7.2.2",
102
+ "unified": "^11.0.5",
103
+ "unist-util-visit": "^5.1.0"
104
+ },
105
+ "devDependencies": {
106
+ "@eslint/js": "^10.0.1",
107
+ "@tailwindcss/vite": "^4.2.2",
108
+ "@types/cors": "^2.8.19",
109
+ "@types/express": "^5.0.6",
110
+ "@types/file-saver": "^2.0.7",
111
+ "@types/hast": "^3.0.4",
112
+ "@types/node": "^25.5.0",
113
+ "@types/react": "^19.1.9",
114
+ "@types/react-dom": "^19.1.7",
115
+ "@types/turndown": "^5.0.6",
116
+ "@vitejs/plugin-react": "^6.0.1",
117
+ "buffer": "^6.0.3",
118
+ "cors": "^2.8.6",
119
+ "eslint": "^10.1.0",
120
+ "eslint-plugin-react-hooks": "^7.0.1",
121
+ "eslint-plugin-react-refresh": "^0.5.2",
122
+ "express": "^5.2.1",
123
+ "globals": "^17.4.0",
124
+ "puppeteer": "^24.40.0",
125
+ "react": "^19.0.0",
126
+ "react-dom": "^19.0.0",
127
+ "react-router-dom": "^7.13.2",
128
+ "tailwindcss": "^4.1.11",
129
+ "tsx": "^4.21.0",
130
+ "tw-animate-css": "^1.3.6",
131
+ "typescript": "^6.0.2",
132
+ "typescript-eslint": "^8.57.2",
133
+ "vite": "^8.0.2",
134
+ "vite-plugin-dts": "^4.5.4",
135
+ "vite-plugin-node-polyfills": "^0.25.0",
136
+ "picomatch": "^4.0.3"
137
+ },
138
+ "peerDependencies": {
139
+ "react": ">=18",
140
+ "react-dom": ">=18",
141
+ "react-router-dom": "^7"
142
+ },
143
+ "engines": {
144
+ "node": ">=20.19.0"
145
+ },
146
+ "publishConfig": {
147
+ "access": "public"
148
+ },
149
+ "packageManager": "pnpm@10.17.1+sha512.17c560fca4867ae9473a3899ad84a88334914f379be46d455cbf92e5cf4b39d34985d452d2583baf19967fa76cb5c17bc9e245529d0b98745721aa7200ecaf7a"
150
+ }
package/scripts/cli.mjs CHANGED
@@ -8,6 +8,8 @@ const commands = {
8
8
  "generate-changelog-index": "./generate-changelog-index.mjs",
9
9
  "generate-search-index": "./generate-search-index.mjs",
10
10
  "generate-shiki-bundle": "./generate-shiki-bundle.mjs",
11
+ "generate-sitemap": "./generate-sitemap.mjs",
12
+ "generate-feed": "./generate-feed.mjs",
11
13
  }
12
14
 
13
15
  if (!command || !commands[command]) {
@@ -0,0 +1,122 @@
1
+ import fs from "node:fs/promises"
2
+ import path from "node:path"
3
+ import yaml from "js-yaml"
4
+
5
+ const rootDir = process.cwd()
6
+ const publicDir = path.join(rootDir, "public")
7
+
8
+ function escapeXml(str) {
9
+ return String(str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;")
10
+ }
11
+
12
+ async function loadSiteConfig() {
13
+ const configPath = path.join(publicDir, "config", "site.yaml")
14
+ try {
15
+ const content = await fs.readFile(configPath, "utf8")
16
+ return yaml.load(content)
17
+ } catch {
18
+ return {}
19
+ }
20
+ }
21
+
22
+ async function loadChangelogIndex(lang) {
23
+ const indexPath = path.join(publicDir, `changelog-index-${lang}.json`)
24
+ try {
25
+ const content = await fs.readFile(indexPath, "utf8")
26
+ return JSON.parse(content)
27
+ } catch {
28
+ return { lang, items: [] }
29
+ }
30
+ }
31
+
32
+ async function main() {
33
+ const config = await loadSiteConfig()
34
+ const siteUrl = config?.site?.url
35
+ if (!siteUrl) {
36
+ console.warn("[feed] Skipping: site.url is not configured in site.yaml")
37
+ return
38
+ }
39
+
40
+ const feedConfig = config?.feed || {}
41
+ if (feedConfig.enabled === false) {
42
+ console.log("[feed] Disabled in config")
43
+ return
44
+ }
45
+
46
+ const siteTitle = feedConfig.title || config?.site?.title || "Documentation"
47
+ const siteDescription = feedConfig.description || config?.site?.description || ""
48
+ const limit = feedConfig.limit || 20
49
+ const baseUrl = siteUrl.replace(/\/+$/, "")
50
+
51
+ // 收集所有语言的 changelog
52
+ const docsRoot = path.join(publicDir, "docs")
53
+ const entries = await fs.readdir(docsRoot, { withFileTypes: true })
54
+ const langs = entries.filter(entry => entry.isDirectory()).map(entry => entry.name)
55
+
56
+ const allItems = []
57
+ for (const lang of langs) {
58
+ const index = await loadChangelogIndex(lang)
59
+ for (const item of index.items || []) {
60
+ allItems.push({ ...item, lang })
61
+ }
62
+ }
63
+
64
+ // 按日期降序排序
65
+ allItems.sort((a, b) => {
66
+ const dateA = Date.parse(a.date || "")
67
+ const dateB = Date.parse(b.date || "")
68
+ if (Number.isNaN(dateA) && Number.isNaN(dateB)) return 0
69
+ if (Number.isNaN(dateA)) return 1
70
+ if (Number.isNaN(dateB)) return -1
71
+ return dateB - dateA
72
+ })
73
+
74
+ const items = allItems.slice(0, limit)
75
+
76
+ if (items.length === 0) {
77
+ console.log("[feed] No changelog items found")
78
+ return
79
+ }
80
+
81
+ const lastBuildDate = new Date().toUTCString()
82
+
83
+ const itemsXml = items.map(item => {
84
+ const link = `${baseUrl}${item.path}`
85
+ const pubDate = item.date ? new Date(item.date).toUTCString() : lastBuildDate
86
+ const tags = []
87
+ if (item.type) tags.push(`<category>${escapeXml(item.type)}</category>`)
88
+ if (item.breaking) tags.push(`<category>breaking</category>`)
89
+
90
+ return ` <item>
91
+ <title>${escapeXml(item.title)}</title>
92
+ <link>${escapeXml(link)}</link>
93
+ <guid isPermaLink="true">${escapeXml(link)}</guid>
94
+ <description>${escapeXml(item.summary || "")}</description>
95
+ <pubDate>${pubDate}</pubDate>${tags.length > 0 ? "\n " + tags.join("\n ") : ""}
96
+ </item>`
97
+ }).join("\n")
98
+
99
+ const rss = `<?xml version="1.0" encoding="UTF-8"?>
100
+ <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
101
+ <channel>
102
+ <title>${escapeXml(siteTitle)}</title>
103
+ <description>${escapeXml(siteDescription)}</description>
104
+ <link>${escapeXml(baseUrl)}</link>
105
+ <atom:link href="${escapeXml(baseUrl)}/feed.xml" rel="self" type="application/rss+xml"/>
106
+ <lastBuildDate>${lastBuildDate}</lastBuildDate>
107
+ <language>zh-cn</language>
108
+ <generator>react-docs-ui</generator>
109
+ ${itemsXml}
110
+ </channel>
111
+ </rss>
112
+ `
113
+
114
+ const outputPath = path.join(publicDir, "feed.xml")
115
+ await fs.writeFile(outputPath, rss, "utf8")
116
+ console.log(`[feed] Generated ${items.length} items to feed.xml`)
117
+ }
118
+
119
+ main().catch((error) => {
120
+ console.error("[feed] Failed:", error)
121
+ process.exitCode = 1
122
+ })