@monkeyplus/flow 6.0.53 → 6.0.54

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.
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monkeyplus/flow",
3
- "version": "6.0.53",
3
+ "version": "6.0.54",
4
4
  "description": "@monkeyplus/flow package-first runtime with Vite, Nitro, Vue and a workspace playground.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -4,6 +4,34 @@ import pageDefinitions from "virtual:flow/pages";
4
4
  import { getFlowImageRuntimeUtils } from "../../modules/images/runtime/server.mjs";
5
5
  import { mergeLayoutContextValues } from "../../src/runtime/layout-context.mjs";
6
6
  import { localizeRoutePattern, normalizePath, toPublicRoute } from "../../src/runtime/locale-routing.mjs";
7
+ function mergeHeadDefinitions(...heads) {
8
+ const result = {};
9
+ for (const head of heads) {
10
+ if (!head) continue;
11
+ for (const [key, value] of Object.entries(head)) {
12
+ if (["meta", "link", "script", "style", "noscript"].includes(key)) {
13
+ result[key] = [...result[key] || [], ...Array.isArray(value) ? value : []];
14
+ } else if (["htmlAttrs", "bodyAttrs"].includes(key)) {
15
+ result[key] = { ...result[key], ...value };
16
+ } else if (key === "templateParams") {
17
+ result.templateParams = result.templateParams || {};
18
+ for (const [tpKey, tpValue] of Object.entries(value || {})) {
19
+ if (typeof tpValue === "object" && tpValue !== null && !Array.isArray(tpValue)) {
20
+ result.templateParams[tpKey] = {
21
+ ...result.templateParams[tpKey] || {},
22
+ ...tpValue
23
+ };
24
+ } else {
25
+ result.templateParams[tpKey] = tpValue;
26
+ }
27
+ }
28
+ } else {
29
+ result[key] = value;
30
+ }
31
+ }
32
+ }
33
+ return result;
34
+ }
7
35
  const dynamicRouteCache = /* @__PURE__ */ new Map();
8
36
  let runtimeConfigRequire;
