@monkeyplus/flow 6.0.56 → 6.0.58
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/package.json +1 -1
- package/server/lib/pages.d.ts +3 -1
- package/server/lib/pages.mjs +57 -2
- package/server/lib/render.mjs +30 -2
- package/src/public/index.d.ts +1 -1
- package/src/public/index.mjs +3 -1
- package/src/public/vite.mjs +6 -1
- package/src/runtime/boot.d.ts +0 -17
- package/src/runtime/composables.d.ts +9 -1
- package/src/runtime/composables.mjs +22 -0
- package/src/runtime/islands.mjs +1 -0
- package/src/runtime/pages.d.ts +23 -0
- package/src/runtime/virtual.d.ts +1 -1
package/package.json
CHANGED
package/server/lib/pages.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DynamicRouteEntry, FlowLocale, GetUrlOptions, HeadDefinition, PageDefinition, PageLocaleDefinition, PageUrlInfo } from '../../src/runtime/pages';
|
|
1
|
+
import type { DynamicRouteEntry, FlowLocale, GetUrlOptions, HeadDefinition, PageDefinition, PageLocaleDefinition, PageUrlInfo, BreadcrumbItem } from '../../src/runtime/pages';
|
|
2
2
|
export interface ResolvedPage {
|
|
3
3
|
definition: PageDefinition;
|
|
4
4
|
locale: FlowLocale;
|
|
@@ -13,8 +13,10 @@ export interface ResolvedPage {
|
|
|
13
13
|
*/
|
|
14
14
|
seo: HeadDefinition;
|
|
15
15
|
context: Record<string, unknown>;
|
|
16
|
+
breadcrumbs: BreadcrumbItem[];
|
|
16
17
|
}
|
|
17
18
|
export declare function getUrl(namePage: string, localeCode?: string, options?: GetUrlOptions): Promise<string | undefined>;
|
|
18
19
|
export declare function getUrls(withLocale?: boolean, omitNoPublish?: boolean): Promise<(string | PageUrlInfo)[]>;
|
|
19
20
|
export declare function resolvePage(pathname: string, request?: Request): Promise<ResolvedPage | undefined>;
|
|
20
21
|
export declare function resolvePageByName(name: string, pathname: string, request?: Request): Promise<ResolvedPage | undefined>;
|
|
22
|
+
export declare function resolveBreadcrumbs(pageName: string, pathname: string, localeCode: string, params: Record<string, string>, dynamic: DynamicRouteEntry | undefined, request: Request | undefined, visited?: Set<string>): Promise<BreadcrumbItem[]>;
|
package/server/lib/pages.mjs
CHANGED
|
@@ -98,10 +98,14 @@ function createLocale(code) {
|
|
|
98
98
|
function createContext(definition, locale, localePage, pathname, params, dynamic, request) {
|
|
99
99
|
const imageUtils = getFlowImageRuntimeUtils();
|
|
100
100
|
const preview = request?.headers.get("cookie")?.includes("flow_preview=true") || false;
|
|
101
|
+
const config = getFlowRuntimeConfig();
|
|
102
|
+
const siteUrl = config.flow?.siteUrl || "";
|
|
103
|
+
const fullPath = siteUrl ? `${siteUrl.replace(/\/$/, "")}${pathname}` : pathname;
|
|
101
104
|
return {
|
|
102
105
|
dynamic,
|
|
103
106
|
locale,
|
|
104
107
|
path: pathname,
|
|
108
|
+
fullPath,
|
|
105
109
|
name: definition.name,
|
|
106
110
|
page: localePage,
|
|
107
111
|
params,
|
|
@@ -317,6 +321,7 @@ export async function resolvePage(pathname, request) {
|
|
|
317
321
|
const assign = match.localePage.dynamic?.assign;
|
|
318
322
|
const resolvedContext = mergeResolvedContext(context, layoutContext.context, dynamic, assign);
|
|
319
323
|
const head = mergeHeadDefinitions(layoutContext.head.global, layoutContext.head.layout, pageHead);
|
|
324
|
+
const breadcrumbs = await resolveBreadcrumbs(match.definition.name, pathname, match.localeCode, match.params, dynamic, request);
|
|
320
325
|
return {
|
|
321
326
|
definition: match.definition,
|
|
322
327
|
locale,
|
|
@@ -327,7 +332,8 @@ export async function resolvePage(pathname, request) {
|
|
|
327
332
|
dynamic,
|
|
328
333
|
head,
|
|
329
334
|
seo: head,
|
|
330
|
-
context: resolvedContext
|
|
335
|
+
context: resolvedContext,
|
|
336
|
+
breadcrumbs
|
|
331
337
|
};
|
|
332
338
|
}
|
|
333
339
|
return void 0;
|
|
@@ -350,6 +356,7 @@ export async function resolvePageByName(name, pathname, request) {
|
|
|
350
356
|
const layoutContext = await resolveLayoutContext(definition, ctx);
|
|
351
357
|
const context = localePage.context ? await localePage.context(ctx) : {};
|
|
352
358
|
const head = mergeHeadDefinitions(layoutContext.head.global, layoutContext.head.layout, pageHead);
|
|
359
|
+
const breadcrumbs = await resolveBreadcrumbs(definition.name, pathname, localeCode, params, void 0, request);
|
|
353
360
|
return {
|
|
354
361
|
definition,
|
|
355
362
|
locale,
|
|
@@ -359,8 +366,56 @@ export async function resolvePageByName(name, pathname, request) {
|
|
|
359
366
|
params,
|
|
360
367
|
head,
|
|
361
368
|
seo: head,
|
|
362
|
-
context: mergeResolvedContext(context, layoutContext.context)
|
|
369
|
+
context: mergeResolvedContext(context, layoutContext.context),
|
|
370
|
+
breadcrumbs
|
|
363
371
|
};
|
|
364
372
|
}
|
|
365
373
|
return void 0;
|
|
366
374
|
}
|
|
375
|
+
export async function resolveBreadcrumbs(pageName, pathname, localeCode, params, dynamic, request, visited = /* @__PURE__ */ new Set()) {
|
|
376
|
+
if (visited.has(pageName)) {
|
|
377
|
+
return [];
|
|
378
|
+
}
|
|
379
|
+
visited.add(pageName);
|
|
380
|
+
const definition = pageDefinitions.find((candidate) => candidate.name === pageName);
|
|
381
|
+
if (!definition) return [];
|
|
382
|
+
const localePage = definition.locales[localeCode];
|
|
383
|
+
if (!localePage || !localePage.breadcrumb) return [];
|
|
384
|
+
const locale = createLocale(localeCode);
|
|
385
|
+
const ctx = createContext(definition, locale, localePage, pathname, params, dynamic, request);
|
|
386
|
+
const pageContext = await executeContextDefinition(localePage.context, pageName, ctx);
|
|
387
|
+
const pageHead = await executeContextDefinition(localePage.head, pageName, ctx);
|
|
388
|
+
const breadcrumbCtx = {
|
|
389
|
+
...ctx,
|
|
390
|
+
context: pageContext,
|
|
391
|
+
head: pageHead,
|
|
392
|
+
seo: pageHead.seo || pageHead
|
|
393
|
+
};
|
|
394
|
+
const result = await localePage.breadcrumb(breadcrumbCtx);
|
|
395
|
+
if (!result) return [];
|
|
396
|
+
let currentItems = [];
|
|
397
|
+
if (result.items) {
|
|
398
|
+
currentItems = result.items;
|
|
399
|
+
} else if (result.item) {
|
|
400
|
+
currentItems = [result.item];
|
|
401
|
+
}
|
|
402
|
+
for (const item of currentItems) {
|
|
403
|
+
if (!item.url || item.url === "#") {
|
|
404
|
+
item.url = await ctx.utils.getUrl(pageName, localeCode, { params });
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
let parentItems = [];
|
|
408
|
+
if (result.parent) {
|
|
409
|
+
let parentName = "";
|
|
410
|
+
let parentParams = params;
|
|
411
|
+
if (typeof result.parent === "string") {
|
|
412
|
+
parentName = result.parent;
|
|
413
|
+
} else {
|
|
414
|
+
parentName = result.parent.name;
|
|
415
|
+
parentParams = result.parent.params;
|
|
416
|
+
}
|
|
417
|
+
const parentPathname = await ctx.utils.getUrl(parentName, localeCode, { params: parentParams }) || "/";
|
|
418
|
+
parentItems = await resolveBreadcrumbs(parentName, parentPathname, localeCode, parentParams, void 0, request, visited);
|
|
419
|
+
}
|
|
420
|
+
return [...parentItems, ...currentItems];
|
|
421
|
+
}
|
package/server/lib/render.mjs
CHANGED
|
@@ -142,6 +142,7 @@ ${cleanTrace}`);
|
|
|
142
142
|
};
|
|
143
143
|
app.provide("context", context);
|
|
144
144
|
app.provide("utils", utils);
|
|
145
|
+
app.provide("breadcrumbs", page.breadcrumbs);
|
|
145
146
|
const head = createHead();
|
|
146
147
|
head.use(UnheadSchemaOrg());
|
|
147
148
|
head.push({
|
|
@@ -149,6 +150,9 @@ ${cleanTrace}`);
|
|
|
149
150
|
lang: page.locale.lang
|
|
150
151
|
}
|
|
151
152
|
});
|
|
153
|
+
if (page.head) {
|
|
154
|
+
head.push(page.head);
|
|
155
|
+
}
|
|
152
156
|
head.push(normalizeSeoToHead(page.head, fallbackTitle, fallbackDescription));
|
|
153
157
|
app.use(head);
|
|
154
158
|
installFlowVuePlugins(app);
|
|
@@ -168,7 +172,8 @@ export async function renderDocument(page, clientAssets) {
|
|
|
168
172
|
title: fallbackTitle,
|
|
169
173
|
locale: page.locale,
|
|
170
174
|
mode,
|
|
171
|
-
images: getFlowImageBootPayload()
|
|
175
|
+
images: getFlowImageBootPayload(),
|
|
176
|
+
breadcrumbs: page.breadcrumbs
|
|
172
177
|
};
|
|
173
178
|
const rendered = await renderBody(page);
|
|
174
179
|
const body = stripVueFragmentMarkers(rendered.body);
|
|
@@ -198,5 +203,28 @@ export async function renderDocument(page, clientAssets) {
|
|
|
198
203
|
].join("\n "),
|
|
199
204
|
body: pageMarkup
|
|
200
205
|
});
|
|
201
|
-
|
|
206
|
+
let finalHtml = await transformHtmlTemplate(rendered.head, html);
|
|
207
|
+
const schemaOrgConfig = page.head.templateParams?.schemaOrg;
|
|
208
|
+
if (schemaOrgConfig?.inLanguage && schemaOrgConfig.inLanguage !== page.locale.lang) {
|
|
209
|
+
finalHtml = finalHtml.replace(/<script[^>]*data-hid="schema-org-graph"[^>]*>([\s\S]*?)<\/script>/, (match, content) => {
|
|
210
|
+
try {
|
|
211
|
+
const data = JSON.parse(content);
|
|
212
|
+
const replaceLang = (obj) => {
|
|
213
|
+
if (Array.isArray(obj)) {
|
|
214
|
+
obj.forEach(replaceLang);
|
|
215
|
+
} else if (typeof obj === "object" && obj !== null) {
|
|
216
|
+
if (obj.inLanguage === page.locale.lang) {
|
|
217
|
+
obj.inLanguage = schemaOrgConfig.inLanguage;
|
|
218
|
+
}
|
|
219
|
+
Object.values(obj).forEach(replaceLang);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
replaceLang(data);
|
|
223
|
+
return match.replace(content, JSON.stringify(data));
|
|
224
|
+
} catch (e) {
|
|
225
|
+
return match;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
return finalHtml;
|
|
202
230
|
}
|
package/src/public/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { ContentDirectoryNode, ContentEntry, ContentFileNode, ContentTreeNode, } from '../../modules/content/query.ts';
|
|
2
2
|
export type { FlowBootPayload } from '../runtime/boot.ts';
|
|
3
|
-
export { useContext, useGlobal, useHead, useLocale, usePage, useSeo, useSharedContext, useUtils, useView, } from '../runtime/composables.ts';
|
|
3
|
+
export { useContext, useGlobal, useHead, useLocale, usePage, useSeo, useSharedContext, useUrl, useUtils, useView, useBreadcrumb, } from '../runtime/composables.ts';
|
|
4
4
|
export { defineFlowConfig, defineFlowModule, resolveFlowConfig } from '../runtime/config.ts';
|
|
5
5
|
export type { FlowConfig, UserFlowConfig, } from '../runtime/config.ts';
|
|
6
6
|
export { useSchemaOrg } from '../runtime/head.ts';
|
package/src/public/index.mjs
CHANGED
|
@@ -6,8 +6,10 @@ export {
|
|
|
6
6
|
usePage,
|
|
7
7
|
useSeo,
|
|
8
8
|
useSharedContext,
|
|
9
|
+
useUrl,
|
|
9
10
|
useUtils,
|
|
10
|
-
useView
|
|
11
|
+
useView,
|
|
12
|
+
useBreadcrumb
|
|
11
13
|
} from "../runtime/composables.mjs";
|
|
12
14
|
export { defineFlowConfig, defineFlowModule, resolveFlowConfig } from "../runtime/config.mjs";
|
|
13
15
|
export { useSchemaOrg } from "../runtime/head.mjs";
|
package/src/public/vite.mjs
CHANGED
|
@@ -343,6 +343,9 @@ export function createFlowViteConfig(options = {}) {
|
|
|
343
343
|
const { imports: userImports, ...userAutoImport } = options.userFlowConfig?.autoImport || {};
|
|
344
344
|
const uiOptions = options.userFlowConfig?.ui || {};
|
|
345
345
|
return defineConfig({
|
|
346
|
+
define: {
|
|
347
|
+
"import.meta.env.FLOW_SITE_URL": JSON.stringify(flowConfig.siteUrl || "")
|
|
348
|
+
},
|
|
346
349
|
plugins: [
|
|
347
350
|
createFlowVirtualServerModules(projectRoot, flowConfig),
|
|
348
351
|
createFlowVirtualClientPages(projectRoot),
|
|
@@ -382,9 +385,11 @@ export function createFlowViteConfig(options = {}) {
|
|
|
382
385
|
"useUtils",
|
|
383
386
|
"useSharedContext",
|
|
384
387
|
"useGlobal",
|
|
388
|
+
"useUrl",
|
|
385
389
|
"useLocale",
|
|
386
390
|
"usePage",
|
|
387
|
-
"useView"
|
|
391
|
+
"useView",
|
|
392
|
+
"useBreadcrumb"
|
|
388
393
|
],
|
|
389
394
|
...mappedNitroImports
|
|
390
395
|
},
|
package/src/runtime/boot.d.ts
CHANGED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { FlowImageMeta, FlowImageOptions } from '../../modules/images/runtime/types.ts';
|
|
2
|
-
import type { FlowHydrationMode, FlowLocale } from './pages';
|
|
3
|
-
export interface FlowImageBootPayload {
|
|
4
|
-
all: Record<string, FlowImageMeta>;
|
|
5
|
-
options: FlowImageOptions;
|
|
6
|
-
generateOutput: boolean;
|
|
7
|
-
strapiURL?: string;
|
|
8
|
-
}
|
|
9
|
-
export interface FlowBootPayload {
|
|
10
|
-
path: string;
|
|
11
|
-
bundle: string;
|
|
12
|
-
template: string;
|
|
13
|
-
title: string;
|
|
14
|
-
locale: FlowLocale;
|
|
15
|
-
mode: FlowHydrationMode;
|
|
16
|
-
images?: FlowImageBootPayload;
|
|
17
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FlowLocale, PageContextUtils, PageDefinition } from './pages.ts';
|
|
1
|
+
import type { BreadcrumbItem, FlowLocale, PageContextUtils, PageDefinition } from './pages.ts';
|
|
2
2
|
export declare function useContext<T = any>(): T;
|
|
3
3
|
export declare function useSeo(): any;
|
|
4
4
|
export declare function useHead<T = any>(): T;
|
|
@@ -8,3 +8,11 @@ export declare function useGlobal<T = any>(): T;
|
|
|
8
8
|
export declare function useLocale(): FlowLocale;
|
|
9
9
|
export declare function usePage(): PageDefinition;
|
|
10
10
|
export declare function useView(): PageDefinition['view'];
|
|
11
|
+
export interface UrlInfo {
|
|
12
|
+
pathname: string;
|
|
13
|
+
siteUrl?: string;
|
|
14
|
+
href: string;
|
|
15
|
+
joinUrl: (...params: string[]) => string;
|
|
16
|
+
}
|
|
17
|
+
export declare function useUrl(): UrlInfo;
|
|
18
|
+
export declare function useBreadcrumb(): BreadcrumbItem[];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { joinURL } from "ufo";
|
|
1
2
|
import { inject } from "vue";
|
|
2
3
|
export function useContext() {
|
|
3
4
|
const ctx = inject("context", {});
|
|
@@ -37,3 +38,24 @@ export function useView() {
|
|
|
37
38
|
const ctx = inject("context", {});
|
|
38
39
|
return { ...ctx.page?.view || {} };
|
|
39
40
|
}
|
|
41
|
+
export function useUrl() {
|
|
42
|
+
const ctx = inject("context", {});
|
|
43
|
+
const pathname = ctx.path || "/";
|
|
44
|
+
const siteUrl = import.meta.env.FLOW_SITE_URL || void 0;
|
|
45
|
+
let href = pathname || "/";
|
|
46
|
+
if (siteUrl) {
|
|
47
|
+
const base = siteUrl.endsWith("/") ? siteUrl.slice(0, -1) : siteUrl;
|
|
48
|
+
const path = href.startsWith("/") ? href : `/${href}`;
|
|
49
|
+
href = base + path;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
pathname,
|
|
53
|
+
siteUrl,
|
|
54
|
+
href,
|
|
55
|
+
joinUrl: (...params) => joinURL(siteUrl || "", ...params)
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function useBreadcrumb() {
|
|
59
|
+
const breadcrumbs = inject("breadcrumbs", []);
|
|
60
|
+
return breadcrumbs;
|
|
61
|
+
}
|
package/src/runtime/islands.mjs
CHANGED
|
@@ -61,6 +61,7 @@ async function hydrateIsland(element, boot) {
|
|
|
61
61
|
const imageUtils = createBootImageUtils(boot);
|
|
62
62
|
app.use(getClientHead());
|
|
63
63
|
app.provide("utils", imageUtils);
|
|
64
|
+
app.provide("breadcrumbs", boot?.breadcrumbs || []);
|
|
64
65
|
installFlowVuePlugins(app);
|
|
65
66
|
app.mount(element);
|
|
66
67
|
element.dataset.flowIslandHydrated = "true";
|
package/src/runtime/pages.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ export interface PageContextUtils {
|
|
|
99
99
|
export interface PageContextInput {
|
|
100
100
|
locale: FlowLocale;
|
|
101
101
|
path: string;
|
|
102
|
+
fullPath?: string;
|
|
102
103
|
name: string;
|
|
103
104
|
view: PageViewDefinition;
|
|
104
105
|
page: PageLocaleDefinition;
|
|
@@ -107,6 +108,27 @@ export interface PageContextInput {
|
|
|
107
108
|
utils: PageContextUtils;
|
|
108
109
|
preview?: boolean;
|
|
109
110
|
}
|
|
111
|
+
export interface BreadcrumbItem {
|
|
112
|
+
title: string;
|
|
113
|
+
caption?: string;
|
|
114
|
+
url?: string;
|
|
115
|
+
}
|
|
116
|
+
export interface BreadcrumbDefinition {
|
|
117
|
+
parent?: string | {
|
|
118
|
+
name: string;
|
|
119
|
+
params: Record<string, string>;
|
|
120
|
+
};
|
|
121
|
+
item?: BreadcrumbItem;
|
|
122
|
+
items?: BreadcrumbItem[];
|
|
123
|
+
}
|
|
124
|
+
export interface BreadcrumbContextInput extends PageContextInput {
|
|
125
|
+
context: Record<string, unknown>;
|
|
126
|
+
head: HeadDefinition;
|
|
127
|
+
/**
|
|
128
|
+
* @deprecated Use head.
|
|
129
|
+
*/
|
|
130
|
+
seo: HeadDefinition;
|
|
131
|
+
}
|
|
110
132
|
export interface PageLocaleDefinition {
|
|
111
133
|
url: string;
|
|
112
134
|
head?: (ctx: PageContextInput) => MaybePromise<HeadDefinition>;
|
|
@@ -115,6 +137,7 @@ export interface PageLocaleDefinition {
|
|
|
115
137
|
*/
|
|
116
138
|
seo?: (ctx: PageContextInput) => MaybePromise<HeadDefinition>;
|
|
117
139
|
context?: (ctx: PageContextInput) => MaybePromise<Record<string, unknown>>;
|
|
140
|
+
breadcrumb?: (ctx: BreadcrumbContextInput) => MaybePromise<BreadcrumbDefinition>;
|
|
118
141
|
dynamic?: DynamicRouteOptions;
|
|
119
142
|
}
|
|
120
143
|
export interface PageDefinition {
|
package/src/runtime/virtual.d.ts
CHANGED