@vuepress/client 2.0.0-beta.29 → 2.0.0-beta.35

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 (48) hide show
  1. package/lib/app.js +16 -39
  2. package/lib/components/ClientOnly.d.ts +1 -1
  3. package/lib/components/Vuepress.d.ts +1 -1
  4. package/lib/composables/pageData.d.ts +4 -4
  5. package/lib/composables/pageData.js +1 -12
  6. package/lib/composables/pageFrontmatter.d.ts +1 -5
  7. package/lib/composables/pageFrontmatter.js +0 -4
  8. package/lib/composables/pageHead.d.ts +0 -9
  9. package/lib/composables/pageHead.js +0 -18
  10. package/lib/composables/pageHeadTitle.d.ts +0 -8
  11. package/lib/composables/pageHeadTitle.js +0 -6
  12. package/lib/composables/pageLang.d.ts +0 -7
  13. package/lib/composables/pageLang.js +0 -6
  14. package/lib/composables/pagesData.d.ts +1 -1
  15. package/lib/composables/routeLocale.d.ts +0 -5
  16. package/lib/composables/routeLocale.js +0 -5
  17. package/lib/composables/siteLocaleData.d.ts +0 -7
  18. package/lib/composables/siteLocaleData.js +0 -9
  19. package/lib/composables/updateHead.d.ts +0 -13
  20. package/lib/composables/updateHead.js +1 -102
  21. package/lib/{utils → helpers}/defineClientAppEnhance.d.ts +0 -0
  22. package/lib/{utils → helpers}/defineClientAppEnhance.js +0 -0
  23. package/lib/{utils → helpers}/defineClientAppSetup.d.ts +0 -0
  24. package/lib/{utils → helpers}/defineClientAppSetup.js +0 -0
  25. package/lib/{utils → helpers}/index.d.ts +0 -0
  26. package/lib/{utils → helpers}/index.js +0 -0
  27. package/lib/{utils → helpers}/withBase.d.ts +0 -0
  28. package/lib/{utils → helpers}/withBase.js +0 -0
  29. package/lib/index.d.ts +4 -3
  30. package/lib/index.js +4 -3
  31. package/lib/resolvers.d.ts +15 -0
  32. package/lib/resolvers.js +64 -0
  33. package/lib/router.d.ts +5 -0
  34. package/lib/router.js +40 -0
  35. package/lib/setupDevtools.d.ts +3 -0
  36. package/lib/setupDevtools.js +21 -0
  37. package/lib/{registerGlobalComponents.d.ts → setupGlobalComponents.d.ts} +1 -1
  38. package/lib/{registerGlobalComponents.js → setupGlobalComponents.js} +1 -1
  39. package/lib/setupGlobalComputed.d.ts +34 -0
  40. package/lib/setupGlobalComputed.js +45 -0
  41. package/lib/setupUpdateHead.d.ts +13 -0
  42. package/lib/setupUpdateHead.js +101 -0
  43. package/lib/types/index.d.ts +0 -5
  44. package/package.json +6 -5
  45. package/templates/{index.ssr.html → index.build.html} +0 -0
  46. package/types.d.ts +2 -0
  47. package/lib/provideGlobalComputed.d.ts +0 -20
  48. package/lib/provideGlobalComputed.js +0 -33
package/lib/app.js CHANGED
@@ -1,24 +1,19 @@
1
1
  import { clientAppEnhances } from '@internal/clientAppEnhances';
2
2
  import { clientAppRootComponents } from '@internal/clientAppRootComponents';
3
3
  import { clientAppSetups } from '@internal/clientAppSetups';
4
- import { pagesComponents } from '@internal/pagesComponents';
5
- import { pagesRoutes } from '@internal/pagesRoutes';
6
- import { removeEndingSlash } from '@vuepress/shared';
7
4
  import { createApp, createSSRApp, h } from 'vue';
8
- import { createMemoryHistory, createRouter, createWebHistory, RouterView, START_LOCATION, } from 'vue-router';
9
- import { pageData, resolvePageData, setupUpdateHead, siteData, } from './composables';
10
- import { provideGlobalComputed } from './provideGlobalComputed';
11
- import { registerGlobalComponents } from './registerGlobalComponents';
5
+ import { RouterView } from 'vue-router';
6
+ import { siteData } from './composables';
7
+ import { createVueRouter } from './router';
8
+ import { setupDevtools } from './setupDevtools';
9
+ import { setupGlobalComponents } from './setupGlobalComponents';
10
+ import { setupGlobalComputed } from './setupGlobalComputed';
11
+ import { setupUpdateHead } from './setupUpdateHead';
12
12
  /**
13
13
  * - use `createApp` in dev mode
14
14
  * - use `createSSRApp` in build mode
15
15
  */
16
16
  const appCreator = __VUEPRESS_DEV__ ? createApp : createSSRApp;
17
- /**
18
- * - use `createWebHistory` in dev mode and build mode client bundle
19
- * - use `createMemoryHistory` in build mode server bundle
20
- */
21
- const historyCreator = __VUEPRESS_SSR__ ? createMemoryHistory : createWebHistory;
22
17
  export const createVueApp = async () => {
23
18
  // create vue app
24
19
  const app = appCreator({
@@ -36,33 +31,15 @@ export const createVueApp = async () => {
36
31
  ];
37
32
  },
38
33
  });
