config.mts 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. import "dotenv/config";
  2. import { fileURLToPath, URL } from "node:url";
  3. import { defineConfig } from "vitepress";
  4. import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
  5. import Icons from "unplugin-icons/vite";
  6. import { FileSystemIconLoader } from "unplugin-icons/loaders";
  7. import { SVG, cleanupSVG, parseColors, runSVGO } from "@iconify/tools";
  8. import {
  9. S3Client,
  10. ListObjectsCommand,
  11. GetObjectCommand,
  12. } from "@aws-sdk/client-s3";
  13. import fs from "node:fs";
  14. import path from "node:path";
  15. import { exec } from "child_process";
  16. import { buildSideBar } from "../utils/sideBar";
  17. const DOC_BASE_PATH = "pages";
  18. if (process.env.NODE_ENV === "production") {
  19. // 执行清理pages命令
  20. await new Promise((resolve, reject) =>
  21. exec(
  22. `git checkout -- ${DOC_BASE_PATH} & git clean -df ${DOC_BASE_PATH}`,
  23. (error, stdout, stderr) => {
  24. if (error) {
  25. console.error(`清理pages时出错: ${error.message}`);
  26. reject(stderr);
  27. }
  28. console.log(`清理pages结果: ${stdout}`);
  29. resolve(stdout);
  30. }
  31. )
  32. );
  33. }
  34. // 从S3构建pages里面的markdown文件
  35. const s3 = new S3Client({
  36. credentials: {
  37. accessKeyId: process.env.VITE_AWS_S3_ACCESS_KEY_ID!,
  38. secretAccessKey: process.env.VITE_AWS_S3_SECRET_ACCESS_KEY!,
  39. },
  40. region: process.env.VITE_AWS_S3_REGION!,
  41. });
  42. const command = new ListObjectsCommand({
  43. Bucket: process.env.VITE_DOCS_LIST_BUCKET,
  44. });
  45. const { Contents: contents } = await s3.send(command);
  46. await Promise.all(
  47. contents!.map((content) => {
  48. return new Promise(async (resolve, reject) => {
  49. try {
  50. const command = new GetObjectCommand({
  51. Bucket: process.env.VITE_DOCS_LIST_BUCKET,
  52. Key: content.Key,
  53. ResponseCacheControl: "no-cache",
  54. });
  55. const file = await s3.send(command);
  56. const writePath = path.join(DOC_BASE_PATH, content.Key!);
  57. const directory = path.dirname(writePath);
  58. fs.mkdirSync(directory, { recursive: true });
  59. fs.writeFileSync(writePath, await file.Body!.transformToString());
  60. resolve(content.Key);
  61. } catch (e) {
  62. reject(e);
  63. }
  64. fs.writeFile;
  65. });
  66. })
  67. );
  68. // 构建sideBar数据
  69. let { rootSideBar, zhHKSideBar } = buildSideBar(contents);
  70. // rootSideBar = rootSideBar.map(sb => { sb.items = undefined;return sb })
  71. import util from "util";
  72. console.log(
  73. util.inspect(rootSideBar, { showHidden: false, depth: null, colors: true }),
  74. util.inspect(zhHKSideBar, { showHidden: false, depth: null, colors: true })
  75. );
  76. // process.exit();
  77. // https://vitepress.dev/reference/site-config
  78. export default defineConfig({
  79. title: "CocoBlockly帮助文档",
  80. description: "Cococlass help documents",
  81. srcDir: DOC_BASE_PATH,
  82. // themeConfig: {
  83. // search: {
  84. // provider: "local",
  85. // },
  86. // },
  87. appearance: false,
  88. vite: {
  89. publicDir: "../public",
  90. envDir: "../",
  91. // optimizeDeps: {
  92. // include: ["vue-i18n"],
  93. // },
  94. ssr: {
  95. // SSG Vue-i18n workaround
  96. noExternal: [/vue-i18n/],
  97. },
  98. plugins: [
  99. VueI18nPlugin({
  100. /* options */
  101. // locale messages resource pre-compile option
  102. // include: resolve(dirname(fileURLToPath(import.meta.url)), './path/to/src/locales/**'),
  103. }),
  104. Icons({
  105. compiler: "vue3",
  106. customCollections: {
  107. "ccrbi-plain": FileSystemIconLoader(
  108. "assets/icons/plain",
  109. async (svgStr) => {
  110. const svg = new SVG(svgStr);
  111. cleanupSVG(svg);
  112. parseColors(svg, {
  113. defaultColor: "currentColor",
  114. callback: (attr, colorStr, color) => {
  115. // console.log('Color:', colorStr, color);
  116. // 普通图标
  117. return "currentColor";
  118. // Change black to 'currentColor'
  119. // const blackColor = stringToColor("black");
  120. // if (color && compareColors(color, blackColor!)) {
  121. // return "currentColor";
  122. // }
  123. // switch (color?.type) {
  124. // case "none":
  125. // case "current":
  126. // return color;
  127. // }
  128. // throw new Error(
  129. // `Unexpected color "${colorStr}" in attribute ${attr}`
  130. // );
  131. },
  132. });
  133. // Optimise, but do not change shapes because they are animated
  134. runSVGO(svg, {
  135. keepShapes: true,
  136. });
  137. return svg.toMinifiedString({});
  138. }
  139. ),
  140. "ccrbi-colored": FileSystemIconLoader(
  141. "assets/icons/colored",
  142. async (svgStr) => {
  143. const svg = new SVG(svgStr);
  144. cleanupSVG(svg);
  145. // Optimise, but do not change shapes because they are animated
  146. runSVGO(svg, {
  147. keepShapes: true,
  148. });
  149. return svg.toMinifiedString({});
  150. }
  151. ),
  152. },
  153. }),
  154. ],
  155. resolve: {
  156. alias: [
  157. {
  158. find: /^.*\/VPNavBar\.vue$/,
  159. replacement: fileURLToPath(
  160. new URL("../components/CustomNavBar.vue", import.meta.url)
  161. ),
  162. },
  163. {
  164. find: "@/",
  165. replacement: fileURLToPath(new URL("../", import.meta.url)),
  166. },
  167. ],
  168. },
  169. },
  170. locales: {
  171. root: {
  172. label: "简体中文",
  173. lang: "zh-CN",
  174. themeConfig: {
  175. logo: "/logo.png",
  176. siteTitle: false,
  177. // https://vitepress.dev/reference/default-theme-config
  178. // nav: [
  179. // { text: 'Home', link: '/' },
  180. // { text: 'Examples', link: '/markdown-examples' }
  181. // ],
  182. // sidebar: [
  183. // { text: "关于CocoBlockly X", link: "/docs" },
  184. // { text: "常见问题解答", link: "/docs/常见问题解答" },
  185. // {
  186. // text: "开始使用CocoBlockly X",
  187. // link: "/docs/start-using-cocoblockly-x",
  188. // collapsed: true,
  189. // items: [],
  190. // },
  191. // {
  192. // text: "电子模块基本教学",
  193. // collapsed: true,
  194. // items: [{ text: "todo", link: "/docs" }],
  195. // },
  196. // ],
  197. sidebar: rootSideBar,
  198. // socialLinks: [
  199. // { icon: 'github', link: 'https://github.com/vuejs/vitepress' }
  200. // ]
  201. },
  202. },
  203. "zh-HK": {
  204. label: "繁体中文",
  205. lang: "zh-HK",
  206. themeConfig: {
  207. logo: "/logo.png",
  208. siteTitle: false,
  209. // https://vitepress.dev/reference/default-theme-config
  210. // nav: [
  211. // { text: 'Home', link: '/' },
  212. // { text: 'Examples', link: '/markdown-examples' }
  213. // ],
  214. sidebar: [
  215. { text: "什麽是CocoBlockly X", link: "/zh-HK/docs" },
  216. { text: "常見問題解答", link: "/zh-HK/docs/faq" },
  217. {
  218. text: "開始使用CocoBlockly X",
  219. link: "/zh-HK/docs/start-using-cocoblockly-x",
  220. },
  221. {
  222. text: "電子模組基本教學",
  223. collapsed: true,
  224. items: [{ text: "todo", link: "/zh-HK/docs" }],
  225. },
  226. ],
  227. // socialLinks: [
  228. // { icon: 'github', link: 'https://github.com/vuejs/vitepress' }
  229. // ]
  230. },
  231. },
  232. },
  233. });