meno-core 1.0.39 → 1.0.40
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/build-astro.ts +195 -68
- package/dist/bin/cli.js +1 -1
- package/dist/build-static.js +6 -6
- package/dist/chunks/{chunk-WK5XLASY.js → chunk-3NOZVNM4.js} +3 -3
- package/dist/chunks/{chunk-W6HDII4T.js → chunk-GKICS7CF.js} +27 -14
- package/dist/chunks/chunk-GKICS7CF.js.map +7 -0
- package/dist/chunks/{chunk-P3FX5HJM.js → chunk-LOJLO2EY.js} +1 -1
- package/dist/chunks/chunk-LOJLO2EY.js.map +7 -0
- package/dist/chunks/{chunk-HNAS6BSS.js → chunk-MOCRENNU.js} +55 -5
- package/dist/chunks/{chunk-HNAS6BSS.js.map → chunk-MOCRENNU.js.map} +3 -3
- package/dist/chunks/{chunk-NV25WXCA.js → chunk-OJ5SROQN.js} +5 -3
- package/dist/chunks/chunk-OJ5SROQN.js.map +7 -0
- package/dist/chunks/{chunk-AIXKUVNG.js → chunk-V4SVSX3X.js} +3 -3
- package/dist/chunks/{chunk-KULPBDC7.js → chunk-Z7SAOCDG.js} +5 -2
- package/dist/chunks/{chunk-KULPBDC7.js.map → chunk-Z7SAOCDG.js.map} +2 -2
- package/dist/chunks/{constants-5CRJRQNR.js → constants-L75FR445.js} +2 -2
- package/dist/entries/server-router.js +6 -6
- package/dist/lib/client/index.js +5 -5
- package/dist/lib/client/index.js.map +2 -2
- package/dist/lib/server/index.js +2007 -197
- package/dist/lib/server/index.js.map +4 -4
- package/dist/lib/shared/index.js +3 -3
- package/dist/lib/test-utils/index.js +1 -1
- package/lib/client/core/builders/embedBuilder.ts +2 -2
- package/lib/server/astro/cmsPageEmitter.ts +417 -0
- package/lib/server/astro/componentEmitter.ts +90 -5
- package/lib/server/astro/nodeToAstro.ts +830 -37
- package/lib/server/astro/pageEmitter.ts +39 -3
- package/lib/server/astro/tailwindMapper.ts +69 -8
- package/lib/server/astro/templateTransformer.ts +107 -0
- package/lib/server/index.ts +9 -0
- package/lib/server/routes/api/components.ts +62 -0
- package/lib/server/routes/api/core-routes.ts +8 -0
- package/lib/server/ssr/ssrRenderer.ts +30 -10
- package/lib/server/webflow/buildWebflow.ts +415 -0
- package/lib/server/webflow/index.ts +22 -0
- package/lib/server/webflow/nodeToWebflow.ts +423 -0
- package/lib/server/webflow/styleMapper.ts +241 -0
- package/lib/server/webflow/types.ts +196 -0
- package/lib/shared/constants.ts +2 -0
- package/lib/shared/types/components.ts +1 -0
- package/lib/shared/validation/schemas.ts +1 -0
- package/package.json +1 -1
- package/dist/chunks/chunk-NV25WXCA.js.map +0 -7
- package/dist/chunks/chunk-P3FX5HJM.js.map +0 -7
- package/dist/chunks/chunk-W6HDII4T.js.map +0 -7
- /package/dist/chunks/{chunk-WK5XLASY.js.map → chunk-3NOZVNM4.js.map} +0 -0
- /package/dist/chunks/{chunk-AIXKUVNG.js.map → chunk-V4SVSX3X.js.map} +0 -0
- /package/dist/chunks/{constants-5CRJRQNR.js.map → constants-L75FR445.js.map} +0 -0
package/build-astro.ts
CHANGED
|
@@ -39,7 +39,10 @@ import { collectComponentLibraries, filterLibrariesByContext, mergeLibraries, ge
|
|
|
39
39
|
import { migrateTemplatesDirectory } from "./lib/server/migrateTemplates";
|
|
40
40
|
import { emitAstroComponent } from "./lib/server/astro/componentEmitter";
|
|
41
41
|
import { emitAstroPage } from "./lib/server/astro/pageEmitter";
|
|
42
|
+
import { emitCMSPage } from './lib/server/astro/cmsPageEmitter';
|
|
42
43
|
import { collectAllMappingClasses } from "./lib/server/astro/cssCollector";
|
|
44
|
+
import { buildImageMetadataMap } from "./lib/server/ssr/imageMetadata";
|
|
45
|
+
import { extractUtilityClassesFromHTML, generateUtilityCSS } from "./lib/shared/cssGeneration";
|
|
43
46
|
|
|
44
47
|
// ---------------------------------------------------------------------------
|
|
45
48
|
// Helpers
|
|
@@ -118,6 +121,28 @@ function escapeTemplateLiteral(s: string): string {
|
|
|
118
121
|
return s.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
|
|
119
122
|
}
|
|
120
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Compute locale → URL path map for a page's slug translations.
|
|
126
|
+
* Used by locale list rendering to generate correct links.
|
|
127
|
+
*/
|
|
128
|
+
function computePageSlugMap(
|
|
129
|
+
slugs: Record<string, string>,
|
|
130
|
+
i18nConfig: I18nConfig
|
|
131
|
+
): Record<string, string> {
|
|
132
|
+
const map: Record<string, string> = {};
|
|
133
|
+
for (const localeConfig of i18nConfig.locales) {
|
|
134
|
+
const code = localeConfig.code;
|
|
135
|
+
const isDefault = code === i18nConfig.defaultLocale;
|
|
136
|
+
const slug = slugs[code] || '';
|
|
137
|
+
if (isDefault) {
|
|
138
|
+
map[code] = slug === '' ? '/' : `/${slug}`;
|
|
139
|
+
} else {
|
|
140
|
+
map[code] = slug === '' ? `/${code}` : `/${code}/${slug}`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return map;
|
|
144
|
+
}
|
|
145
|
+
|
|
121
146
|
/**
|
|
122
147
|
* Map a CMS field type to a Zod schema string for the Astro content config.
|
|
123
148
|
*/
|
|
@@ -126,7 +151,8 @@ function cmsFieldToZod(field: CMSFieldDefinition): string {
|
|
|
126
151
|
case 'string':
|
|
127
152
|
case 'text':
|
|
128
153
|
case 'rich-text':
|
|
129
|
-
|
|
154
|
+
// Support both plain strings and i18n objects { _i18n: true, en: "...", pl: "..." }
|
|
155
|
+
return 'z.union([z.string(), z.object({ _i18n: z.literal(true) }).passthrough()])';
|
|
130
156
|
case 'number':
|
|
131
157
|
return 'z.number()';
|
|
132
158
|
case 'boolean':
|
|
@@ -180,6 +206,8 @@ interface PageRenderResult {
|
|
|
180
206
|
pageName?: string;
|
|
181
207
|
/** Whether this is a CMS template page */
|
|
182
208
|
isCMSPage?: boolean;
|
|
209
|
+
/** SSR fallback HTML for complex nodes (list, locale-list) keyed by element path */
|
|
210
|
+
ssrFallbackCollector?: Map<string, string>;
|
|
183
211
|
}
|
|
184
212
|
|
|
185
213
|
interface AstroBuildStats {
|
|
@@ -275,6 +303,12 @@ export async function buildAstroProject(
|
|
|
275
303
|
const globalLibraries = configService.getLibraries();
|
|
276
304
|
const componentLibraries = collectComponentLibraries(globalComponents);
|
|
277
305
|
|
|
306
|
+
// Build image metadata map for responsive image generation
|
|
307
|
+
const imageMetadataMap = await buildImageMetadataMap();
|
|
308
|
+
if (imageMetadataMap.size > 0) {
|
|
309
|
+
console.log(`Loaded image metadata for ${imageMetadataMap.size} image(s)\n`);
|
|
310
|
+
}
|
|
311
|
+
|
|
278
312
|
// ----------------------------------------------------------
|
|
279
313
|
// 2. Clean and create output directory
|
|
280
314
|
// ----------------------------------------------------------
|
|
@@ -350,7 +384,7 @@ export async function buildAstroProject(
|
|
|
350
384
|
|
|
351
385
|
// Helper to process a render result
|
|
352
386
|
function processRenderResult(
|
|
353
|
-
result: { html: string; meta: string; title: string; javascript: string; componentCSS?: string; locale: string; interactiveStylesMap: Map<string, InteractiveStyles>; preloadImages: any[]; neededCollections: Set<string> },
|
|
387
|
+
result: { html: string; meta: string; title: string; javascript: string; componentCSS?: string; locale: string; interactiveStylesMap: Map<string, InteractiveStyles>; preloadImages: any[]; neededCollections: Set<string>; ssrFallbackCollector?: Map<string, string> },
|
|
354
388
|
urlPath: string,
|
|
355
389
|
astroFilePath: string,
|
|
356
390
|
fileDepth: number,
|
|
@@ -388,6 +422,7 @@ export async function buildAstroProject(
|
|
|
388
422
|
pageData,
|
|
389
423
|
pageName,
|
|
390
424
|
isCMSPage,
|
|
425
|
+
ssrFallbackCollector: result.ssrFallbackCollector,
|
|
391
426
|
});
|
|
392
427
|
}
|
|
393
428
|
|
|
@@ -460,6 +495,13 @@ export async function buildAstroProject(
|
|
|
460
495
|
}
|
|
461
496
|
}
|
|
462
497
|
|
|
498
|
+
// Pre-compute layout dependencies needed by both CMS and regular page emission
|
|
499
|
+
const fontPreloads = generateFontPreloadTags();
|
|
500
|
+
const mergedLibraries = mergeLibraries(globalLibraries, componentLibraries);
|
|
501
|
+
const buildLibraries = filterLibrariesByContext(mergedLibraries, 'build');
|
|
502
|
+
const libraryTags = generateLibraryTags(buildLibraries);
|
|
503
|
+
const defaultTheme = themeConfig.default || 'light';
|
|
504
|
+
|
|
463
505
|
// ---------- CMS template pages ----------
|
|
464
506
|
const templatesDir = projectPaths.templates();
|
|
465
507
|
const templateSchemas: CMSSchema[] = [];
|
|
@@ -494,54 +536,114 @@ export async function buildAstroProject(
|
|
|
494
536
|
templateSchemas.push(cmsSchema);
|
|
495
537
|
console.log(` CMS Collection: ${cmsSchema.id}`);
|
|
496
538
|
|
|
539
|
+
// Count items for stats
|
|
497
540
|
const items = await cmsService.queryItems({ collection: cmsSchema.id });
|
|
498
|
-
|
|
541
|
+
const itemCount = items.length;
|
|
542
|
+
|
|
543
|
+
if (itemCount === 0) {
|
|
499
544
|
console.log(` No items found in cms/${cmsSchema.id}/`);
|
|
500
|
-
|
|
545
|
+
} else {
|
|
546
|
+
console.log(` Found ${itemCount} item(s)`);
|
|
501
547
|
}
|
|
502
548
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
for (const localeConfig of i18nConfig.locales) {
|
|
507
|
-
const locale = localeConfig.code;
|
|
508
|
-
const isDefault = locale === i18nConfig.defaultLocale;
|
|
509
|
-
|
|
510
|
-
const isDevBuild = process.env.MENO_DEV_BUILD === 'true';
|
|
511
|
-
if (!isDevBuild && isItemDraftForLocale(item, locale)) {
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);
|
|
516
|
-
const itemWithUrl: CMSItem = { ...item, _url: itemPath };
|
|
517
|
-
|
|
518
|
-
const result = await renderPageSSR(
|
|
519
|
-
pageData,
|
|
520
|
-
globalComponents,
|
|
521
|
-
itemPath,
|
|
522
|
-
siteUrl,
|
|
523
|
-
locale,
|
|
524
|
-
i18nConfig,
|
|
525
|
-
slugMappings,
|
|
526
|
-
{ cms: itemWithUrl },
|
|
527
|
-
cmsService,
|
|
528
|
-
true
|
|
529
|
-
);
|
|
549
|
+
// Render SSR once for metadata collection (interactive styles, component CSS, JS)
|
|
550
|
+
const defaultLocale = i18nConfig.defaultLocale;
|
|
551
|
+
const dummyPath = cmsSchema.urlPattern.replace('{{slug}}', '__placeholder__');
|
|
530
552
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
553
|
+
const metaResult = await renderPageSSR(
|
|
554
|
+
pageData,
|
|
555
|
+
globalComponents,
|
|
556
|
+
dummyPath,
|
|
557
|
+
siteUrl,
|
|
558
|
+
defaultLocale,
|
|
559
|
+
i18nConfig,
|
|
560
|
+
slugMappings,
|
|
561
|
+
undefined, // no CMS context - just collecting metadata
|
|
562
|
+
cmsService,
|
|
563
|
+
true
|
|
564
|
+
);
|
|
537
565
|
|
|
538
|
-
|
|
566
|
+
// Collect interactive styles and component CSS
|
|
567
|
+
mergeInteractiveStyles(metaResult.interactiveStylesMap);
|
|
568
|
+
if (metaResult.componentCSS) {
|
|
569
|
+
allComponentCSS.add(metaResult.componentCSS);
|
|
570
|
+
}
|
|
539
571
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
572
|
+
// Deduplicate JavaScript by content hash
|
|
573
|
+
const scriptPaths: string[] = [];
|
|
574
|
+
if (metaResult.javascript) {
|
|
575
|
+
const hash = hashContent(metaResult.javascript);
|
|
576
|
+
if (!jsContents.has(hash)) {
|
|
577
|
+
jsContents.set(hash, metaResult.javascript);
|
|
543
578
|
}
|
|
579
|
+
scriptPaths.push(`/_scripts/${hash}.js`);
|
|
544
580
|
}
|
|
581
|
+
|
|
582
|
+
// Determine route file path from urlPattern
|
|
583
|
+
const isMultiLocale = i18nConfig.locales.length > 1;
|
|
584
|
+
const urlPatternWithoutSlash = cmsSchema.urlPattern.replace(/^\//, '');
|
|
585
|
+
const slugPlaceholderIdx = urlPatternWithoutSlash.indexOf('{{');
|
|
586
|
+
const pathPrefix = slugPlaceholderIdx > 0 ? urlPatternWithoutSlash.substring(0, slugPlaceholderIdx) : '';
|
|
587
|
+
|
|
588
|
+
// Generate CMS page with getStaticPaths()
|
|
589
|
+
const ssrFallbacks = metaResult.ssrFallbackCollector ?? new Map<string, string>();
|
|
590
|
+
|
|
591
|
+
// For each locale (or just default), generate a route file
|
|
592
|
+
const localesToEmit = isMultiLocale ? i18nConfig.locales : [{ code: i18nConfig.defaultLocale }];
|
|
593
|
+
|
|
594
|
+
for (const localeEntry of localesToEmit) {
|
|
595
|
+
const localeCode = localeEntry.code;
|
|
596
|
+
const isDefault = localeCode === i18nConfig.defaultLocale;
|
|
597
|
+
|
|
598
|
+
// Route file path: blog/[slug].astro for default, pl/blog/[slug].astro for non-default
|
|
599
|
+
let astroFilePath: string;
|
|
600
|
+
if (pathPrefix) {
|
|
601
|
+
astroFilePath = isDefault
|
|
602
|
+
? `${pathPrefix}[slug].astro`
|
|
603
|
+
: `${localeCode}/${pathPrefix}[slug].astro`;
|
|
604
|
+
} else {
|
|
605
|
+
astroFilePath = isDefault
|
|
606
|
+
? '[slug].astro'
|
|
607
|
+
: `${localeCode}/[slug].astro`;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
const fileDepth = astroFilePath.split('/').length - 1;
|
|
611
|
+
const importPath = layoutImportPath(fileDepth);
|
|
612
|
+
|
|
613
|
+
const astroContent = emitCMSPage({
|
|
614
|
+
pageData,
|
|
615
|
+
globalComponents,
|
|
616
|
+
cmsSchema,
|
|
617
|
+
title: String(pageData.meta?.title || cmsSchema.name),
|
|
618
|
+
meta: metaResult.meta,
|
|
619
|
+
locale: localeCode,
|
|
620
|
+
theme: defaultTheme,
|
|
621
|
+
fontPreloads,
|
|
622
|
+
libraryTags,
|
|
623
|
+
scriptPaths,
|
|
624
|
+
layoutImportPath: importPath,
|
|
625
|
+
fileDepth,
|
|
626
|
+
ssrFallbacks,
|
|
627
|
+
pageName: file.replace('.json', ''),
|
|
628
|
+
breakpoints,
|
|
629
|
+
imageMetadataMap,
|
|
630
|
+
i18nConfig,
|
|
631
|
+
isMultiLocale: false, // Each file handles one locale
|
|
632
|
+
slugMappings,
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
const astroFileFull = join(pagesOutDir, astroFilePath);
|
|
636
|
+
const astroFileDir = astroFileFull.substring(0, astroFileFull.lastIndexOf('/'));
|
|
637
|
+
if (!existsSync(astroFileDir)) {
|
|
638
|
+
mkdirSync(astroFileDir, { recursive: true });
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
await writeFile(astroFileFull, astroContent, 'utf-8');
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
console.log(` Generated: ${pathPrefix}[slug].astro (${itemCount} items × ${localesToEmit.length} locale(s))`);
|
|
645
|
+
|
|
646
|
+
cmsPageCount += itemCount * i18nConfig.locales.length;
|
|
545
647
|
} catch (error: any) {
|
|
546
648
|
console.error(` Error processing template ${file}:`, error?.message || error);
|
|
547
649
|
errorCount++;
|
|
@@ -585,13 +687,6 @@ export async function buildAstroProject(
|
|
|
585
687
|
// ----------------------------------------------------------
|
|
586
688
|
// 7. Generate BaseLayout.astro
|
|
587
689
|
// ----------------------------------------------------------
|
|
588
|
-
const fontPreloads = generateFontPreloadTags();
|
|
589
|
-
|
|
590
|
-
// Merge global + component libraries for the layout
|
|
591
|
-
const mergedLibraries = mergeLibraries(globalLibraries, componentLibraries);
|
|
592
|
-
const buildLibraries = filterLibrariesByContext(mergedLibraries, 'build');
|
|
593
|
-
const libraryTags = generateLibraryTags(buildLibraries);
|
|
594
|
-
|
|
595
690
|
const baseLayoutContent = `---
|
|
596
691
|
import '../styles/global.css';
|
|
597
692
|
|
|
@@ -635,7 +730,7 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
635
730
|
let componentFileCount = 0;
|
|
636
731
|
for (const [compName, compDef] of Object.entries(globalComponents)) {
|
|
637
732
|
try {
|
|
638
|
-
const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints);
|
|
733
|
+
const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints, i18nConfig.defaultLocale);
|
|
639
734
|
await writeFile(join(componentsOutDir, `${compName}.astro`), astroContent, 'utf-8');
|
|
640
735
|
componentFileCount++;
|
|
641
736
|
} catch (error: any) {
|
|
@@ -647,7 +742,7 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
647
742
|
// ----------------------------------------------------------
|
|
648
743
|
// 8. Generate .astro page files (component-structured)
|
|
649
744
|
// ----------------------------------------------------------
|
|
650
|
-
const
|
|
745
|
+
const allFallbackHtml: string[] = []; // Collect SSR fallback HTML for utility CSS generation
|
|
651
746
|
|
|
652
747
|
for (const result of allResults) {
|
|
653
748
|
const importPath = layoutImportPath(result.fileDepth);
|
|
@@ -672,10 +767,21 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
672
767
|
|
|
673
768
|
let astroContent: string;
|
|
674
769
|
|
|
675
|
-
// Use component-structured emission for
|
|
676
|
-
|
|
677
|
-
if (result.pageData && !result.isCMSPage) {
|
|
770
|
+
// Use component-structured emission for pages with page data
|
|
771
|
+
if (result.pageData) {
|
|
678
772
|
try {
|
|
773
|
+
// Use SSR fallback collector from the initial render (paths already match nodeToAstro convention)
|
|
774
|
+
const ssrFallbacks = result.ssrFallbackCollector ?? new Map<string, string>();
|
|
775
|
+
ssrFallbacks.forEach((html) => {
|
|
776
|
+
allFallbackHtml.push(html);
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
// Compute slug map for locale list rendering
|
|
780
|
+
const pageSlugMap: Record<string, string> | undefined =
|
|
781
|
+
result.pageData.meta?.slugs
|
|
782
|
+
? computePageSlugMap(result.pageData.meta.slugs, i18nConfig)
|
|
783
|
+
: undefined;
|
|
784
|
+
|
|
679
785
|
astroContent = emitAstroPage({
|
|
680
786
|
pageData: result.pageData,
|
|
681
787
|
globalComponents,
|
|
@@ -688,9 +794,13 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
688
794
|
scriptPaths,
|
|
689
795
|
layoutImportPath: importPath,
|
|
690
796
|
fileDepth: result.fileDepth,
|
|
691
|
-
ssrFallbacks
|
|
797
|
+
ssrFallbacks,
|
|
692
798
|
pageName: result.pageName || 'index',
|
|
693
799
|
breakpoints,
|
|
800
|
+
imageMetadataMap,
|
|
801
|
+
i18nConfig: i18nConfig.locales.length > 1 ? i18nConfig : undefined,
|
|
802
|
+
currentPageSlugMap: pageSlugMap,
|
|
803
|
+
slugMappings: i18nConfig.locales.length > 1 ? slugMappings : undefined,
|
|
694
804
|
});
|
|
695
805
|
} catch (error: any) {
|
|
696
806
|
// Fallback to SSR HTML if component emission fails
|
|
@@ -698,8 +808,9 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
698
808
|
astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
|
|
699
809
|
}
|
|
700
810
|
} else {
|
|
701
|
-
//
|
|
811
|
+
// Pages without pageData: use SSR fallback
|
|
702
812
|
astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
|
|
813
|
+
allFallbackHtml.push(result.html);
|
|
703
814
|
}
|
|
704
815
|
|
|
705
816
|
const astroFileFull = join(pagesOutDir, result.astroFilePath);
|
|
@@ -713,6 +824,26 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
713
824
|
|
|
714
825
|
console.log(`Generated ${allResults.length} .astro page file(s)`);
|
|
715
826
|
|
|
827
|
+
// ----------------------------------------------------------
|
|
828
|
+
// 8.5. Generate utility CSS for SSR fallback HTML
|
|
829
|
+
// ----------------------------------------------------------
|
|
830
|
+
if (allFallbackHtml.length > 0) {
|
|
831
|
+
const allClasses = new Set<string>();
|
|
832
|
+
for (const html of allFallbackHtml) {
|
|
833
|
+
for (const cls of extractUtilityClassesFromHTML(html)) {
|
|
834
|
+
allClasses.add(cls);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
if (allClasses.size > 0) {
|
|
838
|
+
const utilityCSS = generateUtilityCSS(allClasses, breakpoints, responsiveScales);
|
|
839
|
+
if (utilityCSS) {
|
|
840
|
+
const existingCSS = await readFile(join(stylesDir, 'global.css'), 'utf-8');
|
|
841
|
+
await writeFile(join(stylesDir, 'global.css'), existingCSS + '\n\n/* SSR fallback utility classes */\n' + utilityCSS, 'utf-8');
|
|
842
|
+
console.log(`Added ${allClasses.size} utility classes for SSR fallback content`);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
716
847
|
// ----------------------------------------------------------
|
|
717
848
|
// 9. Generate CMS content collections (if templates exist)
|
|
718
849
|
// ----------------------------------------------------------
|
|
@@ -738,15 +869,8 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
738
869
|
const rawContent = await readFile(join(cmsItemsDir, itemFile), 'utf-8');
|
|
739
870
|
const item = JSON.parse(rawContent) as CMSItem;
|
|
740
871
|
|
|
741
|
-
//
|
|
742
|
-
const resolved: Record<string, unknown> = {};
|
|
743
|
-
for (const [key, value] of Object.entries(item)) {
|
|
744
|
-
if (isI18nValue(value)) {
|
|
745
|
-
resolved[key] = resolveI18nValue(value, i18nConfig.defaultLocale, i18nConfig);
|
|
746
|
-
} else {
|
|
747
|
-
resolved[key] = value;
|
|
748
|
-
}
|
|
749
|
-
}
|
|
872
|
+
// Keep i18n values as-is so getStaticPaths() can resolve per-locale
|
|
873
|
+
const resolved: Record<string, unknown> = { ...item };
|
|
750
874
|
|
|
751
875
|
await writeFile(
|
|
752
876
|
join(collectionDir, itemFile),
|
|
@@ -836,7 +960,6 @@ export { collections };
|
|
|
836
960
|
},
|
|
837
961
|
dependencies: {
|
|
838
962
|
'astro': '^4.0.0',
|
|
839
|
-
'@astrojs/sitemap': '^3.0.0',
|
|
840
963
|
'@astrojs/tailwind': '^5.0.0',
|
|
841
964
|
'tailwindcss': '^3.4.0',
|
|
842
965
|
},
|
|
@@ -845,12 +968,16 @@ export { collections };
|
|
|
845
968
|
await writeFile(join(outDir, 'package.json'), JSON.stringify(packageJson, null, 2), 'utf-8');
|
|
846
969
|
|
|
847
970
|
// astro.config.mjs
|
|
971
|
+
const localeCodes = i18nConfig.locales.map(l => l.code);
|
|
972
|
+
const i18nBlock = i18nConfig.locales.length > 1
|
|
973
|
+
? `\n i18n: {\n defaultLocale: '${i18nConfig.defaultLocale}',\n locales: [${localeCodes.map(c => `'${c}'`).join(', ')}],\n routing: { prefixDefaultLocale: false },\n },`
|
|
974
|
+
: '';
|
|
975
|
+
|
|
848
976
|
const astroConfig = `import { defineConfig } from 'astro/config';
|
|
849
|
-
import sitemap from '@astrojs/sitemap';
|
|
850
977
|
import tailwind from '@astrojs/tailwind';
|
|
851
978
|
|
|
852
|
-
export default defineConfig({${siteUrl ? `\n site: '${siteUrl}',` : ''}
|
|
853
|
-
integrations: [
|
|
979
|
+
export default defineConfig({${siteUrl ? `\n site: '${siteUrl}',` : ''}${i18nBlock}
|
|
980
|
+
integrations: [tailwind({ applyBaseStyles: false })],
|
|
854
981
|
});
|
|
855
982
|
`;
|
|
856
983
|
|
package/dist/bin/cli.js
CHANGED
|
@@ -82,7 +82,7 @@ function getMatchingHeaders(pathname, headersMap) {
|
|
|
82
82
|
return result;
|
|
83
83
|
}
|
|
84
84
|
async function startStaticServer(distPath) {
|
|
85
|
-
const { SERVE_PORT } = await import("../chunks/constants-
|
|
85
|
+
const { SERVE_PORT } = await import("../chunks/constants-L75FR445.js");
|
|
86
86
|
const headersMap = parseHeadersFile(distPath);
|
|
87
87
|
const server = await createRuntimeServer({
|
|
88
88
|
port: SERVE_PORT,
|
package/dist/build-static.js
CHANGED
|
@@ -9,17 +9,17 @@ import {
|
|
|
9
9
|
hashContent,
|
|
10
10
|
injectTrackingScript,
|
|
11
11
|
isCMSPage
|
|
12
|
-
} from "./chunks/chunk-
|
|
13
|
-
import "./chunks/chunk-
|
|
12
|
+
} from "./chunks/chunk-3NOZVNM4.js";
|
|
13
|
+
import "./chunks/chunk-GKICS7CF.js";
|
|
14
14
|
import "./chunks/chunk-A6KWUEA6.js";
|
|
15
15
|
import "./chunks/chunk-YSZ5IUFM.js";
|
|
16
16
|
import "./chunks/chunk-WQFG7PAH.js";
|
|
17
|
-
import "./chunks/chunk-
|
|
18
|
-
import "./chunks/chunk-
|
|
19
|
-
import "./chunks/chunk-
|
|
17
|
+
import "./chunks/chunk-LOJLO2EY.js";
|
|
18
|
+
import "./chunks/chunk-V4SVSX3X.js";
|
|
19
|
+
import "./chunks/chunk-OJ5SROQN.js";
|
|
20
20
|
import "./chunks/chunk-PGH3ATYI.js";
|
|
21
21
|
import "./chunks/chunk-UB44F4Z2.js";
|
|
22
|
-
import "./chunks/chunk-
|
|
22
|
+
import "./chunks/chunk-Z7SAOCDG.js";
|
|
23
23
|
import "./chunks/chunk-KSBZ2L7C.js";
|
|
24
24
|
export {
|
|
25
25
|
buildCMSItemPath,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
migrateTemplatesDirectory,
|
|
16
16
|
parseJSON,
|
|
17
17
|
prepareClientData
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-GKICS7CF.js";
|
|
19
19
|
import {
|
|
20
20
|
minifyJS,
|
|
21
21
|
projectPaths
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
import {
|
|
27
27
|
isItemDraftForLocale,
|
|
28
28
|
isItemFullyPublished
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-OJ5SROQN.js";
|
|
30
30
|
import {
|
|
31
31
|
isI18nValue,
|
|
32
32
|
resolveI18nValue
|
|
@@ -1130,4 +1130,4 @@ export {
|
|
|
1130
1130
|
injectTrackingScript,
|
|
1131
1131
|
buildStaticPages
|
|
1132
1132
|
};
|
|
1133
|
-
//# sourceMappingURL=chunk-
|
|
1133
|
+
//# sourceMappingURL=chunk-3NOZVNM4.js.map
|
|
@@ -16,14 +16,14 @@ import {
|
|
|
16
16
|
isSafePathSegment,
|
|
17
17
|
isValidIdentifier,
|
|
18
18
|
resolvePaletteColor
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-LOJLO2EY.js";
|
|
20
20
|
import {
|
|
21
21
|
extractAttributesFromNode,
|
|
22
22
|
isHtmlMapping,
|
|
23
23
|
processStructure,
|
|
24
24
|
resolveHtmlMapping,
|
|
25
25
|
skipEmptyTemplateAttributes
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-V4SVSX3X.js";
|
|
27
27
|
import {
|
|
28
28
|
DEFAULT_PREFETCH_CONFIG,
|
|
29
29
|
SSRRegistry,
|
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
singularize,
|
|
61
61
|
validateCMSItem,
|
|
62
62
|
validateComponentDefinition
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-OJ5SROQN.js";
|
|
64
64
|
import {
|
|
65
65
|
DEFAULT_BREAKPOINTS,
|
|
66
66
|
DEFAULT_I18N_CONFIG,
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
NODE_TYPE,
|
|
82
82
|
RAW_HTML_PREFIX,
|
|
83
83
|
init_constants
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-Z7SAOCDG.js";
|
|
85
85
|
import {
|
|
86
86
|
__require
|
|
87
87
|
} from "./chunk-KSBZ2L7C.js";
|
|
@@ -1992,7 +1992,8 @@ async function buildComponentHTML(node, globalComponents = {}, pageComponents =
|
|
|
1992
1992
|
const interactiveStylesMap = /* @__PURE__ */ new Map();
|
|
1993
1993
|
const preloadImages = [];
|
|
1994
1994
|
const neededCollections = /* @__PURE__ */ new Set();
|
|
1995
|
-
|
|
1995
|
+
const ssrFallbackCollector = /* @__PURE__ */ new Map();
|
|
1996
|
+
if (!node) return { html: "", interactiveStylesMap, preloadImages, neededCollections, ssrFallbackCollector };
|
|
1996
1997
|
ssrComponentRegistry.merge(globalComponents);
|
|
1997
1998
|
ssrComponentRegistry.merge(pageComponents);
|
|
1998
1999
|
const breakpoints = await loadBreakpointConfig();
|
|
@@ -2016,10 +2017,12 @@ async function buildComponentHTML(node, globalComponents = {}, pageComponents =
|
|
|
2016
2017
|
// Collect high-priority images for preloading
|
|
2017
2018
|
neededCollections,
|
|
2018
2019
|
// Track collections that need client-side data
|
|
2019
|
-
isProductionBuild
|
|
2020
|
+
isProductionBuild,
|
|
2021
|
+
ssrFallbackCollector
|
|
2022
|
+
// Collect SSR fallback HTML for complex nodes
|
|
2020
2023
|
};
|
|
2021
2024
|
const html = await renderNode(node, ctx);
|
|
2022
|
-
return { html, interactiveStylesMap, preloadImages, neededCollections };
|
|
2025
|
+
return { html, interactiveStylesMap, preloadImages, neededCollections, ssrFallbackCollector };
|
|
2023
2026
|
}
|
|
2024
2027
|
async function renderNestedListPlaceholder(node, ctx) {
|
|
2025
2028
|
const sourceValue = node.source || node.collection;
|
|
@@ -2123,7 +2126,11 @@ async function processList(node, ctx) {
|
|
|
2123
2126
|
const templateContent = await renderChildrenAsync(node.children, templateCtx);
|
|
2124
2127
|
templateHtml = `<template data-meno-item>${templateContent}</template>`;
|
|
2125
2128
|
}
|
|
2126
|
-
|
|
2129
|
+
const listResult = childrenHTML + templateHtml;
|
|
2130
|
+
if (ctx.ssrFallbackCollector && ctx.elementPath) {
|
|
2131
|
+
ctx.ssrFallbackCollector.set(ctx.elementPath.join("."), listResult);
|
|
2132
|
+
}
|
|
2133
|
+
return listResult;
|
|
2127
2134
|
}
|
|
2128
2135
|
async function getCollectionItems(node, source, ctx) {
|
|
2129
2136
|
if (!ctx.cmsService) return [];
|
|
@@ -2318,8 +2325,8 @@ async function renderNode(node, ctx) {
|
|
|
2318
2325
|
}
|
|
2319
2326
|
const purify = getDOMPurify();
|
|
2320
2327
|
const sanitizedHtml = purify ? purify.sanitize(htmlContent, {
|
|
2321
|
-
ALLOWED_TAGS: ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "tspan", "image", "defs", "use", "linearGradient", "radialGradient", "stop", "clipPath", "mask", "pattern", "marker", "symbol", "a", "div", "span", "p", "br", "button", "img", "iframe", "video", "audio", "source", "canvas", "b", "i", "u", "strong", "em", "sub", "sup", "mark", "s", "small", "del", "ins", "q", "abbr", "code", "pre", "blockquote", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6"],
|
|
2322
|
-
ALLOWED_ATTR: ["class", "id", "style", "width", "height", "viewBox", "xmlns", "fill", "stroke", "stroke-width", "stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "d", "cx", "cy", "r", "x", "y", "x1", "y1", "x2", "y2", "points", "href", "src", "alt", "target", "rel", "data-*", "aria-*", "transform", "opacity", "fill-opacity", "stroke-opacity", "font-size", "font-family", "text-anchor", "dominant-baseline", "offset", "stop-color", "stop-opacity", "frameborder", "allowfullscreen", "allow", "title"],
|
|
2328
|
+
ALLOWED_TAGS: ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "tspan", "image", "defs", "use", "linearGradient", "radialGradient", "stop", "clipPath", "mask", "pattern", "marker", "symbol", "a", "div", "span", "p", "br", "button", "img", "iframe", "video", "audio", "source", "canvas", "b", "i", "u", "strong", "em", "sub", "sup", "mark", "s", "small", "del", "ins", "q", "abbr", "code", "pre", "blockquote", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6", "style", "animate", "animateTransform", "animateMotion", "set"],
|
|
2329
|
+
ALLOWED_ATTR: ["class", "id", "style", "width", "height", "viewBox", "xmlns", "fill", "stroke", "stroke-width", "stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "d", "cx", "cy", "r", "x", "y", "x1", "y1", "x2", "y2", "points", "href", "src", "alt", "target", "rel", "data-*", "aria-*", "transform", "opacity", "fill-opacity", "stroke-opacity", "font-size", "font-family", "text-anchor", "dominant-baseline", "offset", "stop-color", "stop-opacity", "frameborder", "allowfullscreen", "allow", "title", "attributeName", "values", "dur", "begin", "end", "repeatCount", "repeatDur", "keyTimes", "keySplines", "calcMode", "from", "to", "by", "additive", "accumulate", "type", "rotate", "keyPoints", "path"],
|
|
2323
2330
|
KEEP_CONTENT: true
|
|
2324
2331
|
}) : htmlContent;
|
|
2325
2332
|
const optimizedHtml = ctx.imageMetadataMap ? rewriteRichTextImages(sanitizedHtml, ctx.imageMetadataMap) : sanitizedHtml;
|
|
@@ -2803,7 +2810,11 @@ function renderLocaleList(node, ctx) {
|
|
|
2803
2810
|
const linksHTML = showSeparator ? links.join(`<span${separatorClassAttr}></span>`) : links.join("");
|
|
2804
2811
|
const nodeAttributes = extractAttributesFromNode(node);
|
|
2805
2812
|
const attrsStr = buildAttributes(nodeAttributes);
|
|
2806
|
-
|
|
2813
|
+
const localeListResult = `<div data-locale-list="true"${containerClassAttr}${localeListStyleAttr}${attrsStr}>${linksHTML}</div>`;
|
|
2814
|
+
if (ctx.ssrFallbackCollector && ctx.elementPath) {
|
|
2815
|
+
ctx.ssrFallbackCollector.set(ctx.elementPath.join("."), localeListResult);
|
|
2816
|
+
}
|
|
2817
|
+
return localeListResult;
|
|
2807
2818
|
}
|
|
2808
2819
|
return '<div data-locale-list="true"></div>';
|
|
2809
2820
|
}
|
|
@@ -2831,7 +2842,7 @@ async function renderPageSSR(pageData, globalComponents = {}, pagePath = "/", ba
|
|
|
2831
2842
|
}
|
|
2832
2843
|
}
|
|
2833
2844
|
const pageComponents = pageData?.components || {};
|
|
2834
|
-
const { html: contentHTML, interactiveStylesMap, preloadImages, neededCollections } = rootNode ? await buildComponentHTML(rootNode, globalComponents, pageComponents, effectiveLocale, config, slugMappings, pagePath, cmsContext, cmsService, isProductionBuild) : { html: "", interactiveStylesMap: /* @__PURE__ */ new Map(), preloadImages: [], neededCollections: /* @__PURE__ */ new Set() };
|
|
2845
|
+
const { html: contentHTML, interactiveStylesMap, preloadImages, neededCollections, ssrFallbackCollector } = rootNode ? await buildComponentHTML(rootNode, globalComponents, pageComponents, effectiveLocale, config, slugMappings, pagePath, cmsContext, cmsService, isProductionBuild) : { html: "", interactiveStylesMap: /* @__PURE__ */ new Map(), preloadImages: [], neededCollections: /* @__PURE__ */ new Set(), ssrFallbackCollector: /* @__PURE__ */ new Map() };
|
|
2835
2846
|
const javascript = await collectComponentJavaScript(globalComponents, pageComponents);
|
|
2836
2847
|
const componentCSS = collectComponentCSS(globalComponents, pageComponents);
|
|
2837
2848
|
const fullUrl = baseUrl ? `${baseUrl}${pagePath}` : pagePath;
|
|
@@ -2851,7 +2862,8 @@ async function renderPageSSR(pageData, globalComponents = {}, pagePath = "/", ba
|
|
|
2851
2862
|
locale: effectiveLocale,
|
|
2852
2863
|
interactiveStylesMap,
|
|
2853
2864
|
preloadImages,
|
|
2854
|
-
neededCollections
|
|
2865
|
+
neededCollections,
|
|
2866
|
+
ssrFallbackCollector
|
|
2855
2867
|
};
|
|
2856
2868
|
}
|
|
2857
2869
|
|
|
@@ -3749,6 +3761,7 @@ export {
|
|
|
3749
3761
|
generateThemeColorVariablesCSS,
|
|
3750
3762
|
generateVariablesCSS,
|
|
3751
3763
|
buildSlugIndex,
|
|
3764
|
+
translatePath,
|
|
3752
3765
|
resolveSlugToPageId,
|
|
3753
3766
|
escapeHtml,
|
|
3754
3767
|
buildAttributes,
|
|
@@ -3777,4 +3790,4 @@ export {
|
|
|
3777
3790
|
FileSystemCMSProvider,
|
|
3778
3791
|
migrateTemplatesDirectory
|
|
3779
3792
|
};
|
|
3780
|
-
//# sourceMappingURL=chunk-
|
|
3793
|
+
//# sourceMappingURL=chunk-GKICS7CF.js.map
|