iles
Version:
Vite & Vue powered static site generator with partial hydration
43 lines (42 loc) • 1.61 kB
JavaScript
import { computed, ref, inject } from 'vue';
import { routeLocationKey } from 'vue-router';
import { propsFromRoute } from '../props';
import { toReactive } from './reactivity';
export const pageDataKey = Symbol('[iles-page-data]');
function last(arr) {
return arr[arr.length - 1];
}
function injectFromApp(key, app) {
const result = app ? app._context.provides[key] : inject(key);
if (!result)
throw new Error('Page data not properly injected in app. Are you using it inside an island?');
return result;
}
const _lastPageChange = ref(new Date());
export const forcePageUpdate = () => { _lastPageChange.value = new Date(); };
export const computedInPage = (fn) => {
return computed(() => {
_lastPageChange.value; // track dependency to recompute as needed.
return fn();
});
};
export function pageFromRoute(route) {
return (last(route.matched)?.components?.default || {});
}
function reactiveFromFn(fn) {
return toReactive(computed(fn));
}
export function installPageData(app, siteRef) {
const route = injectFromApp(routeLocationKey, app);
const page = computedInPage(() => pageFromRoute(route));
const meta = reactiveFromFn(() => page.value.meta || {});
const frontmatter = reactiveFromFn(() => page.value.frontmatter || {});
const props = computedInPage(() => propsFromRoute(route));
const site = toReactive(siteRef);
const pageData = { route, page, meta, frontmatter, site, props };
app.provide(pageDataKey, pageData);
return pageData;
}
export function usePage(app) {
return injectFromApp(pageDataKey, app);
}