import "dotenv/config"; import { fileURLToPath, URL } from "node:url"; import { defineConfig } from "vitepress"; import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite"; import Icons from "unplugin-icons/vite"; import { FileSystemIconLoader } from "unplugin-icons/loaders"; import { SVG, cleanupSVG, parseColors, runSVGO } from "@iconify/tools"; import ImageFiguresPlugin from "markdown-it-image-figures"; import { S3Client, ListObjectsCommand, GetObjectCommand, } from "@aws-sdk/client-s3"; import fs from "node:fs"; import path from "node:path"; import { exec } from "child_process"; import { buildSideBar } from "../utils/sideBar"; const DOC_BASE_PATH = "pages"; if (process.env.NODE_ENV === "production") { // 执行清理pages文件夹命令 await new Promise((resolve, reject) => exec( `git checkout -- ${DOC_BASE_PATH} & git clean -df ${DOC_BASE_PATH}`, (error, stdout, stderr) => { if (error) { console.error(`清理pages时出错: ${error.message}`); reject(stderr); } console.log(`清理pages结果: ${stdout}`); resolve(stdout); } ) ); } // 从S3构建pages里面的markdown文件 const s3 = new S3Client({ credentials: { accessKeyId: process.env.VITE_AWS_S3_ACCESS_KEY_ID!, secretAccessKey: process.env.VITE_AWS_S3_SECRET_ACCESS_KEY!, }, region: process.env.VITE_AWS_S3_REGION!, }); const command = new ListObjectsCommand({ Bucket: process.env.VITE_DOCS_LIST_BUCKET, }); const { Contents: contents } = await s3.send(command); await Promise.all( contents!.map((content) => { return new Promise(async (resolve, reject) => { try { const command = new GetObjectCommand({ Bucket: process.env.VITE_DOCS_LIST_BUCKET, Key: content.Key, ResponseCacheControl: "no-cache", }); const file = await s3.send(command); const writePath = path.join(DOC_BASE_PATH, content.Key!); const directory = path.dirname(writePath); fs.mkdirSync(directory, { recursive: true }); fs.writeFileSync(writePath, await file.Body!.transformToString()); resolve(content.Key); } catch (e) { reject(e); } fs.writeFile; }); }) ); // 构建sideBar数据 function readJsonFile(filePath) { try { // 同步读取文件内容,如果文件不存在会抛出异常 const data = fs.readFileSync(filePath, "utf8"); return JSON.parse(data); // 解析 JSON 数据 } catch (err) { if (err.code === "ENOENT") { console.error("File not found:", filePath); // 可以返回默认值或者进行其他处理 return {}; // 返回 null 或者其他默认值 } else { throw err; // 抛出其他异常 } } } const sideBarSortMap = { "zh-CN": readJsonFile("pages/zh-CN::SIDEBAR_SORTED_MAP.json"), "zh-HK": readJsonFile("pages/zh-HK::SIDEBAR_SORTED_MAP.json"), "en-US": readJsonFile("pages/en-US::SIDEBAR_SORTED_MAP.json"), }; let { rootSideBar, zhHKSideBar, enUSSideBar } = buildSideBar( contents, sideBarSortMap ); // import util from "util"; // console.log( // util.inspect(sideBarSortMap, { // showHidden: false, // depth: null, // colors: true, // }), // util.inspect(rootSideBar, { showHidden: false, depth: null, colors: true }) // ); // https://vitepress.dev/reference/site-config export default defineConfig({ title: "可可智慧教育平台", description: "可可智慧教育平台", base: "/help/", srcDir: DOC_BASE_PATH, ignoreDeadLinks: true, lastUpdated: true, themeConfig: { search: { provider: "local", options: { locales: { root: { translations: { button: { buttonText: "搜索文档", buttonAriaLabel: "搜索文档", }, modal: { noResultsText: "无法找到相关结果", resetButtonTitle: "清除查询条件", footer: { selectText: "选择", navigateText: "切换", closeText: "关闭", }, }, }, }, "zh-HK": { translations: { button: { buttonText: "搜索文档hk", buttonAriaLabel: "搜索文档hk", }, modal: { noResultsText: "无法找到相关结果", resetButtonTitle: "清除查询条件", footer: { selectText: "选择", navigateText: "切换", closeText: "关闭", }, }, }, }, }, }, }, }, appearance: false, markdown: { breaks: true, config: (md) => { md.use(ImageFiguresPlugin, { figcaption: true }); }, }, vite: { publicDir: "../public", envDir: "../", ssr: { // SSG Vue-i18n workaround noExternal: ["vue-i18n", "mark.js"], }, plugins: [ VueI18nPlugin({}), Icons({ compiler: "vue3", customCollections: { "ccrbi-plain": FileSystemIconLoader( "assets/icons/plain", async (svgStr) => { const svg = new SVG(svgStr); cleanupSVG(svg); parseColors(svg, { defaultColor: "currentColor", callback: (attr, colorStr, color) => { // console.log('Color:', colorStr, color); // 普通图标 return "currentColor"; // Change black to 'currentColor' // const blackColor = stringToColor("black"); // if (color && compareColors(color, blackColor!)) { // return "currentColor"; // } // switch (color?.type) { // case "none": // case "current": // return color; // } // throw new Error( // `Unexpected color "${colorStr}" in attribute ${attr}` // ); }, }); // Optimise, but do not change shapes because they are animated runSVGO(svg, { keepShapes: true, }); return svg.toMinifiedString({}); } ), "ccrbi-colored": FileSystemIconLoader( "assets/icons/colored", async (svgStr) => { const svg = new SVG(svgStr); cleanupSVG(svg); // Optimise, but do not change shapes because they are animated runSVGO(svg, { keepShapes: true, }); return svg.toMinifiedString({}); } ), }, }), ], resolve: { alias: [ { find: /^.*\/VPNavBar\.vue$/, replacement: fileURLToPath( new URL("../components/CustomNavBar.vue", import.meta.url) ), }, { find: "@/", replacement: fileURLToPath(new URL("../", import.meta.url)), }, ], }, }, locales: { root: { label: "简体中文", lang: "zh-CN", themeConfig: { outline: { label: "本页目录", level: "deep" }, logo: "/logo.png", siteTitle: false, // https://vitepress.dev/reference/default-theme-config // nav: [ // { text: 'Home', link: '/' }, // { text: 'Examples', link: '/markdown-examples' } // ], // sidebar: [ // { text: "关于CocoBlockly X", link: "/docs" }, // { text: "常见问题解答", link: "/docs/常见问题解答" }, // { // text: "开始使用CocoBlockly X", // link: "/docs/start-using-cocoblockly-x", // collapsed: true, // items: [], // }, // { // text: "电子模块基本教学", // collapsed: true, // items: [{ text: "todo", link: "/docs" }], // }, // ], sidebar: rootSideBar, // socialLinks: [ // { icon: 'github', link: 'https://github.com/vuejs/vitepress' } // ] }, }, "zh-HK": { label: "繁体中文", lang: "zh-HK", themeConfig: { outline: { label: "本頁目錄", level: "deep" }, logo: "/logo.png", siteTitle: false, // https://vitepress.dev/reference/default-theme-config // nav: [ // { text: 'Home', link: '/' }, // { text: 'Examples', link: '/markdown-examples' } // ], // sidebar: [ // { text: "什麽是CocoBlockly X", link: "/zh-HK/docs" }, // { text: "常見問題解答", link: "/zh-HK/docs/faq" }, // { // text: "開始使用CocoBlockly X", // link: "/zh-HK/docs/start-using-cocoblockly-x", // }, // { // text: "電子模組基本教學", // collapsed: true, // items: [{ text: "todo", link: "/zh-HK/docs" }], // }, // ], sidebar: zhHKSideBar, // socialLinks: [ // { icon: 'github', link: 'https://github.com/vuejs/vitepress' } // ] }, }, "en-US": { label: "English", lang: "en-US", themeConfig: { outline: { label: "On this page", level: "deep" }, logo: "/logo.png", siteTitle: false, // https://vitepress.dev/reference/default-theme-config // nav: [ // { text: 'Home', link: '/' }, // { text: 'Examples', link: '/markdown-examples' } // ], // sidebar: [ // { text: "什麽是CocoBlockly X", link: "/zh-HK/docs" }, // { text: "常見問題解答", link: "/zh-HK/docs/faq" }, // { // text: "開始使用CocoBlockly X", // link: "/zh-HK/docs/start-using-cocoblockly-x", // }, // { // text: "電子模組基本教學", // collapsed: true, // items: [{ text: "todo", link: "/zh-HK/docs" }], // }, // ], sidebar: enUSSideBar, // socialLinks: [ // { icon: 'github', link: 'https://github.com/vuejs/vitepress' } // ] }, }, }, });