UNPKG

vuepress-theme-hope

Version:

A light vuepress theme with tons of features

1,344 lines (1,322 loc) 127 kB
import { i as getTag, n as getCategory, r as getStringArray, t as getAuthor } from "../infoGetter-CiYuSeA7.js"; import { createRequire } from "node:module"; import { TemplateRendererOutlet, colors, fs, getDirname, logger, path, sanitizeFileName } from "vuepress/utils"; import { Logger, addViteConfig, addViteOptimizeDepsExclude, addViteOptimizeDepsInclude, addViteSsrNoExternal, chainWebpack, dateSorter, deepAssign, endsWith, ensureEndingSlash, entries, fromEntries, getBundlerName, getDate, getFullLocaleConfig, getModulePath, isArray, isFunction, isLinkHttp, isPlainObject, isString, keys, removeEndingSlash, removeLeadingSlash, startsWith, values } from "@vuepress/helper"; import { createConverter } from "vuepress-shared"; import { watch } from "chokidar"; import { hashSync } from "bcrypt-ts/node"; import { backToTopPlugin } from "@vuepress/plugin-back-to-top"; import { copyCodePlugin } from "@vuepress/plugin-copy-code"; import { iconPlugin } from "@vuepress/plugin-icon"; import { linksCheckPlugin } from "@vuepress/plugin-links-check"; import { markdownChartPlugin } from "@vuepress/plugin-markdown-chart"; import { markdownExtPlugin } from "@vuepress/plugin-markdown-ext"; import { markdownHintPlugin } from "@vuepress/plugin-markdown-hint"; import { markdownIncludePlugin } from "@vuepress/plugin-markdown-include"; import { markdownMathPlugin } from "@vuepress/plugin-markdown-math"; import { markdownPreviewPlugin } from "@vuepress/plugin-markdown-preview"; import { markdownTabPlugin } from "@vuepress/plugin-markdown-tab"; import { nprogressPlugin } from "@vuepress/plugin-nprogress"; import { photoSwipePlugin } from "@vuepress/plugin-photo-swipe"; import { themeDataPlugin } from "@vuepress/plugin-theme-data"; import { activeHeaderLinksPlugin } from "@vuepress/plugin-active-header-links"; import { blogPlugin } from "@vuepress/plugin-blog"; import { catalogPlugin } from "@vuepress/plugin-catalog"; import { commentPlugin } from "@vuepress/plugin-comment"; import { componentsPlugin } from "vuepress-plugin-components"; import { copyrightPlugin } from "@vuepress/plugin-copyright"; import { markdownImagePlugin } from "@vuepress/plugin-markdown-image"; import { markdownStylizePlugin } from "@vuepress/plugin-markdown-stylize"; import { mdEnhancePlugin } from "vuepress-plugin-md-enhance"; import { noticePlugin } from "@vuepress/plugin-notice"; import { redirectPlugin } from "@vuepress/plugin-redirect"; import { rtlPlugin } from "@vuepress/plugin-rtl"; import { seoPlugin } from "@vuepress/plugin-seo"; import { sitemapPlugin } from "@vuepress/plugin-sitemap"; import { shikiPlugin } from "@vuepress/plugin-shiki"; import { useReadingTimePlugin } from "@vuepress/plugin-reading-time"; import { useSassPalettePlugin } from "@vuepress/plugin-sass-palette"; import { gitPlugin } from "@vuepress/plugin-git"; //#region src/node/compact/checkLegacyStyle.ts /** * @deprecated You should use scss style files in v2 and avoid using it * @param app - VuePress app instance */ const checkLegacyStyle = (app) => { if (fs.existsSync(app.dir.source(".vuepress/styles/index.styl")) && !fs.existsSync(app.dir.source(".vuepress/styles/index.scss"))) logger.error(`V2 style switched to scss instead of stylus, so you should remove ${colors.magenta("index.styl")} and create ${colors.magenta("index.scss")} under ${colors.cyan(".vuepress/styles.")}`); if (fs.existsSync(app.dir.source(".vuepress/styles/palette.styl")) && !fs.existsSync(app.dir.source(".vuepress/styles/palette.scss")) && !fs.existsSync(app.dir.source(".vuepress/styles/config.scss"))) logger.error(`V2 style switched to scss instead of stylus, so you should remove ${colors.magenta("palette.styl")} and create ${colors.magenta("config.scss")} / ${colors.magenta("palette.scss")} under ${colors.cyan(".vuepress/styles.")}.`); }; //#endregion //#region package.json var version = "2.0.0-rc.107"; //#endregion //#region src/node/utils.ts const __dirname = getDirname(import.meta.url); const logger$1 = new Logger("vuepress-theme-hope"); const BUNDLE_FOLDER = removeEndingSlash(path.resolve(__dirname, "../bundle")); const CLIENT_FOLDER = removeEndingSlash(path.resolve(__dirname, "../client")); const TEMPLATE_FOLDER = removeEndingSlash(path.resolve(__dirname, "../../templates")); const VERSION = version; //#endregion //#region src/node/compact/convertFrontmatter.ts const DEPRECATED_FRONTMATTER_OPTIONS = [ ["authors", "author"], ["time", "date"], ["visitor", "pageview"], ["copyrightText", "copyright"], ["anchorDisplay", "toc"], ["updateTime", "lastUpdated"], ["contributor", "contributors"], ["editLinks", "editLink"] ]; const DEPRECATED_HOME_FRONTMATTER_OPTIONS = [["darkHeroImage", "heroImageDark"], ["action", "actions"]]; const DROPPED_FRONTMATTER_OPTIONS = [ ["metaTitle", "Please use custom resolver to set metaTitle."], ["mediaLink", "Social media links are no longer displayed in footer."], ["password", "Simple password protection is no longer supported."], ["search", "Search plugin no longer support this option."] ]; /** * @deprecated You should use V2 standard frontmatter and avoid using it * @param frontmatter - Page frontmatter * @param filePathRelative - Page file path relative to source directory * @returns Converted frontmatter */ const convertFrontmatter = (frontmatter, filePathRelative) => { const { deprecatedLogger, droppedLogger } = createConverter("frontmatter"); DEPRECATED_FRONTMATTER_OPTIONS.forEach(([oldOption, newOption]) => { deprecatedLogger({ options: frontmatter, old: oldOption, new: newOption, scope: filePathRelative ? `${filePathRelative} frontmatter` : "" }); }); DROPPED_FRONTMATTER_OPTIONS.forEach(([old, msg]) => { droppedLogger({ options: frontmatter, old, scope: `${filePathRelative ? `${filePathRelative} ` : ""}${msg}` }); }); if ("meta" in frontmatter) { logger$1.warn(`${colors.magenta("meta")} in frontmatter is deprecated in V2, please use ${colors.magenta("head")} instead.${filePathRelative ? `Found in ${filePathRelative}` : ""}`); frontmatter.head = [...frontmatter.head ?? [], ...frontmatter.meta.map((item) => ["meta", item])]; delete frontmatter.meta; } if ("canonicalUrl" in frontmatter && isString(frontmatter.canonicalUrl)) { logger$1.warn(`${colors.magenta("canonicalUrl")} in frontmatter is deprecated, please use ${colors.magenta("head")} instead.${filePathRelative ? `Found in ${filePathRelative}` : ""}`); frontmatter.head = [...frontmatter.head ?? [], ["link", { rel: "canonical", href: frontmatter.canonicalUrl }]]; delete frontmatter.canonicalUrl; } if (frontmatter.home === true) { if (frontmatter.layout === "BlogHome") { logger$1.warn(`${colors.magenta("layout: BlogHome")} in frontmatter is deprecated, please use ${colors.magenta("layout: Blog")} instead.${filePathRelative ? `Found in ${filePathRelative}` : ""}`); frontmatter.layout = "Blog"; } if (!("layout" in frontmatter)) DEPRECATED_HOME_FRONTMATTER_OPTIONS.forEach(([oldOption, newOption]) => { deprecatedLogger({ options: frontmatter, old: oldOption, new: newOption, scope: filePathRelative }); }); } if (frontmatter.layout === "SlidePage") { logger$1.warn(`${colors.magenta("layout: SlidePage")} in frontmatter is deprecated, please use ${colors.magenta("layout: Slides")} instead.${filePathRelative ? `Found in ${filePathRelative}` : ""}`); frontmatter.layout = "Slides"; } if (typeof frontmatter.sidebarDepth === "number") { logger$1.warn(`${colors.magenta("sidebarDepth")} in frontmatter is deprecated, please use ${colors.magenta("toc.levels")} instead.${filePathRelative ? `Found in ${filePathRelative}` : ""}`); if (frontmatter.toc !== false) frontmatter.toc = { levels: [2, frontmatter.sidebarDepth + 2] }; } if (typeof frontmatter.headerDepth === "number") { logger$1.warn(`${colors.magenta("headerDepth")} in frontmatter is deprecated, please use ${colors.magenta("toc.levels")} instead.${filePathRelative ? `Found in ${filePathRelative}` : ""}`); if (frontmatter.toc !== false) frontmatter.toc = { levels: [2, frontmatter.headerDepth + 2] }; } return frontmatter; }; //#endregion //#region src/node/compact/convertNavbarOptions.ts const { deprecatedLogger: deprecatedLogger$1 } = createConverter("theme navbar"); const handleNavbarOptions = (config, localePath) => config.map((item) => { if (isString(item)) return item; if (isPlainObject(item)) { deprecatedLogger$1({ options: item, old: "items", new: "children", scope: localePath }); if ("children" in item && isArray(item.children)) handleNavbarOptions(item.children, localePath); return item; } return null; }).filter((item) => item != null); /** * @deprecated You should use V2 standard navbar config and avoid using it * @param config - Legacy navbar config * @param localePath - Current locale path, used for logger * @returns Converted navbar config or false if the config is invalid */ const convertNavbarOptions = (config, localePath = "") => { if (config === false) return false; if (isArray(config)) return handleNavbarOptions(config, localePath); logger$1.error(`${colors.magenta("navbar")} config should be an array`); return false; }; /** * @deprecated You should use V2 standard navbar config and avoid using it * @param options - Legacy navbar layout options */ const convertNavbarLayoutOptions = (options) => { if (isPlainObject(options.navbarLayout)) { if ("left" in options.navbarLayout) { logger$1.warn(`To have better meaning under RTL layout, ${colors.magenta("navbarLayout.left")}" option is deprecated, please use ${colors.magenta("navbarLayout.start")} instead`); options.navbarLayout.start = options.navbarLayout.left; } if ("right" in options.navbarLayout) { logger$1.warn(`To have better meaning under RTL layout, ${colors.magenta("navbarLayout.right")}" option is deprecated, please use ${colors.magenta("navbarLayout.end")} instead`); options.navbarLayout.end = options.navbarLayout.right; } } }; //#endregion //#region src/node/compact/convertSidebarOptions.ts const { deprecatedLogger, droppedLogger } = createConverter("theme sidebar"); const handleArraySidebarOptions = (config, localePath) => config.map((item) => { if (isString(item)) return item; if (isPlainObject(item)) { [ ["title", "text"], ["path", "link"], ["collapsable", "collapsible"] ].forEach(([oldOption, newOption]) => { deprecatedLogger({ options: item, old: oldOption, new: newOption, scope: localePath }); }); droppedLogger({ options: item, old: "sidebarDepth", scope: localePath }); if ("children" in item && isArray(item.children)) handleArraySidebarOptions(item.children, localePath); return item; } return null; }).filter((item) => item != null); /** * @deprecated You should use V2 standard sidebar config and avoid using it * @param config - Original sidebar config * @param localePath - Current locale path, used for logger * @returns Converted sidebar config */ const convertSidebarOptions = (config, localePath = "") => { if (config === false || config === "structure") return config; if (isArray(config)) return handleArraySidebarOptions(config, localePath); if (isPlainObject(config)) return fromEntries(entries(config).map(([key, value]) => { if (isArray(value)) return [key, handleArraySidebarOptions(value, `${localePath} > ${key}`)]; if (value === "structure" || value === false) return [key, value]; logger$1.error("\"sidebar\" value should be an array, \"structure\" or false when setting as an object"); return [key, false]; })); logger$1.error(`${colors.magenta("sidebar")} config should be: an array, an object, "structure" or false`); return false; }; //#endregion //#region src/node/compact/convertThemeOptions.ts const DEPRECATED_THEME_OPTIONS = [ ["hideSiteNameonMobile", "hideSiteNameOnMobile"], ["fullScreen", "fullscreen"], ["wideBreakPoint", "pcBreakPoint"] ]; /** * @deprecated You should use V2 standard options and avoid using it * @param options - Theme options * @param plugins - Theme plugins options * @param localePath - Locale path */ const convertBlogOptions = (options, plugins, localePath) => { if (isPlainObject(options.blog)) { const blogOptions = options.blog; if ("links" in blogOptions) { logger$1.warn(`${colors.magenta("blog.links")} options is deprecated, please use ${colors.magenta("blog.medias")} instead${localePath ? ` , found in locale path ${localePath}` : ""}.`); blogOptions.medias = blogOptions.links; delete blogOptions.links; } if ("perPage" in blogOptions) { logger$1.warn(`${colors.magenta("blog.perPage")} options is deprecated, please use ${colors.magenta("blog.articlePerPage")} instead${localePath ? ` , found in locale path ${localePath}` : ""}.`); blogOptions.articlePerPage = blogOptions.perPage; delete blogOptions.perPage; } if ("autoExcerpt" in blogOptions) { logger$1.error(`${colors.magenta("blog.autoExcerpt")} options is no longer supported, please use ${colors.magenta("plugins.blog.excerptLength")} instead${localePath ? ` , found in locale path ${localePath}` : ""}.`); delete blogOptions.autoExcerpt; } if (!plugins.blog) logger$1.warn(`Blog feature is tree-shakable in v2, you should set ${colors.magenta("plugins.blog: true")} in theme options to enable it.`); } }; /** * @deprecated You should use V2 standard options and avoid using it * @param themeLocaleOptions - Theme locale options * @param localePath - Locale path */ const convertFooterOptions = (themeLocaleOptions, localePath) => { if (isPlainObject(themeLocaleOptions.footer)) { const { footer } = themeLocaleOptions; if ("copyright" in footer) { logger$1.warn(`${colors.magenta("footer.copyright")} options is deprecated, please use ${colors.magenta("copyright")} instead${localePath ? ` , found in locale path ${localePath}` : ""}.`); themeLocaleOptions.copyright = footer.copyright; } if ("display" in footer) { logger$1.warn(`${colors.magenta("footer.display")} options is deprecated, please use ${colors.magenta("displayFooter")} instead${localePath ? ` , found in locale path ${localePath}` : ""}.`); themeLocaleOptions.displayFooter = footer.display; } if ("content" in footer) { logger$1.warn(`${colors.magenta("footer.content")} options is deprecated, please use ${colors.magenta("footer")} instead${localePath ? ` , found in locale path ${localePath}` : ""}.`); themeLocaleOptions.footer = footer.content; } else delete themeLocaleOptions.footer; } }; /** * @deprecated You should use V2 standard options and avoid using it * @param themeOptions - Theme options */ const covertPluginOptions = (themeOptions) => { const { deprecatedLogger } = createConverter("theme plugin options"); const markdownOptions = themeOptions.markdown ??= {}; const pluginOptions = themeOptions.plugins; if (isArray(pluginOptions.components)) { logger$1.warn(`${colors.magenta("plugins.components")} no longer accepts array, please set it to ${colors.magenta("plugin.components.components")} instead.`); pluginOptions.components = { components: pluginOptions.components }; } if (pluginOptions.linksCheck) deprecatedLogger({ options: themeOptions, old: "plugins.linksCheck", new: "markdown.linksCheck" }); if (isPlainObject(pluginOptions.mdEnhance)) { const { mdEnhance: mdEnhanceOptions } = pluginOptions; if ("alert" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.alert", new: "markdown.alert" }); if ("hint" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.hint", new: "markdown.hint" }); if ("figure" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.figure", new: "markdown.figure" }); if ("imgLazyload" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.imgLazyload", new: "markdown.imgLazyload" }); if ("imgSize" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.imgSize", new: "markdown.imgSize" }); if ("imgSize" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.obsidianImgSize", new: "markdown.obsidianImgSize" }); if ("imgMark" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.imgMark", new: "markdown.imgMark" }); if ("katex" in mdEnhanceOptions) { logger$1.warn(`${colors.magenta("plugins.mdEnhance.katex")} is deprecated, you should use ${colors.magenta("markdown.math")} instead.`); pluginOptions.markdownMath = { type: "katex", ...isPlainObject(mdEnhanceOptions.katex) ? mdEnhanceOptions.katex : {} }; } if ("mathjax" in mdEnhanceOptions) { logger$1.warn(`${colors.magenta("plugins.mdEnhance.mathjax")} is deprecated, you should use ${colors.magenta("markdown.math")} instead.`); pluginOptions.markdownMath = { type: "mathjax", ...isPlainObject(mdEnhanceOptions.mathjax) ? mdEnhanceOptions.mathjax : {} }; } if ("codetabs" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.codetabs", new: "markdown.codeTabs" }); if ("tabs" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.tabs", new: "markdown.tabs" }); if ("gfm" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.gfm", new: "markdown.gfm" }); if ("footnote" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.footnote", new: "markdown.footnote" }); if ("tasklist" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.tasklist", new: "markdown.tasklist" }); if ("breaks" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.breaks", new: "markdown.breaks" }); if ("linkify" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.linkify", new: "markdown.linkify" }); if ("component" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.component", new: "markdown.component" }); if ("vPre" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.vPre", new: "markdown.vPre" }); if ("include" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.include", new: "markdown.include" }); if ("align" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.align", new: "markdown.align" }); if ("attrs" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.attrs", new: "markdown.attrs" }); if ("mark" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.mark", new: "markdown.mark" }); if ("spoiler" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.spoiler", new: "markdown.spoiler" }); if ("sup" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.sup", new: "markdown.sup" }); if ("sub" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.sub", new: "markdown.sub" }); if ("stylize" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.stylize", new: "markdown.stylize" }); if ("revealJs" in mdEnhanceOptions) { logger$1.warn(`${colors.magenta("plugins.mdEnhance.revealJs")} is deprecated, you should install ${colors.cyan("@vuepress/plugin-revealjs")} and use ${colors.magenta("markdown.revealjs")} instead.`); markdownOptions.revealjs = true; } if ("chart" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.chart", new: "markdown.chartjs" }); if ("echarts" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.echarts", new: "markdown.echarts" }); if ("flowchart" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.flowchart", new: "markdown.flowchart" }); if ("mermaid" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.mermaid", new: "markdown.mermaid" }); if ("markmap" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.markmap", new: "markdown.markmap" }); if ("plantuml" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.plantuml", new: "markdown.plantuml" }); if ("demo" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.demo", new: "markdown.demo" }); if ("vuePlayground" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.vuePlayground", new: "markdown.vuePlayground" }); if ("kotlinPlayground" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.kotlinPlayground", new: "markdown.kotlinPlayground" }); if ("sandpack" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.sandpack", new: "markdown.sandpack" }); if ("playground" in mdEnhanceOptions) deprecatedLogger({ options: themeOptions, old: "plugins.mdEnhance.playground", new: "markdown.playground" }); delete pluginOptions.mdEnhance; } if ("markdownHint" in pluginOptions) { logger$1.warn(`${colors.magenta("plugins.markdownHint")} is deprecated, you should use ${colors.magenta("markdown.alert")} and ${colors.magenta("markdown.hint")} instead.`); if (isPlainObject(pluginOptions.markdownHint)) { const markdownHint = pluginOptions.markdownHint; if ("alert" in markdownHint) deprecatedLogger({ options: themeOptions, old: "plugins.markdownHint.alert", new: "markdown.alert" }); if ("hint" in markdownHint) deprecatedLogger({ options: themeOptions, old: "plugins.markdownHint.hint", new: "markdown.hint" }); } else if (pluginOptions.markdownHint === false) markdownOptions.hint = false; delete pluginOptions.markdownHint; } if (pluginOptions.markdownImg) { logger$1.warn(`${colors.magenta("plugins.markdownImg")} is deprecated, you should use ${colors.magenta("markdown.figure")} ${colors.magenta("markdown.imgLazyload")} ${colors.magenta("markdown.imgMark")} ${colors.magenta("markdown.imgSize")} and ${colors.magenta("markdown.obsidianImgSize")} instead.`); if (isPlainObject(pluginOptions.markdownImg)) { deprecatedLogger({ options: themeOptions, old: "plugins.markdownImg.figure", new: "markdown.figure" }); deprecatedLogger({ options: themeOptions, old: "plugins.markdownImg.lazyload", new: "markdown.imgLazyload" }); deprecatedLogger({ options: themeOptions, old: "plugins.markdownImg.mark", new: "markdown.imgMark" }); deprecatedLogger({ options: themeOptions, old: "plugins.markdownImg.size", new: "markdown.imgSize" }); deprecatedLogger({ options: themeOptions, old: "plugins.markdownImg.obsidian", new: "markdown.obsidianImgSize" }); } else if (pluginOptions.markdownImg === true) { markdownOptions.figure = true; markdownOptions.imgLazyload = true; } delete pluginOptions.markdownImg; } if (pluginOptions.markdownMath) { logger$1.warn(`${colors.magenta("plugins.markdownMath")} is deprecated, you should use ${colors.magenta("markdown.math")} instead.`); deprecatedLogger({ options: themeOptions, old: "plugins.markdownMath", new: "markdown.math" }); delete pluginOptions.markdownMath; } if (pluginOptions.markdownTab) { logger$1.warn(`${colors.magenta("plugins.markdownTab")} is deprecated, you should use ${colors.magenta("markdown.tabs")} and ${colors.magenta("markdown.codeTabs")} instead.`); if (isPlainObject(pluginOptions.markdownTab)) { deprecatedLogger({ options: themeOptions, old: "plugins.markdownTab.tabs", new: "markdown.tabs" }); deprecatedLogger({ options: themeOptions, old: "plugins.markdownTab.code", new: "markdown.codeTabs" }); } else if (pluginOptions.markdownTab === true) { markdownOptions.codeTabs = true; markdownOptions.tabs = true; } delete pluginOptions.markdownTab; } if (pluginOptions.searchPro) { logger$1.warn(`${colors.magenta("plugins.searchPro")} is deprecated, you should replace ${colors.cyan("vuepress-plugin-search-pro")} with ${colors.cyan("@vuepress/plugin-slimsearch")} in ${colors.green("package.json")} and use ${colors.magenta("plugins.slimsearch")} instead.`); pluginOptions.slimsearch = pluginOptions.searchPro; delete pluginOptions.searchPro; } if (pluginOptions.prismjs) { logger$1.warn(`${colors.magenta("plugins.prismjs")} is deprecated, you should use ${colors.magenta("markdown.highlighter")} with ${colors.cyan("{ type: \"prismjs\", ...other options }")} instead.`); markdownOptions.highlighter = { type: "prismjs", ...isPlainObject(pluginOptions.prismjs) ? pluginOptions.prismjs : {} }; delete pluginOptions.prismjs; } if (pluginOptions.shiki) { logger$1.warn(`${colors.magenta("plugins.shiki")} is deprecated, you should use ${colors.magenta("markdown.highlighter")} with ${colors.cyan("{ type: \"shiki\", ...other options }")} instead.`); markdownOptions.highlighter = { type: "shiki", ...isPlainObject(pluginOptions.shiki) ? pluginOptions.shiki : {} }; delete pluginOptions.shiki; } if (pluginOptions.revealjs) deprecatedLogger({ options: themeOptions, old: "plugins.revealjs", new: "markdown.revealjs" }); }; /** * @deprecated You should use V2 standard options and avoid using it * @param themeOptions - Theme options * @returns Converted theme options */ const convertThemeOptions = (themeOptions) => { const { deprecatedLogger, droppedLogger } = createConverter("theme options"); const plugins = themeOptions.plugins ??= {}; covertPluginOptions(themeOptions); DEPRECATED_THEME_OPTIONS.forEach(([oldOption, newOption]) => { deprecatedLogger({ options: themeOptions, old: oldOption, new: newOption }); }); if ("navbar" in themeOptions) themeOptions.navbar = convertNavbarOptions(themeOptions.navbar); if ("sidebar" in themeOptions) themeOptions.sidebar = convertSidebarOptions(themeOptions.sidebar); convertNavbarLayoutOptions(themeOptions); convertBlogOptions(themeOptions, plugins); convertFooterOptions(themeOptions); deprecatedLogger({ options: themeOptions, old: "iconAssets", new: "plugins.icon.assets" }); deprecatedLogger({ options: themeOptions, old: "iconPrefix", new: "plugins.icon.prefix" }); if (themeOptions.addThis) droppedLogger({ options: themeOptions, old: "addThis" }); if (isPlainObject(themeOptions.copyright) || themeOptions.copyright === true) logger$1.warn(`${colors.magenta("copyright")} is deprecated in V2, please use ${colors.magenta("plugins.copyright")} instead.`); if (isPlainObject(themeOptions.encrypt)) { const encrypt = themeOptions.encrypt; if ("global" in encrypt && typeof encrypt.global !== "boolean") { logger$1.warn(`${colors.magenta("encrypt.global")} is deprecated in V2, please use ${colors.magenta("encrypt.admin")} instead.`); encrypt.admin = encrypt.global; } if ("status" in encrypt) { logger$1.warn(`${colors.magenta("encrypt.status")} is deprecated, please use ${colors.magenta("encrypt.global")} instead.`); encrypt.global = encrypt.status === "global"; delete encrypt.status; } } if ("locales" in themeOptions && isPlainObject(themeOptions.locales)) entries(themeOptions.locales).forEach(([localePath, localeConfig]) => { DEPRECATED_THEME_OPTIONS.forEach(([oldOption, newOption]) => { deprecatedLogger({ options: localeConfig, old: oldOption, new: newOption, scope: "themeConfig.locales" }); }); if ("navbar" in localeConfig) localeConfig.navbar = convertNavbarOptions(localeConfig.navbar, localePath); if ("sidebar" in localeConfig) localeConfig.sidebar = convertSidebarOptions(localeConfig.sidebar, localePath); if (typeof localeConfig.headingDepth === "number") { logger$1.warn(`${colors.magenta("headingDepth")} is deprecated, please use ${colors.magenta("toc.levels")} instead.`); if (localeConfig.toc !== false) localeConfig.toc = { levels: [2, localeConfig.headingDepth + 2] }; } if (typeof localeConfig.headerDepth === "number") { logger$1.warn(`${colors.magenta("headerDepth")} is deprecated, please use ${colors.magenta("toc.levels")} instead.`); if (localeConfig.toc !== false) localeConfig.toc = { levels: [2, localeConfig.headerDepth + 2] }; } convertNavbarLayoutOptions(localeConfig); convertBlogOptions(localeConfig, plugins, localePath); convertFooterOptions(localeConfig); }); return themeOptions; }; //#endregion //#region src/node/helpers.ts const navbar = (options) => options; const sidebar = (options) => options; const arraySidebar = (sidebarConfig) => sidebarConfig; const objectSidebar = (sidebarConfig) => sidebarConfig; const backToTop = (backToTopConfig) => backToTopConfig; const blog = (options) => options; const catalog = (options) => options; const comment = (options) => options; const components = (options) => options; const copyCode = (options) => options; const copyright = (options) => options; const feed = (options) => options; const git = (options) => options; const linksCheck = (options) => options; const notice = (options) => options; const photoSwipe = (options) => options; const prismjs = (options) => options; const pwa = (options) => options; const readingTime = (options) => options; const redirect = (options) => options; const revealjs = (options) => options; const seo = (options) => options; const shiki = (options) => options; const sitemap = (options) => options; const watermark = (options) => options; //#endregion //#region src/node/check/checkFrontmatter.ts const checkFrontmatter = (page) => { const frontmatter = page.frontmatter; const { filePathRelative } = page; ["category", "tag"].forEach((key) => { if (key in frontmatter && !(isString(frontmatter[key]) || isArray(frontmatter[key]) && frontmatter[key].every((value) => isString(value)))) { logger$1.warn(`${colors.magenta(key)} property in Page FrontMatter should be ${colors.cyan("string")} or ${colors.cyan(" string[]")}${filePathRelative ? `, found in ${filePathRelative}` : ""}.`); delete frontmatter[key]; } }); if ("date" in frontmatter && !(frontmatter.date instanceof Date)) { logger$1.warn(`${colors.magenta("date")} in frontMatter should be ${colors.cyan("a valid Date")}${filePathRelative ? `, found in ${filePathRelative}` : ""}.`); delete frontmatter.date; } if ("sidebar" in frontmatter && typeof frontmatter.sidebar !== "boolean") { logger$1.warn(`${colors.magenta("sidebar")} in frontMatter should be ${colors.cyan("boolean")}${filePathRelative ? `, found in ${filePathRelative}` : ""}.`); delete frontmatter.sidebar; } [ "title", "shortTitle", "containerClass" ].forEach((key) => { if (key in frontmatter && !isString(frontmatter[key])) { logger$1.warn(`${colors.magenta(key)} in frontMatter should be ${colors.cyan("string")}${filePathRelative ? `, found in ${filePathRelative}` : ""}.`); delete frontmatter[key]; } }); [ "home", "navbar", "index", "lastUpdated", "editLink", "breadcrumb", "breadcrumbIcon", "breadcrumbExclude", "pageview", "article" ].forEach((key) => { if (key in frontmatter && typeof frontmatter[key] !== "boolean") { logger$1.warn(`${colors.magenta(key)} in frontMatter should be ${colors.cyan("boolean")}${filePathRelative ? `, found in ${filePathRelative}` : ""}.`); delete frontmatter[key]; } }); Object.keys(frontmatter).forEach((key) => { if (key.includes(".")) logger$1.warn(`${colors.magenta(key)} in frontMatter should not contain ${colors.cyan(".")}${filePathRelative ? `, found in ${filePathRelative}` : ""}.`); }); }; //#endregion //#region src/node/check/checkMarkdownOptions.ts const KNOWN_CORE_MARKDOWN_OPTIONS = [ "anchor", "assets", "component", "emoji", "frontmatter", "headers", "title", "importCode", "links", "sfc", "slugify", "toc", "vPre" ]; const KNOWN_THEME_MARKDOWN_OPTIONS = [ "linksCheck", "gfm", "breaks", "linkify", "footnote", "tasklist", "component", "vPre", "alert", "hint", "figure", "imgLazyload", "imgMark", "imgSize", "legacyImgSize", "obsidianImgSize", "include", "preview", "align", "attrs", "sup", "sub", "mark", "spoiler", "stylize", "tabs", "codeTabs", "math", "highlighter", "revealjs", "chartjs", "echarts", "flowchart", "markmap", "mermaid", "plantuml", "DANGEROUS_ALLOW_SCRIPT_EXECUTION", "DANGEROUS_SCRIPT_EXECUTION_ALLOWLIST", "demo", "playground", "kotlinPlayground", "vuePlayground", "sandpack" ]; /** * Check vuepress markdown options for noob users * * @param vuepressMarkdownOptions - VuePress markdown options * @param themeMarkdownOptions - Theme markdown options */ const checkVuePressMarkdownOptions = (vuepressMarkdownOptions, themeMarkdownOptions) => { keys(vuepressMarkdownOptions).forEach((key) => { if (!KNOWN_CORE_MARKDOWN_OPTIONS.includes(key)) if (KNOWN_THEME_MARKDOWN_OPTIONS.includes(key)) { logger$1.warn(`You are setting "${colors.magenta(`markdown.${key}`)}" option in ${colors.cyan("vuepress config file")}, but it's not supported by VuePress. You need to set the option in ${colors.cyan("theme options")}.`); themeMarkdownOptions[key] = vuepressMarkdownOptions[key]; } else logger$1.warn(`You are setting "${colors.magenta(`markdown.${key}`)}" option in ${colors.cyan("vuepress config file")}, but it's not supported by VuePress.`); }); }; /** * Check theme plugin options for noob users * * @param vuepressMarkdownOptions - VuePress markdown options * @param themeMarkdownOptions - Theme markdown options */ const checkThemeMarkdownOptions = (vuepressMarkdownOptions, themeMarkdownOptions) => { keys(themeMarkdownOptions).forEach((key) => { if (!KNOWN_THEME_MARKDOWN_OPTIONS.includes(key)) if (KNOWN_CORE_MARKDOWN_OPTIONS.includes(key)) { logger$1.warn(`You are setting "${colors.magenta(`markdown.${key}`)}" option in ${colors.cyan("theme options")}, but it's not supported by theme. You need to set the option in ${colors.cyan("vuepress config file")}.`); vuepressMarkdownOptions[key] = themeMarkdownOptions[key]; } else logger$1.warn(`You are setting "${colors.magenta(`markdown.${key}`)}" option in ${colors.cyan("theme options")}, but it's not supported by theme.`); }); }; //#endregion //#region src/node/check/utils.ts const PLUGIN_CHECKLIST = [ ["@vuepress/plugin-active-header-links", "plugins.activeHeaderLinks"], ["@vuepress/plugin-blog", "plugins.blog"], ["@vuepress/plugin-catalog", "plugins.catalog"], ["@vuepress/plugin-comment", "plugins.comment"], ["@vuepress/plugin-copy-code", "plugins.copyCode"], ["@vuepress/plugin-copyright", "plugins.copyright"], ["@vuepress/plugin-docsearch", "plugins.docsearch"], ["@vuepress/plugin-feed", "plugins.feed"], ["@vuepress/plugin-git", "plugins.git"], ["@vuepress/plugin-icon", "plugins.icon"], ["@vuepress/plugin-links-check", "markdown.linksCheck"], ["@vuepress/plugin-markdown-hint", ["markdown.alert", "markdown.hint"]], ["@vuepress/plugin-markdown-image", [ "markdown.figure", "markdown.imgLazyload", "markdown.imgMark", "markdown.imgSize", "markdown.obsidianImgSize" ]], ["@vuepress/plugin-markdown-math", "markdown.math"], ["@vuepress/plugin-markdown-tab", ["markdown.tabs", "markdown.codeTabs"]], ["@vuepress/plugin-meilisearch", "plugins.meilisearch"], ["@vuepress/plugin-notice", "plugins.notice"], ["@vuepress/plugin-nprogress", "plugins.nprogress"], ["@vuepress/plugin-photo-swipe", "plugins.photoSwipe"], ["@vuepress/plugin-prismjs", "markdown.highlighter: { type: \"prismjs\", ... your options }"], ["@vuepress/plugin-pwa", "plugins.pwa"], ["@vuepress/plugin-reading-time", "plugins.readingTime"], ["@vuepress/plugin-redirect", "plugins.redirect"], ["@vuepress/plugin-revealjs", "markdown.revealjs"], [ "@vuepress/plugin-rtl", "", "Set \"rtl: true\" in the needed theme locales." ], ["@vuepress/plugin-search", "plugins.search"], ["@vuepress/plugin-seo", "plugins.seo"], ["@vuepress/plugin-shiki", "markdown.highlighter: { type: \"shiki\", ... your options }"], ["@vuepress/plugin-slimsearch", "plugins.slimsearch"], ["@vuepress/plugin-sitemap", "plugins.sitemap"], [ "@vuepress/plugin-theme-data", "", "This plugin is called internally." ], ["@vuepress/plugin-watermark", "plugins.watermark"], ["vuepress-plugin-components", "plugins.components"], ["vuepress-plugin-md-enhance", "plugins.mdEnhance"] ]; //#endregion //#region src/node/check/checkPluginsOptions.ts const KNOWN_THEME_PLUGIN_KEYS = new Set(PLUGIN_CHECKLIST.flatMap(([, key]) => key).filter((key) => key.startsWith("plugins.")).map((key) => key.split(".")[1])); /** * Check theme plugin options for noob users * * @param plugins - Theme plugin options */ const checkPluginsOptions = (plugins) => { keys(plugins).forEach((key) => { if (!KNOWN_THEME_PLUGIN_KEYS.has(key)) logger$1.warn(`You are setting "${colors.magenta(`plugins.${key}`)}" option in ${colors.cyan("theme options")}, but it's not supported by theme. You need to install the plugin yourself, import it in ${colors.cyan("vuepress config file")} and call it manually in "${colors.magenta("plugins")}" options.`); }); }; //#endregion //#region src/node/check/checkVuePressVersion.ts const BUNDLERS = ["vite", "webpack"]; const BUNDLER_PREFIX = "@vuepress/bundler-"; const VUEPRESS_BUNDLERS = new Set(BUNDLERS.map((bundler) => `${BUNDLER_PREFIX}${bundler}`)); const VUEPRESS_CORE_PACKAGES = new Set([ "core", "client", "cli", "markdown", "shared", "utils" ].map((item) => `@vuepress/${item}`)); const DEPRECATED_PACKAGES = new Set(BUNDLERS.map((item) => `vuepress-${item}`)); const checkVuePressVersion = () => { const sourceFolderPath = path.join(process.cwd(), process.argv[3]); const bundlerNames = []; const corePackageNames = []; const require = createRequire(`${sourceFolderPath}/`); let dir = sourceFolderPath; let foundVuePress = false; const checkPackage = (pkgName) => { if (pkgName === "vuepress") foundVuePress = true; else if (DEPRECATED_PACKAGES.has(pkgName)) console.error(colors.red(`❌ ${pkgName} is deprecated and you must remove it from deps!`)); else if (VUEPRESS_CORE_PACKAGES.has(pkgName)) corePackageNames.push(pkgName); else if (VUEPRESS_BUNDLERS.has(pkgName)) bundlerNames.push(pkgName); }; do { if (fs.existsSync(path.resolve(dir, "package.json"))) { const content = JSON.parse(fs.readFileSync(path.resolve(dir, "package.json"), "utf-8")); keys({ ...content.dependencies, ...content.devDependencies }).forEach((name) => { checkPackage(name); }); } if (foundVuePress || dir === path.dirname(dir)) break; } while (dir = path.dirname(dir)); if (!foundVuePress) { console.error(`❌ ${colors.cyan("VuePress")} ${colors.red("package is not found in current project!")} You must manually install it!`); return false; } if (bundlerNames.length === 0) { console.error(`${colors.red("❌ No VuePress bundler is detected in the current project!")} You should install one of ${[...VUEPRESS_BUNDLERS].map((str) => colors.cyan(str)).join(", ")}`); return false; } let isVersionMatch = true; const { version: vuePressVersion } = require("vuepress/package.json"); bundlerNames.forEach((pkgName) => { const { version } = require(`${pkgName}/package.json`); if (version !== vuePressVersion) { console.error(`❌ Package version mismatch: ${colors.cyan(pkgName)} is using ${colors.magenta(version)} while ${colors.cyan("vuepress")} is using ${colors.magenta(vuePressVersion)}`); isVersionMatch = false; } }); corePackageNames.forEach((pkgName) => { const { version } = require(`${pkgName}/package.json`); if (version === vuePressVersion) console.warn(`${colors.cyan(pkgName)} is no longer needed, you should remove it from deps and change all ${colors.cyan(pkgName)} imports to ${colors.cyan(pkgName.slice(1))}`); else { console.error(`Package version mismatch: ${colors.cyan(pkgName)} is using ${colors.magenta(version)} while ${colors.cyan("vuepress")} is using ${colors.magenta(vuePressVersion)}`); isVersionMatch = false; } }); return isVersionMatch; }; //#endregion //#region src/node/check/checkUserPlugins.ts /** * Check user plugin options for noob users * * @param app - VuePress app instance */ const checkUserPlugins = (app) => { PLUGIN_CHECKLIST.forEach(([pluginName, optionName, hint = ""]) => { const themeIndex = app.pluginApi.plugins.findIndex((item) => item.name === "vuepress-theme-hope"); if (app.pluginApi.plugins.slice(themeIndex + 1).some(({ name }) => name === pluginName)) logger$1.error(`You are not allowed to use plugin "${colors.magenta(pluginName)}" yourself in ${colors.cyan("vuepress config file")}. ${hint || (optionName ? `Set "${colors.magenta(isString(optionName) ? optionName : optionName.join(","))}" in ${colors.cyan("theme options")} to customize it.` : "")}`); }); }; //#endregion //#region src/node/config/getEncryptConfig.ts const hashPasswords = (passwords, key) => { if (isString(passwords)) return [hashSync(passwords)]; if (isArray(passwords)) return passwords.map((password) => { if (isString(password)) return hashSync(password); logger$1.error(`\ ${colors.magenta(key)} config is invalid. All password MUST be string. But we found one’s type is ${typeof password}. Please fix it!\ `); return null; }).filter((item) => item != null); logger$1.error(`\ ${colors.magenta(key)} config is invalid. All password MUST be string. But we found a ${JSON.stringify(passwords)}. Please fix it!\ `); return null; }; const getEncryptConfig = ({ admin, config, global } = {}) => { const result = {}; if (admin) { if (global) result.global = true; if (isPlainObject(admin)) { const tokens = hashPasswords(admin.password, "encrypt.admin.password"); if (tokens) result.admin = { tokens, hint: admin.hint }; } else { const tokens = hashPasswords(admin, "encrypt.admin"); if (tokens) result.admin = { tokens }; } } if (config) result.config = fromEntries(entries(config).map(([key, options]) => { if (isPlainObject(options)) { const tokens = hashPasswords(options.password, `encrypt.config[${key}].password`); return tokens ? [key, { tokens, hint: options.hint }] : null; } const tokens = hashPasswords(options, `encrypt.config[${key}]`); return tokens ? [key, { tokens }] : null; }).filter((item) => item != null)); return result; }; //#endregion //#region src/node/config/getSocialMediaIcons.ts const getSocialMediaIcons = (themeData) => { const iconData = {}; const isIconInvalid = (key, value) => { if (isString(value)) { const templatePath = `${TEMPLATE_FOLDER}/socialMediaIcons/${key.toLocaleLowerCase()}.svg`; if (fs.existsSync(templatePath)) { iconData[key] = fs.readFileSync(templatePath, { encoding: "utf-8" }); return false; } logger$1.warn(`${key} is not a built-in media, you should provide an icon for it!`); return true; } if (isPlainObject(value)) { if (isLinkHttp(value.icon) || startsWith(value.icon, "<svg")) return false; logger$1.warn(`${key}'s icon ${value.icon} in blog media config is invalid!`); return true; } logger$1.warn(`${key} icon in blog media config has an invalid config!`); return true; }; entries(themeData.blog?.medias ?? {}).forEach(([key, value]) => { if (isIconInvalid(key, value)) delete themeData.blog?.medias?.[key]; }); entries(themeData.locales).forEach(([path, { blog }]) => { entries(blog?.medias ?? {}).forEach(([key, value]) => { if (isIconInvalid(key, value)) delete themeData.locales[path].blog?.medias?.[key]; }); }); return iconData; }; //#endregion //#region src/node/locales/de.ts const deLocale = { lang: "de-DE", navbarLocales: { langName: "Deutsch", selectLangAriaLabel: "Sprache wählen" }, metaLocales: { author: "Autor", date: "Datum", origin: "Original", views: "Besucher", category: "Kategorie", tag: "Tag", readingTime: "Lesezeit", words: "Wörter", toc: "Auf dieser Seite", prev: "Vorherige", next: "Nächste", contributors: "Mitwirkende", editLink: "Diese Seite barbeiten", print: "Drucken" }, blogLocales: { article: "Artikel", articleList: "Artikel Liste", category: "Kategorie", tag: "Tag", timeline: "Timeline", timelineTitle: "Yesterday Once More!", all: "Alle", intro: "Persönliche Einleitung", star: "Star", empty: "$text ist leer" }, paginationLocales: { prev: "Vorherige", next: "Nächste", navigate: "Springe zu", action: "Los", errorText: "Bitte gib eine Nummer zwischen 1 und $page ein!" }, outlookLocales: { themeColor: "Design-Farbe", darkmode: "Design-Modus", fullscreen: "Vollbild" }, encryptLocales: { iconLabel: "Seite verschlüsselt", placeholder: "Passwort eingeben", remember: "Passwort merken", errorHint: "Bitte das korrekte Passwort eingeben!" }, routerLocales: { skipToContent: "Zum Hauptinhalt springen", notFoundTitle: "Seite nicht gefunden", notFoundMsg: [ "Hier gibt es nichts.", "Wie sind wir hier hergekommen?", "Das ist wohl eine Vier-Null-Vier.", "Sieht aus als hättest du einen kaputten Link gefunden." ], back: "Zurück", home: "Zur Startseite" } }; //#endregion //#region src/node/locales/deAT.ts const deATLocale = { lang: "de-AT", navbarLocales: { langName: "Deutsch (Österreich)", selectLangAriaLabel: "Sprache wählen" }, metaLocales: { author: "Autor", date: "Datum", origin: "Original", views: "Besucher", category: "Kategorie", tag: "Tag", readingTime: "Lesezeit", words: "Wörter", toc: "On This Page", prev: "Prev", next: "Next", contributors: "Mitwirkende", editLink: "Diese Seite barbeiten", print: "Drucken" }, blogLocales: { article: "Artikel", articleList: "Artikel Liste", category: "Kategorie", tag: "Tag", timeline: "Timeline", timelineTitle: "Yesterday Once More!", all: "Alle", intro: "Persönliche Einleitung", star: "Star", empty: "$text ist leer" }, paginationLocales: { prev: "Vorheriges", next: "Nächstes", navigate: "Springe zu", action: "Los", errorText: "Bitte gib eine Nummer zwischen 1 und $page ein!" }, outlookLocales: { themeColor: "Design-Farbe", darkmode: "Design-Modus", fullscreen: "Full Screen" }, encryptLocales: { iconLabel: "Page Encrypted", placeholder: "Entre a senha", remember: "Remember password", errorHint: "Bitte das korrekte Passwort eingeben!" }, routerLocales: { skipToContent: "Zum Hauptinhalt springen", notFoundTitle: "Seite nicht gefunden", notFoundMsg: [ "Hier gibt es nichts.", "Wie sind wir hier hergekommen?", "Das ist wohl eine Vier-Null-Vier.", "Sieht aus als hättest du einen kaputten Link gefunden." ], back: "Zurück", home: "Zur Startseite" } }; //#endregion //#region src/node/locales/en.ts const enLocale = { lang: "en-US", navbarLocales: { langName: "English", selectLangAriaLabel: "Select language" }, metaLocales: { author: "Author", date: "Writing Date", origin: "Original", views: "Page views", category: "Category", tag: "Tag", readingTime: "Reading Time", words: "Words", toc: "On This Page", prev: "Prev", next: "Next", contributors: "Contributors", editLink: "Edit this page", print: "Print" }, blogLocales: { article: "Articles", articleList: "Article List", category: "Category", tag: "Tag", timeline: "Timeline", timelineTitle: "Yesterday Once More!", all: "All", intro: "Personal Intro", star: "Star", empty: "No $text" }, paginationLocales: { prev: "Prev", next: "Next", navigate: "Jump to", action: "Go", errorText: "Please enter a number between 1 and $page !" }, outlookLocales: { themeColor: "Theme Color", darkmode: "Theme Mode", fullscreen: "Full Screen" }, encryptLocales: { iconLabel: "Page Encrypted", placeholder: "Enter password", remember: "Remember password", errorHint: "Please enter the correct password!" }, routerLocales: { skipToContent: "Skip to main content", notFoundTitle: "Page not found", notFoundMsg: [ "There’s nothing here.", "How did we get here?", "That’s a Four-Oh-Four.", "Looks like we've got some broken links." ], back: "Go back", home: "Take me home" } }; //#endregion //#region src/node/locales/es.ts const esLocale = { lang: "es-ES", navbarLocales: { langName: "Español", selectLangAriaLabel: "Seleccionar idioma" }, metaLocales: { author: "Autor", date: "Fecha de publicación", origin: "Original", views: "Páginas vistas", category: "Categoría", tag: "Etiquetas", readingTime: "Tiempo de lectura", words: "Palabras", toc: "En esta página", prev: "Anterior", next: "Siguiente", contributors: "Contribuidores", editLink: "Editar esta página", print: "Imprimir" }, blogLocales: { article: "Artículos", articleList: "Lista de artículos", category: "Categoría", tag: "Etiquetas", timeline: "Línea de tiempo", timelineTitle: "Ayer una vez más!", all: "Todos", intro: "Introducción personal", star: "Estrella", empty: "$text está vacío" }, paginationLocales: { prev: "Anterior", next: "Siguiente", navigate: "Saltar a", action: "Ir", errorText: "Por favor ingrese un número entre 1 y $page !" }, outlookLocales: { themeColor: "Color del tema", darkmode: "Modo del tema", fullscreen: "Pantalla completa" }, encryptLocales: { iconLabel: "Página encriptada", placeholder: "Ingre