themekit-js 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +27 -0
- package/bin/themekit.js +2 -0
- package/client.d.ts +5 -0
- package/dist/client/app/components/ClientOnly.js +10 -0
- package/dist/client/app/components/Content.js +23 -0
- package/dist/client/app/composables/codeGroups.js +40 -0
- package/dist/client/app/composables/copyCode.js +73 -0
- package/dist/client/app/composables/head.js +81 -0
- package/dist/client/app/composables/preFetch.js +99 -0
- package/dist/client/app/data.js +59 -0
- package/dist/client/app/devtools.js +29 -0
- package/dist/client/app/index.js +140 -0
- package/dist/client/app/router.js +233 -0
- package/dist/client/app/ssr.js +10 -0
- package/dist/client/app/theme.js +1 -0
- package/dist/client/app/utils.js +119 -0
- package/dist/client/index.d.ts +1446 -0
- package/dist/client/index.js +9 -0
- package/dist/client/shared.js +139 -0
- package/dist/client/theme-default/Layout.vue +94 -0
- package/dist/client/theme-default/NotFound.vue +109 -0
- package/dist/client/theme-default/components/VPAlgoliaSearchBox.vue +99 -0
- package/dist/client/theme-default/components/VPBackdrop.vue +41 -0
- package/dist/client/theme-default/components/VPBadge.vue +86 -0
- package/dist/client/theme-default/components/VPButton.vue +123 -0
- package/dist/client/theme-default/components/VPCarbonAds.vue +109 -0
- package/dist/client/theme-default/components/VPContent.vue +98 -0
- package/dist/client/theme-default/components/VPDoc.vue +193 -0
- package/dist/client/theme-default/components/VPDocAside.vue +46 -0
- package/dist/client/theme-default/components/VPDocAsideCarbonAds.vue +18 -0
- package/dist/client/theme-default/components/VPDocAsideOutline.vue +87 -0
- package/dist/client/theme-default/components/VPDocAsideSponsors.vue +17 -0
- package/dist/client/theme-default/components/VPDocFooter.vue +145 -0
- package/dist/client/theme-default/components/VPDocFooterLastUpdated.vue +50 -0
- package/dist/client/theme-default/components/VPDocOutlineItem.vue +59 -0
- package/dist/client/theme-default/components/VPFeature.vue +123 -0
- package/dist/client/theme-default/components/VPFeatures.vue +121 -0
- package/dist/client/theme-default/components/VPFlyout.vue +136 -0
- package/dist/client/theme-default/components/VPFooter.vue +60 -0
- package/dist/client/theme-default/components/VPHero.vue +336 -0
- package/dist/client/theme-default/components/VPHome.vue +43 -0
- package/dist/client/theme-default/components/VPHomeContent.vue +52 -0
- package/dist/client/theme-default/components/VPHomeFeatures.vue +14 -0
- package/dist/client/theme-default/components/VPHomeHero.vue +24 -0
- package/dist/client/theme-default/components/VPHomeSponsors.vue +116 -0
- package/dist/client/theme-default/components/VPImage.vue +46 -0
- package/dist/client/theme-default/components/VPLink.vue +33 -0
- package/dist/client/theme-default/components/VPLocalNav.vue +171 -0
- package/dist/client/theme-default/components/VPLocalNavOutlineDropdown.vue +190 -0
- package/dist/client/theme-default/components/VPLocalSearchBox.vue +856 -0
- package/dist/client/theme-default/components/VPMenu.vue +72 -0
- package/dist/client/theme-default/components/VPMenuGroup.vue +47 -0
- package/dist/client/theme-default/components/VPMenuLink.vue +54 -0
- package/dist/client/theme-default/components/VPNav.vue +57 -0
- package/dist/client/theme-default/components/VPNavBar.vue +267 -0
- package/dist/client/theme-default/components/VPNavBarAppearance.vue +25 -0
- package/dist/client/theme-default/components/VPNavBarExtra.vue +94 -0
- package/dist/client/theme-default/components/VPNavBarHamburger.vue +79 -0
- package/dist/client/theme-default/components/VPNavBarMenu.vue +29 -0
- package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +42 -0
- package/dist/client/theme-default/components/VPNavBarMenuLink.vue +53 -0
- package/dist/client/theme-default/components/VPNavBarSearch.vue +194 -0
- package/dist/client/theme-default/components/VPNavBarSearchButton.vue +208 -0
- package/dist/client/theme-default/components/VPNavBarSocialLinks.vue +27 -0
- package/dist/client/theme-default/components/VPNavBarTitle.vue +76 -0
- package/dist/client/theme-default/components/VPNavBarTranslations.vue +47 -0
- package/dist/client/theme-default/components/VPNavScreen.vue +99 -0
- package/dist/client/theme-default/components/VPNavScreenAppearance.vue +33 -0
- package/dist/client/theme-default/components/VPNavScreenMenu.vue +23 -0
- package/dist/client/theme-default/components/VPNavScreenMenuGroup.vue +111 -0
- package/dist/client/theme-default/components/VPNavScreenMenuGroupLink.vue +39 -0
- package/dist/client/theme-default/components/VPNavScreenMenuGroupSection.vue +34 -0
- package/dist/client/theme-default/components/VPNavScreenMenuLink.vue +39 -0
- package/dist/client/theme-default/components/VPNavScreenSocialLinks.vue +14 -0
- package/dist/client/theme-default/components/VPNavScreenTranslations.vue +73 -0
- package/dist/client/theme-default/components/VPPage.vue +7 -0
- package/dist/client/theme-default/components/VPSidebar.vue +137 -0
- package/dist/client/theme-default/components/VPSidebarItem.vue +250 -0
- package/dist/client/theme-default/components/VPSkipLink.vue +68 -0
- package/dist/client/theme-default/components/VPSocialLink.vue +50 -0
- package/dist/client/theme-default/components/VPSocialLinks.vue +27 -0
- package/dist/client/theme-default/components/VPSponsors.vue +48 -0
- package/dist/client/theme-default/components/VPSponsorsGrid.vue +48 -0
- package/dist/client/theme-default/components/VPSwitch.vue +63 -0
- package/dist/client/theme-default/components/VPSwitchAppearance.vue +52 -0
- package/dist/client/theme-default/components/VPTeamMembers.vue +66 -0
- package/dist/client/theme-default/components/VPTeamMembersItem.vue +225 -0
- package/dist/client/theme-default/components/VPTeamPage.vue +58 -0
- package/dist/client/theme-default/components/VPTeamPageSection.vue +77 -0
- package/dist/client/theme-default/components/VPTeamPageTitle.vue +63 -0
- package/dist/client/theme-default/components/icons/VPIconAlignJustify.vue +8 -0
- package/dist/client/theme-default/components/icons/VPIconAlignLeft.vue +8 -0
- package/dist/client/theme-default/components/icons/VPIconAlignRight.vue +8 -0
- package/dist/client/theme-default/components/icons/VPIconArrowLeft.vue +7 -0
- package/dist/client/theme-default/components/icons/VPIconArrowRight.vue +7 -0
- package/dist/client/theme-default/components/icons/VPIconChevronDown.vue +5 -0
- package/dist/client/theme-default/components/icons/VPIconChevronLeft.vue +5 -0
- package/dist/client/theme-default/components/icons/VPIconChevronRight.vue +5 -0
- package/dist/client/theme-default/components/icons/VPIconChevronUp.vue +5 -0
- package/dist/client/theme-default/components/icons/VPIconEdit.vue +6 -0
- package/dist/client/theme-default/components/icons/VPIconHeart.vue +5 -0
- package/dist/client/theme-default/components/icons/VPIconLanguages.vue +9 -0
- package/dist/client/theme-default/components/icons/VPIconMinus.vue +5 -0
- package/dist/client/theme-default/components/icons/VPIconMinusSquare.vue +6 -0
- package/dist/client/theme-default/components/icons/VPIconMoon.vue +5 -0
- package/dist/client/theme-default/components/icons/VPIconMoreHorizontal.vue +7 -0
- package/dist/client/theme-default/components/icons/VPIconPlus.vue +5 -0
- package/dist/client/theme-default/components/icons/VPIconPlusSquare.vue +6 -0
- package/dist/client/theme-default/components/icons/VPIconSun.vue +13 -0
- package/dist/client/theme-default/composables/aside.js +17 -0
- package/dist/client/theme-default/composables/data.js +2 -0
- package/dist/client/theme-default/composables/edit-link.js +16 -0
- package/dist/client/theme-default/composables/flyout.js +41 -0
- package/dist/client/theme-default/composables/langs.js +26 -0
- package/dist/client/theme-default/composables/local-nav.js +18 -0
- package/dist/client/theme-default/composables/nav.js +30 -0
- package/dist/client/theme-default/composables/outline.js +178 -0
- package/dist/client/theme-default/composables/prev-next.js +57 -0
- package/dist/client/theme-default/composables/sidebar.js +136 -0
- package/dist/client/theme-default/composables/sponsor-grid.js +94 -0
- package/dist/client/theme-default/fonts/inter-italic-cyrillic-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-cyrillic.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-greek-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-greek.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-latin-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-latin.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-italic-vietnamese.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-cyrillic-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-cyrillic.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-greek-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-greek.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-latin-ext.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-latin.woff2 +0 -0
- package/dist/client/theme-default/fonts/inter-roman-vietnamese.woff2 +0 -0
- package/dist/client/theme-default/index.js +3 -0
- package/dist/client/theme-default/styles/base.css +252 -0
- package/dist/client/theme-default/styles/components/custom-block.css +208 -0
- package/dist/client/theme-default/styles/components/vp-code-group.css +85 -0
- package/dist/client/theme-default/styles/components/vp-code.css +7 -0
- package/dist/client/theme-default/styles/components/vp-doc.css +570 -0
- package/dist/client/theme-default/styles/components/vp-sponsor.css +155 -0
- package/dist/client/theme-default/styles/fonts.css +157 -0
- package/dist/client/theme-default/styles/icons.css +123 -0
- package/dist/client/theme-default/styles/utils.css +9 -0
- package/dist/client/theme-default/styles/vars.css +563 -0
- package/dist/client/theme-default/support/lru.js +33 -0
- package/dist/client/theme-default/support/sidebar.js +89 -0
- package/dist/client/theme-default/support/translation.js +49 -0
- package/dist/client/theme-default/support/utils.js +33 -0
- package/dist/client/theme-default/without-fonts.js +32 -0
- package/dist/node/cli.js +444 -0
- package/dist/node/index.d.ts +4588 -0
- package/dist/node/index.js +198 -0
- package/dist/node/serve-BjvG349_.js +50301 -0
- package/lib/vue-demi.mjs +34 -0
- package/package.json +223 -0
- package/template/.vitepress/config.js +28 -0
- package/template/.vitepress/theme/Layout.vue +21 -0
- package/template/.vitepress/theme/index.js +29 -0
- package/template/.vitepress/theme/style.css +143 -0
- package/template/api-examples.md +49 -0
- package/template/index.md +28 -0
- package/template/markdown-examples.md +85 -0
- package/theme-without-fonts.d.ts +2 -0
- package/theme.d.ts +30 -0
- package/types/default-theme.d.ts +533 -0
- package/types/docsearch.d.ts +144 -0
- package/types/index.d.ts +3 -0
- package/types/local-search.d.ts +33 -0
- package/types/shared.d.ts +199 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { inject, markRaw, nextTick, reactive, readonly } from 'vue';
|
|
2
|
+
import { notFoundPageData, treatAsHtml } from '../shared';
|
|
3
|
+
import { siteDataRef } from './data';
|
|
4
|
+
import { getScrollOffset, inBrowser, withBase } from './utils';
|
|
5
|
+
export const RouterSymbol = Symbol();
|
|
6
|
+
// we are just using URL to parse the pathname and hash - the base doesn't
|
|
7
|
+
// matter and is only passed to support same-host hrefs.
|
|
8
|
+
const fakeHost = 'http://a.com';
|
|
9
|
+
const getDefaultRoute = () => ({
|
|
10
|
+
path: '/',
|
|
11
|
+
component: null,
|
|
12
|
+
data: notFoundPageData
|
|
13
|
+
});
|
|
14
|
+
export function createRouter(loadPageModule, fallbackComponent) {
|
|
15
|
+
const route = reactive(getDefaultRoute());
|
|
16
|
+
const router = {
|
|
17
|
+
route,
|
|
18
|
+
go
|
|
19
|
+
};
|
|
20
|
+
async function go(href = inBrowser ? location.href : '/') {
|
|
21
|
+
href = normalizeHref(href);
|
|
22
|
+
if ((await router.onBeforeRouteChange?.(href)) === false)
|
|
23
|
+
return;
|
|
24
|
+
if (inBrowser && href !== normalizeHref(location.href)) {
|
|
25
|
+
// save scroll position before changing url
|
|
26
|
+
history.replaceState({ scrollPosition: window.scrollY }, document.title);
|
|
27
|
+
history.pushState(null, '', href);
|
|
28
|
+
}
|
|
29
|
+
await loadPage(href);
|
|
30
|
+
await router.onAfterRouteChanged?.(href);
|
|
31
|
+
}
|
|
32
|
+
let latestPendingPath = null;
|
|
33
|
+
async function loadPage(href, scrollPosition = 0, isRetry = false) {
|
|
34
|
+
if ((await router.onBeforePageLoad?.(href)) === false)
|
|
35
|
+
return;
|
|
36
|
+
const targetLoc = new URL(href, fakeHost);
|
|
37
|
+
const pendingPath = (latestPendingPath = targetLoc.pathname);
|
|
38
|
+
try {
|
|
39
|
+
let page = await loadPageModule(pendingPath);
|
|
40
|
+
if (!page) {
|
|
41
|
+
throw new Error(`Page not found: ${pendingPath}`);
|
|
42
|
+
}
|
|
43
|
+
if (latestPendingPath === pendingPath) {
|
|
44
|
+
latestPendingPath = null;
|
|
45
|
+
const { default: comp, __pageData } = page;
|
|
46
|
+
if (!comp) {
|
|
47
|
+
throw new Error(`Invalid route component: ${comp}`);
|
|
48
|
+
}
|
|
49
|
+
route.path = inBrowser ? pendingPath : withBase(pendingPath);
|
|
50
|
+
route.component = markRaw(comp);
|
|
51
|
+
route.data = import.meta.env.PROD
|
|
52
|
+
? markRaw(__pageData)
|
|
53
|
+
: readonly(__pageData);
|
|
54
|
+
if (inBrowser) {
|
|
55
|
+
nextTick(() => {
|
|
56
|
+
let actualPathname = siteDataRef.value.base +
|
|
57
|
+
__pageData.relativePath.replace(/(?:(^|\/)index)?\.md$/, '$1');
|
|
58
|
+
if (!siteDataRef.value.cleanUrls && !actualPathname.endsWith('/')) {
|
|
59
|
+
actualPathname += '.html';
|
|
60
|
+
}
|
|
61
|
+
if (actualPathname !== targetLoc.pathname) {
|
|
62
|
+
targetLoc.pathname = actualPathname;
|
|
63
|
+
href = actualPathname + targetLoc.search + targetLoc.hash;
|
|
64
|
+
history.replaceState(null, '', href);
|
|
65
|
+
}
|
|
66
|
+
if (targetLoc.hash && !scrollPosition) {
|
|
67
|
+
let target = null;
|
|
68
|
+
try {
|
|
69
|
+
target = document.getElementById(decodeURIComponent(targetLoc.hash).slice(1));
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
console.warn(e);
|
|
73
|
+
}
|
|
74
|
+
if (target) {
|
|
75
|
+
scrollTo(target, targetLoc.hash);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
window.scrollTo(0, scrollPosition);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
if (!/fetch|Page not found/.test(err.message) &&
|
|
86
|
+
!/^\/404(\.html|\/)?$/.test(href)) {
|
|
87
|
+
console.error(err);
|
|
88
|
+
}
|
|
89
|
+
// retry on fetch fail: the page to hash map may have been invalidated
|
|
90
|
+
// because a new deploy happened while the page is open. Try to fetch
|
|
91
|
+
// the updated pageToHash map and fetch again.
|
|
92
|
+
if (!isRetry) {
|
|
93
|
+
try {
|
|
94
|
+
const res = await fetch(siteDataRef.value.base + 'hashmap.json');
|
|
95
|
+
window.__VP_HASH_MAP__ = await res.json();
|
|
96
|
+
await loadPage(href, scrollPosition, true);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
catch (e) { }
|
|
100
|
+
}
|
|
101
|
+
if (latestPendingPath === pendingPath) {
|
|
102
|
+
latestPendingPath = null;
|
|
103
|
+
route.path = inBrowser ? pendingPath : withBase(pendingPath);
|
|
104
|
+
route.component = fallbackComponent ? markRaw(fallbackComponent) : null;
|
|
105
|
+
route.data = notFoundPageData;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (inBrowser) {
|
|
110
|
+
window.addEventListener('click', (e) => {
|
|
111
|
+
// temporary fix for docsearch action buttons
|
|
112
|
+
const button = e.target.closest('button');
|
|
113
|
+
if (button)
|
|
114
|
+
return;
|
|
115
|
+
const link = e.target.closest('a');
|
|
116
|
+
if (link &&
|
|
117
|
+
!link.closest('.vp-raw') &&
|
|
118
|
+
(link instanceof SVGElement || !link.download)) {
|
|
119
|
+
const { target } = link;
|
|
120
|
+
const { href, origin, pathname, hash, search } = new URL(link.href instanceof SVGAnimatedString
|
|
121
|
+
? link.href.animVal
|
|
122
|
+
: link.href, link.baseURI);
|
|
123
|
+
const currentUrl = new URL(location.href); // copy to keep old data
|
|
124
|
+
// only intercept inbound html links
|
|
125
|
+
if (!e.ctrlKey &&
|
|
126
|
+
!e.shiftKey &&
|
|
127
|
+
!e.altKey &&
|
|
128
|
+
!e.metaKey &&
|
|
129
|
+
!target &&
|
|
130
|
+
origin === currentUrl.origin &&
|
|
131
|
+
treatAsHtml(pathname)) {
|
|
132
|
+
e.preventDefault();
|
|
133
|
+
if (pathname === currentUrl.pathname &&
|
|
134
|
+
search === currentUrl.search) {
|
|
135
|
+
// scroll between hash anchors in the same page
|
|
136
|
+
// avoid duplicate history entries when the hash is same
|
|
137
|
+
if (hash !== currentUrl.hash) {
|
|
138
|
+
history.pushState(null, '', href);
|
|
139
|
+
// still emit the event so we can listen to it in themes
|
|
140
|
+
window.dispatchEvent(new HashChangeEvent('hashchange', {
|
|
141
|
+
oldURL: currentUrl.href,
|
|
142
|
+
newURL: href
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
if (hash) {
|
|
146
|
+
// use smooth scroll when clicking on header anchor links
|
|
147
|
+
scrollTo(link, hash, link.classList.contains('header-anchor'));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
window.scrollTo(0, 0);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
go(href);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}, { capture: true });
|
|
159
|
+
window.addEventListener('popstate', async (e) => {
|
|
160
|
+
await loadPage(normalizeHref(location.href), (e.state && e.state.scrollPosition) || 0);
|
|
161
|
+
router.onAfterRouteChanged?.(location.href);
|
|
162
|
+
});
|
|
163
|
+
window.addEventListener('hashchange', (e) => {
|
|
164
|
+
e.preventDefault();
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
handleHMR(route);
|
|
168
|
+
return router;
|
|
169
|
+
}
|
|
170
|
+
export function useRouter() {
|
|
171
|
+
const router = inject(RouterSymbol);
|
|
172
|
+
if (!router) {
|
|
173
|
+
throw new Error('useRouter() is called without provider.');
|
|
174
|
+
}
|
|
175
|
+
return router;
|
|
176
|
+
}
|
|
177
|
+
export function useRoute() {
|
|
178
|
+
return useRouter().route;
|
|
179
|
+
}
|
|
180
|
+
export function scrollTo(el, hash, smooth = false) {
|
|
181
|
+
let target = null;
|
|
182
|
+
try {
|
|
183
|
+
target = el.classList.contains('header-anchor')
|
|
184
|
+
? el
|
|
185
|
+
: document.getElementById(decodeURIComponent(hash).slice(1));
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
console.warn(e);
|
|
189
|
+
}
|
|
190
|
+
if (target) {
|
|
191
|
+
const targetPadding = parseInt(window.getComputedStyle(target).paddingTop, 10);
|
|
192
|
+
const targetTop = window.scrollY +
|
|
193
|
+
target.getBoundingClientRect().top -
|
|
194
|
+
getScrollOffset() +
|
|
195
|
+
targetPadding;
|
|
196
|
+
function scrollToTarget() {
|
|
197
|
+
// only smooth scroll if distance is smaller than screen height.
|
|
198
|
+
if (!smooth || Math.abs(targetTop - window.scrollY) > window.innerHeight)
|
|
199
|
+
window.scrollTo(0, targetTop);
|
|
200
|
+
else
|
|
201
|
+
window.scrollTo({ left: 0, top: targetTop, behavior: 'smooth' });
|
|
202
|
+
}
|
|
203
|
+
requestAnimationFrame(scrollToTarget);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function handleHMR(route) {
|
|
207
|
+
// update route.data on HMR updates of active page
|
|
208
|
+
if (import.meta.hot) {
|
|
209
|
+
// hot reload pageData
|
|
210
|
+
import.meta.hot.on('vitepress:pageData', (payload) => {
|
|
211
|
+
if (shouldHotReload(payload)) {
|
|
212
|
+
route.data = payload.pageData;
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function shouldHotReload(payload) {
|
|
218
|
+
const payloadPath = payload.path.replace(/(?:(^|\/)index)?\.md$/, '$1');
|
|
219
|
+
const locationPath = location.pathname
|
|
220
|
+
.replace(/(?:(^|\/)index)?\.html$/, '')
|
|
221
|
+
.slice(siteDataRef.value.base.length - 1);
|
|
222
|
+
return payloadPath === locationPath;
|
|
223
|
+
}
|
|
224
|
+
function normalizeHref(href) {
|
|
225
|
+
const url = new URL(href, fakeHost);
|
|
226
|
+
url.pathname = url.pathname.replace(/(^|\/)index(\.html)?$/, '$1');
|
|
227
|
+
// ensure correct deep link so page refresh lands on correct files.
|
|
228
|
+
if (siteDataRef.value.cleanUrls)
|
|
229
|
+
url.pathname = url.pathname.replace(/\.html$/, '');
|
|
230
|
+
else if (!url.pathname.endsWith('/') && !url.pathname.endsWith('.html'))
|
|
231
|
+
url.pathname += '.html';
|
|
232
|
+
return url.pathname + url.search + url.hash;
|
|
233
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// entry for SSR
|
|
2
|
+
import { createApp } from './index';
|
|
3
|
+
import { renderToString } from 'vue/server-renderer';
|
|
4
|
+
export async function render(path) {
|
|
5
|
+
const { app, router } = await createApp();
|
|
6
|
+
await router.go(path);
|
|
7
|
+
const ctx = { content: '' };
|
|
8
|
+
ctx.content = await renderToString(app, ctx);
|
|
9
|
+
return ctx;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { siteDataRef } from './data';
|
|
2
|
+
import { inBrowser, EXTERNAL_URL_RE, sanitizeFileName } from '../shared';
|
|
3
|
+
import { h, onMounted, onUnmounted, shallowRef } from 'vue';
|
|
4
|
+
export { inBrowser } from '../shared';
|
|
5
|
+
/**
|
|
6
|
+
* Join two paths by resolving the slash collision.
|
|
7
|
+
*/
|
|
8
|
+
export function joinPath(base, path) {
|
|
9
|
+
return `${base}${path}`.replace(/\/+/g, '/');
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Append base to internal (non-relative) urls
|
|
13
|
+
*/
|
|
14
|
+
export function withBase(path) {
|
|
15
|
+
return EXTERNAL_URL_RE.test(path) || !path.startsWith('/')
|
|
16
|
+
? path
|
|
17
|
+
: joinPath(siteDataRef.value.base, path);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Converts a url path to the corresponding js chunk filename.
|
|
21
|
+
*/
|
|
22
|
+
export function pathToFile(path) {
|
|
23
|
+
let pagePath = path.replace(/\.html$/, '');
|
|
24
|
+
pagePath = decodeURIComponent(pagePath);
|
|
25
|
+
pagePath = pagePath.replace(/\/$/, '/index'); // /foo/ -> /foo/index
|
|
26
|
+
if (import.meta.env.DEV) {
|
|
27
|
+
// always force re-fetch content in dev
|
|
28
|
+
pagePath += `.md?t=${Date.now()}`;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// in production, each .md file is built into a .md.js file following
|
|
32
|
+
// the path conversion scheme.
|
|
33
|
+
// /foo/bar.html -> ./foo_bar.md
|
|
34
|
+
if (inBrowser) {
|
|
35
|
+
const base = import.meta.env.BASE_URL;
|
|
36
|
+
pagePath =
|
|
37
|
+
sanitizeFileName(pagePath.slice(base.length).replace(/\//g, '_') || 'index') + '.md';
|
|
38
|
+
// client production build needs to account for page hash, which is
|
|
39
|
+
// injected directly in the page's html
|
|
40
|
+
let pageHash = __VP_HASH_MAP__[pagePath.toLowerCase()];
|
|
41
|
+
if (!pageHash) {
|
|
42
|
+
pagePath = pagePath.endsWith('_index.md')
|
|
43
|
+
? pagePath.slice(0, -9) + '.md'
|
|
44
|
+
: pagePath.slice(0, -3) + '_index.md';
|
|
45
|
+
pageHash = __VP_HASH_MAP__[pagePath.toLowerCase()];
|
|
46
|
+
}
|
|
47
|
+
if (!pageHash)
|
|
48
|
+
return null;
|
|
49
|
+
pagePath = `${base}${__ASSETS_DIR__}/${pagePath}.${pageHash}.js`;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// ssr build uses much simpler name mapping
|
|
53
|
+
pagePath = `./${sanitizeFileName(pagePath.slice(1).replace(/\//g, '_'))}.md.js`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return pagePath;
|
|
57
|
+
}
|
|
58
|
+
export let contentUpdatedCallbacks = [];
|
|
59
|
+
/**
|
|
60
|
+
* Register callback that is called every time the markdown content is updated
|
|
61
|
+
* in the DOM.
|
|
62
|
+
*/
|
|
63
|
+
export function onContentUpdated(fn) {
|
|
64
|
+
contentUpdatedCallbacks.push(fn);
|
|
65
|
+
onUnmounted(() => {
|
|
66
|
+
contentUpdatedCallbacks = contentUpdatedCallbacks.filter((f) => f !== fn);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
export function defineClientComponent(loader, args, cb) {
|
|
70
|
+
return {
|
|
71
|
+
setup() {
|
|
72
|
+
const comp = shallowRef();
|
|
73
|
+
onMounted(async () => {
|
|
74
|
+
let res = await loader();
|
|
75
|
+
// interop module default
|
|
76
|
+
if (res && (res.__esModule || res[Symbol.toStringTag] === 'Module')) {
|
|
77
|
+
res = res.default;
|
|
78
|
+
}
|
|
79
|
+
comp.value = res;
|
|
80
|
+
await cb?.();
|
|
81
|
+
});
|
|
82
|
+
return () => (comp.value ? h(comp.value, ...(args ?? [])) : null);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export function getScrollOffset() {
|
|
87
|
+
let scrollOffset = siteDataRef.value.scrollOffset;
|
|
88
|
+
let offset = 0;
|
|
89
|
+
let padding = 24;
|
|
90
|
+
if (typeof scrollOffset === 'object' && 'padding' in scrollOffset) {
|
|
91
|
+
padding = scrollOffset.padding;
|
|
92
|
+
scrollOffset = scrollOffset.selector;
|
|
93
|
+
}
|
|
94
|
+
if (typeof scrollOffset === 'number') {
|
|
95
|
+
offset = scrollOffset;
|
|
96
|
+
}
|
|
97
|
+
else if (typeof scrollOffset === 'string') {
|
|
98
|
+
offset = tryOffsetSelector(scrollOffset, padding);
|
|
99
|
+
}
|
|
100
|
+
else if (Array.isArray(scrollOffset)) {
|
|
101
|
+
for (const selector of scrollOffset) {
|
|
102
|
+
const res = tryOffsetSelector(selector, padding);
|
|
103
|
+
if (res) {
|
|
104
|
+
offset = res;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return offset;
|
|
110
|
+
}
|
|
111
|
+
function tryOffsetSelector(selector, padding) {
|
|
112
|
+
const el = document.querySelector(selector);
|
|
113
|
+
if (!el)
|
|
114
|
+
return 0;
|
|
115
|
+
const bot = el.getBoundingClientRect().bottom;
|
|
116
|
+
if (bot < 0)
|
|
117
|
+
return 0;
|
|
118
|
+
return bot + padding;
|
|
119
|
+
}
|