fix: fix mermaid error
							parent
							
								
									78f58a5141
								
							
						
					
					
						commit
						e7dfaafec3
					
				|  | @ -0,0 +1,4 @@ | |||
| { | ||||
|   "singleQuote": true, | ||||
|   "semi": false | ||||
| } | ||||
|  | @ -0,0 +1,3 @@ | |||
| { | ||||
|   "editor.tabSize": 2 | ||||
| } | ||||
|  | @ -1,14 +1,18 @@ | |||
| import { viteBundler } from "@vuepress/bundler-vite"; | ||||
| import { webpackBundler } from "@vuepress/bundler-webpack"; | ||||
| import { UserConfig, defineUserConfig } from "@vuepress/cli"; | ||||
| // import { UserConfig, defineUserConfig } from "@vuepress/cli";
 | ||||
| import { UserConfig, defineUserConfig } from "vuepress/cli"; | ||||
| import { searchPlugin } from "@vuepress/plugin-search"; | ||||
| import markdownItFootnote from "markdown-it-footnote"; | ||||
| import { defaultTheme } from "vuepress"; | ||||
| import * as navbar from "./config/navbar"; | ||||
| import { MermaidPlugin } from "./config/plugins/mermaidPlugin"; | ||||
| import * as sidebar from "./config/sidebar"; | ||||
| import { docsPlugin } from "./theme/index"; | ||||
| import theme from './theme.js' | ||||
| import { registerComponentsPlugin } from '@vuepress/plugin-register-components' | ||||
| import process from 'node:process' | ||||
| // import { getDirname, path } from '@vuepress/utils'
 | ||||
| import { getDirname, path } from 'vuepress/utils' | ||||
| import { MermaidPlugin } from './plugins/mermaid/node/mermaid' | ||||
| 
 | ||||
