@monkeyplus/flow 6.0.11 → 6.0.13
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/README.md +63 -1
- package/package.json +1 -1
- package/server/lib/pages.mjs +48 -5
- package/src/public/index.d.ts +2 -0
- package/src/public/index.mjs +1 -0
- package/src/public/nitro.mjs +2 -0
- package/src/public/vite.mjs +5 -0
- package/src/runtime/layout-context.d.ts +7 -0
- package/src/runtime/layout-context.mjs +14 -0
- package/src/runtime/page-discovery.mjs +24 -3
- package/src/runtime/virtual-pages.d.ts +1 -0
- package/src/runtime/virtual-pages.mjs +21 -0
- package/src/runtime/virtual.d.ts +6 -0
package/README.md
CHANGED
|
@@ -16,10 +16,26 @@
|
|
|
16
16
|
|
|
17
17
|
El workspace consume la API fuente del root para mantener DX local, mientras que `dist/` genera un artefacto publicable con exports ya compilados.
|
|
18
18
|
|
|
19
|
+
## Guia de uso
|
|
20
|
+
|
|
21
|
+
La guia detallada de authoring vive en `docs/authoring.md` e incluye:
|
|
22
|
+
|
|
23
|
+
- como registrar y configurar modulos
|
|
24
|
+
- como definir paginas estaticas y dinamicas
|
|
25
|
+
- como organizar templates, layouts y `*.context.ts`
|
|
26
|
+
- como trabajar con `FlowIsland` y `client/islands/*`
|
|
27
|
+
|
|
28
|
+
Documentacion complementaria:
|
|
29
|
+
|
|
30
|
+
- `docs/modules.md`: referencia de modulos builtin
|
|
31
|
+
- `docs/recipes.md`: recetas basadas en el playground actual
|
|
32
|
+
|
|
33
|
+
Si vas a crear o mantener una app en Flow, ese archivo deberia ser el punto de entrada principal.
|
|
34
|
+
|
|
19
35
|
## API pública
|
|
20
36
|
|
|
21
37
|
```ts
|
|
22
|
-
import { defineFlowConfig, definePage } from '@monkeyplus/flow';
|
|
38
|
+
import { defineFlowConfig, defineLayoutContext, definePage } from '@monkeyplus/flow';
|
|
23
39
|
import { FlowIsland } from '@monkeyplus/flow/components';
|
|
24
40
|
import { getClientHead } from '@monkeyplus/flow/head';
|
|
25
41
|
import sitemapModule from '@monkeyplus/flow/modules/sitemap';
|
|
@@ -29,6 +45,52 @@ import { createFlowViteConfig } from '@monkeyplus/flow/vite';
|
|
|
29
45
|
import { installFlowVuePlugins } from '@monkeyplus/flow/vue';
|
|
30
46
|
```
|
|
31
47
|
|
|
48
|
+
## Contexto de layout
|
|
49
|
+
|
|
50
|
+
Los layouts pueden tener un handler de contexto colocalizado usando `views/layouts/<Layout>.context.ts`.
|
|
51
|
+
|
|
52
|
+
Opcionalmente puedes definir `views/layouts/global.context.ts` para compartir datos entre todos los layouts. Flow fusiona primero el contexto global y luego el contexto especifico del layout, por lo que el layout especifico tiene prioridad si repite una clave.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import type { GlobalLayoutContextValue } from './global.context';
|
|
56
|
+
// views/layouts/Default.context.ts
|
|
57
|
+
import { defineLayoutContext } from '@monkeyplus/flow';
|
|
58
|
+
|
|
59
|
+
const defaultLayoutContext = defineLayoutContext({
|
|
60
|
+
async setup(ctx) {
|
|
61
|
+
return {
|
|
62
|
+
menuName: 'main',
|
|
63
|
+
localeCode: ctx.locale.code,
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export type DefaultLayoutContextValue = GlobalLayoutContextValue & Awaited<ReturnType<typeof defaultLayoutContext.setup>>;
|
|
69
|
+
|
|
70
|
+
export default defaultLayoutContext;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Ese resultado se expone en el layout bajo `context.layout`.
|
|
74
|
+
|
|
75
|
+
```vue
|
|
76
|
+
<script setup lang="ts">
|
|
77
|
+
import type { DefaultLayoutContextValue } from './Default.context';
|
|
78
|
+
|
|
79
|
+
const props = defineProps<{
|
|
80
|
+
context?: {
|
|
81
|
+
layout?: DefaultLayoutContextValue
|
|
82
|
+
}
|
|
83
|
+
}>();
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<template>
|
|
87
|
+
<slot />
|
|
88
|
+
<small>{{ props.context?.layout?.menuName }}</small>
|
|
89
|
+
</template>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Esto reemplaza el patrón anterior de `shared/contexts` para casos que pertenecen al layout. Si una lógica debe compartirse entre varios layouts, puedes ponerla en `views/layouts/global.context.ts` o extraerla a un helper `.ts` reutilizable y llamarlo desde cada `*.context.ts`.
|
|
93
|
+
|
|
32
94
|
## Playground
|
|
33
95
|
|
|
34
96
|
La app de referencia vive en `playground/` y ya no en la raíz. Eso permite mantener el root enfocado en la distribución del paquete sin perder el flujo de desarrollo existente.
|
package/package.json
CHANGED
package/server/lib/pages.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import layoutContexts from "virtual:flow/layout-contexts";
|
|
2
3
|
import pageDefinitions from "virtual:flow/pages";
|
|
3
4
|
import { getFlowImageRuntimeUtils } from "../../modules/images/runtime/server.mjs";
|
|
5
|
+
import { mergeLayoutContextValues } from "../../src/runtime/layout-context.mjs";
|
|
4
6
|
import { localizeRoutePattern, normalizePath, toPublicRoute } from "../../src/runtime/locale-routing.mjs";
|
|
5
7
|
const dynamicRouteCache = /* @__PURE__ */ new Map();
|
|
6
8
|
let runtimeConfigRequire;
|
|
@@ -88,6 +90,24 @@ function createContext(definition, locale, localePage, pathname, params, dynamic
|
|
|
88
90
|
}
|
|
89
91
|
};
|
|
90
92
|
}
|
|
93
|
+
function asContextRecord(value) {
|
|
94
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
95
|
+
}
|
|
96
|
+
async function resolveLayoutContext(definition, ctx) {
|
|
97
|
+
const layoutKey = (definition.view.layout || "default").toLowerCase();
|
|
98
|
+
const globalLayoutContext = layoutContexts.global;
|
|
99
|
+
const layoutContext = layoutKey === "global" ? void 0 : layoutContexts[layoutKey];
|
|
100
|
+
const resolvedGlobalContext = globalLayoutContext?.setup ? asContextRecord(await globalLayoutContext.setup(ctx)) : void 0;
|
|
101
|
+
const resolvedLayoutContext = layoutContext?.setup ? asContextRecord(await layoutContext.setup(ctx)) : void 0;
|
|
102
|
+
return mergeLayoutContextValues(resolvedGlobalContext, resolvedLayoutContext);
|
|
103
|
+
}
|
|
104
|
+
function mergeResolvedContext(context, layoutContext, dynamic, assign) {
|
|
105
|
+
const resolvedContext = assign && dynamic?.context ? { ...context, [assign]: dynamic.context, dynamic } : dynamic ? { ...context, dynamic } : context;
|
|
106
|
+
return {
|
|
107
|
+
...resolvedContext,
|
|
108
|
+
layout: layoutContext
|
|
109
|
+
};
|
|
110
|
+
}
|
|
91
111
|
function isDynamicPattern(pattern) {
|
|
92
112
|
return pattern.includes("/:") || pattern.includes("/**");
|
|
93
113
|
}
|
|
@@ -110,6 +130,26 @@ function replacePath(pattern, url) {
|
|
|
110
130
|
function combineName(name, dynamicName) {
|
|
111
131
|
return `${name.replace(/\/*$/, "")}/${dynamicName.replace(/^\/*/, "")}`;
|
|
112
132
|
}
|
|
133
|
+
function resolveUrlTarget(namePage, explicitDynamicName) {
|
|
134
|
+
if (explicitDynamicName || !namePage.includes("/")) {
|
|
135
|
+
return {
|
|
136
|
+
namePage,
|
|
137
|
+
dynamicName: explicitDynamicName
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const match = pageDefinitions.filter((candidate) => candidate.name && namePage.startsWith(`${candidate.name}/`)).sort((left, right) => right.name.length - left.name.length)[0];
|
|
141
|
+
if (!match) {
|
|
142
|
+
return {
|
|
143
|
+
namePage,
|
|
144
|
+
dynamicName: explicitDynamicName
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const dynamicName = namePage.slice(match.name.length + 1);
|
|
148
|
+
return {
|
|
149
|
+
namePage: match.name,
|
|
150
|
+
dynamicName: dynamicName || explicitDynamicName
|
|
151
|
+
};
|
|
152
|
+
}
|
|
113
153
|
function getEnabledLocaleCodes() {
|
|
114
154
|
const runtimeConfig = getFlowRuntimeConfig();
|
|
115
155
|
return runtimeConfig.flow?.locale?.locales || [];
|
|
@@ -143,8 +183,9 @@ export async function getUrl(namePage, localeCode, options = {}) {
|
|
|
143
183
|
const enabledLocales = getEnabledLocaleCodes();
|
|
144
184
|
const targetLocale = localeCode || enabledLocales[0];
|
|
145
185
|
const runtimeConfig = getFlowRuntimeConfig();
|
|
186
|
+
const target = resolveUrlTarget(namePage, options.dynamicName);
|
|
146
187
|
for (const definition of pageDefinitions) {
|
|
147
|
-
if (definition.name !== namePage) {
|
|
188
|
+
if (definition.name !== target.namePage) {
|
|
148
189
|
continue;
|
|
149
190
|
}
|
|
150
191
|
const localeEntries = targetLocale ? [targetLocale] : Object.keys(definition.locales);
|
|
@@ -160,11 +201,11 @@ export async function getUrl(namePage, localeCode, options = {}) {
|
|
|
160
201
|
if (options.params) {
|
|
161
202
|
return replacePath(localizedRoute, options.params);
|
|
162
203
|
}
|
|
163
|
-
if (localePage.dynamic &&
|
|
204
|
+
if (localePage.dynamic && target.dynamicName) {
|
|
164
205
|
const locale = createLocale(code);
|
|
165
206
|
const ctx = createContext(definition, locale, localePage, toPublicRoute(runtimeConfig.flow, code, localePage.url), {});
|
|
166
207
|
const entries = await getDynamicEntries(definition, code, ctx);
|
|
167
|
-
const entry = entries.find((candidate) => candidate.name ===
|
|
208
|
+
const entry = entries.find((candidate) => candidate.name === target.dynamicName);
|
|
168
209
|
if (!entry) {
|
|
169
210
|
return void 0;
|
|
170
211
|
}
|
|
@@ -235,9 +276,10 @@ export async function resolvePage(pathname) {
|
|
|
235
276
|
}
|
|
236
277
|
const ctx = createContext(match.definition, locale, match.localePage, pathname, match.params, dynamic);
|
|
237
278
|
const head = match.localePage.head ? await match.localePage.head(ctx) : match.localePage.seo ? await match.localePage.seo(ctx) : {};
|
|
279
|
+
const layoutContext = await resolveLayoutContext(match.definition, ctx);
|
|
238
280
|
const context = match.localePage.context ? await match.localePage.context(ctx) : {};
|
|
239
281
|
const assign = match.localePage.dynamic?.assign;
|
|
240
|
-
const resolvedContext =
|
|
282
|
+
const resolvedContext = mergeResolvedContext(context, layoutContext, dynamic, assign);
|
|
241
283
|
return {
|
|
242
284
|
definition: match.definition,
|
|
243
285
|
locale,
|
|
@@ -268,6 +310,7 @@ export async function resolvePageByName(name, pathname) {
|
|
|
268
310
|
const params = {};
|
|
269
311
|
const ctx = createContext(definition, locale, localePage, pathname, params);
|
|
270
312
|
const head = localePage.head ? await localePage.head(ctx) : localePage.seo ? await localePage.seo(ctx) : {};
|
|
313
|
+
const layoutContext = await resolveLayoutContext(definition, ctx);
|
|
271
314
|
const context = localePage.context ? await localePage.context(ctx) : {};
|
|
272
315
|
return {
|
|
273
316
|
definition,
|
|
@@ -278,7 +321,7 @@ export async function resolvePageByName(name, pathname) {
|
|
|
278
321
|
params,
|
|
279
322
|
head,
|
|
280
323
|
seo: head,
|
|
281
|
-
context
|
|
324
|
+
context: mergeResolvedContext(context, layoutContext)
|
|
282
325
|
};
|
|
283
326
|
}
|
|
284
327
|
return void 0;
|
package/src/public/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export type { ContentDirectoryNode, ContentEntry, ContentFileNode, ContentTreeNo
|
|
|
2
2
|
export type { FlowBootPayload } from '../runtime/boot.ts';
|
|
3
3
|
export { defineFlowConfig, defineFlowModule, resolveFlowConfig } from '../runtime/config.ts';
|
|
4
4
|
export type { FlowConfig, UserFlowConfig, } from '../runtime/config.ts';
|
|
5
|
+
export { defineLayoutContext } from '../runtime/layout-context.ts';
|
|
6
|
+
export type { LayoutContextDefinition, LayoutContextValue } from '../runtime/layout-context.ts';
|
|
5
7
|
export { definePage } from '../runtime/pages.ts';
|
|
6
8
|
export type { FlowHydrationMode, FlowLocale, HeadDefinition, PageContextInput, PageDefinition, PageLocaleDefinition, PageViewDefinition, } from '../runtime/pages.ts';
|
|
7
9
|
export { queryContent } from './query-content.ts';
|
package/src/public/index.mjs
CHANGED
package/src/public/nitro.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { createFlowBuildHooks } from "../runtime/ssg.mjs";
|
|
|
6
6
|
import {
|
|
7
7
|
createVirtualBaseTemplatesModule,
|
|
8
8
|
createVirtualIslandsModule,
|
|
9
|
+
createVirtualLayoutContextsModule,
|
|
9
10
|
createVirtualLayoutsModule,
|
|
10
11
|
createVirtualPagesModule,
|
|
11
12
|
createVirtualTemplatesModule
|
|
@@ -50,6 +51,7 @@ export function createFlowNitroConfig(options = {}) {
|
|
|
50
51
|
"virtual:flow/islands": createVirtualIslandsModule(projectRoot),
|
|
51
52
|
"virtual:flow/templates": createVirtualTemplatesModule(projectRoot),
|
|
52
53
|
"virtual:flow/layouts": createVirtualLayoutsModule(projectRoot),
|
|
54
|
+
"virtual:flow/layout-contexts": createVirtualLayoutContextsModule(projectRoot),
|
|
53
55
|
"virtual:flow/bases": createVirtualBaseTemplatesModule(projectRoot),
|
|
54
56
|
...flowModules.nitro.virtual
|
|
55
57
|
},
|
package/src/public/vite.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
createVirtualClientPageAssetsModule,
|
|
15
15
|
createVirtualClientPagesModule,
|
|
16
16
|
createVirtualIslandsModule,
|
|
17
|
+
createVirtualLayoutContextsModule,
|
|
17
18
|
createVirtualLayoutsModule,
|
|
18
19
|
createVirtualPagesModule,
|
|
19
20
|
createVirtualTemplatesModule
|
|
@@ -32,12 +33,14 @@ const flowRestartPatterns = [
|
|
|
32
33
|
];
|
|
33
34
|
const flowFullReloadPatterns = [
|
|
34
35
|
/^views\/.+\.vue$/,
|
|
36
|
+
/^views\/layouts\/.+\.context\.(ts|js|mjs|mts)$/,
|
|
35
37
|
/^client\/pages\/.+\.ts$/,
|
|
36
38
|
/^client\/islands\/.+\.ts$/
|
|
37
39
|
];
|
|
38
40
|
const flowStructureReloadPatterns = [
|
|
39
41
|
/^pages\/.+\.ts$/,
|
|
40
42
|
/^views\/.+\.vue$/,
|
|
43
|
+
/^views\/layouts\/.+\.context\.(ts|js|mjs|mts)$/,
|
|
41
44
|
/^views\/templates\/.+\.vue$/,
|
|
42
45
|
/^views\/layouts\/.+\.vue$/,
|
|
43
46
|
/^views\/base\/.+\.html$/,
|
|
@@ -57,6 +60,7 @@ function getVirtualModuleIdsForPath(projectPath) {
|
|
|
57
60
|
}
|
|
58
61
|
if (projectPath.startsWith("views/layouts/")) {
|
|
59
62
|
ids.add("virtual:flow/layouts");
|
|
63
|
+
ids.add("virtual:flow/layout-contexts");
|
|
60
64
|
}
|
|
61
65
|
if (projectPath.startsWith("views/base/")) {
|
|
62
66
|
ids.add("virtual:flow/bases");
|
|
@@ -179,6 +183,7 @@ function createFlowVirtualServerModules(projectRoot, flowConfig) {
|
|
|
179
183
|
["virtual:flow/islands", () => createVirtualIslandsModule(projectRoot)],
|
|
180
184
|
["virtual:flow/templates", () => createVirtualTemplatesModule(projectRoot)],
|
|
181
185
|
["virtual:flow/layouts", () => createVirtualLayoutsModule(projectRoot)],
|
|
186
|
+
["virtual:flow/layout-contexts", () => createVirtualLayoutContextsModule(projectRoot)],
|
|
182
187
|
["virtual:flow/bases", () => createVirtualBaseTemplatesModule(projectRoot)]
|
|
183
188
|
]);
|
|
184
189
|
return {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MaybePromise, PageContextInput } from './pages.ts';
|
|
2
|
+
export interface LayoutContextDefinition {
|
|
3
|
+
setup: (ctx: PageContextInput) => MaybePromise<Record<string, unknown>>;
|
|
4
|
+
}
|
|
5
|
+
export type LayoutContextValue<T extends LayoutContextDefinition> = Awaited<ReturnType<T['setup']>>;
|
|
6
|
+
export declare function defineLayoutContext(context: LayoutContextDefinition): LayoutContextDefinition;
|
|
7
|
+
export declare function mergeLayoutContextValues(...contexts: Array<Record<string, unknown> | undefined>): Record<string, unknown>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function defineLayoutContext(context) {
|
|
2
|
+
return context;
|
|
3
|
+
}
|
|
4
|
+
export function mergeLayoutContextValues(...contexts) {
|
|
5
|
+
return contexts.reduce((result, context) => {
|
|
6
|
+
if (!context) {
|
|
7
|
+
return result;
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
...result,
|
|
11
|
+
...context
|
|
12
|
+
};
|
|
13
|
+
}, {});
|
|
14
|
+
}
|
|
@@ -53,6 +53,26 @@ function replacePath(pattern, url) {
|
|
|
53
53
|
function combineName(name, dynamicName) {
|
|
54
54
|
return `${name.replace(/\/*$/, "")}/${dynamicName.replace(/^\/*/, "")}`;
|
|
55
55
|
}
|
|
56
|
+
function resolveUrlTarget(definitions, namePage, explicitDynamicName) {
|
|
57
|
+
if (explicitDynamicName || !namePage.includes("/")) {
|
|
58
|
+
return {
|
|
59
|
+
namePage,
|
|
60
|
+
dynamicName: explicitDynamicName
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const match = definitions.filter((candidate) => candidate.name && namePage.startsWith(`${candidate.name}/`)).sort((left, right) => right.name.length - left.name.length)[0];
|
|
64
|
+
if (!match) {
|
|
65
|
+
return {
|
|
66
|
+
namePage,
|
|
67
|
+
dynamicName: explicitDynamicName
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const dynamicName = namePage.slice(match.name.length + 1);
|
|
71
|
+
return {
|
|
72
|
+
namePage: match.name,
|
|
73
|
+
dynamicName: dynamicName || explicitDynamicName
|
|
74
|
+
};
|
|
75
|
+
}
|
|
56
76
|
function createContext(definitions, flowConfig, definition, locale, localePage, pathname, params, dynamic) {
|
|
57
77
|
return {
|
|
58
78
|
dynamic,
|
|
@@ -111,7 +131,8 @@ export async function loadPageDefinitions(projectRoot, flowConfig) {
|
|
|
111
131
|
return pages;
|
|
112
132
|
}
|
|
113
133
|
export async function getUrlFromDefinitions(definitions, flowConfig, namePage, localeCode = flowConfig.locale.locales[0], options = {}) {
|
|
114
|
-
const
|
|
134
|
+
const target = resolveUrlTarget(definitions, namePage, options.dynamicName);
|
|
135
|
+
const definition = definitions.find((candidate) => candidate.name === target.namePage);
|
|
115
136
|
if (!definition) {
|
|
116
137
|
return void 0;
|
|
117
138
|
}
|
|
@@ -126,9 +147,9 @@ export async function getUrlFromDefinitions(definitions, flowConfig, namePage, l
|
|
|
126
147
|
if (options.params) {
|
|
127
148
|
return replacePath(localizedRoute, options.params);
|
|
128
149
|
}
|
|
129
|
-
if (localePage.dynamic &&
|
|
150
|
+
if (localePage.dynamic && target.dynamicName) {
|
|
130
151
|
const entries = await getDynamicEntries(definitions, flowConfig, definition, localeCode, localePage);
|
|
131
|
-
const entry = entries.find((candidate) => candidate.name ===
|
|
152
|
+
const entry = entries.find((candidate) => candidate.name === target.dynamicName);
|
|
132
153
|
if (!entry) {
|
|
133
154
|
return void 0;
|
|
134
155
|
}
|
|
@@ -2,6 +2,7 @@ import type { FlowConfig } from './config';
|
|
|
2
2
|
export declare function createVirtualPagesModule(projectRoot: string, flowConfig: FlowConfig): string;
|
|
3
3
|
export declare function createVirtualTemplatesModule(projectRoot: string): string;
|
|
4
4
|
export declare function createVirtualLayoutsModule(projectRoot: string): string;
|
|
5
|
+
export declare function createVirtualLayoutContextsModule(projectRoot: string): string;
|
|
5
6
|
export declare function createVirtualBaseTemplatesModule(projectRoot: string): string;
|
|
6
7
|
export declare function createVirtualIslandsModule(projectRoot: string): string;
|
|
7
8
|
export declare function createVirtualClientPagesModule(projectRoot: string): string;
|
|
@@ -89,6 +89,27 @@ export function createVirtualLayoutsModule(projectRoot) {
|
|
|
89
89
|
const files = existsSync(layoutsDir) ? collectFiles(layoutsDir, [".vue"]) : [];
|
|
90
90
|
return createVirtualVueModuleSource(files, "layouts");
|
|
91
91
|
}
|
|
92
|
+
export function createVirtualLayoutContextsModule(projectRoot) {
|
|
93
|
+
const layoutsDir = resolve(projectRoot, "views/layouts");
|
|
94
|
+
const files = existsSync(layoutsDir) ? collectFiles(layoutsDir, [".context.ts", ".context.js", ".context.mjs", ".context.mts"]) : [];
|
|
95
|
+
const imports = files.map((filePath, index) => {
|
|
96
|
+
return `import item_${index} from ${JSON.stringify(toAbsoluteImport(filePath))};`;
|
|
97
|
+
});
|
|
98
|
+
const entries = files.map((filePath, index) => {
|
|
99
|
+
const key = basename(filePath, extname(filePath)).replace(/\.context$/i, "").toLowerCase();
|
|
100
|
+
return `${JSON.stringify(key)}: item_${index}`;
|
|
101
|
+
});
|
|
102
|
+
return [
|
|
103
|
+
...imports,
|
|
104
|
+
"",
|
|
105
|
+
"const layoutContexts = {",
|
|
106
|
+
...entries.map((entry) => ` ${entry},`),
|
|
107
|
+
"};",
|
|
108
|
+
"",
|
|
109
|
+
"export default layoutContexts;",
|
|
110
|
+
""
|
|
111
|
+
].join("\n");
|
|
112
|
+
}
|
|
92
113
|
export function createVirtualBaseTemplatesModule(projectRoot) {
|
|
93
114
|
const baseDir = resolve(projectRoot, "views/base");
|
|
94
115
|
const files = existsSync(baseDir) ? collectFiles(baseDir, [".html"]) : [];
|
package/src/runtime/virtual.d.ts
CHANGED
|
@@ -113,6 +113,12 @@ declare module 'virtual:flow/layouts' {
|
|
|
113
113
|
export default layouts;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
declare module 'virtual:flow/layout-contexts' {
|
|
117
|
+
const layoutContexts: Record<string, import('./layout-context').LayoutContextDefinition>;
|
|
118
|
+
|
|
119
|
+
export default layoutContexts;
|
|
120
|
+
}
|
|
121
|
+
|
|
116
122
|
declare module 'virtual:flow/bases' {
|
|
117
123
|
const bases: Record<string, string>;
|
|
118
124
|
|