hirsun-vuepress-theme-hope-plus
Version:
A light vuepress theme with tons of features and typewriter effect
1,431 lines (1,392 loc) • 88.6 kB
JavaScript
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)
)
),
(_