| const __dirname = getDirname(import.meta.url) | ||||
| console.log('>>> __dirname -> ', __dirname) | ||||
| const isProduction = process.env.NODE_ENV === "production"; | ||||
| const forMainRepo = process.env.XRAY_DOCS_MAIN_REPO === "true"; | ||||
| const useVite = process.env.XRAY_DOCS_USE_VITE === "true"; | ||||
|  | @ -28,6 +32,9 @@ export default defineUserConfig(<UserConfig>{ | |||
|         }, | ||||
|       }, | ||||
|     }), | ||||
|     registerComponentsPlugin({ | ||||
|       componentsDir: path.resolve(__dirname, './theme/components'), | ||||
|     }), | ||||
|   ], | ||||
|   base: forMainRepo ? "/" : "/Xray-docs-next/", | ||||
|   locales: { | ||||
|  | @ -42,103 +49,7 @@ export default defineUserConfig(<UserConfig>{ | |||
|       description: "Official document of Xray", | ||||
|     }, | ||||
|   }, | ||||
|   theme: defaultTheme({ | ||||
|     ...docsPlugin, | ||||
|     smoothScroll: true, | ||||
|     repo: "xtls/xray-core", | ||||
|     docsRepo: "xtls/Xray-docs-next", | ||||
|     docsDir: "docs", | ||||
|     docsBranch: "main", | ||||
|     editLinks: true, | ||||
|     enableToggle: true, | ||||
| 
 | ||||
|     themePlugins: { | ||||
|       git: isProduction, | ||||
|     }, | ||||
|     locales: { | ||||
|       "/": { | ||||
|         navbar: navbar.hans, | ||||
|         repoLabel: "查看源码", | ||||
|         editLinkText: "帮助我们改善此页面!", | ||||
|         tip: "提示", | ||||
|         warning: "注意", | ||||
|         danger: "警告", | ||||
|         lastUpdatedText: "最近更改", | ||||
|         selectLanguageName: "简体中文", | ||||
|         selectLanguageText: "多语言", | ||||
|         selectLanguageAriaLabel: "多语言", | ||||
|         sidebar: { | ||||
|           "/config/": sidebar.getConfigSidebar( | ||||
|             "特性详解", | ||||
|             "基础配置", | ||||
|             "入站代理", | ||||
|             "出站代理", | ||||
|             "底层传输", | ||||
|             "/config/", | ||||
|           ), | ||||
|           "/document/": sidebar.getDocumentSidebar( | ||||
|             "快速入门文档", | ||||
|             "/document/", | ||||
|           ), | ||||
|           "/document/level-0/": sidebar.getDocumentLv0Sidebar( | ||||
|             "小小白白话文", | ||||
|             "/document/level-0/", | ||||
|           ), | ||||
|           "/document/level-1/": sidebar.getDocumentLv1Sidebar( | ||||
|             "入门技巧", | ||||
|             "/document/level-1/", | ||||
|           ), | ||||
|           "/document/level-2/": sidebar.getDocumentLv2Sidebar( | ||||
|             "进阶技巧", | ||||
|             "/document/level-2/", | ||||
|           ), | ||||
|           "/development/": sidebar.getDevelopmentSidebar( | ||||
|             "开发指南", | ||||
|             "协议详解", | ||||
|             "/development/", | ||||
|           ), | ||||
|         }, | ||||
|       }, | ||||
|       "/en/": { | ||||
|         repoLabel: "Source", | ||||
|         editLinkText: "Help us improve this page on GitHub!", | ||||
|         tip: "Tip", | ||||
|         warning: "Warning", | ||||
|         danger: "Danger", | ||||
|         lastUpdatedText: "Last Updated", | ||||
|         selectLanguageName: "English (WIP)", | ||||
|         // TODO: translation
 | ||||
|         sidebar: { | ||||
|           "/en/config/": sidebar.getConfigSidebar( | ||||
|             "Xray Features", | ||||
|             "Config Reference", | ||||
|             "Inbound Protocol", | ||||
|             "Outbound Protocol", | ||||
|             "Stream Transport Protocol", | ||||
|             "/en/config/", | ||||
|           ), | ||||
|           "/en/document/level-0/": sidebar.getDocumentLv0Sidebar( | ||||
|             "Beginner Tutorial", | ||||
|             "/en/document/level-0/", | ||||
|           ), | ||||
|           "/en/document/level-1/": sidebar.getDocumentLv1Sidebar( | ||||
|             "Getting Started Tips", | ||||
|             "/en/document/level-1/", | ||||
|           ), | ||||
|           "/en/document/level-2/": sidebar.getDocumentLv2Sidebar( | ||||
|             "Advanced Documentation", | ||||
|             "/en/document/level-2/", | ||||
|           ), | ||||
|           "/en/development/": sidebar.getDevelopmentSidebar( | ||||
|             "Developer Guide", | ||||
|             "Protocol Details", | ||||
|             "/en/development/", | ||||
|           ), | ||||
|         }, | ||||
|         navbar: navbar.en, | ||||
|       }, | ||||
|     }, | ||||
|   }), | ||||
|   theme, | ||||
|   head: [["link", { rel: "icon", href: `/logo.png` }]], | ||||
|   markdown: { | ||||
|     toc: { | ||||
|  |  | |||
|  | @ -0,0 +1,3 @@ | |||
| // export * from './head'
 | ||||
| export * from './navbar/index.js' | ||||
| export * from './sidebar/index.js' | ||||
|  | @ -1,18 +0,0 @@ | |||
| import { NavbarConfig } from "@vuepress/theme-default"; | ||||
| 
 | ||||
| export const hans: NavbarConfig = [ | ||||
|   { text: "首页", link: "/" }, | ||||
|   { text: "大史记", link: "/about/news.md" }, | ||||
|   { text: "配置指南", link: "/config/" }, | ||||
|   { text: "开发指南", link: "/development/" }, | ||||
|   { text: "使用指南", link: "/document/" }, | ||||
| ]; | ||||
| 
 | ||||
| // TODO: translation
 | ||||
| export const en: NavbarConfig = [ | ||||
|   { text: "Homepage", link: "/en" }, | ||||
|   { text: "Website History", link: "/en/about/news.md" }, | ||||
|   { text: "Config Reference", link: "/en/config/" }, | ||||
|   { text: "Developer Guide", link: "/en/development/" }, | ||||
|   { text: "Quick Start", link: "/en/document/" }, | ||||
| ]; | ||||
|  | @ -0,0 +1,10 @@ | |||
| import { NavbarConfig } from '@vuepress/theme-default' | ||||
| 
 | ||||
| // TODO: translation
 | ||||
| export const navbarEn: NavbarConfig = [ | ||||
|   { text: 'Homepage', link: '/en' }, | ||||
|   { text: 'Website History', link: '/en/about/news.md' }, | ||||
|   { text: 'Config Reference', link: '/en/config/' }, | ||||
|   { text: 'Developer Guide', link: '/en/development/' }, | ||||
|   { text: 'Quick Start', link: '/en/document/' }, | ||||
| ] | ||||
|  | @ -0,0 +1,2 @@ | |||
| export * from './en.js' | ||||
| export * from './zh.js' | ||||
|  | @ -0,0 +1,9 @@ | |||
| import { NavbarConfig } from '@vuepress/theme-default' | ||||
| 
 | ||||
| export const navbarZh: NavbarConfig = [ | ||||
|   { text: '首页', link: '/' }, | ||||
|   { text: '大史记', link: '/about/news.md' }, | ||||
|   { text: '配置指南', link: '/config/' }, | ||||
|   { text: '开发指南', link: '/development/' }, | ||||
|   { text: '使用指南', link: '/document/' }, | ||||
| ] | ||||
|  | @ -1,23 +0,0 @@ | |||
| // Reference: https://github.com/mermaid-js/mermaid
 | ||||
| 
 | ||||
| import { hash } from "@vuepress/utils"; | ||||
| 
 | ||||
| const MermaidPlugin = function (md) { | ||||
|   const fence = md.renderer.rules.fence; | ||||
|   md.renderer.rules.fence = (...args) => { | ||||
|     const [tokens, idx] = args; | ||||
|     const { info } = tokens[idx]; | ||||
|     if (info.trim() === "mermaid") { | ||||
|       const token = tokens[idx]; | ||||
|       const key = `mermaid_${hash(idx)}`; | ||||
|       let { content } = token; | ||||
|       return `<Mermaid identifier="${key}" graph="${encodeURI( | ||||
|         content, | ||||
|       )}"></Mermaid>`;
 | ||||
|     } | ||||
|     const rawCode = fence(...args); | ||||
|     return `${rawCode}`; | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export { MermaidPlugin }; | ||||
|  | @ -1,185 +0,0 @@ | |||
| import { SidebarConfigArray } from "@vuepress/theme-default"; | ||||
| 
 | ||||
| export function getConfigSidebar( | ||||
|   feature: string, | ||||
|   config: string, | ||||
|   inbound: string, | ||||
|   outbound: string, | ||||
|   transport: string, | ||||
|   path: string | ||||
| ): SidebarConfigArray { | ||||
|   return [ | ||||
|     { | ||||
|       text: feature, | ||||
|       children: [ | ||||
|         path + "features/xtls.md", | ||||
|         path + "features/fallback.md", | ||||
|         path + "features/browser_dialer.md", | ||||
|         path + "features/env.md", | ||||
|         path + "features/multiple.md", | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: config, | ||||
|       children: [ | ||||
|         path + "", | ||||
|         path + "log.md", | ||||
|         path + "api.md", | ||||
|         path + "dns.md", | ||||
|         path + "fakedns.md", | ||||
|         path + "inbound.md", | ||||
|         path + "outbound.md", | ||||
|         path + "policy.md", | ||||
|         path + "reverse.md", | ||||
|         path + "routing.md", | ||||
|         path + "stats.md", | ||||
|         path + "transport.md", | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: inbound, | ||||
|       children: [ | ||||
|         path + "inbounds/dokodemo.md", | ||||
|         path + "inbounds/http.md", | ||||
|         path + "inbounds/shadowsocks.md", | ||||
|         path + "inbounds/socks.md", | ||||
|         path + "inbounds/trojan.md", | ||||
|         path + "inbounds/vless.md", | ||||
|         path + "inbounds/vmess.md", | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: outbound, | ||||
|       children: [ | ||||
|         path + "outbounds/blackhole.md", | ||||
|         path + "outbounds/dns.md", | ||||
|         path + "outbounds/freedom.md", | ||||
|         path + "outbounds/http.md", | ||||
|         path + "outbounds/shadowsocks.md", | ||||
|         path + "outbounds/socks.md", | ||||
|         path + "outbounds/trojan.md", | ||||
|         path + "outbounds/vless.md", | ||||
|         path + "outbounds/vmess.md", | ||||
|         path + "outbounds/wireguard.md", | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: transport, | ||||
|       children: [ | ||||
|         path + "transports/grpc.md", | ||||
|         path + "transports/h2.md", | ||||
|         path + "transports/mkcp.md", | ||||
|         path + "transports/quic.md", | ||||
|         path + "transports/tcp.md", | ||||
|         path + "transports/websocket.md", | ||||
|       ], | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| export function getDocumentSidebar( | ||||
|   title: string, | ||||
|   path: string | ||||
| ): SidebarConfigArray { | ||||
|   return [ | ||||
|     { | ||||
|       text: title, | ||||
|       children: [ | ||||
|         path + "install.md", | ||||
|         path + "config.md", | ||||
|         path + "command.md", | ||||
|         path + "document.md", | ||||
|         path + "level-0", | ||||
|         path + "level-1", | ||||
|         path + "level-2", | ||||
|       ], | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| export function getDocumentLv0Sidebar( | ||||
|   title: string, | ||||
|   path: string | ||||
| ): SidebarConfigArray { | ||||
|   return [ | ||||
|     { | ||||
|       text: title, | ||||
|       children: [ | ||||
|         path + "ch01-preface.md", | ||||
|         path + "ch02-preparation.md", | ||||
|         path + "ch03-ssh.md", | ||||
|         path + "ch04-security.md", | ||||
|         path + "ch05-webpage.md", | ||||
|         path + "ch06-certificates.md", | ||||
|         path + "ch07-xray-server.md", | ||||
|         path + "ch08-xray-clients.md", | ||||
|         path + "ch09-appendix.md", | ||||
|       ], | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| export function getDocumentLv1Sidebar( | ||||
|   title: string, | ||||
|   path: string | ||||
| ): SidebarConfigArray { | ||||
|   return [ | ||||
|     { | ||||
|       text: title, | ||||
|       children: [ | ||||
|         path + "fallbacks-lv1.md", | ||||
|         path + "routing-lv1-part1.md", | ||||
|         path + "routing-lv1-part2.md", | ||||
|         path + "work.md", | ||||
|         path + "fallbacks-with-sni.md", | ||||
|       ], | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| export function getDocumentLv2Sidebar( | ||||
|   title: string, | ||||
|   path: string | ||||
| ): SidebarConfigArray { | ||||
|   return [ | ||||
|     { | ||||
|       text: title, | ||||
|       children: [ | ||||
|         path + "transparent_proxy/transparent_proxy.md", | ||||
|         path + "tproxy.md", | ||||
|         path + "tproxy_ipv4_and_ipv6.md", | ||||
|         path + "nginx_or_haproxy_tls_tunnel.md", | ||||
|         path + "iptables_gid.md", | ||||
|         path + "redirect.md", | ||||
|         path + "warp.md", | ||||
|         path + "traffic_stats.md", | ||||
|       ], | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| export function getDevelopmentSidebar( | ||||
|   title: string, | ||||
|   protocols: string, | ||||
|   path: string | ||||
| ): SidebarConfigArray { | ||||
|   return [ | ||||
|     { | ||||
|       text: title, | ||||
|       children: [ | ||||
|         path + "intro/compile.md", | ||||
|         path + "intro/design.md", | ||||
|         path + "intro/guide.md", | ||||
|         { | ||||
|           text: protocols, | ||||
|           children: [ | ||||
|             path + "protocols/vless.md", | ||||
|             path + "protocols/vmess.md", | ||||
|             path + "protocols/muxcool.md", | ||||
|             path + "protocols/mkcp.md", | ||||
|           ], | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
|  | @ -0,0 +1,145 @@ | |||
| import type { SidebarConfig } from '@vuepress/theme-default' | ||||
| 
 | ||||
| export const sidebarEn: SidebarConfig = { | ||||
|   '/en/config/': [ | ||||
|     { | ||||
|       text: 'feature', | ||||
|       children: [ | ||||
|         '/en/config/features/xtls.md', | ||||
|         '/en/config/features/fallback.md', | ||||
|         '/en/config/features/browser_dialer.md', | ||||
|         '/en/config/features/env.md', | ||||
|         '/en/config/features/multiple.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: 'config', | ||||
|       children: [ | ||||
|         '/en/config/README.md', | ||||
|         '/en/config/log.md', | ||||
|         '/en/config/api.md', | ||||
|         '/en/config/dns.md', | ||||
|         '/en/config/fakedns.md', | ||||
|         '/en/config/inbound.md', | ||||
|         '/en/config/outbound.md', | ||||
|         '/en/config/policy.md', | ||||
|         '/en/config/reverse.md', | ||||
|         '/en/config/routing.md', | ||||
|         '/en/config/stats.md', | ||||
|         '/en/config/transport.md', | ||||
|         '/en/config/metrics.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: 'inbound', | ||||
|       children: [ | ||||
|         '/en/config/inbounds/dokodemo.md', | ||||
|         '/en/config/inbounds/http.md', | ||||
|         '/en/config/inbounds/shadowsocks.md', | ||||
|         '/en/config/inbounds/socks.md', | ||||
|         '/en/config/inbounds/trojan.md', | ||||
|         '/en/config/inbounds/vless.md', | ||||
|         '/en/config/inbounds/vmess.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: 'outbound', | ||||
|       children: [ | ||||
|         '/en/config/outbounds/blackhole.md', | ||||
|         '/en/config/outbounds/dns.md', | ||||
|         '/en/config/outbounds/freedom.md', | ||||
|         '/en/config/outbounds/http.md', | ||||
|         '/en/config/outbounds/shadowsocks.md', | ||||
|         '/en/config/outbounds/socks.md', | ||||
|         '/en/config/outbounds/trojan.md', | ||||
|         '/en/config/outbounds/vless.md', | ||||
|         '/en/config/outbounds/vmess.md', | ||||
|         '/en/config/outbounds/wireguard.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: 'transport', | ||||
|       children: [ | ||||
|         '/en/config/transports/domainsocket.md', | ||||
|         '/en/config/transports/grpc.md', | ||||
|         '/en/config/transports/h2.md', | ||||
|         '/en/config/transports/mkcp.md', | ||||
|         '/en/config/transports/quic.md', | ||||
|         '/en/config/transports/tcp.md', | ||||
|         '/en/config/transports/websocket.md', | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
|   '/en/document/': [ | ||||
|     { | ||||
|       text: 'Quick Start', | ||||
|       children: [ | ||||
|         '/en/document/README.md', | ||||
|         '/en/document/install.md', | ||||
|         '/en/document/config.md', | ||||
|         '/en/document/command.md', | ||||
|         '/en/document/document.md', | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       text: 'Beginner Tutorial', | ||||
|       children: [ | ||||
|         '/en/document/level-0/README.md', | ||||
|         '/en/document/level-0/ch01-preface.md', | ||||
|         '/en/document/level-0/ch02-preparation.md', | ||||
|         '/en/document/level-0/ch03-ssh.md', | ||||
|         '/en/document/level-0/ch04-security.md', | ||||
|         '/en/document/level-0/ch05-webpage.md', | ||||
|         '/en/document/level-0/ch06-certificates.md', | ||||
|         '/en/document/level-0/ch07-xray-server.md', | ||||
|         '/en/document/level-0/ch08-xray-clients.md', | ||||
|         '/en/document/level-0/ch09-appendix.md', | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       text: 'Getting Started Tips', | ||||
|       children: [ | ||||
|         '/en/document/level-1/README.md', | ||||
|         '/en/document/level-1/fallbacks-lv1.md', | ||||
|         '/en/document/level-1/routing-lv1-part1.md', | ||||
|         '/en/document/level-1/routing-lv1-part2.md', | ||||
|         '/en/document/level-1/work.md', | ||||
|         '/en/document/level-1/fallbacks-with-sni.md', | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       text: 'Advanced Documentation', | ||||
|       children: [ | ||||
|         '/en/document/level-2/README.md', | ||||
|         '/en/document/level-2/transparent_proxy/transparent_proxy.md', | ||||
|         '/en/document/level-2/tproxy.md', | ||||
|         '/en/document/level-2/tproxy_ipv4_and_ipv6.md', | ||||
|         '/en/document/level-2/nginx_or_haproxy_tls_tunnel.md', | ||||
|         '/en/document/level-2/iptables_gid.md', | ||||
|         '/en/document/level-2/redirect.md', | ||||
|         '/en/document/level-2/warp.md', | ||||
|         '/en/document/level-2/traffic_stats.md', | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   '/en/development/': [ | ||||
|     { | ||||
|       text: 'Developer Guide', | ||||
|       children: [ | ||||
|         '/en/development/README.md', | ||||
|         '/en/development/intro/compile.md', | ||||
|         '/en/development/intro/design.md', | ||||
|         '/en/development/intro/guide.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: 'Protocol Details', | ||||
|       children: [ | ||||
|         '/en/development/protocols/vless.md', | ||||
|         '/en/development/protocols/vmess.md', | ||||
|         '/en/development/protocols/muxcool.md', | ||||
|         '/en/development/protocols/mkcp.md', | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
| } | ||||
|  | @ -0,0 +1,2 @@ | |||
| export * from './en.js' | ||||
| export * from './zh.js' | ||||
|  | @ -0,0 +1,145 @@ | |||
| import type { SidebarConfig } from '@vuepress/theme-default' | ||||
| 
 | ||||
| export const sidebarZh: SidebarConfig = { | ||||
|   '/config/': [ | ||||
|     { | ||||
|       text: '特性详解', | ||||
|       children: [ | ||||
|         '/config/features/xtls.md', | ||||
|         '/config/features/fallback.md', | ||||
|         '/config/features/browser_dialer.md', | ||||
|         '/config/features/env.md', | ||||
|         '/config/features/multiple.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: '基础配置', | ||||
|       children: [ | ||||
|         '/config/README.md', | ||||
|         '/config/log.md', | ||||
|         '/config/api.md', | ||||
|         '/config/dns.md', | ||||
|         '/config/fakedns.md', | ||||
|         '/config/inbound.md', | ||||
|         '/config/outbound.md', | ||||
|         '/config/policy.md', | ||||
|         '/config/reverse.md', | ||||
|         '/config/routing.md', | ||||
|         '/config/stats.md', | ||||
|         '/config/transport.md', | ||||
|         '/config/metrics.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: '入站代理', | ||||
|       children: [ | ||||
|         '/config/inbounds/dokodemo.md', | ||||
|         '/config/inbounds/http.md', | ||||
|         '/config/inbounds/shadowsocks.md', | ||||
|         '/config/inbounds/socks.md', | ||||
|         '/config/inbounds/trojan.md', | ||||
|         '/config/inbounds/vless.md', | ||||
|         '/config/inbounds/vmess.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: '出站代理', | ||||
|       children: [ | ||||
|         '/config/outbounds/blackhole.md', | ||||
|         '/config/outbounds/dns.md', | ||||
|         '/config/outbounds/freedom.md', | ||||
|         '/config/outbounds/http.md', | ||||
|         '/config/outbounds/shadowsocks.md', | ||||
|         '/config/outbounds/socks.md', | ||||
|         '/config/outbounds/trojan.md', | ||||
|         '/config/outbounds/vless.md', | ||||
|         '/config/outbounds/vmess.md', | ||||
|         '/config/outbounds/wireguard.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: '底层传输', | ||||
|       children: [ | ||||
|         '/config/transports/domainsocket.md', | ||||
|         '/config/transports/grpc.md', | ||||
|         '/config/transports/h2.md', | ||||
|         '/config/transports/mkcp.md', | ||||
|         '/config/transports/quic.md', | ||||
|         '/config/transports/tcp.md', | ||||
|         '/config/transports/websocket.md', | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
|   '/document/': [ | ||||
|     { | ||||
|       text: '快速入门文档', | ||||
|       children: [ | ||||
|         '/document/README.md', | ||||
|         '/document/install.md', | ||||
|         '/document/config.md', | ||||
|         '/document/command.md', | ||||
|         '/document/document.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: '小小白白话文', | ||||
|       children: [ | ||||
|         '/document/level-0/README.md', | ||||
|         '/document/level-0/ch01-preface.md', | ||||
|         '/document/level-0/ch02-preparation.md', | ||||
|         '/document/level-0/ch03-ssh.md', | ||||
|         '/document/level-0/ch04-security.md', | ||||
|         '/document/level-0/ch05-webpage.md', | ||||
|         '/document/level-0/ch06-certificates.md', | ||||
|         '/document/level-0/ch07-xray-server.md', | ||||
|         '/document/level-0/ch08-xray-clients.md', | ||||
|         '/document/level-0/ch09-appendix.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: '入门技巧', | ||||
|       children: [ | ||||
|         '/document/level-1/README.md', | ||||
|         '/document/level-1/fallbacks-lv1.md', | ||||
|         '/document/level-1/routing-lv1-part1.md', | ||||
|         '/document/level-1/routing-lv1-part2.md', | ||||
|         '/document/level-1/work.md', | ||||
|         '/document/level-1/fallbacks-with-sni.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: '进阶技巧', | ||||
|       children: [ | ||||
|         '/document/level-2/README.md', | ||||
|         '/document/level-2/transparent_proxy/transparent_proxy.md', | ||||
|         '/document/level-2/tproxy.md', | ||||
|         '/document/level-2/tproxy_ipv4_and_ipv6.md', | ||||
|         '/document/level-2/nginx_or_haproxy_tls_tunnel.md', | ||||
|         '/document/level-2/iptables_gid.md', | ||||
|         '/document/level-2/redirect.md', | ||||
|         '/document/level-2/warp.md', | ||||
|         '/document/level-2/traffic_stats.md', | ||||
|       ], | ||||
|     } | ||||
|   ], | ||||
|   '/development/': [ | ||||
|     { | ||||
|       text: '开发指南', | ||||
|       children: [ | ||||
|         '/development/README.md', | ||||
|         '/development/intro/compile.md', | ||||
|         '/development/intro/design.md', | ||||
|         '/development/intro/guide.md', | ||||
|       ], | ||||
|     }, | ||||
|     { | ||||
|       text: '协议详解', | ||||
|       children: [ | ||||
|         '/development/protocols/vless.md', | ||||
|         '/development/protocols/vmess.md', | ||||
|         '/development/protocols/muxcool.md', | ||||
|         '/development/protocols/mkcp.md', | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
| } | ||||
|  | @ -0,0 +1,9 @@ | |||
| // FIXME: Should correct handle dark selector
 | ||||
| export const getDarkmodeStatus = (): boolean => { | ||||
|   const html = document.documentElement; | ||||
| 
 | ||||
|   return ( | ||||
|     html.classList.contains("dark") || | ||||
|     html.getAttribute("data-theme") === "dark" | ||||
|   ); | ||||
| }; | ||||
|  | @ -0,0 +1,65 @@ | |||
| import type { PluginSimple } from "markdown-it"; | ||||
| import type Renderer from "markdown-it/lib/renderer.js"; | ||||
| 
 | ||||
| const mermaidRenderer: Renderer.RenderRule = (tokens: any, index: any) => | ||||
|   `<Mermaid id="mermaid-${index}" code="${encodeURI( | ||||
|     tokens[index].content, | ||||
|   )}"></Mermaid>`;
 | ||||
| 
 | ||||
| interface MermaidOptions { | ||||
|   content: string; | ||||
|   diagram?: string; | ||||
|   title?: string; | ||||
| } | ||||
| 
 | ||||
| export const getMermaidContent = ({ | ||||
|   diagram = "mermaid", | ||||
|   content, | ||||
|   title = "", | ||||
| }: MermaidOptions): string => `\ | ||||
| ${title | ||||
|     ? `\ | ||||
| --- | ||||
| title: ${title} | ||||
| --- | ||||
| 
 | ||||
| ` | ||||
|     : "" | ||||
|   }\ | ||||
| ${diagram === "mermaid" | ||||
|     ? "" | ||||
|     : `\ | ||||
| ${diagram} | ||||
| ` | ||||
|   }\ | ||||
| ${diagram === "mermaid" || diagram === "sankey-beta" | ||||
|     ? content | ||||
|     : content | ||||
|       .split("\n") | ||||
|       .map((line) => (line ? `  ${line}` : "")) | ||||
|       .join("\n") | ||||
|   }\ | ||||
| `;
 | ||||
| 
 | ||||
| const getMermaid = (options: MermaidOptions, index: number): string => | ||||
|   `<Mermaid id="mermaid-${index}" code="${encodeURI(getMermaidContent(options))}"${options.title ? ` title="${encodeURI(options.title)}"` : ""}></Mermaid>`; | ||||
| 
 | ||||
| export const MermaidPlugin: PluginSimple = (md) => { | ||||
|   // Handle ```mermaid blocks
 | ||||
|   const fence = md.renderer.rules.fence; | ||||
| 
 | ||||
|   md.renderer.rules.fence = (...args): string => { | ||||
|     const [tokens, index] = args; | ||||
|     const { content, info } = tokens[index]; | ||||
| 
 | ||||
|     const fenceInfo = info.trim(); | ||||
| 
 | ||||
|     if (fenceInfo === "mermaid") return getMermaid({ content }, index); | ||||
| 
 | ||||
|     const [name, ...rest] = fenceInfo.split(" "); | ||||
| 
 | ||||
|     return fence!(...args); | ||||
|   }; | ||||
| 
 | ||||
|   md.renderer.rules["mermaid"] = mermaidRenderer; | ||||
| }; | ||||
|  | @ -0,0 +1,74 @@ | |||
| import { defaultTheme } from '@vuepress/theme-default' | ||||
| // import { path, getDirname } from '@vuepress/utils'
 | ||||
| import { path, getDirname } from 'vuepress/utils' | ||||
| import process from 'node:process' | ||||
| import { navbarEn, navbarZh, sidebarEn, sidebarZh } from './config/index.js' | ||||
| 
 | ||||
| let __dirname = getDirname(import.meta.url) | ||||
| const isProduction = process.env.NODE_ENV === 'production' | ||||
| 
 | ||||
| export default defaultTheme({ | ||||
|   name: 'vuepress-theme-xray', | ||||
|   smoothScroll: true, | ||||
|   repo: 'xtls/xray-core', | ||||
|   docsDir: 'docs', | ||||
|   locales: { | ||||
|     '/': { | ||||
|       navbar: navbarZh, | ||||
|       sidebar: sidebarZh, | ||||
|       repoLabel: '查看源码', | ||||
|       editLinkText: '帮助我们改善此页面!', | ||||
|       tip: '提示', | ||||
|       warning: '注意', | ||||
|       danger: '警告', | ||||
|       lastUpdatedText: '最近更改', | ||||
|       selectLanguageName: '简体中文', | ||||
|       selectLanguageText: '多语言', | ||||
|       selectLanguageAriaLabel: '多语言', | ||||
|       docsDir: 'docs', | ||||
|       backToHome: 'back to home', | ||||
|       openInNewWindow: 'open in new tag', | ||||
|       toggleColorMode: 'toggle color mode', | ||||
|       toggleSidebar: 'toggle side bar', | ||||
|     }, | ||||
|     '/en/': { | ||||
|       // TODO: translation
 | ||||
|       sidebar: sidebarEn, | ||||
|       navbar: navbarEn, | ||||
|       selectLanguageName: 'English (WIP)', | ||||
|       selectLanguageText: 'Multiple language', | ||||
|       selectLanguageAriaLabel: 'Multiple language', | ||||
|       editLinkText: 'Help us improve this page on GitHub!', | ||||
|       lastUpdatedText: 'Last Updated', | ||||
|       contributorsText: 'contributors', | ||||
|       // repoLabel: 'Source',
 | ||||
|       tip: 'Tip', | ||||
|       warning: 'Warning', | ||||
|       danger: 'Danger', | ||||
| 
 | ||||
|       // 404 page
 | ||||
|       notFound: [ | ||||
|         '这里什么都没有', | ||||
|         '我们怎么到这来了?', | ||||
|         '这是一个 404 页面', | ||||
|         '看起来我们进入了错误的链接', | ||||
|       ], | ||||
|       backToHome: 'back to home', | ||||
|       openInNewWindow: 'open in new tag', | ||||
|       toggleColorMode: 'toggle color mode', | ||||
|       toggleSidebar: 'toggle side bar', | ||||
|     }, | ||||
|     docsRepo: 'xtls/Xray-docs-next', | ||||
|     docsBranch: 'main', | ||||
|     editLinks: true, | ||||
|     enableToggle: true, | ||||
|     smoothScroll: true, | ||||
|     // logo: '/logo.png',
 | ||||
| 
 | ||||
|     // sidebar: 'auto',
 | ||||
| 
 | ||||
|     themePlugins: { | ||||
|       git: isProduction, | ||||
|     }, | ||||
|   }, | ||||
| }) | ||||
|  | @ -1,4 +1,5 @@ | |||
| import { defineClientAppEnhance } from "@vuepress/client"; | ||||
| // import { defineClientAppEnhance } from "@vuepress/client";
 | ||||
| import { defineClientAppEnhance } from "vuepress/client"; | ||||
| import Tab from "./components/Tab.vue"; | ||||
| import Tabs from "./components/Tabs.vue"; | ||||
| import Mermaid from "./components/Mermaid.vue"; | ||||
|  |  | |||
|  | @ -3,60 +3,81 @@ | |||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { useMutationObserver } from "@vueuse/core"; | ||||
| import { | ||||
|   computed, | ||||
|   defineComponent, | ||||
|   h, | ||||
|   onMounted, | ||||
|   nextTick, | ||||
|   toRef, | ||||
|   ref, | ||||
|   shallowRef, | ||||
|   watch, | ||||
|   reactive, | ||||
|   nextTick, | ||||
|   toRef | ||||
| } from "vue"; | ||||
| import { useDarkMode } from "@vuepress/theme-default/lib/client"; | ||||
| 
 | ||||
| import { getDarkmodeStatus } from "../../plugins/mermaid/helpers/darkmode.js"; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|   name: "Mermaid", | ||||
|   props: { | ||||
|     identifier: String, | ||||
|     graph: String, | ||||
|   }, | ||||
|   setup(props) { | ||||
|     const dark = useDarkMode(); | ||||
|     const chartID = toRef(props, "identifier"); | ||||
|     const rawGraph = toRef(props, "graph"); | ||||
|     const html = reactive({ innerHtml: "" }); | ||||
|     onMounted(() => { | ||||
|       nextTick(async function () { | ||||
|         const mermaid = await import("mermaid"); | ||||
|         mermaid.default.initialize({ | ||||
|           startOnLoad: false, | ||||
|           theme: dark.value ? "dark" : "default", | ||||
|         }); | ||||
|         mermaid.default | ||||
|           .render(chartID.value!, decodeURI(rawGraph.value!)) | ||||
|           .then(({ svg, bindFunctions }) => { | ||||
|             html.innerHtml = svg; | ||||
|           }); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     watch(dark, async () => { | ||||
|   props: { | ||||
|     id: { type: String, required: true }, | ||||
|     code: { type: String, required: true }, | ||||
|   }, | ||||
| 
 | ||||
|   setup(props) { | ||||
|     const html = reactive({ innerHtml: "" }); | ||||
| 
 | ||||
|     const chartID = toRef(props, "id"); | ||||
|     const rawGraph = toRef(props, "code"); | ||||
| 
 | ||||
|     const isDarkmode = ref(false); | ||||
| 
 | ||||
|     const renderMermaid = async (): Promise<void> => { | ||||
|       const mermaid = await import("mermaid"); | ||||
| 
 | ||||
|       mermaid.default.initialize({ | ||||
|         theme: isDarkmode.value ? "dark" : "default", | ||||
|         startOnLoad: false, | ||||
|         theme: dark.value ? "dark" : "default", | ||||
|       }); | ||||
|       mermaid.default | ||||
|         .render(chartID.value!, decodeURI(rawGraph.value!)) | ||||
|         .then(({ svg, bindFunctions }) => { | ||||
|           html.innerHtml = svg; | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|       mermaid.default.render(chartID.value!, decodeURI(rawGraph.value!)).then(({ svg, bindFunctions }) => { | ||||
|         html.innerHtml = svg; | ||||
|       }); | ||||
|     }; | ||||
| 
 | ||||
|     onMounted(() => { | ||||
|       isDarkmode.value = getDarkmodeStatus() | ||||
|       nextTick(renderMermaid) | ||||
|     }) | ||||
| 
 | ||||
|     // watch darkmode change | ||||
|     if (typeof document !== 'undefined') { | ||||
|       useMutationObserver( | ||||
|         document.documentElement, | ||||
|         () => { | ||||
|           isDarkmode.value = getDarkmodeStatus(); | ||||
|         }, | ||||
|         { | ||||
|           attributeFilter: ["class", "data-theme"], | ||||
|           attributes: true, | ||||
|         }, | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     watch(isDarkmode, () => renderMermaid()); | ||||
| 
 | ||||
|     return { | ||||
|       tag: chartID, | ||||
|       payload: html, | ||||
|     }; | ||||
|       payload: html | ||||
|     } | ||||
| 
 | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style scoped></style> | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| import { Theme } from "@vuepress/core"; | ||||
| import { path } from "@vuepress/utils"; | ||||
| // import { Theme } from "@vuepress/core";
 | ||||
| import { Theme } from "vuepress/core"; | ||||
| // import { path } from "@vuepress/utils";
 | ||||
| import { path } from "vuepress/utils"; | ||||
| import { defaultTheme } from "vuepress"; | ||||
| 
 | ||||
| export const docsPlugin: Theme = (options, app) => { | ||||
|  |  | |||
							
								
								
									
										37
									
								
								package.json
								
								
								
								
							
							
						
						
									
										37
									
								
								package.json
								
								
								
								
							|  | @ -8,44 +8,39 @@ | |||
|   "devDependencies": { | ||||
|     "@types/bootstrap": "^5.2.0", | ||||
|     "@types/jquery": "^3.5.14", | ||||
|     "@types/mermaid": "^9.2.0", | ||||
|     "@types/node": "^20.11.0", | ||||
|     "@vuepress/bundler-vite": "^2.0.0-rc.0", | ||||
|     "@vuepress/bundler-webpack": "2.0.0-rc.0", | ||||
|     "@vuepress/plugin-back-to-top": "^2.0.0-rc.0", | ||||
|     "@vuepress/plugin-debug": "^2.0.0-beta.33", | ||||
|     "@vuepress/plugin-search": "^2.0.0-rc.0", | ||||
|     "typescript": "^5.2.2", | ||||
|     "@vuepress/bundler-vite": "2.0.0-rc.2", | ||||
|     "@vuepress/bundler-webpack": "2.0.0-rc.2", | ||||
|     "@vuepress/plugin-back-to-top": "^2.0.0-rc.3", | ||||
|     "@vuepress/plugin-search": "2.0.0-rc.3", | ||||
|     "postcss-loader": "^8.0.0", | ||||
|     "prettier": "^3.2.2", | ||||
|     "sass": "^1.51.0", | ||||
|     "sass-loader": "^13.3.2", | ||||
|     "typescript": "^5.2.2", | ||||
|     "vue-property-decorator": "^9.1.2", | ||||
|     "vuepress": "^2.0.0-rc.0" | ||||
|     "vuepress": "2.0.0-rc.2" | ||||
|   }, | ||||
|   "packageManager": "pnpm@8.10.5", | ||||
|   "scripts": { | ||||
|     "docs:dev": "vuepress dev docs", | ||||
|     "docs:build": "vuepress build docs", | ||||
|     "docs:dev": "vuepress dev docs --clean-temp --clean-cache", | ||||
|     "docs:build": "vuepress build docs --clean-temp --clean-cache", | ||||
|     "docs:serve": "anywhere -s -h localhost -d docs/.vuepress/dist", | ||||
|     "lint": "prettier --write ." | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@popperjs/core": "^2.11.5", | ||||
|     "@vuepress/plugin-google-analytics": "2.0.0-rc.3", | ||||
|     "@vuepress/plugin-register-components": "2.0.0-rc.3", | ||||
|     "@vuepress/plugin-shiki": "2.0.0-rc.3", | ||||
|     "@vuepress/theme-default": "2.0.0-rc.3", | ||||
|     "@vueuse/core": "^10.7.2", | ||||
|     "anywhere": "^1.6.0", | ||||
|     "bootstrap": "^5.2.0", | ||||
|     "esbuild": "^0.19.0", | ||||
|     "jquery": "^3.6.0", | ||||
|     "markdown-it-footnote": "^4.0.0", | ||||
|     "mermaid": "^10.7.0", | ||||
|     "vuepress-plugin-mermaidjs": "^2.0.0-beta.2", | ||||
|     "@vuepress/cli": "2.0.0-rc.0", | ||||
|     "@vuepress/client": "2.0.0-rc.0", | ||||
|     "@vuepress/core": "2.0.0-rc.0", | ||||
|     "@vuepress/plugin-google-analytics": "2.0.0-rc.0", | ||||
|     "@vuepress/plugin-register-components": "2.0.0-rc.0", | ||||
|     "@vuepress/plugin-shiki": "2.0.0-rc.0", | ||||
|     "@vuepress/theme-default": "2.0.0-rc.0", | ||||
|     "@vuepress/utils": "2.0.0-rc.0", | ||||
|     "anywhere": "^1.6.0", | ||||
|     "vue": "^3.4.15" | ||||
|     "vue": "3.3.13" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										2321
									
								
								pnpm-lock.yaml
								
								
								
								
							
							
						
						
									
										2321
									
								
								pnpm-lock.yaml
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,8 +1,20 @@ | |||
| { | ||||
|   "compilerOptions": { | ||||
|     "module": "commonjs", | ||||
|     "target": "esnext", | ||||
|     "sourceMap": true | ||||
|     "module": "ESNext", | ||||
|     "target": "ES2022", | ||||
|     "lib": [ | ||||
|       "DOM", | ||||
|       "ES2022" | ||||
|     ], | ||||
|     "sourceMap": false, | ||||
|     "strict": true, | ||||
|     "moduleResolution": "Bundler", | ||||
|   }, | ||||
|   "exclude": ["node_modules"] | ||||
| } | ||||
|   "include": [ | ||||
|     "./docs/.vuepress/**/*.ts", | ||||
|     "./docs/.vuepress/**/*.vue" | ||||
|   ], | ||||
|   "exclude": [ | ||||
|     "node_modules" | ||||
|   ] | ||||
| } | ||||
|  | @ -0,0 +1,4 @@ | |||
| import { splitVendorChunkPlugin } from 'vite' | ||||
| export default defineConfig({ | ||||
|   plugins: [splitVendorChunkPlugin()], | ||||
| }) | ||||
		Loading…
	
		Reference in New Issue
	
	 Aoleou
						Aoleou