9
37
  function getFlowRuntimeConfig() {
@@ -101,7 +129,12 @@ async function resolveLayoutContext(definition, ctx) {
101
129
  const layoutContext = layoutKey === "global" ? void 0 : layoutContexts[layoutKey];
102
130
  const resolvedGlobalContext = globalLayoutContext?.setup ? asContextRecord(await globalLayoutContext.setup(ctx)) : void 0;
103
131
  const resolvedLayoutContext = layoutContext?.setup ? asContextRecord(await layoutContext.setup(ctx)) : void 0;
104
- return mergeLayoutContextValues(resolvedGlobalContext, resolvedLayoutContext);
132
+ const resolvedGlobalHead = globalLayoutContext?.head ? await globalLayoutContext.head(ctx) : void 0;
133
+ const resolvedLayoutHead = layoutContext?.head ? await layoutContext.head(ctx) : void 0;
134
+ return {
135
+ context: mergeLayoutContextValues(resolvedGlobalContext, resolvedLayoutContext),
136
+ head: { global: resolvedGlobalHead, layout: resolvedLayoutHead }
137
+ };
105
138
  }
106
139
  function mergeResolvedContext(context, layoutContext, dynamic, assign) {
107
140
  const resolvedContext = assign && dynamic?.context ? { ...context, [assign]: dynamic.context, dynamic } : dynamic ? { ...context, dynamic } : context;
@@ -277,11 +310,12 @@ export async function resolvePage(pathname, request) {
277
310
  continue;
278
311
  }
279
312
  const ctx = createContext(match.definition, locale, match.localePage, pathname, match.params, dynamic, request);
280
- const head = match.localePage.head ? await match.localePage.head(ctx) : match.localePage.seo ? await match.localePage.seo(ctx) : {};
313
+ const pageHead = match.localePage.head ? await match.localePage.head(ctx) : match.localePage.seo ? await match.localePage.seo(ctx) : {};
281
314
  const layoutContext = await resolveLayoutContext(match.definition, ctx);
282
315
  const context = match.localePage.context ? await match.localePage.context(ctx) : {};
283
316
  const assign = match.localePage.dynamic?.assign;
284
- const resolvedContext = mergeResolvedContext(context, layoutContext, dynamic, assign);
317
+ const resolvedContext = mergeResolvedContext(context, layoutContext.context, dynamic, assign);
318
+ const head = mergeHeadDefinitions(layoutContext.head.global, layoutContext.head.layout, pageHead);
285
319
  return {
286
320
  definition: match.definition,
287
321
  locale,
@@ -311,9 +345,10 @@ export async function resolvePageByName(name, pathname, request) {
311
345
  const locale = createLocale(localeCode);
312
346
  const params = {};
313
347
  const ctx = createContext(definition, locale, localePage, pathname, params, void 0, request);
314
- const head = localePage.head ? await localePage.head(ctx) : localePage.seo ? await localePage.seo(ctx) : {};
348
+ const pageHead = localePage.head ? await localePage.head(ctx) : localePage.seo ? await localePage.seo(ctx) : {};
315
349
  const layoutContext = await resolveLayoutContext(definition, ctx);
316
350
  const context = localePage.context ? await localePage.context(ctx) : {};
351
+ const head = mergeHeadDefinitions(layoutContext.head.global, layoutContext.head.layout, pageHead);
317
352
  return {
318
353
  definition,
319
354
  locale,
@@ -323,7 +358,7 @@ export async function resolvePageByName(name, pathname, request) {
323
358
  params,
324
359
  head,
325
360
  seo: head,
326
- context: mergeResolvedContext(context, layoutContext)
361
+ context: mergeResolvedContext(context, layoutContext.context)
327
362
  };
328
363
  }
329
364
  return void 0;
@@ -1,5 +1,5 @@
1
1
  import islands from "virtual:flow/islands";
2
- import { createSSRApp, h, defineComponent } from "vue";
2
+ import { createSSRApp, defineComponent, h } from "vue";
3
3
  import { createBootImageUtils } from "./components/image-shared.mjs";
4
4
  import { getClientHead } from "./head.mjs";
5
5
  import { installFlowVuePlugins } from "./vue.mjs";
@@ -47,7 +47,7 @@ async function hydrateIsland(element, boot) {
47
47
  const slotEl = element.querySelector(`div[data-flow-slot-template="${name}"]`);
48
48
  if (slotEl) {
49
49
  const html = slotEl.innerHTML;
50
- clientSlots[name] = () => h("div", { "data-flow-slot": name, style: "display: contents;", innerHTML: html });
50
+ clientSlots[name] = () => h("div", { "data-flow-slot": name, "style": "display: contents;", "innerHTML": html });
51
51
  }
52
52
  }
53
53
  }
@@ -1,7 +1,8 @@
1
- import type { MaybePromise, PageContextInput } from './pages.ts';
1
+ import type { HeadDefinition, MaybePromise, PageContextInput } from './pages.ts';
2
2
  export interface LayoutContextDefinition {
3
- setup: (ctx: PageContextInput) => MaybePromise<Record<string, unknown>>;
3
+ setup?: (ctx: PageContextInput) => MaybePromise<Record<string, unknown>>;
4
+ head?: (ctx: PageContextInput) => MaybePromise<HeadDefinition>;
4
5
  }
5
- export type LayoutContextValue<T extends LayoutContextDefinition> = Awaited<ReturnType<T['setup']>>;
6
+ export type LayoutContextValue<T extends LayoutContextDefinition> = T['setup'] extends (...args: any) => any ? Awaited<ReturnType<T['setup']>> : Record<string, unknown>;
6
7
  export declare function defineLayoutContext(context: LayoutContextDefinition): LayoutContextDefinition;
7
8
  export declare function mergeLayoutContextValues(...contexts: Array<Record<string, unknown> | undefined>): Record<string, unknown>;