UNPKG

hirsun-vuepress-theme-hope-plus

Version:
1,431 lines (1,392 loc) 88.6 kB
import { isLinkHttp, isLinkMailto, isLinkTel, isString, ensureEndingSlash, isArray, isPlainObject, isLinkExternal } from '@vuepress/shared'; import { useRouter, useRoute } from 'vue-router'; import { isAbsoluteUrl, resolveRouteWithRedirect, inferRouteLink, getAuthor, getCategory, getTag, getDate, keys, startsWith, VPLink, isActiveLink, IconBase, entries, resolveRepoLink, resolveRepoType, fromEntries, BitbucketIcon, GiteeIcon, GitHubIcon, GitLabIcon, SourceIcon, hasGlobalComponent, RenderDefault, generateIndexFromHash } from 'vuepress-shared/client'; import { withBase, usePageFrontmatter, usePageData, useSiteData, useRouteLocale, useSiteLocaleData, ClientOnly, Content, usePageLang } from '@vuepress/client'; import { useEventListener, usePreferredDark, useStorage, useFullscreen, useScrollLock, useToggle, useThrottleFn, useMutationObserver } from '@vueuse/core'; import { h, resolveComponent, computed, inject, ref, onMounted, watch, defineComponent, toRef, provide, shallowRef, onUnmounted, Transition, TransitionGroup } from 'vue'; import { useReadingTimeData, useReadingTimeLocale } from 'vuepress-plugin-reading-time2/client'; import { a as useThemeLocaleData, b as useThemeData, u as usePure } from './themeData-51227756.js'; import noopModule from 'vuepress-shared/noopModule'; import { ExternalLinkIcon } from '@vuepress/plugin-external-link-icon/client'; import cssVariables from './styles/variables.module.scss?module'; import { sidebarData } from '@temp/theme-hope/sidebar'; import 'balloon-css/balloon.css'; const HopeIcon = (props) => { const { icon = "", color, size } = props; const style = {}; if (color) style["color"] = color; if (size) style["height"] = Number.isNaN(Number(size)) ? size : `${size}px`; return isLinkHttp(icon) ? h("img", { class: "icon", src: icon, "no-view": "", style }) : isAbsoluteUrl(icon) ? h("img", { class: "icon", src: withBase(icon), "no-view": "", style }) : h(resolveComponent("FontIcon"), props); }; HopeIcon.displayName = "HopeIcon"; var HopeIcon$1 = HopeIcon; var ArticleInfoType = /* @__PURE__ */ ((ArticleInfoType2) => { ArticleInfoType2["type"] = "y"; ArticleInfoType2["title"] = "t"; ArticleInfoType2["shortTitle"] = "s"; ArticleInfoType2["icon"] = "i"; ArticleInfoType2["author"] = "a"; ArticleInfoType2["date"] = "d"; ArticleInfoType2["localizedDate"] = "l"; ArticleInfoType2["category"] = "c"; ArticleInfoType2["tag"] = "g"; ArticleInfoType2["isEncrypted"] = "n"; ArticleInfoType2["isOriginal"] = "o"; ArticleInfoType2["readingTime"] = "r"; ArticleInfoType2["excerpt"] = "e"; ArticleInfoType2["sticky"] = "u"; ArticleInfoType2["cover"] = "v"; ArticleInfoType2["index"] = "I"; ArticleInfoType2["order"] = "O"; return ArticleInfoType2; })(ArticleInfoType || {}); var PageType = /* @__PURE__ */ ((PageType2) => { PageType2["article"] = "a"; PageType2["home"] = "h"; PageType2["slide"] = "s"; PageType2["page"] = "p"; return PageType2; })(PageType || {}); const resolveLinkInfo = (router, item, preferFull = false) => { const encodedPath = encodeURI(item); let result = resolveRouteWithRedirect(router, inferRouteLink(encodedPath)); if (result.name === "404") result = resolveRouteWithRedirect(router, encodedPath); const { fullPath, meta, name } = result; return { text: !preferFull && meta[ArticleInfoType.shortTitle] ? meta[ArticleInfoType.shortTitle] : meta[ArticleInfoType.title] || item, link: name === "404" ? item : fullPath, ...meta[ArticleInfoType.icon] ? { icon: meta[ArticleInfoType.icon] } : {} }; }; const useNavigate = () => { const router = useRouter(); const route = useRoute(); return (url) => { if (url) if (isAbsoluteUrl(url)) { if (route.path !== url) void router.push(url); } else if (isLinkHttp(url) || isLinkMailto(url)) { if (window) window.open(url); } else { const base = route.path.slice(0, route.path.lastIndexOf("/")); void router.push(`${base}/${encodeURI(url)}`); } }; }; const usePageAuthor = () => { const themeLocale = useThemeLocaleData(); const frontmatter = usePageFrontmatter(); return computed(() => { const { author } = frontmatter.value; if (author) return getAuthor(author); if (author === false) return []; return getAuthor(themeLocale.value.author, false); }); }; const usePageCategory = () => { const frontmatter = usePageFrontmatter(); return computed( () => getCategory(frontmatter.value.category).map((name) => { var _a, _b; return { name, // this is a hack path: ENABLE_BLOG ? ((_b = (_a = inject(Symbol.for("categoryMap"))) == null ? void 0 : _a.value.map[name]) == null ? void 0 : _b.path) || "" : "" }; }) ); }; const usePageTag = () => { const frontmatter = usePageFrontmatter(); return computed( () => getTag(frontmatter.value.tag).map((name) => { var _a, _b; return { name, // this is a hack path: ENABLE_BLOG ? ((_b = (_a = inject(Symbol.for("tagMap"))) == null ? void 0 : _a.value.map[name]) == null ? void 0 : _b.path) || "" : "" }; }) ); }; const usePageDate = () => { const frontmatter = usePageFrontmatter(); const page = usePageData(); return computed(() => { const date = getDate(frontmatter.value.date); if (date) return date; const { createdTime } = page.value.git || {}; if (createdTime) return new Date(createdTime); return null; }); }; const usePageInfo = () => { const themeLocale = useThemeLocaleData(); const page = usePageData(); const frontmatter = usePageFrontmatter(); const author = usePageAuthor(); const category = usePageCategory(); const tag = usePageTag(); const date = usePageDate(); const readingTimeData = useReadingTimeData(); const readingTimeLocale = useReadingTimeLocale(); const info = computed( () => ({ author: author.value, category: category.value, date: date.value, localizedDate: page.value.localizedDate, tag: tag.value, isOriginal: frontmatter.value.isOriginal || false, readingTime: readingTimeData.value, readingTimeLocale: readingTimeLocale.value, pageview: "pageview" in frontmatter.value ? frontmatter.value.pageview : true }) ); const items = computed( () => "pageInfo" in frontmatter.value ? frontmatter.value.pageInfo : "pageInfo" in themeLocale.value ? themeLocale.value.pageInfo : null ); return { info, items }; }; const { mobileBreakPoint, pcBreakPoint } = cssVariables; const getPixels = (length) => length.endsWith("px") ? Number(length.slice(0, -2)) : null; const useWindowSize = () => { const isMobile = ref(false); const isPC = ref(false); const windowSizeHandler = () => { isMobile.value = window.innerWidth <= (getPixels(mobileBreakPoint) ?? 719); isPC.value = window.innerWidth >= (getPixels(pcBreakPoint) ?? 1440); }; onMounted(() => { windowSizeHandler(); useEventListener("resize", windowSizeHandler, false); useEventListener("orientationchange", windowSizeHandler, false); }); return { isMobile, isPC }; }; const darkModeSymbol = Symbol( __VUEPRESS_DEV__ ? "darkMode" : "" ); const useDarkmode = () => { const darkmode = inject(darkModeSymbol); if (!darkmode) throw new Error("useDarkmode() is called without provider."); return darkmode; }; const injectDarkmode = (app) => { const themeData = useThemeData(); const isDarkPreferred = usePreferredDark(); const status = useStorage( "vuepress-theme-hope-scheme", "auto" ); const config = computed(() => themeData.value.darkmode || "switch"); const isDarkmode = computed(() => { const darkmode = config.value; return darkmode === "disable" ? false : ( // force darkmode darkmode === "enable" ? true : ( // auto darkmode === "auto" ? isDarkPreferred.value : ( // toggle darkmode === "toggle" ? status.value === "dark" : ( // switch status.value === "dark" || status.value === "auto" && isDarkPreferred.value ) ) ) ); }); const canToggle = computed(() => { const darkmode = config.value; return darkmode === "switch" || darkmode === "toggle"; }); app.provide(darkModeSymbol, { canToggle, config, isDarkmode, status }); Object.defineProperties(app.config.globalProperties, { $isDarkmode: { get: () => isDarkmode.value } }); }; const setupDarkmode = () => { const { isDarkmode } = useDarkmode(); const updateDOM = (isDark = isDarkmode.value) => document.documentElement.setAttribute( "data-theme", isDark ? "dark" : "light" ); onMounted(() => { watch(isDarkmode, updateDOM, { immediate: true }); }); }; var AutoLink = defineComponent({ name: "AutoLink", inheritAttrs: false, props: { /** * @description Autolink config */ config: { type: Object, required: true }, /** * @description Whether it's active only when exact match */ exact: Boolean, /** * @description Whether to hide externalLinkIcon */ noExternalLinkIcon: Boolean }, emits: ["focusout"], slots: Object, setup(props, { attrs, emit, slots }) { const route = useRoute(); const siteData = useSiteData(); const config = toRef(props, "config"); const hasHttpProtocol = computed(() => isLinkHttp(config.value.link)); const hasNonHttpProtocol = computed( () => isLinkMailto(config.value.link) || isLinkTel(config.value.link) ); const linkTarget = computed( () => hasNonHttpProtocol.value ? void 0 : config.value.target || (hasHttpProtocol.value ? "_blank" : void 0) ); const isBlankTarget = computed(() => linkTarget.value === "_blank"); const renderVPLink = computed( () => !hasHttpProtocol.value && !hasNonHttpProtocol.value && !isBlankTarget.value ); const anchorRel = computed( () => hasNonHttpProtocol.value ? void 0 : config.value.rel || (isBlankTarget.value ? "noopener noreferrer" : void 0) ); const linkAriaLabel = computed( () => config.value.ariaLabel || config.value.text ); const shouldBeActiveInSubpath = computed(() => { if (props.exact) return false; const localeKeys = keys(siteData.value.locales); return localeKeys.length ? ( // check all the locales localeKeys.every((key) => key !== config.value.link) ) : ( // check root config.value.link !== "/" ); }); const isActive = computed( () => renderVPLink.value ? config.value.activeMatch ? new RegExp(config.value.activeMatch).test(route.path) : ( // if this link is active in subpath !shouldBeActiveInSubpath.value ? route.path === config.value.link : startsWith(route.path, config.value.link) ) : false ); return () => { const { before, after, default: defaultSlot } = slots; const { text, icon, link } = config.value; return renderVPLink.value ? h( VPLink, { to: link, "aria-label": linkAriaLabel.value, ...attrs, // class needs to be merged manually class: ["nav-link", { active: isActive.value }, attrs["class"]], onFocusout: () => emit("focusout") }, () => defaultSlot ? defaultSlot() : [before ? before() : h(HopeIcon$1, { icon }), text, after == null ? void 0 : after()] ) : h( "a", { href: link, rel: anchorRel.value, target: linkTarget.value, "aria-label": linkAriaLabel.value, ...attrs, // class needs to be merged manually class: ["nav-link", attrs["class"]], onFocusout: () => emit("focusout") }, defaultSlot ? defaultSlot() : [ before ? before() : h(HopeIcon$1, { icon }), text, props.noExternalLinkIcon ? null : h(ExternalLinkIcon), after == null ? void 0 : after() ] ); }; } }); const isActiveSidebarItem = (route, item, exact = false) => { if ("activeMatch" in item) return new RegExp(item.activeMatch).test(route.path); if (isActiveLink(route, item.link)) return true; if (item.children && !exact) return item.children.some((child) => isActiveSidebarItem(route, child)); return false; }; const isMatchedSidebarItem = (route, item) => { if (item.type === "group") return item.children.some((child) => { if (child.type === "group") return isMatchedSidebarItem(route, child); return child.type === "page" && isActiveSidebarItem(route, child, true); }) || "prefix" in item && isActiveLink(route, item.prefix); return false; }; const renderItem = (config, props) => isString(config.link) ? ( // if the item has link, render it as `<AutoLink>` h(AutoLink, { ...props, config }) ) : ( // if the item only has text, render it as `<p>` h("p", props, [h(HopeIcon$1, { icon: config.icon }), config.text]) ); const renderChildren$1 = (children) => { const route = useRoute(); if (!children) return null; return h( "ul", { class: "vp-sidebar-sub-headers" }, children.map((child) => { const active = isActiveSidebarItem(route, child, true); return h("li", { class: "vp-sidebar-sub-header" }, [ renderItem(child, { class: ["vp-sidebar-link", "vp-heading", { active }] }), renderChildren$1(child.children) ]); }) ); }; const resolvePrefix = (prefix = "", path = "") => isAbsoluteUrl(path) ? path : `${ensureEndingSlash(prefix)}${path}`; const headerToSidebarItem = (header, headerDepth) => { const page = usePageData(); return { type: "heading", text: header.title, link: `${page.value.path}#${header.slug}`, children: headersToSidebarItemChildren(header.children, headerDepth) }; }; const headersToSidebarItemChildren = (headers, headerDepth) => headerDepth > 0 ? headers.map((header) => headerToSidebarItem(header, headerDepth - 1)) : []; const resolveHeadingSidebarItems = (headerDepth) => { const page = usePageData(); return headersToSidebarItemChildren(page.value.headers, headerDepth); }; const resolveArraySidebarItems = (sidebarConfig, headerDepth, prefix = "") => { const router = useRouter(); const page = usePageData(); const handleChildItem = (item, pathPrefix = prefix) => { var _a; const childItem = isString(item) ? resolveLinkInfo(router, resolvePrefix(pathPrefix, item)) : item.link ? { ...item, ...!isLinkExternal(item.link) ? { link: resolveLinkInfo( router, resolvePrefix(pathPrefix, item.link) ).link } : {} } : item; if ("children" in childItem) { const prefix2 = resolvePrefix(pathPrefix, childItem.prefix); const children = childItem.children === "structure" ? sidebarData[prefix2] : childItem.children; return { type: "group", ...childItem, prefix: prefix2, children: children.map((item2) => handleChildItem(item2, prefix2)) }; } return { type: "page", ...childItem, children: ( // if the sidebar item is current page and children is not set // use headers of current page as children childItem.link === page.value.path ? headersToSidebarItemChildren( // skip h1 header ((_a = page.value.headers[0]) == null ? void 0 : _a.level) === 1 ? page.value.headers[0].children : page.value.headers, headerDepth ) : [] ) }; }; return sidebarConfig.map((item) => handleChildItem(item)); }; const resolveMultiSidebarItems = (sidebarConfig, headerDepth) => { const page = usePageData(); const sidebarRoutes = keys(sidebarConfig).sort((x, y) => y.length - x.length); for (const base of sidebarRoutes) if (startsWith(decodeURI(page.value.path), base)) { const matchedConfig = sidebarConfig[base]; return matchedConfig ? resolveArraySidebarItems( matchedConfig === "structure" ? sidebarData[base] : matchedConfig === "heading" ? resolveHeadingSidebarItems(headerDepth) : matchedConfig, headerDepth, base ) : []; } console.warn(`${page.value.path} is missing sidebar config.`); return []; }; const resolveSidebarItems = (sidebarConfig, headerDepth) => { const routeLocale = useRouteLocale(); return sidebarConfig === false ? [] : sidebarConfig === "heading" ? resolveHeadingSidebarItems(headerDepth) : sidebarConfig === "structure" ? resolveArraySidebarItems( sidebarData[routeLocale.value], headerDepth, routeLocale.value ) : isArray(sidebarConfig) ? resolveArraySidebarItems(sidebarConfig, headerDepth) : isPlainObject(sidebarConfig) ? resolveMultiSidebarItems(sidebarConfig, headerDepth) : []; }; const sidebarItemsSymbol = Symbol( __VUEPRESS_DEV__ ? "sidebarItems" : "" ); const setupSidebarItems = () => { const frontmatter = usePageFrontmatter(); const themeLocale = useThemeLocaleData(); const sidebarConfig = computed( () => frontmatter.value.home ? false : frontmatter.value.sidebar ?? themeLocale.value.sidebar ?? "structure" ); const headerDepth = computed( () => frontmatter.value.headerDepth ?? themeLocale.value.headerDepth ?? 2 ); const sidebarItems = computed( () => resolveSidebarItems(sidebarConfig.value, headerDepth.value) ); provide(sidebarItemsSymbol, sidebarItems); }; const useSidebarItems = () => { const sidebarItems = inject(sidebarItemsSymbol); if (!sidebarItems) throw new Error("useSidebarItems() is called without provider."); return sidebarItems; }; var PageFooter = defineComponent({ name: "PageFooter", setup() { const frontmatter = usePageFrontmatter(); const themeLocale = useThemeLocaleData(); const author = usePageAuthor(); const enable = computed(() => { const { copyright: copyright2, footer } = frontmatter.value; return footer !== false && Boolean(copyright2 || footer || themeLocale.value.displayFooter); }); const content = computed(() => { const { footer } = frontmatter.value; return footer === false ? false : isString(footer) ? footer : themeLocale.value.footer || ""; }); const copyright = computed( () => "copyright" in frontmatter.value ? frontmatter.value.copyright : "copyright" in themeLocale.value ? themeLocale.value.copyright : author.value.length ? `Copyright © ${( new Date()).getFullYear()} ${author.value[0].name}` : false ); return () => enable.value ? h("footer", { class: "vp-footer-wrapper" }, [ content.value ? h("div", { class: "vp-footer", innerHTML: content.value }) : null, copyright.value ? h("div", { class: "vp-copyright", innerHTML: copyright.value }) : null ]) : null; } }); var DropdownLink = defineComponent({ name: "NavbarDropdownLink", props: { /** * Dropdown config * * 下拉列表配置 */ config: { type: Object, required: true } }, slots: Object, setup(props, { slots }) { const page = usePageData(); const config = toRef(props, "config"); const dropdownAriaLabel = computed( () => config.value.ariaLabel || config.value.text ); const open = ref(false); watch( () => page.value.path, () => { open.value = false; } ); const handleDropdown = (event) => { const isTriggerByTab = event.detail === 0; if (isTriggerByTab) open.value = !open.value; }; return () => { var _a; return h("div", { class: ["dropdown-wrapper", { open: open.value }] }, [ h( "button", { type: "button", class: "dropdown-title", "aria-label": dropdownAriaLabel.value, onClick: handleDropdown }, [ ((_a = slots.title) == null ? void 0 : _a.call(slots)) || h("span", { class: "title" }, [ h(HopeIcon$1, { icon: config.value.icon }), props.config.text ]), h("span", { class: "arrow" }), h( "ul", { class: "nav-dropdown" }, config.value.children.map((child, index) => { const isLastChild = index === config.value.children.length - 1; return h( "li", { class: "dropdown-item" }, "children" in child ? [ h( "h4", { class: "dropdown-subtitle" }, child.link ? h(AutoLink, { config: child, onFocusout: () => { if ( // no children child.children.length === 0 && isLastChild ) open.value = false; } }) : h("span", child.text) ), h( "ul", { class: "dropdown-subitem-wrapper" }, child.children.map( (grandchild, grandIndex) => h( "li", { class: "dropdown-subitem" }, h(AutoLink, { config: grandchild, onFocusout: () => { if ( // last item of grandchild grandIndex === child.children.length - 1 && isLastChild ) open.value = false; } }) ) ) ) ] : h(AutoLink, { config: child, onFocusout: () => { if (isLastChild) open.value = false; } }) ); }) ) ] ) ]); }; } }); const I18nIcon = () => h(IconBase, { name: "i18n" }, () => [ h("path", { d: "M379.392 460.8 494.08 575.488l-42.496 102.4L307.2 532.48 138.24 701.44l-71.68-72.704L234.496 460.8l-45.056-45.056c-27.136-27.136-51.2-66.56-66.56-108.544h112.64c7.68 14.336 16.896 27.136 26.112 35.84l45.568 46.08 45.056-45.056C382.976 312.32 409.6 247.808 409.6 204.8H0V102.4h256V0h102.4v102.4h256v102.4H512c0 70.144-37.888 161.28-87.04 210.944L378.88 460.8zM576 870.4 512 1024H409.6l256-614.4H768l256 614.4H921.6l-64-153.6H576zM618.496 768h196.608L716.8 532.48 618.496 768z" }) ]); I18nIcon.displayName = "I18nIcon"; const resolveNavbarItem = (router, item, prefix = "") => { if (isString(item)) return resolveLinkInfo(router, `${prefix}${item}`); if ("children" in item) return { ...item, ...item.link && !isLinkExternal(item.link) ? resolveLinkInfo(router, `${prefix}${item.link}`) : {}, children: item.children.map( (child) => resolveNavbarItem(router, child, `${prefix}${item.prefix || ""}`) ) }; return { ...item, link: isLinkExternal(item.link) ? item.link : resolveLinkInfo(router, `${prefix}${item.link}`).link }; }; const useNavbarItems = () => { const themeLocaleData = useThemeLocaleData(); const router = useRouter(); const getNavbarItems = () => (themeLocaleData.value.navbar || []).map( (item) => resolveNavbarItem(router, item) ); const navbarItems = ref(getNavbarItems()); watch(themeLocaleData, () => { navbarItems.value = getNavbarItems(); }); return navbarItems; }; const useNavbarLanguageDropdown = () => { const router = useRouter(); const route = useRoute(); const routeLocale = useRouteLocale(); const siteLocale = useSiteLocaleData(); const themeData = useThemeData(); const themeLocale = useThemeLocaleData(); return computed(() => { const localePaths = keys(siteLocale.value.locales); const extraLocales = entries(themeData.value.extraLocales ?? {}); if (localePaths.length < 2 && !extraLocales.length) return null; const { path, fullPath } = router.currentRoute.value; const { navbarLocales } = themeLocale.value; const languageDropdown = { text: "", ariaLabel: navbarLocales == null ? void 0 : navbarLocales.selectLangAriaLabel, children: [ ...localePaths.map((targetLocalePath) => { var _a, _b, _c; const targetSiteLocale = ((_a = siteLocale.value.locales) == null ? void 0 : _a[targetLocalePath]) ?? {}; const targetThemeLocale = ((_b = themeData.value.locales) == null ? void 0 : _b[targetLocalePath]) ?? {}; const targetLang = targetSiteLocale.lang || ""; const text = ((_c = targetThemeLocale.navbarLocales) == null ? void 0 : _c.langName) ?? targetLang; let link; if (targetLang === siteLocale.value.lang) { link = path; } else { const targetLocalePage = path.replace( routeLocale.value, targetLocalePath ); link = // try to link to the corresponding page of current page router.getRoutes().some((item) => item.path === targetLocalePage) ? ( // try to keep current hash across languages fullPath.replace(path, targetLocalePage) ) : ( // or fallback to homepage targetThemeLocale.home ?? targetLocalePath ); } return { text, link }; }), ...extraLocales.map(([text, path2]) => ({ text, link: path2.replace( ":route", route.path.replace(routeLocale.value, "") ) })) ] }; return languageDropdown; }); }; const useNavbarRepo = () => { const themeLocale = useThemeLocaleData(); const repo = computed(() => themeLocale.value.repo || null); const repoLink = computed( () => repo.value ? resolveRepoLink(repo.value) : null ); const repoType = computed( () => repo.value ? resolveRepoType(repo.value) : null ); const repoLabel = computed( () => repoLink.value ? themeLocale.value.repoLabel ?? (repoType.value === null ? "Source" : repoType.value) : null ); return computed(() => { if (!repoLink.value || !repoLabel.value || themeLocale.value.repoDisplay === false) return null; return { type: repoType.value || "Source", label: repoLabel.value, link: repoLink.value }; }); }; var LanguageDropdown = defineComponent({ name: "LanguageDropdown", setup() { const dropdown = useNavbarLanguageDropdown(); return () => dropdown.value ? h( "div", { class: "nav-item" }, h( DropdownLink, { class: "i18n-dropdown", config: dropdown.value }, { title: () => { var _a; return h(I18nIcon, { "aria-label": (_a = dropdown.value) == null ? void 0 : _a.ariaLabel, style: { width: "1rem", height: "1rem", verticalAlign: "middle" } }); } } ) ) : null; } }); var NavScreenDropdown = defineComponent({ name: "NavScreenDropdown", props: { /** * Navbar Screen Dropdown list config * * 导航栏下拉列表配置 */ config: { type: Object, required: true } }, setup(props) { const page = usePageData(); const config = toRef(props, "config"); const dropdownAriaLabel = computed( () => config.value.ariaLabel || config.value.text ); const open = ref(false); watch( () => page.value.path, () => { open.value = false; } ); const isLastItemOfArray = (item, arr) => arr[arr.length - 1] === item; return () => [ h( "button", { type: "button", class: ["nav-screen-dropdown-title", { active: open.value }], "aria-label": dropdownAriaLabel.value, onClick: () => { open.value = !open.value; } }, [ h("span", { class: "title" }, [ h(HopeIcon$1, { icon: config.value.icon }), props.config.text ]), h("span", { class: ["arrow", open.value ? "down" : "end"] }) ] ), h( "ul", { class: ["nav-screen-dropdown", { hide: !open.value }] }, config.value.children.map( (child) => h( "li", { class: "dropdown-item" }, "children" in child ? [ h( "h4", { class: "dropdown-subtitle" }, child.link ? h(AutoLink, { config: child, onFocusout: () => { if (isLastItemOfArray(child, config.value.children) && child.children.length === 0) open.value = false; } }) : h("span", child.text) ), h( "ul", { class: "dropdown-subitem-wrapper" }, child.children.map( (grandchild) => h( "li", { class: "dropdown-subitem" }, h(AutoLink, { config: grandchild, onFocusout: () => { if (isLastItemOfArray(grandchild, child.children) && isLastItemOfArray(child, config.value.children)) open.value = false; } }) ) ) ) ] : h(AutoLink, { config: child, onFocusout: () => { if (isLastItemOfArray(child, config.value.children)) open.value = false; } }) ) ) ) ]; } }); var NavScreenLinks = defineComponent({ name: "NavScreenLinks", setup() { const navbarConfig = useNavbarItems(); return () => navbarConfig.value.length ? h( "nav", { class: "nav-screen-links" }, navbarConfig.value.map( (config) => h( "div", { class: "navbar-links-item" }, "children" in config ? h(NavScreenDropdown, { config }) : h(AutoLink, { config }) ) ) ) : null; } }); const DarkIcon = () => h( IconBase, { name: "dark" }, () => h("path", { d: "M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z" }) ); DarkIcon.displayName = "DarkIcon"; const LightIcon = () => h( IconBase, { name: "light" }, () => h("path", { d: "M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z" }) ); LightIcon.displayName = "LightIcon"; const AutoIcon = () => h( IconBase, { name: "auto" }, () => h("path", { d: "M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z" }) ); AutoIcon.displayName = "AutoIcon"; const EnterFullScreenIcon = () => h( IconBase, { name: "enter-fullscreen" }, () => h("path", { d: "M762.773 90.24h-497.28c-96.106 0-174.4 78.293-174.4 174.4v497.28c0 96.107 78.294 174.4 174.4 174.4h497.28c96.107 0 175.04-78.293 174.4-174.4V264.64c0-96.213-78.186-174.4-174.4-174.4zm-387.2 761.173H215.04c-21.867 0-40.427-17.92-41.067-41.066V649.92c0-22.507 17.92-40.427 40.427-40.427 11.307 0 21.227 4.694 28.48 11.947 7.253 7.253 11.947 17.92 11.947 28.48v62.293l145.28-145.28c15.893-15.893 41.813-15.893 57.706 0 15.894 15.894 15.894 41.814 0 57.707l-145.28 145.28h62.294c22.506 0 40.426 17.92 40.426 40.427s-17.173 41.066-39.68 41.066zM650.24 165.76h160.427c21.866 0 40.426 17.92 41.066 41.067v160.426c0 22.507-17.92 40.427-40.426 40.427-11.307 0-21.227-4.693-28.48-11.947-7.254-7.253-11.947-17.92-11.947-28.48v-62.186L625.6 450.347c-15.893 15.893-41.813 15.893-57.707 0-15.893-15.894-15.893-41.814 0-57.707l145.28-145.28H650.88c-22.507 0-40.427-17.92-40.427-40.427s17.174-41.173 39.787-41.173z" }) ); EnterFullScreenIcon.displayName = "EnterFullScreenIcon"; const CancelFullScreenIcon = () => h( IconBase, { name: "cancel-fullscreen" }, () => h("path", { d: "M778.468 78.62H247.922c-102.514 0-186.027 83.513-186.027 186.027V795.08c0 102.514 83.513 186.027 186.027 186.027h530.432c102.514 0 186.71-83.513 186.026-186.027V264.647C964.494 162.02 880.981 78.62 778.468 78.62zM250.88 574.35h171.122c23.324 0 43.122 19.115 43.804 43.805v171.121c0 24.008-19.114 43.122-43.122 43.122-12.06 0-22.641-5.006-30.378-12.743s-12.743-19.115-12.743-30.379V722.83L224.597 877.91c-16.953 16.952-44.6 16.952-61.553 0-16.953-16.954-16.953-44.602 0-61.554L318.009 661.39h-66.446c-24.007 0-43.122-19.114-43.122-43.122 0-24.12 18.432-43.918 42.439-43.918zm521.899-98.873H601.657c-23.325 0-43.122-19.114-43.805-43.804V260.55c0-24.007 19.115-43.122 43.122-43.122 12.06 0 22.642 5.007 30.379 12.743s12.743 19.115 12.743 30.38v66.445l154.965-154.965c16.953-16.953 44.601-16.953 61.554 0 16.953 16.953 16.953 44.6 0 61.554L705.536 388.55h66.446c24.007 0 43.122 19.115 43.122 43.122.114 24.007-18.318 43.804-42.325 43.804z" }) ); CancelFullScreenIcon.displayName = "CancelFullScreenIcon"; const OutlookIcon = () => h(IconBase, { name: "outlook" }, () => [ h("path", { d: "M224 800c0 9.6 3.2 44.8 6.4 54.4 6.4 48-48 76.8-48 76.8s80 41.6 147.2 0 134.4-134.4 38.4-195.2c-22.4-12.8-41.6-19.2-57.6-19.2C259.2 716.8 227.2 761.6 224 800zM560 675.2l-32 51.2c-51.2 51.2-83.2 32-83.2 32 25.6 67.2 0 112-12.8 128 25.6 6.4 51.2 9.6 80 9.6 54.4 0 102.4-9.6 150.4-32l0 0c3.2 0 3.2-3.2 3.2-3.2 22.4-16 12.8-35.2 6.4-44.8-9.6-12.8-12.8-25.6-12.8-41.6 0-54.4 60.8-99.2 137.6-99.2 6.4 0 12.8 0 22.4 0 12.8 0 38.4 9.6 48-25.6 0-3.2 0-3.2 3.2-6.4 0-3.2 3.2-6.4 3.2-6.4 6.4-16 6.4-16 6.4-19.2 9.6-35.2 16-73.6 16-115.2 0-105.6-41.6-198.4-108.8-268.8C704 396.8 560 675.2 560 675.2zM224 419.2c0-28.8 22.4-51.2 51.2-51.2 28.8 0 51.2 22.4 51.2 51.2 0 28.8-22.4 51.2-51.2 51.2C246.4 470.4 224 448 224 419.2zM320 284.8c0-22.4 19.2-41.6 41.6-41.6 22.4 0 41.6 19.2 41.6 41.6 0 22.4-19.2 41.6-41.6 41.6C339.2 326.4 320 307.2 320 284.8zM457.6 208c0-12.8 12.8-25.6 25.6-25.6 12.8 0 25.6 12.8 25.6 25.6 0 12.8-12.8 25.6-25.6 25.6C470.4 233.6 457.6 220.8 457.6 208zM128 505.6C128 592 153.6 672 201.6 736c28.8-60.8 112-60.8 124.8-60.8-16-51.2 16-99.2 16-99.2l316.8-422.4c-48-19.2-99.2-32-150.4-32C297.6 118.4 128 291.2 128 505.6zM764.8 86.4c-22.4 19.2-390.4 518.4-390.4 518.4-22.4 28.8-12.8 76.8 22.4 99.2l9.6 6.4c35.2 22.4 80 12.8 99.2-25.6 0 0 6.4-12.8 9.6-19.2 54.4-105.6 275.2-524.8 288-553.6 6.4-19.2-3.2-32-19.2-32C777.6 76.8 771.2 80 764.8 86.4z" }) ]); OutlookIcon.displayName = "OutlookIcon"; var AppearanceSwitch = defineComponent({ name: "AppearanceSwitch", setup() { const { config, status } = useDarkmode(); const toggleDarkMode = () => { if (config.value === "switch") status.value = { light: "dark", dark: "auto", auto: "light" }[status.value]; else status.value = status.value === "light" ? "dark" : "light"; }; return () => h( "button", { type: "button", id: "appearance-switch", onClick: () => toggleDarkMode() }, [ h(AutoIcon, { style: { display: status.value === "auto" ? "block" : "none" } }), h(DarkIcon, { style: { display: status.value === "dark" ? "block" : "none" } }), h(LightIcon, { style: { display: status.value === "light" ? "block" : "none" } }) ] ); } }); var AppearanceMode = defineComponent({ name: "AppearanceMode", setup() { const themeLocale = useThemeLocaleData(); const { canToggle } = useDarkmode(); const locale = computed(() => themeLocale.value.outlookLocales.darkmode); return () => canToggle.value ? h("div", { class: "appearance-wrapper" }, [ h( "label", { class: "appearance-title", for: "appearance-switch" }, locale.value ), h(AppearanceSwitch) ]) : null; } }); const THEME_COLOR_KEY = "VUEPRESS_THEME_COLOR"; var ThemeColorPicker = defineComponent({ name: "ThemeColorPicker", props: { /** * Theme color picker config * * 主题色选择器配置 */ themeColor: { type: Object, required: true } }, setup(props) { const setThemeColor = (theme = "") => { const classes = document.documentElement.classList; const themes = keys(props.themeColor); if (!theme) { localStorage.removeItem(THEME_COLOR_KEY); classes.remove(...themes); return; } classes.remove( ...themes.filter((themeColorClass) => themeColorClass !== theme) ); classes.add(theme); localStorage.setItem(THEME_COLOR_KEY, theme); }; onMounted(() => { const theme = localStorage.getItem(THEME_COLOR_KEY); if (theme) setThemeColor(theme); }); return () => h("ul", { id: "theme-color-picker" }, [ h( "li", h("span", { class: "theme-color", onClick: () => setThemeColor() }) ), entries(props.themeColor).map( ([color, value]) => h( "li", h("span", { style: { background: value }, onClick: () => setThemeColor(color) }) ) ) ]); } }); const enableThemeColor = cssVariables["enableThemeColor"] === "true"; const themeColor = enableThemeColor ? fromEntries( entries(cssVariables).filter(([key]) => key.startsWith("theme-")) ) : {}; var ThemeColor = defineComponent({ name: "ThemeColor", setup() { const themeLocale = useThemeLocaleData(); const locale = computed(() => themeLocale.value.outlookLocales.themeColor); return () => enableThemeColor ? h("div", { class: "theme-color-wrapper" }, [ h( "label", { class: "theme-color-title", for: "theme-color-picker" }, locale.value ), h(ThemeColorPicker, { themeColor }) ]) : null; } }); var ToggleFullScreenButton = defineComponent({ name: "ToggleFullScreenButton", setup() { const themeLocale = useThemeLocaleData(); const { isSupported, isFullscreen, toggle } = useFullscreen(); const fullscreenLocale = computed( () => themeLocale.value.outlookLocales.fullscreen ); return () => isSupported ? h("div", { class: "full-screen-wrapper" }, [ h( "label", { class: "full-screen-title", for: "full-screen-switch" }, fullscreenLocale.value ), h( "button", { type: "button", id: "full-screen-switch", class: "full-screen", ariaPressed: isFullscreen.value, onClick: () => toggle() }, isFullscreen.value ? h(CancelFullScreenIcon) : h(EnterFullScreenIcon) ) ]) : null; } }); var OutlookSettings = defineComponent({ name: "OutlookSettings", setup() { const themeData = useThemeData(); const pure = usePure(); const enableFullScreen = computed( () => !pure.value && themeData.value.fullscreen ); return () => h(ClientOnly, () => [ enableThemeColor ? h(ThemeColor) : null, h(AppearanceMode), enableFullScreen.value ? h(ToggleFullScreenButton) : null ]); } }); var NavScreen = defineComponent({ name: "NavScreen", props: { /** * Whether to show the screen * * 是否显示 */ show: Boolean }, emits: ["close"], slots: Object, setup(props, { emit, slots }) { const page = usePageData(); const { isMobile } = useWindowSize(); const body = shallowRef(); const isLocked = useScrollLock(body); onMounted(() => { body.value = document.body; watch(isMobile, (value) => { if (!value && props.show) { isLocked.value = false; emit("close"); } }); watch( () => page.value.path, () => { isLocked.value = false; emit("close"); } ); }); onUnmounted(() => { isLocked.value = false; }); return () => h( Transition, { name: "fade", onEnter: () => { isLocked.value = true; }, onAfterLeave: () => { isLocked.value = false; } }, () => { var _a, _b; return props.show ? h( "div", { id: "nav-screen" }, h("div", { class: "vp-nav-screen-container" }, [ (_a = slots.before) == null ? void 0 : _a.call(slots), h(NavScreenLinks), h("div", { class: "vp-outlook-wrapper" }, h(OutlookSettings)), (_b = slots.after) == null ? void 0 : _b.call(slots) ]) ) : null; } ); } }); var NavbarBrand = defineComponent({ name: "NavbarBrand", setup() { const routeLocale = useRouteLocale(); const siteLocale = useSiteLocaleData(); const themeLocale = useThemeLocaleData(); const siteBrandLink = computed( () => themeLocale.value.home || routeLocale.value ); const siteTitle = computed(() => siteLocale.value.title); const siteBrandTitle = computed( () => themeLocale.value.navTitle ?? siteTitle.value ); const siteBrandLogo = computed( () => themeLocale.value.logo ? withBase(themeLocale.value.logo) : null ); const siteBrandLogoDark = computed( () => themeLocale.value.logoDark ? withBase(themeLocale.value.logoDark) : null ); return () => h(VPLink, { to: siteBrandLink.value, class: "vp-brand" }, () => [ siteBrandLogo.value ? h("img", { class: [ "vp-nav-logo", { light: Boolean(siteBrandLogoDark.value) } ], src: siteBrandLogo.value, alt: siteTitle.value }) : null, siteBrandLogoDark.value ? h("img", { class: ["vp-nav-logo dark"], src: siteBrandLogoDark.value, alt: siteTitle.value }) : null, siteBrandTitle.value ? h( "span", { class: [ "vp-site-name", { "hide-in-pad": siteBrandLogo.value && themeLocale.value.hideSiteNameOnMobile !== false } ] }, siteBrandTitle.value ) : null ]); } }); var NavbarLinks = defineComponent({ name: "NavbarLinks", setup() { const navbarConfig = useNavbarItems(); return () => navbarConfig.value.length ? h( "nav", { class: "vp-nav-links" }, navbarConfig.value.map( (config) => h( "div", { class: "nav-item hide-in-mobile" }, "children" in config ? h(DropdownLink, { config }) : h(AutoLink, { config }) ) ) ) : null; } }); var RepoLink = defineComponent({ name: "RepoLink", components: { BitbucketIcon, GiteeIcon, GitHubIcon, GitLabIcon, SourceIcon }, setup() { const repo = useNavbarRepo(); return () => repo.value ? h( "div", { class: "nav-item vp-repo" }, h( "a", { class: "vp-repo-link", href: repo.value.link, target: "_blank", rel: "noopener noreferrer", "aria-label": repo.value.label }, h(resolveComponent(`${repo.value.type}Icon`), { style: { width: "1.25rem", height: "1.25rem", verticalAlign: "middle" } }) ) ) : null; } }); const ToggleNavbarButton = ({ active = false }, { emit }) => h( "button", { type: "button", class: ["vp-toggle-navbar-button", { "is-active": active }], "aria-label": "Toggle Navbar", "aria-expanded": active, "aria-controls": "nav-screen", onClick: () => emit("toggle") }, h("span", [ h("span", { class: "vp-top" }), h("span", { class: "vp-middle" }), h("span", { class: "vp-bottom" }) ]) ); ToggleNavbarButton.displayName = "ToggleNavbarButton"; var ToggleNavbarButton$1 = ToggleNavbarButton; const ToggleSidebarButton = (_, { emit }) => h( "button", { type: "button", class: "vp-toggle-sidebar-button", title: "Toggle Sidebar", onClick: () => emit("toggle") }, h("span", { class: "icon" }) ); ToggleSidebarButton.displayName = "ToggleSidebarButton"; ToggleSidebarButton.emits = ["toggle"]; var ToggleSidebarButton$1 = ToggleSidebarButton; var OutlookButton = defineComponent({ name: "OutlookButton", setup() { const { isSupported } = useFullscreen(); const themeData = useThemeData(); const pure = usePure(); const page = usePageData(); const { canToggle } = useDarkmode(); const open = ref(false); const enableFullScreen = computed( () => !pure.value && themeData.value.fullscreen && isSupported ); watch( () => page.value.path, () => { open.value = false; } ); return () => canToggle.value || enableFullScreen.value || enableThemeColor ? h( "div", { class: "nav-item hide-in-mobile" }, // only AppearanceSwitch is enabled canToggle.value && !enableFullScreen.value && !enableThemeColor ? h(AppearanceSwitch) : ( // only FullScreen is enabled enableFullScreen.value && !canToggle.value && !enableThemeColor ? h(ToggleFullScreenButton) : h( "button", { type: "button", class: ["outlook-button", { open: open.value }], tabindex: "-1", "aria-hidden": true }, [ h(OutlookIcon), h("div", { class: "outlook-dropdown" }, h(OutlookSettings)) ] ) ) ) : null; } }); var Navbar = defineComponent({ name: "NavBar", emits: ["toggleSidebar"], slots: Object, setup(_props, { emit, slots }) { const themeLocale = useThemeLocaleData(); const { isMobile } = useWindowSize(); const showScreen = ref(false); const autoHide = computed(() => { const { navbarAutoHide = "mobile" } = themeLocale.value; return navbarAutoHide !== "none" && (navbarAutoHide === "always" || isMobile.value); }); const navbarLayout = computed( () => themeLocale.value.navbarLayout || { start: ["Brand"], center: ["Links"], end: ["Language", "Repo", "Outlook", "Search"] } ); const navbarComponentMap = { Brand: NavbarBrand, Language: HAS_MULTIPLE_LANGUAGES ? LanguageDropdown : noopModule, Links: NavbarLinks, Repo: RepoLink, Outlook: OutlookButton, Search: hasGlobalComponent("Docsearch") ? resolveComponent("Docsearch") : hasGlobalComponent("SearchBox") ? resolveComponent("SearchBox") : noopModule }; const getNavbarComponent = (component) => navbarComponentMap[component] ?? (hasGlobalComponent(component) ? resolveComponent(component) : noopModule); return () => { var _a, _b, _c, _d, _e, _f; return [ h( "header", { id: "navbar", class: [ "vp-navbar", { "auto-hide": autoHide.value, "hide-icon": themeLocale.value.navbarIcon === false } ] }, [ h("div", { class: "vp-navbar-start" }, [ h(ToggleSidebarButton$1, { onToggle: () => { if (showScreen.value) showScreen.value = false; emit("toggleSidebar"); } }), (_a = slots.startBefore) == null ? void 0 : _a.call(slots), (navbarLayout.value.start || []).map( (item) => h( getNavbarComponent(item) ) ), (_b = slots.startAfter) == null ? void 0 : _b.call(slots) ]), h("div", { class: "vp-navbar-center" }, [ (_c = slots.centerBefore) == null ? void 0 : _c.call(slots), (navbarLayout.value.center || []).map( (item) => h( getNavbarComponent(item) ) ), (_d = slots.centerAfter) == null ? void 0 : _d.call(slots) ]), h("div", { class: "vp-navbar-end" }, [ (_e = slots.endBefore) == null ? void 0 : _e.call(slots), (navbarLayout.value.end || []).map( (item) => h( getNavbarComponent(item) ) ), (_