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.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -0
  3. package/bin/themekit.js +2 -0
  4. package/client.d.ts +5 -0
  5. package/dist/client/app/components/ClientOnly.js +10 -0
  6. package/dist/client/app/components/Content.js +23 -0
  7. package/dist/client/app/composables/codeGroups.js +40 -0
  8. package/dist/client/app/composables/copyCode.js +73 -0
  9. package/dist/client/app/composables/head.js +81 -0
  10. package/dist/client/app/composables/preFetch.js +99 -0
  11. package/dist/client/app/data.js +59 -0
  12. package/dist/client/app/devtools.js +29 -0
  13. package/dist/client/app/index.js +140 -0
  14. package/dist/client/app/router.js +233 -0
  15. package/dist/client/app/ssr.js +10 -0
  16. package/dist/client/app/theme.js +1 -0
  17. package/dist/client/app/utils.js +119 -0
  18. package/dist/client/index.d.ts +1446 -0
  19. package/dist/client/index.js +9 -0
  20. package/dist/client/shared.js +139 -0
  21. package/dist/client/theme-default/Layout.vue +94 -0
  22. package/dist/client/theme-default/NotFound.vue +109 -0
  23. package/dist/client/theme-default/components/VPAlgoliaSearchBox.vue +99 -0
  24. package/dist/client/theme-default/components/VPBackdrop.vue +41 -0
  25. package/dist/client/theme-default/components/VPBadge.vue +86 -0
  26. package/dist/client/theme-default/components/VPButton.vue +123 -0
  27. package/dist/client/theme-default/components/VPCarbonAds.vue +109 -0
  28. package/dist/client/theme-default/components/VPContent.vue +98 -0
  29. package/dist/client/theme-default/components/VPDoc.vue +193 -0
  30. package/dist/client/theme-default/components/VPDocAside.vue +46 -0
  31. package/dist/client/theme-default/components/VPDocAsideCarbonAds.vue +18 -0
  32. package/dist/client/theme-default/components/VPDocAsideOutline.vue +87 -0
  33. package/dist/client/theme-default/components/VPDocAsideSponsors.vue +17 -0
  34. package/dist/client/theme-default/components/VPDocFooter.vue +145 -0
  35. package/dist/client/theme-default/components/VPDocFooterLastUpdated.vue +50 -0
  36. package/dist/client/theme-default/components/VPDocOutlineItem.vue +59 -0
  37. package/dist/client/theme-default/components/VPFeature.vue +123 -0
  38. package/dist/client/theme-default/components/VPFeatures.vue +121 -0
  39. package/dist/client/theme-default/components/VPFlyout.vue +136 -0
  40. package/dist/client/theme-default/components/VPFooter.vue +60 -0
  41. package/dist/client/theme-default/components/VPHero.vue +336 -0
  42. package/dist/client/theme-default/components/VPHome.vue +43 -0
  43. package/dist/client/theme-default/components/VPHomeContent.vue +52 -0
  44. package/dist/client/theme-default/components/VPHomeFeatures.vue +14 -0
  45. package/dist/client/theme-default/components/VPHomeHero.vue +24 -0
  46. package/dist/client/theme-default/components/VPHomeSponsors.vue +116 -0
  47. package/dist/client/theme-default/components/VPImage.vue +46 -0
  48. package/dist/client/theme-default/components/VPLink.vue +33 -0
  49. package/dist/client/theme-default/components/VPLocalNav.vue +171 -0
  50. package/dist/client/theme-default/components/VPLocalNavOutlineDropdown.vue +190 -0
  51. package/dist/client/theme-default/components/VPLocalSearchBox.vue +856 -0
  52. package/dist/client/theme-default/components/VPMenu.vue +72 -0
  53. package/dist/client/theme-default/components/VPMenuGroup.vue +47 -0
  54. package/dist/client/theme-default/components/VPMenuLink.vue +54 -0
  55. package/dist/client/theme-default/components/VPNav.vue +57 -0
  56. package/dist/client/theme-default/components/VPNavBar.vue +267 -0
  57. package/dist/client/theme-default/components/VPNavBarAppearance.vue +25 -0
  58. package/dist/client/theme-default/components/VPNavBarExtra.vue +94 -0
  59. package/dist/client/theme-default/components/VPNavBarHamburger.vue +79 -0
  60. package/dist/client/theme-default/components/VPNavBarMenu.vue +29 -0
  61. package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +42 -0
  62. package/dist/client/theme-default/components/VPNavBarMenuLink.vue +53 -0
  63. package/dist/client/theme-default/components/VPNavBarSearch.vue +194 -0
  64. package/dist/client/theme-default/components/VPNavBarSearchButton.vue +208 -0
  65. package/dist/client/theme-default/components/VPNavBarSocialLinks.vue +27 -0
  66. package/dist/client/theme-default/components/VPNavBarTitle.vue +76 -0
  67. package/dist/client/theme-default/components/VPNavBarTranslations.vue +47 -0
  68. package/dist/client/theme-default/components/VPNavScreen.vue +99 -0
  69. package/dist/client/theme-default/components/VPNavScreenAppearance.vue +33 -0
  70. package/dist/client/theme-default/components/VPNavScreenMenu.vue +23 -0
  71. package/dist/client/theme-default/components/VPNavScreenMenuGroup.vue +111 -0
  72. package/dist/client/theme-default/components/VPNavScreenMenuGroupLink.vue +39 -0
  73. package/dist/client/theme-default/components/VPNavScreenMenuGroupSection.vue +34 -0
  74. package/dist/client/theme-default/components/VPNavScreenMenuLink.vue +39 -0
  75. package/dist/client/theme-default/components/VPNavScreenSocialLinks.vue +14 -0
  76. package/dist/client/theme-default/components/VPNavScreenTranslations.vue +73 -0
  77. package/dist/client/theme-default/components/VPPage.vue +7 -0
  78. package/dist/client/theme-default/components/VPSidebar.vue +137 -0
  79. package/dist/client/theme-default/components/VPSidebarItem.vue +250 -0
  80. package/dist/client/theme-default/components/VPSkipLink.vue +68 -0
  81. package/dist/client/theme-default/components/VPSocialLink.vue +50 -0
  82. package/dist/client/theme-default/components/VPSocialLinks.vue +27 -0
  83. package/dist/client/theme-default/components/VPSponsors.vue +48 -0
  84. package/dist/client/theme-default/components/VPSponsorsGrid.vue +48 -0
  85. package/dist/client/theme-default/components/VPSwitch.vue +63 -0
  86. package/dist/client/theme-default/components/VPSwitchAppearance.vue +52 -0
  87. package/dist/client/theme-default/components/VPTeamMembers.vue +66 -0
  88. package/dist/client/theme-default/components/VPTeamMembersItem.vue +225 -0
  89. package/dist/client/theme-default/components/VPTeamPage.vue +58 -0
  90. package/dist/client/theme-default/components/VPTeamPageSection.vue +77 -0
  91. package/dist/client/theme-default/components/VPTeamPageTitle.vue +63 -0
  92. package/dist/client/theme-default/components/icons/VPIconAlignJustify.vue +8 -0
  93. package/dist/client/theme-default/components/icons/VPIconAlignLeft.vue +8 -0
  94. package/dist/client/theme-default/components/icons/VPIconAlignRight.vue +8 -0
  95. package/dist/client/theme-default/components/icons/VPIconArrowLeft.vue +7 -0
  96. package/dist/client/theme-default/components/icons/VPIconArrowRight.vue +7 -0
  97. package/dist/client/theme-default/components/icons/VPIconChevronDown.vue +5 -0
  98. package/dist/client/theme-default/components/icons/VPIconChevronLeft.vue +5 -0
  99. package/dist/client/theme-default/components/icons/VPIconChevronRight.vue +5 -0
  100. package/dist/client/theme-default/components/icons/VPIconChevronUp.vue +5 -0
  101. package/dist/client/theme-default/components/icons/VPIconEdit.vue +6 -0
  102. package/dist/client/theme-default/components/icons/VPIconHeart.vue +5 -0
  103. package/dist/client/theme-default/components/icons/VPIconLanguages.vue +9 -0
  104. package/dist/client/theme-default/components/icons/VPIconMinus.vue +5 -0
  105. package/dist/client/theme-default/components/icons/VPIconMinusSquare.vue +6 -0
  106. package/dist/client/theme-default/components/icons/VPIconMoon.vue +5 -0
  107. package/dist/client/theme-default/components/icons/VPIconMoreHorizontal.vue +7 -0
  108. package/dist/client/theme-default/components/icons/VPIconPlus.vue +5 -0
  109. package/dist/client/theme-default/components/icons/VPIconPlusSquare.vue +6 -0
  110. package/dist/client/theme-default/components/icons/VPIconSun.vue +13 -0
  111. package/dist/client/theme-default/composables/aside.js +17 -0
  112. package/dist/client/theme-default/composables/data.js +2 -0
  113. package/dist/client/theme-default/composables/edit-link.js +16 -0
  114. package/dist/client/theme-default/composables/flyout.js +41 -0
  115. package/dist/client/theme-default/composables/langs.js +26 -0
  116. package/dist/client/theme-default/composables/local-nav.js +18 -0
  117. package/dist/client/theme-default/composables/nav.js +30 -0
  118. package/dist/client/theme-default/composables/outline.js +178 -0
  119. package/dist/client/theme-default/composables/prev-next.js +57 -0
  120. package/dist/client/theme-default/composables/sidebar.js +136 -0
  121. package/dist/client/theme-default/composables/sponsor-grid.js +94 -0
  122. package/dist/client/theme-default/fonts/inter-italic-cyrillic-ext.woff2 +0 -0
  123. package/dist/client/theme-default/fonts/inter-italic-cyrillic.woff2 +0 -0
  124. package/dist/client/theme-default/fonts/inter-italic-greek-ext.woff2 +0 -0
  125. package/dist/client/theme-default/fonts/inter-italic-greek.woff2 +0 -0
  126. package/dist/client/theme-default/fonts/inter-italic-latin-ext.woff2 +0 -0
  127. package/dist/client/theme-default/fonts/inter-italic-latin.woff2 +0 -0
  128. package/dist/client/theme-default/fonts/inter-italic-vietnamese.woff2 +0 -0
  129. package/dist/client/theme-default/fonts/inter-roman-cyrillic-ext.woff2 +0 -0
  130. package/dist/client/theme-default/fonts/inter-roman-cyrillic.woff2 +0 -0
  131. package/dist/client/theme-default/fonts/inter-roman-greek-ext.woff2 +0 -0
  132. package/dist/client/theme-default/fonts/inter-roman-greek.woff2 +0 -0
  133. package/dist/client/theme-default/fonts/inter-roman-latin-ext.woff2 +0 -0
  134. package/dist/client/theme-default/fonts/inter-roman-latin.woff2 +0 -0
  135. package/dist/client/theme-default/fonts/inter-roman-vietnamese.woff2 +0 -0
  136. package/dist/client/theme-default/index.js +3 -0
  137. package/dist/client/theme-default/styles/base.css +252 -0
  138. package/dist/client/theme-default/styles/components/custom-block.css +208 -0
  139. package/dist/client/theme-default/styles/components/vp-code-group.css +85 -0
  140. package/dist/client/theme-default/styles/components/vp-code.css +7 -0
  141. package/dist/client/theme-default/styles/components/vp-doc.css +570 -0
  142. package/dist/client/theme-default/styles/components/vp-sponsor.css +155 -0
  143. package/dist/client/theme-default/styles/fonts.css +157 -0
  144. package/dist/client/theme-default/styles/icons.css +123 -0
  145. package/dist/client/theme-default/styles/utils.css +9 -0
  146. package/dist/client/theme-default/styles/vars.css +563 -0
  147. package/dist/client/theme-default/support/lru.js +33 -0
  148. package/dist/client/theme-default/support/sidebar.js +89 -0
  149. package/dist/client/theme-default/support/translation.js +49 -0
  150. package/dist/client/theme-default/support/utils.js +33 -0
  151. package/dist/client/theme-default/without-fonts.js +32 -0
  152. package/dist/node/cli.js +444 -0
  153. package/dist/node/index.d.ts +4588 -0
  154. package/dist/node/index.js +198 -0
  155. package/dist/node/serve-BjvG349_.js +50301 -0
  156. package/lib/vue-demi.mjs +34 -0
  157. package/package.json +223 -0
  158. package/template/.vitepress/config.js +28 -0
  159. package/template/.vitepress/theme/Layout.vue +21 -0
  160. package/template/.vitepress/theme/index.js +29 -0
  161. package/template/.vitepress/theme/style.css +143 -0
  162. package/template/api-examples.md +49 -0
  163. package/template/index.md +28 -0
  164. package/template/markdown-examples.md +85 -0
  165. package/theme-without-fonts.d.ts +2 -0
  166. package/theme.d.ts +30 -0
  167. package/types/default-theme.d.ts +533 -0
  168. package/types/docsearch.d.ts +144 -0
  169. package/types/index.d.ts +3 -0
  170. package/types/local-search.d.ts +33 -0
  171. 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
+ }