39
- // create vue-router
40
- const router = createRouter({
41
- // TODO: it might be an issue of vue-router that have to remove the ending slash
42
- history: historyCreator(removeEndingSlash(siteData.value.base)),
43
- routes: pagesRoutes,
44
- scrollBehavior: (to, from, savedPosition) => {
45
- if (savedPosition)
46
- return savedPosition;
47
- if (to.hash)
48
- return { el: to.hash };
49
- return { top: 0 };
50
- },
51
- });
52
- router.beforeResolve(async (to, from) => {
53
- var _a;
54
- if (to.path !== from.path || from === START_LOCATION) {
55
- // ensure page data and page component have been loaded
56
- ;
57
- [pageData.value] = await Promise.all([
58
- resolvePageData(to.name),
59
- (_a = pagesComponents[to.name]) === null || _a === void 0 ? void 0 : _a.__asyncLoader(),
60
- ]);
61
- }
62
- });
63
- // global computed and global components
64
- provideGlobalComputed(app, router);
65
- registerGlobalComponents(app);
34
+ // create vue-router instance
35
+ const router = createVueRouter();
36
+ // global components and computed
37
+ setupGlobalComponents(app);
38
+ const globalComputed = setupGlobalComputed(app, router);
39
+ // setup devtools in dev mode
40
+ if (__VUEPRESS_DEV__ || __VUE_PROD_DEVTOOLS__) {
41
+ setupDevtools(app, globalComputed);
42
+ }
66
43
  // invoke all clientAppEnhances
67
44
  for (const clientAppEnhance of clientAppEnhances) {
68
45
  await clientAppEnhance({ app, router, siteData });
@@ -1,3 +1,3 @@
1
1
  export declare const ClientOnly: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
2
2
  [key: string]: any;
3
- }>[] | null | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{} & {} & {}>, {}>;
3
+ }>[] | null | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
@@ -3,4 +3,4 @@
3
3
  */
4
4
  export declare const Vuepress: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
5
5
  [key: string]: any;
6
- }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{} & {} & {}>, {}>;
6
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
@@ -5,6 +5,10 @@ export type { PageData };
5
5
  * Ref wrapper of `PageData`
6
6
  */
7
7
  export declare type PageDataRef<T extends Record<any, any> = Record<never, never>> = Ref<PageData<T>>;
8
+ /**
9
+ * Empty page data to be used as the fallback value
10
+ */
11
+ export declare const pageDataEmpty: PageData<Record<never, never>>;
8
12
  /**
9
13
  * Global page data ref
10
14
  */
@@ -13,7 +17,3 @@ export declare const pageData: PageDataRef;
13
17
  * Returns the ref of the data of current page
14
18
  */
15
19
  export declare const usePageData: <T extends Record<any, any> = Record<never, never>>() => PageDataRef<T>;
16
- /**
17
- * Resolve page data according to page key
18
- */
19
- export declare const resolvePageData: (pageKey: string) => Promise<PageData>;
@@ -3,7 +3,7 @@ import { pagesData } from './pagesData';
3
3
  /**
4
4
  * Empty page data to be used as the fallback value
5
5
  */
6
- const pageDataEmpty = readonly({
6
+ export const pageDataEmpty = readonly({
7
7
  key: '',
8
8
  path: '',
9
9
  title: '',
@@ -20,17 +20,6 @@ export const pageData = ref(pageDataEmpty);
20
20
  * Returns the ref of the data of current page
21
21
  */
22
22
  export const usePageData = () => pageData;
23
- /**
24
- * Resolve page data according to page key
25
- */
26
- export const resolvePageData = async (pageKey) => {
27
- const pageDataResolver = pagesData.value[pageKey];
28
- if (!pageDataResolver) {
29
- return pageDataEmpty;
30
- }
31
- const pageData = await pageDataResolver();
32
- return pageData !== null && pageData !== void 0 ? pageData : pageDataEmpty;
33
- };
34
23
  if (import.meta.webpackHot || import.meta.hot) {
35
24
  // reuse vue HMR runtime
36
25
  __VUE_HMR_RUNTIME__.updatePageData = (data) => {
@@ -1,4 +1,4 @@
1
- import type { PageData, PageFrontmatter } from '@vuepress/shared';
1
+ import type { PageFrontmatter } from '@vuepress/shared';
2
2
  import type { ComputedRef, InjectionKey } from 'vue';
3
3
  export type { PageFrontmatter };
4
4
  /**
@@ -13,7 +13,3 @@ export declare const pageFrontmatterSymbol: InjectionKey<PageFrontmatterRef>;
13
13
  * Returns the ref of the frontmatter of current page
14
14
  */
15
15
  export declare const usePageFrontmatter: <T extends Record<any, any> = Record<string, unknown>>() => PageFrontmatterRef<T>;
16
- /**
17
- * Resolve page frontmatter from page data
18
- */
19
- export declare const resolvePageFrontmatter: (pageData: PageData) => PageFrontmatter;
@@ -13,7 +13,3 @@ export const usePageFrontmatter = () => {
13
13
  }
14
14
  return pageFrontmatter;
15
15
  };
16
- /**
17
- * Resolve page frontmatter from page data
18
- */
19
- export const resolvePageFrontmatter = (pageData) => pageData.frontmatter;
@@ -1,8 +1,5 @@
1
1
  import type { HeadConfig } from '@vuepress/shared';
2
2
  import type { ComputedRef, InjectionKey } from 'vue';
3
- import type { PageFrontmatter } from './pageFrontmatter';
4
- import type { PageHeadTitle } from './pageHeadTitle';
5
- import type { SiteLocaleData } from './siteLocaleData';
6
3
  /**
7
4
  * Page head config, which would be used for generate html tags in `<head>`
8
5
  */
@@ -19,9 +16,3 @@ export declare const pageHeadSymbol: InjectionKey<PageHeadRef>;
19
16
  * Returns the ref of the head config of current page
20
17
  */
21
18
  export declare const usePageHead: () => PageHeadRef;
22
- /**
23
- * Merge the head config in frontmatter and site locale
24
- *
25
- * Frontmatter should take priority over site locale
26
- */
27
- export declare const resolvePageHead: (headTitle: PageHeadTitle, frontmatter: PageFrontmatter, siteLocale: SiteLocaleData) => HeadConfig[];
@@ -1,4 +1,3 @@
1
- import { dedupeHead, isArray, isString } from '@vuepress/shared';
2
1
  import { inject } from 'vue';
3
2
  /**
4
3
  * Injection key for page head
@@ -14,20 +13,3 @@ export const usePageHead = () => {
14
13
  }
15
14
  return pageHead;
16
15
  };
17
- /**
18
- * Merge the head config in frontmatter and site locale
19
- *
20
- * Frontmatter should take priority over site locale
21
- */
22
- export const resolvePageHead = (headTitle, frontmatter, siteLocale) => {
23
- const description = isString(frontmatter.description)
24
- ? frontmatter.description
25
- : siteLocale.description;
26
- const head = [
27
- ...(isArray(frontmatter.head) ? frontmatter.head : []),
28
- ...siteLocale.head,
29
- ['title', {}, headTitle],
30
- ['meta', { name: 'description', content: description }],
31
- ];
32
- return dedupeHead(head);
33
- };
@@ -1,6 +1,4 @@
1
1
  import type { ComputedRef, InjectionKey } from 'vue';
2
- import type { PageData } from './pageData';
3
- import type { SiteLocaleData } from './siteLocaleData';
4
2
  /**
5
3
  * Page head title, which would be used as the content of `head > title` tag
6
4
  */
@@ -17,9 +15,3 @@ export declare const pageHeadTitleSymbol: InjectionKey<PageHeadTitleRef>;
17
15
  * Returns the ref of the head title of current page
18
16
  */
19
17
  export declare const usePageHeadTitle: () => PageHeadTitleRef;
20
- /**
21
- * Resolve the content of page head title
22
- *
23
- * It would be used as the content of the `<title>` tag
24
- */
25
- export declare const resolvePageHeadTitle: (page: PageData, siteLocale: SiteLocaleData) => PageHeadTitle;
@@ -13,9 +13,3 @@ export const usePageHeadTitle = () => {
13
13
  }
14
14
  return pageHeadTitle;
15
15
  };
16
- /**
17
- * Resolve the content of page head title
18
- *
19
- * It would be used as the content of the `<title>` tag
20
- */
21
- export const resolvePageHeadTitle = (page, siteLocale) => `${page.title ? `${page.title} | ` : ``}${siteLocale.title}`;
@@ -1,4 +1,3 @@
1
- import type { PageData } from '@vuepress/shared';
2
1
  import type { ComputedRef, InjectionKey } from 'vue';
3
2
  /**
4
3
  * Page language
@@ -16,9 +15,3 @@ export declare const pageLangSymbol: InjectionKey<PageLangRef>;
16
15
  * Returns the ref of the language of current page
17
16
  */
18
17
  export declare const usePageLang: () => PageLangRef;
19
- /**
20
- * Resolve page language from page data
21
- *
22
- * It would be used as the `lang` attribute of `<html>` tag
23
- */
24
- export declare const resolvePageLang: (pageData: PageData) => PageLang;
@@ -13,9 +13,3 @@ export const usePageLang = () => {
13
13
  }
14
14
  return pageLang;
15
15
  };
16
- /**
17
- * Resolve page language from page data
18
- *
19
- * It would be used as the `lang` attribute of `<html>` tag
20
- */
21
- export const resolvePageLang = (pageData) => pageData.lang || 'en';
@@ -6,7 +6,7 @@ import type { Ref } from 'vue';
6
6
  * The key is page key, and the value is an async function that
7
7
  * returns the page data
8
8
  */
9
- export declare type PagesData = Record<string, () => Promise<PageData>>;
9
+ export declare type PagesData = Record<string, (() => Promise<PageData>) | undefined>;
10
10
  /**
11
11
  * Ref wrapper of `PagesData`
12
12
  */
@@ -1,4 +1,3 @@
1
- import type { SiteData } from '@vuepress/shared';
2
1
  import type { ComputedRef, InjectionKey } from 'vue';
3
2
  /**
4
3
  * Route locale path
@@ -16,7 +15,3 @@ export declare const routeLocaleSymbol: InjectionKey<RouteLocaleRef>;
16
15
  * Returns the ref of the route locale path of current page
17
16
  */
18
17
  export declare const useRouteLocale: () => RouteLocaleRef;
19
- /**
20
- * Resolve locale path according to route path and locales config
21
- */
22
- export declare const resolveRouteLocale: (locales: SiteData['locales'], routePath: string) => RouteLocale;
@@ -1,4 +1,3 @@
1
- import { resolveLocalePath } from '@vuepress/shared';
2
1
  import { inject } from 'vue';
3
2
  /**
4
3
  * Injection key for page route locale path
@@ -14,7 +13,3 @@ export const useRouteLocale = () => {
14
13
  }
15
14
  return routeLocale;
16
15
  };
17
- /**
18
- * Resolve locale path according to route path and locales config
19
- */
20
- export const resolveRouteLocale = (locales, routePath) => resolveLocalePath(locales, routePath);
@@ -1,6 +1,5 @@
1
1
  import type { SiteData } from '@vuepress/shared';
2
2
  import type { ComputedRef, InjectionKey } from 'vue';
3
- import type { RouteLocale } from './routeLocale';
4
3
  /**
5
4
  * Site data of current locale
6
5
  */
@@ -17,9 +16,3 @@ export declare const siteLocaleDataSymbol: InjectionKey<SiteLocaleDataRef>;
17
16
  * Returns the ref of the site data of current locale
18
17
  */
19
18
  export declare const useSiteLocaleData: () => SiteLocaleDataRef;
20
- /**
21
- * Resolve site data for specific locale
22
- *
23
- * It would merge the locales fields to the root fields
24
- */
25
- export declare const resolveSiteLocaleData: (site: SiteData, routeLocale: RouteLocale) => SiteLocaleData;
@@ -13,12 +13,3 @@ export const useSiteLocaleData = () => {
13
13
  }
14
14
  return siteLocaleData;
15
15
  };
16
- /**
17
- * Resolve site data for specific locale
18
- *
19
- * It would merge the locales fields to the root fields
20
- */
21
- export const resolveSiteLocaleData = (site, routeLocale) => ({
22
- ...site,
23
- ...site.locales[routeLocale],
24
- });
@@ -1,4 +1,3 @@
1
- import type { HeadConfig } from '@vuepress/shared';
2
1
  import type { InjectionKey } from 'vue';
3
2
  /**
4
3
  * A util function to force update `<head>` of current page
@@ -12,15 +11,3 @@ export declare const updateHeadSymbol: InjectionKey<UpdateHead>;
12
11
  * Returns the `updateHead` util
13
12
  */
14
13
  export declare const useUpdateHead: () => UpdateHead;
15
- /**
16
- * Auto update head and provide as global util in setup
17
- */
18
- export declare const setupUpdateHead: () => void;
19
- /**
20
- * Query the matched head tag of head config
21
- */
22
- export declare const queryHeadTag: ([tagName, attrs, content,]: HeadConfig) => HTMLElement | null;
23
- /**
24
- * Create head tag from head config
25
- */
26
- export declare const createHeadTag: ([tagName, attrs, content,]: HeadConfig) => HTMLElement | null;
@@ -1,8 +1,4 @@
1
- import { isPlainObject, isString } from '@vuepress/shared';
2
- import { inject, onMounted, provide, ref, useSSRContext, watch } from 'vue';
3
- import { useRoute } from 'vue-router';
4
- import { usePageHead } from './pageHead';
5
- import { usePageLang } from './pageLang';
1
+ import { inject } from 'vue';
6
2
  /**
7
3
  * Injection key for `updateHead` util
8
4
  */
@@ -17,100 +13,3 @@ export const useUpdateHead = () => {
17
13
  }
18
14
  return updateHead;
19
15
  };
20
- /**
21
- * Auto update head and provide as global util in setup
22
- */
23
- export const setupUpdateHead = () => {
24
- const route = useRoute();
25
- const head = usePageHead();
26
- const lang = usePageLang();
27
- // ssr-only, extract page meta info to ssrContext
28
- if (__VUEPRESS_SSR__) {
29
- const ssrContext = useSSRContext();
30
- if (ssrContext) {
31
- ssrContext.head = head.value;
32
- ssrContext.lang = lang.value;
33
- }
34
- return;
35
- }
36
- const headTags = ref([]);
37
- // load current head tags from DOM
38
- const loadHead = () => {
39
- head.value.forEach((item) => {
40
- const tag = queryHeadTag(item);
41
- if (tag) {
42
- headTags.value.push(tag);
43
- }
44
- });
45
- };
46
- // update html lang attribute and head tags to DOM
47
- const updateHead = () => {
48
- document.documentElement.lang = lang.value;
49
- headTags.value.forEach((item) => {
50
- if (item.parentNode === document.head) {
51
- document.head.removeChild(item);
52
- }
53
- });
54
- headTags.value.splice(0, headTags.value.length);
55
- head.value.forEach((item) => {
56
- const tag = createHeadTag(item);
57
- if (tag !== null) {
58
- document.head.appendChild(tag);
59
- headTags.value.push(tag);
60
- }
61
- });
62
- };
63
- provide(updateHeadSymbol, updateHead);
64
- onMounted(() => {
65
- loadHead();
66
- updateHead();
67
- // only update head on route change
68
- watch(() => route.path, () => updateHead());
69
- });
70
- };
71
- /**
72
- * Query the matched head tag of head config
73
- */
74
- export const queryHeadTag = ([tagName, attrs, content = '',]) => {
75
- const attrsSelector = Object.entries(attrs)
76
- .map(([key, value]) => {
77
- if (isString(value)) {
78
- return `[${key}="${value}"]`;
79
- }
80
- if (value === true) {
81
- return `[${key}]`;
82
- }
83
- return '';
84
- })
85
- .join('');
86
- const selector = `head > ${tagName}${attrsSelector}`;
87
- const tags = Array.from(document.querySelectorAll(selector));
88
- const matchedTag = tags.find((item) => item.innerText === content);
89
- return matchedTag || null;
90
- };
91
- /**
92
- * Create head tag from head config
93
- */
94
- export const createHeadTag = ([tagName, attrs, content,]) => {
95
- if (!isString(tagName)) {
96
- return null;
97
- }
98
- // create element
99
- const tag = document.createElement(tagName);
100
- // set attributes
101
- if (isPlainObject(attrs)) {
102
- Object.entries(attrs).forEach(([key, value]) => {
103
- if (isString(value)) {
104
- tag.setAttribute(key, value);
105
- }
106
- else if (value === true) {
107
- tag.setAttribute(key, '');
108
- }
109
- });
110
- }
111
- // set content
112
- if (isString(content)) {
113
- tag.appendChild(document.createTextNode(content));
114
- }
115
- return tag;
116
- };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/lib/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export type { PageHeader } from '@vuepress/shared';
2
- export { useRoute, useRouter } from 'vue-router';
3
- export * from './app';
2
+ export { RouterLink, useRoute, useRouter } from 'vue-router';
4
3
  export * from './components';
5
4
  export * from './composables';
5
+ export * from './helpers';
6
6
  export * from './types';
7
- export * from './utils';
7
+ export * from './app';
8
+ export * from './resolvers';
package/lib/index.js CHANGED
@@ -1,6 +1,7 @@
1
- export { useRoute, useRouter } from 'vue-router';
2
- export * from './app';
1
+ export { RouterLink, useRoute, useRouter } from 'vue-router';
3
2
  export * from './components';
4
3
  export * from './composables';
4
+ export * from './helpers';
5
5
  export * from './types';
6
- export * from './utils';
6
+ export * from './app';
7
+ export * from './resolvers';
@@ -0,0 +1,15 @@
1
+ import type { PageData, PageFrontmatter, PageHead, PageHeadTitle, PageLang, RouteLocale, SiteData, SiteLocaleData } from './composables';
2
+ /**
3
+ * Resolver methods to get global computed
4
+ *
5
+ * Users can override corresponding method for advanced customization
6
+ */
7
+ export declare const resolvers: {
8
+ resolvePageData: (pageKey: string) => Promise<PageData>;
9
+ resolvePageFrontmatter: (pageData: PageData) => PageFrontmatter;
10
+ resolvePageHead: (headTitle: PageHeadTitle, frontmatter: PageFrontmatter, siteLocale: SiteLocaleData) => PageHead;
11
+ resolvePageHeadTitle: (page: PageData, siteLocale: SiteLocaleData) => PageHeadTitle;
12
+ resolvePageLang: (pageData: PageData) => PageLang;
13
+ resolveRouteLocale: (locales: SiteData['locales'], routePath: string) => RouteLocale;
14
+ resolveSiteLocaleData: (site: SiteData, routeLocale: RouteLocale) => SiteLocaleData;
15
+ };
@@ -0,0 +1,64 @@
1
+ import { dedupeHead, isArray, isString, resolveLocalePath, } from '@vuepress/shared';
2
+ import { reactive } from 'vue';
3
+ import { pageDataEmpty, pagesData } from './composables';
4
+ /**
5
+ * Resolver methods to get global computed
6
+ *
7
+ * Users can override corresponding method for advanced customization
8
+ */
9
+ export const resolvers = reactive({
10
+ /**
11
+ * Resolve page data according to page key
12
+ */
13
+ resolvePageData: async (pageKey) => {
14
+ const pageDataResolver = pagesData.value[pageKey];
15
+ const pageData = await (pageDataResolver === null || pageDataResolver === void 0 ? void 0 : pageDataResolver());
16
+ return pageData !== null && pageData !== void 0 ? pageData : pageDataEmpty;
17
+ },
18
+ /**
19
+ * Resolve page frontmatter from page data
20
+ */
21
+ resolvePageFrontmatter: (pageData) => pageData.frontmatter,
22
+ /**
23
+ * Merge the head config in frontmatter and site locale
24
+ *
25
+ * Frontmatter should take priority over site locale
26
+ */
27
+ resolvePageHead: (headTitle, frontmatter, siteLocale) => {
28
+ const description = isString(frontmatter.description)
29
+ ? frontmatter.description
30
+ : siteLocale.description;
31
+ const head = [
32
+ ...(isArray(frontmatter.head) ? frontmatter.head : []),
33
+ ...siteLocale.head,
34
+ ['title', {}, headTitle],
35
+ ['meta', { name: 'description', content: description }],
36
+ ];
37
+ return dedupeHead(head);
38
+ },
39
+ /**
40
+ * Resolve the content of page head title
41
+ *
42
+ * It would be used as the content of the `<title>` tag
43
+ */
44
+ resolvePageHeadTitle: (page, siteLocale) => `${page.title ? `${page.title} | ` : ``}${siteLocale.title}`,
45
+ /**
46
+ * Resolve page language from page data
47
+ *
48
+ * It would be used as the `lang` attribute of `<html>` tag
49
+ */
50
+ resolvePageLang: (pageData) => pageData.lang || 'en',
51
+ /**
52
+ * Resolve locale path according to route path and locales config
53
+ */
54
+ resolveRouteLocale: (locales, routePath) => resolveLocalePath(locales, routePath),
55
+ /**
56
+ * Resolve site data for specific locale
57
+ *
58
+ * It would merge the locales fields to the root fields
59
+ */
60
+ resolveSiteLocaleData: (site, routeLocale) => ({
61
+ ...site,
62
+ ...site.locales[routeLocale],
63
+ }),
64
+ });
@@ -0,0 +1,5 @@
1
+ import type { Router } from 'vue-router';
2
+ /**
3
+ * Create vue-router instance
4
+ */
5
+ export declare const createVueRouter: () => Router;
package/lib/router.js ADDED
@@ -0,0 +1,40 @@
1
+ import { pagesComponents } from '@internal/pagesComponents';
2
+ import { pagesRoutes } from '@internal/pagesRoutes';
3
+ import { removeEndingSlash } from '@vuepress/shared';
4
+ import { createMemoryHistory, createRouter, createWebHistory, START_LOCATION, } from 'vue-router';
5
+ import { pageData, siteData } from './composables';
6
+ import { resolvers } from './resolvers';
7
+ /**
8
+ * - use `createWebHistory` in dev mode and build mode client bundle
9
+ * - use `createMemoryHistory` in build mode server bundle
10
+ */
11
+ const historyCreator = __VUEPRESS_SSR__ ? createMemoryHistory : createWebHistory;
12
+ /**
13
+ * Create vue-router instance
14
+ */
15
+ export const createVueRouter = () => {
16
+ const router = createRouter({
17
+ // TODO: it might be an issue of vue-router that have to remove the ending slash
18
+ history: historyCreator(removeEndingSlash(siteData.value.base)),
19
+ routes: pagesRoutes,
20
+ scrollBehavior: (to, from, savedPosition) => {
21
+ if (savedPosition)
22
+ return savedPosition;
23
+ if (to.hash)
24
+ return { el: to.hash };
25
+ return { top: 0 };
26
+ },
27
+ });
28
+ router.beforeResolve(async (to, from) => {
29
+ var _a;
30
+ if (to.path !== from.path || from === START_LOCATION) {
31
+ // ensure page data and page component have been loaded
32
+ ;
33
+ [pageData.value] = await Promise.all([
34
+ resolvers.resolvePageData(to.name),
35
+ (_a = pagesComponents[to.name]) === null || _a === void 0 ? void 0 : _a.__asyncLoader(),
36
+ ]);
37
+ }
38
+ });
39
+ return router;
40
+ };
@@ -0,0 +1,3 @@
1
+ import type { App } from 'vue';
2
+ import type { GlobalComputed } from './setupGlobalComputed';
3
+ export declare const setupDevtools: (app: App, globalComputed: GlobalComputed) => void;
@@ -0,0 +1,21 @@
1
+ import { setupDevtoolsPlugin } from '@vue/devtools-api';
2
+ export const setupDevtools = (app, globalComputed) => {
3
+ setupDevtoolsPlugin({
4
+ app,
5
+ id: 'org.vuejs.vuepress',
6
+ label: 'VuePress',
7
+ packageName: '@vuepress/client',
8
+ homepage: 'https://v2.vuepress.vuejs.org',
9
+ logo: 'https://v2.vuepress.vuejs.org/images/hero.png',
10
+ componentStateTypes: ['VuePress'],
11
+ }, (api) => {
12
+ api.on.inspectComponent((payload) => {
13
+ payload.instanceData.state.push(...Object.entries(globalComputed).map(([name, item]) => ({
14
+ type: 'VuePress',
15
+ key: name,
16
+ editable: false,
17
+ value: item.value,
18
+ })));
19
+ });
20
+ });
21
+ };
@@ -2,4 +2,4 @@ import type { App } from 'vue';
2
2
  /**
3
3
  * Register global built-in components
4
4
  */
5
- export declare const registerGlobalComponents: (app: App) => void;
5
+ export declare const setupGlobalComponents: (app: App) => void;
@@ -2,7 +2,7 @@ import { ClientOnly, Content } from './components';
2
2
  /**
3
3
  * Register global built-in components
4
4
  */
5
- export const registerGlobalComponents = (app) => {
5
+ export const setupGlobalComponents = (app) => {
6
6
  /* eslint-disable vue/match-component-file-name */
7
7
  app.component('ClientOnly', ClientOnly);
8
8
  app.component('Content', Content);
@@ -0,0 +1,34 @@
1
+ import type { App } from 'vue';
2
+ import type { Router } from 'vue-router';
3
+ import type { PageData, PageDataRef, PageFrontmatter, PageFrontmatterRef, PageHead, PageHeadRef, PageHeadTitle, PageHeadTitleRef, PageLang, PageLangRef, RouteLocale, RouteLocaleRef, SiteData, SiteDataRef, SiteLocaleData, SiteLocaleDataRef } from './composables';
4
+ import { withBase } from './helpers';
5
+ /**
6
+ * Vuepress client global computed
7
+ */
8
+ export interface GlobalComputed {
9
+ pageData: PageDataRef;
10
+ pageFrontmatter: PageFrontmatterRef;
11
+ pageHead: PageHeadRef;
12
+ pageHeadTitle: PageHeadTitleRef;
13
+ pageLang: PageLangRef;
14
+ routeLocale: RouteLocaleRef;
15
+ siteData: SiteDataRef;
16
+ siteLocaleData: SiteLocaleDataRef;
17
+ }
18
+ /**
19
+ * Create and provide global computed
20
+ */
21
+ export declare const setupGlobalComputed: (app: App, router: Router) => GlobalComputed;
22
+ declare module '@vue/runtime-core' {
23
+ interface ComponentCustomProperties {
24
+ $frontmatter: PageFrontmatter;
25
+ $head: PageHead;
26
+ $headTitle: PageHeadTitle;
27
+ $lang: PageLang;
28
+ $page: PageData;
29
+ $routeLocale: RouteLocale;
30
+ $site: SiteData;
31
+ $siteLocale: SiteLocaleData;
32
+ $withBase: typeof withBase;
33
+ }
34
+ }
@@ -0,0 +1,45 @@
1
+ import { computed } from 'vue';
2
+ import { pageData, pageFrontmatterSymbol, pageHeadSymbol, pageHeadTitleSymbol, pageLangSymbol, routeLocaleSymbol, siteData, siteLocaleDataSymbol, } from './composables';
3
+ import { withBase } from './helpers';
4
+ import { resolvers } from './resolvers';
5
+ /**
6
+ * Create and provide global computed
7
+ */
8
+ export const setupGlobalComputed = (app, router) => {
9
+ // create global computed
10
+ const routeLocale = computed(() => resolvers.resolveRouteLocale(siteData.value.locales, router.currentRoute.value.path));
11
+ const siteLocaleData = computed(() => resolvers.resolveSiteLocaleData(siteData.value, routeLocale.value));
12
+ const pageFrontmatter = computed(() => resolvers.resolvePageFrontmatter(pageData.value));
13
+ const pageHeadTitle = computed(() => resolvers.resolvePageHeadTitle(pageData.value, siteLocaleData.value));
14
+ const pageHead = computed(() => resolvers.resolvePageHead(pageHeadTitle.value, pageFrontmatter.value, siteLocaleData.value));
15
+ const pageLang = computed(() => resolvers.resolvePageLang(pageData.value));
16
+ // provide global computed
17
+ app.provide(routeLocaleSymbol, routeLocale);
18
+ app.provide(siteLocaleDataSymbol, siteLocaleData);
19
+ app.provide(pageFrontmatterSymbol, pageFrontmatter);
20
+ app.provide(pageHeadTitleSymbol, pageHeadTitle);
21
+ app.provide(pageHeadSymbol, pageHead);
22
+ app.provide(pageLangSymbol, pageLang);
23
+ // provide global helpers
24
+ Object.defineProperties(app.config.globalProperties, {
25
+ $frontmatter: { get: () => pageFrontmatter.value },
26
+ $head: { get: () => pageHead.value },
27
+ $headTitle: { get: () => pageHeadTitle.value },
28
+ $lang: { get: () => pageLang.value },
29
+ $page: { get: () => pageData.value },
30
+ $routeLocale: { get: () => routeLocale.value },
31
+ $site: { get: () => siteData.value },
32
+ $siteLocale: { get: () => siteLocaleData.value },
33
+ $withBase: { get: () => withBase },
34
+ });
35
+ return {
36
+ pageData,
37
+ pageFrontmatter,
38
+ pageHead,
39
+ pageHeadTitle,
40
+ pageLang,
41
+ routeLocale,
42
+ siteData,
43
+ siteLocaleData,
44
+ };
45
+ };
@@ -0,0 +1,13 @@
1
+ import type { HeadConfig } from '@vuepress/shared';
2
+ /**
3
+ * Auto update head and provide as global util
4
+ */
5
+ export declare const setupUpdateHead: () => void;
6
+ /**
7
+ * Query the matched head tag of head config
8
+ */
9
+ export declare const queryHeadTag: ([tagName, attrs, content,]: HeadConfig) => HTMLElement | null;
10
+ /**
11
+ * Create head tag from head config
12
+ */
13
+ export declare const createHeadTag: ([tagName, attrs, content,]: HeadConfig) => HTMLElement | null;
@@ -0,0 +1,101 @@
1
+ import { isPlainObject, isString } from '@vuepress/shared';
2
+ import { onMounted, provide, ref, useSSRContext, watch } from 'vue';
3
+ import { useRoute } from 'vue-router';
4
+ import { updateHeadSymbol, usePageHead, usePageLang } from './composables';
5
+ /**
6
+ * Auto update head and provide as global util
7
+ */
8
+ export const setupUpdateHead = () => {
9
+ const route = useRoute();
10
+ const head = usePageHead();
11
+ const lang = usePageLang();
12
+ // ssr-only, extract page meta info to ssrContext
13
+ if (__VUEPRESS_SSR__) {
14
+ const ssrContext = useSSRContext();
15
+ if (ssrContext) {
16
+ ssrContext.head = head.value;
17
+ ssrContext.lang = lang.value;
18
+ }
19
+ return;
20
+ }
21
+ const headTags = ref([]);
22
+ // load current head tags from DOM
23
+ const loadHead = () => {
24
+ head.value.forEach((item) => {
25
+ const tag = queryHeadTag(item);
26
+ if (tag) {
27
+ headTags.value.push(tag);
28
+ }
29
+ });
30
+ };
31
+ // update html lang attribute and head tags to DOM
32
+ const updateHead = () => {
33
+ document.documentElement.lang = lang.value;
34
+ headTags.value.forEach((item) => {
35
+ if (item.parentNode === document.head) {
36
+ document.head.removeChild(item);
37
+ }
38
+ });
39
+ headTags.value.splice(0, headTags.value.length);
40
+ head.value.forEach((item) => {
41
+ const tag = createHeadTag(item);
42
+ if (tag !== null) {
43
+ document.head.appendChild(tag);
44
+ headTags.value.push(tag);
45
+ }
46
+ });
47
+ };
48
+ provide(updateHeadSymbol, updateHead);
49
+ onMounted(() => {
50
+ loadHead();
51
+ updateHead();
52
+ // only update head on route change
53
+ watch(() => route.path, () => updateHead());
54
+ });
55
+ };
56
+ /**
57
+ * Query the matched head tag of head config
58
+ */
59
+ export const queryHeadTag = ([tagName, attrs, content = '',]) => {
60
+ const attrsSelector = Object.entries(attrs)
61
+ .map(([key, value]) => {
62
+ if (isString(value)) {
63
+ return `[${key}="${value}"]`;
64
+ }
65
+ if (value === true) {
66
+ return `[${key}]`;
67
+ }
68
+ return '';
69
+ })
70
+ .join('');
71
+ const selector = `head > ${tagName}${attrsSelector}`;
72
+ const tags = Array.from(document.querySelectorAll(selector));
73
+ const matchedTag = tags.find((item) => item.innerText === content);
74
+ return matchedTag || null;
75
+ };
76
+ /**
77
+ * Create head tag from head config
78
+ */
79
+ export const createHeadTag = ([tagName, attrs, content,]) => {
80
+ if (!isString(tagName)) {
81
+ return null;
82
+ }
83
+ // create element
84
+ const tag = document.createElement(tagName);
85
+ // set attributes
86
+ if (isPlainObject(attrs)) {
87
+ Object.entries(attrs).forEach(([key, value]) => {
88
+ if (isString(value)) {
89
+ tag.setAttribute(key, value);
90
+ }
91
+ else if (value === true) {
92
+ tag.setAttribute(key, '');
93
+ }
94
+ });
95
+ }
96
+ // set content
97
+ if (isString(content)) {
98
+ tag.appendChild(document.createTextNode(content));
99
+ }
100
+ return tag;
101
+ };
@@ -1,7 +1,2 @@
1
1
  export * from './clientAppEnhance';
2
2
  export * from './clientAppSetup';
3
- declare module 'vue-router' {
4
- interface RouteMeta {
5
- title?: string;
6
- }
7
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vuepress/client",
3
- "version": "2.0.0-beta.29",
3
+ "version": "2.0.0-beta.35",
4
4
  "description": "Client package of VuePress",
5
5
  "keywords": [
6
6
  "vuepress",
@@ -29,16 +29,17 @@
29
29
  "copy": "cpx \"src/**/*.{d.ts,css}\" lib"
30
30
  },
31
31
  "dependencies": {
32
- "@vuepress/shared": "2.0.0-beta.28",
33
- "vue": "^3.2.24",
32
+ "@vue/devtools-api": "^6.0.0-beta.21.1",
33
+ "@vuepress/shared": "2.0.0-beta.35",
34
+ "vue": "^3.2.28",
34
35
  "vue-router": "^4.0.12"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@types/webpack-env": "^1.16.3",
38
- "vite": "^2.7.1"
39
+ "vite": "^2.7.13"
39
40
  },
40
41
  "publishConfig": {
41
42
  "access": "public"
42
43
  },
43
- "gitHead": "2c6eb4270f96b6351cd1f565798bed1f662a6bb2"
44
+ "gitHead": "4bf1c55b6fb863c9251aa80178d5bc6475f5b315"
44
45
  }
File without changes
package/types.d.ts CHANGED
@@ -2,3 +2,5 @@ declare const __VUEPRESS_VERSION__: string
2
2
  declare const __VUEPRESS_DEV__: boolean
3
3
  declare const __VUEPRESS_SSR__: boolean
4
4
  declare const __VUE_HMR_RUNTIME__: Record<string, any>
5
+ declare const __VUE_OPTIONS_API__: boolean
6
+ declare const __VUE_PROD_DEVTOOLS__: boolean
@@ -1,20 +0,0 @@
1
- import type { App } from 'vue';
2
- import type { Router } from 'vue-router';
3
- import type { PageData, PageFrontmatter, PageHeadTitle, PageLang, RouteLocale, SiteData, SiteLocaleData } from './composables';
4
- import { withBase } from './utils';
5
- /**
6
- * Create and provide global computed
7
- */
8
- export declare const provideGlobalComputed: (app: App, router: Router) => void;
9
- declare module '@vue/runtime-core' {
10
- interface ComponentCustomProperties {
11
- $frontmatter: PageFrontmatter;
12
- $headTitle: PageHeadTitle;
13
- $lang: PageLang;
14
- $page: PageData;
15
- $routeLocale: RouteLocale;
16
- $site: SiteData;
17
- $siteLocale: SiteLocaleData;
18
- $withBase: typeof withBase;
19
- }
20
- }
@@ -1,33 +0,0 @@
1
- import { computed } from 'vue';
2
- import { pageData, pageFrontmatterSymbol, pageHeadSymbol, pageHeadTitleSymbol, pageLangSymbol, resolvePageFrontmatter, resolvePageHead, resolvePageHeadTitle, resolvePageLang, resolveRouteLocale, resolveSiteLocaleData, routeLocaleSymbol, siteData, siteLocaleDataSymbol, } from './composables';
3
- import { withBase } from './utils';
4
- /**
5
- * Create and provide global computed
6
- */
7
- export const provideGlobalComputed = (app, router) => {
8
- // create global computed
9
- const routeLocale = computed(() => resolveRouteLocale(siteData.value.locales, router.currentRoute.value.path));
10
- const siteLocaleData = computed(() => resolveSiteLocaleData(siteData.value, routeLocale.value));
11
- const pageFrontmatter = computed(() => resolvePageFrontmatter(pageData.value));
12
- const pageHeadTitle = computed(() => resolvePageHeadTitle(pageData.value, siteLocaleData.value));
13
- const pageHead = computed(() => resolvePageHead(pageHeadTitle.value, pageFrontmatter.value, siteLocaleData.value));
14
- const pageLang = computed(() => resolvePageLang(pageData.value));
15
- // provide global computed
16
- app.provide(routeLocaleSymbol, routeLocale);
17
- app.provide(siteLocaleDataSymbol, siteLocaleData);
18
- app.provide(pageFrontmatterSymbol, pageFrontmatter);
19
- app.provide(pageHeadTitleSymbol, pageHeadTitle);
20
- app.provide(pageHeadSymbol, pageHead);
21
- app.provide(pageLangSymbol, pageLang);
22
- // provide global helpers
23
- Object.defineProperties(app.config.globalProperties, {
24
- $frontmatter: { get: () => pageFrontmatter.value },
25
- $headTitle: { get: () => pageHeadTitle.value },
26
- $lang: { get: () => pageLang.value },
27
- $page: { get: () => pageData.value },
28
- $routeLocale: { get: () => routeLocale.value },
29
- $site: { get: () => siteData.value },
30
- $siteLocale: { get: () => siteLocaleData.value },
31
- $withBase: { get: () => withBase },
32
- });
33
- };