meno-core 1.0.39 → 1.0.41
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/bin/cli.ts +33 -0
- package/build-astro.ts +172 -69
- package/dist/bin/cli.js +30 -2
- package/dist/bin/cli.js.map +2 -2
- package/dist/build-static.js +7 -7
- package/dist/chunks/{chunk-WK5XLASY.js → chunk-EQOSDQS2.js} +4 -4
- package/dist/chunks/{chunk-AIXKUVNG.js → chunk-IBR2F4IL.js} +4 -5
- package/dist/chunks/{chunk-AIXKUVNG.js.map → chunk-IBR2F4IL.js.map} +2 -2
- package/dist/chunks/{chunk-NV25WXCA.js → chunk-IGVQF5GY.js} +11 -7
- package/dist/chunks/chunk-IGVQF5GY.js.map +7 -0
- package/dist/chunks/{chunk-KULPBDC7.js → chunk-LBWIHPN7.js} +9 -3
- package/dist/chunks/chunk-LBWIHPN7.js.map +7 -0
- package/dist/chunks/{chunk-A6KWUEA6.js → chunk-MKB2J6AD.js} +9 -1
- package/dist/chunks/chunk-MKB2J6AD.js.map +7 -0
- package/dist/chunks/{chunk-P3FX5HJM.js → chunk-S2HXJTAF.js} +1 -1
- package/dist/chunks/chunk-S2HXJTAF.js.map +7 -0
- package/dist/chunks/{chunk-W6HDII4T.js → chunk-SK3TLNUP.js} +140 -114
- package/dist/chunks/chunk-SK3TLNUP.js.map +7 -0
- package/dist/chunks/{chunk-HNAS6BSS.js → chunk-SNUROC7E.js} +56 -6
- package/dist/chunks/{chunk-HNAS6BSS.js.map → chunk-SNUROC7E.js.map} +3 -3
- package/dist/chunks/{configService-TXBNUBBL.js → configService-MICL4S2L.js} +2 -2
- package/dist/chunks/{constants-5CRJRQNR.js → constants-ZEU4TZCA.js} +2 -2
- package/dist/entries/server-router.js +7 -7
- package/dist/lib/client/index.js +11 -6
- package/dist/lib/client/index.js.map +2 -2
- package/dist/lib/server/index.js +507 -1587
- 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/ComponentBuilder.ts +1 -1
- package/lib/client/core/builders/embedBuilder.ts +2 -2
- package/lib/client/routing/Router.tsx +6 -0
- package/lib/client/templateEngine.test.ts +178 -0
- package/lib/client/templateEngine.ts +1 -2
- package/lib/server/astro/cmsPageEmitter.ts +420 -0
- package/lib/server/astro/componentEmitter.ts +150 -17
- package/lib/server/astro/nodeToAstro.test.ts +1101 -0
- package/lib/server/astro/nodeToAstro.ts +869 -37
- package/lib/server/astro/pageEmitter.ts +43 -3
- package/lib/server/astro/tailwindMapper.ts +69 -8
- package/lib/server/astro/templateTransformer.ts +107 -0
- package/lib/server/index.ts +26 -3
- package/lib/server/routes/api/components.ts +62 -0
- package/lib/server/routes/api/core-routes.ts +8 -0
- package/lib/server/services/configService.ts +12 -0
- package/lib/server/ssr/htmlGenerator.ts +0 -5
- package/lib/server/ssr/imageMetadata.ts +3 -3
- package/lib/server/ssr/ssrRenderer.ts +78 -29
- 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 +4 -0
- package/lib/shared/types/components.ts +9 -4
- package/lib/shared/validation/propValidator.ts +2 -1
- package/lib/shared/validation/schemas.ts +4 -1
- package/package.json +1 -1
- package/templates/index-router.html +0 -5
- package/dist/chunks/chunk-A6KWUEA6.js.map +0 -7
- package/dist/chunks/chunk-KULPBDC7.js.map +0 -7
- 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-EQOSDQS2.js.map} +0 -0
- /package/dist/chunks/{configService-TXBNUBBL.js.map → configService-MICL4S2L.js.map} +0 -0
- /package/dist/chunks/{constants-5CRJRQNR.js.map → constants-ZEU4TZCA.js.map} +0 -0
|
@@ -76,6 +76,47 @@ function formatDefault(def: PropDefinition): string | null {
|
|
|
76
76
|
return JSON.stringify(val);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Merge the `className` variable onto the root element's class attribute.
|
|
81
|
+
* Handles: class="existing", class:list={[...]}, class={expr}, or no class at all.
|
|
82
|
+
*/
|
|
83
|
+
function mergeClassNameOntoRoot(template: string): string {
|
|
84
|
+
// Find the first opening tag (skip whitespace/newlines)
|
|
85
|
+
const tagMatch = template.match(/^(\s*<)(\w[\w-]*)([\s\S]*?)(\/?>)/);
|
|
86
|
+
if (!tagMatch) return template;
|
|
87
|
+
|
|
88
|
+
const [fullMatch, prefix, tagName, attrs, close] = tagMatch;
|
|
89
|
+
|
|
90
|
+
// Check for existing class:list
|
|
91
|
+
const classListMatch = attrs.match(/\s+class:list=\{(\[[\s\S]*?\])\}/);
|
|
92
|
+
if (classListMatch) {
|
|
93
|
+
const existingList = classListMatch[1];
|
|
94
|
+
// Append className to the array
|
|
95
|
+
const newList = existingList.replace(/\]$/, `, className]`);
|
|
96
|
+
const newAttrs = attrs.replace(classListMatch[0], ` class:list={${newList}}`);
|
|
97
|
+
return prefix + tagName + newAttrs + close + template.slice(fullMatch.length);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check for existing class="..." (static)
|
|
101
|
+
const classStaticMatch = attrs.match(/\s+class="([^"]*)"/);
|
|
102
|
+
if (classStaticMatch) {
|
|
103
|
+
const existing = classStaticMatch[1];
|
|
104
|
+
const newAttrs = attrs.replace(classStaticMatch[0], ` class:list={["${existing}", className]}`);
|
|
105
|
+
return prefix + tagName + newAttrs + close + template.slice(fullMatch.length);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Check for existing class={expr} (dynamic)
|
|
109
|
+
const classDynMatch = attrs.match(/\s+class=\{([^}]+)\}/);
|
|
110
|
+
if (classDynMatch) {
|
|
111
|
+
const expr = classDynMatch[1];
|
|
112
|
+
const newAttrs = attrs.replace(classDynMatch[0], ` class:list={[${expr}, className]}`);
|
|
113
|
+
return prefix + tagName + newAttrs + close + template.slice(fullMatch.length);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// No existing class — add class={className}
|
|
117
|
+
return prefix + tagName + ` class={className}` + attrs + close + template.slice(fullMatch.length);
|
|
118
|
+
}
|
|
119
|
+
|
|
79
120
|
// ---------------------------------------------------------------------------
|
|
80
121
|
// Main emitter
|
|
81
122
|
// ---------------------------------------------------------------------------
|
|
@@ -87,7 +128,8 @@ export function emitAstroComponent(
|
|
|
87
128
|
name: string,
|
|
88
129
|
def: ComponentDefinition,
|
|
89
130
|
allComponents: Record<string, ComponentDefinition>,
|
|
90
|
-
breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS
|
|
131
|
+
breakpoints: BreakpointConfig = DEFAULT_BREAKPOINTS,
|
|
132
|
+
defaultLocale: string = 'en'
|
|
91
133
|
): string {
|
|
92
134
|
const comp = def.component;
|
|
93
135
|
const propDefs = comp.interface || {};
|
|
@@ -110,17 +152,23 @@ export function emitAstroComponent(
|
|
|
110
152
|
fileType: 'component',
|
|
111
153
|
fileName: name,
|
|
112
154
|
breakpoints,
|
|
155
|
+
defaultLocale,
|
|
113
156
|
};
|
|
114
157
|
|
|
115
158
|
// Emit the template body
|
|
116
|
-
|
|
159
|
+
let templateBody = nodeToAstro(structure, ctx);
|
|
160
|
+
|
|
161
|
+
// Merge instance className onto the root element (for acceptsStyles support)
|
|
162
|
+
templateBody = mergeClassNameOntoRoot(templateBody);
|
|
117
163
|
|
|
118
|
-
// Build frontmatter
|
|
119
|
-
const frontmatter = buildFrontmatter(name, propDefs, ctx.imports, ctx.dynamicTags);
|
|
164
|
+
// Build frontmatter (includes class prop for instance style support)
|
|
165
|
+
const frontmatter = buildFrontmatter(name, propDefs, ctx.imports, ctx.dynamicTags, ctx.needsI18nResolver ? defaultLocale : undefined);
|
|
120
166
|
|
|
121
167
|
// Build style/script sections
|
|
122
168
|
const styleSection = comp.css ? `\n<style>\n${comp.css}\n</style>\n` : '';
|
|
123
|
-
const scriptSection = comp.javascript
|
|
169
|
+
const scriptSection = comp.javascript
|
|
170
|
+
? buildScriptSection(comp.javascript, comp, propDefs)
|
|
171
|
+
: '';
|
|
124
172
|
|
|
125
173
|
return `---\n${frontmatter}---\n${templateBody}${styleSection}${scriptSection}`;
|
|
126
174
|
}
|
|
@@ -132,7 +180,8 @@ function buildFrontmatter(
|
|
|
132
180
|
componentName: string,
|
|
133
181
|
propDefs: Record<string, PropDefinition>,
|
|
134
182
|
imports: Set<string>,
|
|
135
|
-
dynamicTags?: Map<string, string
|
|
183
|
+
dynamicTags?: Map<string, string>,
|
|
184
|
+
i18nDefaultLocale?: string
|
|
136
185
|
): string {
|
|
137
186
|
const lines: string[] = [];
|
|
138
187
|
|
|
@@ -145,7 +194,8 @@ function buildFrontmatter(
|
|
|
145
194
|
|
|
146
195
|
const propEntries = Object.entries(propDefs);
|
|
147
196
|
|
|
148
|
-
|
|
197
|
+
// Always generate Props interface and destructuring (at minimum for class prop)
|
|
198
|
+
{
|
|
149
199
|
// Interface
|
|
150
200
|
lines.push('interface Props {');
|
|
151
201
|
for (const [propName, propDef] of propEntries) {
|
|
@@ -154,6 +204,8 @@ function buildFrontmatter(
|
|
|
154
204
|
const optional = 'default' in propDef && propDef.default !== undefined;
|
|
155
205
|
lines.push(` ${propName}${optional ? '?' : ''}: ${tsType};`);
|
|
156
206
|
}
|
|
207
|
+
// Always include class prop for instance style support
|
|
208
|
+
lines.push(' class?: string;');
|
|
157
209
|
lines.push('}');
|
|
158
210
|
lines.push('');
|
|
159
211
|
|
|
@@ -164,21 +216,24 @@ function buildFrontmatter(
|
|
|
164
216
|
const defaultVal = formatDefault(propDef);
|
|
165
217
|
if (defaultVal !== null) {
|
|
166
218
|
destructParts.push(`${propName} = ${defaultVal}`);
|
|
219
|
+
} else if (propDef.type === 'link') {
|
|
220
|
+
destructParts.push(`${propName} = { href: "#" }`);
|
|
167
221
|
} else {
|
|
168
222
|
destructParts.push(propName);
|
|
169
223
|
}
|
|
170
224
|
}
|
|
171
225
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
lines.push(
|
|
226
|
+
// Always include class prop (renamed to className to avoid reserved word)
|
|
227
|
+
destructParts.push('class: className = ""');
|
|
228
|
+
|
|
229
|
+
if (destructParts.length <= 3 && destructParts.join(', ').length < 80) {
|
|
230
|
+
lines.push(`const { ${destructParts.join(', ')} } = Astro.props;`);
|
|
231
|
+
} else {
|
|
232
|
+
lines.push('const {');
|
|
233
|
+
for (const part of destructParts) {
|
|
234
|
+
lines.push(` ${part},`);
|
|
181
235
|
}
|
|
236
|
+
lines.push('} = Astro.props;');
|
|
182
237
|
}
|
|
183
238
|
}
|
|
184
239
|
|
|
@@ -190,6 +245,18 @@ function buildFrontmatter(
|
|
|
190
245
|
}
|
|
191
246
|
}
|
|
192
247
|
|
|
248
|
+
// i18n resolver helper — resolves { _i18n: true, en: "...", pl: "..." } at runtime
|
|
249
|
+
if (i18nDefaultLocale) {
|
|
250
|
+
lines.push('');
|
|
251
|
+
lines.push(`const r = (v: any) => {`);
|
|
252
|
+
lines.push(` if (v && typeof v === 'object' && v._i18n) {`);
|
|
253
|
+
lines.push(` const locale = Astro.currentLocale ?? '${i18nDefaultLocale}';`);
|
|
254
|
+
lines.push(` return v[locale] ?? v['${i18nDefaultLocale}'] ?? Object.values(v).find((s: any) => typeof s === 'string' && s !== '') ?? '';`);
|
|
255
|
+
lines.push(` }`);
|
|
256
|
+
lines.push(` return v ?? '';`);
|
|
257
|
+
lines.push(`};`);
|
|
258
|
+
}
|
|
259
|
+
|
|
193
260
|
if (lines.length > 0) lines.push('');
|
|
194
261
|
return lines.join('\n');
|
|
195
262
|
}
|
|
@@ -203,6 +270,72 @@ function buildNoStructureComponent(
|
|
|
203
270
|
): string {
|
|
204
271
|
let content = '---\n---\n<slot />\n';
|
|
205
272
|
if (comp.css) content += `\n<style>\n${comp.css}\n</style>\n`;
|
|
206
|
-
if (comp.javascript) content += `\n<script>\n${comp.javascript}\n</script>\n`;
|
|
273
|
+
if (comp.javascript) content += `\n<script is:inline>\n${comp.javascript}\n</script>\n`;
|
|
207
274
|
return content;
|
|
208
275
|
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Transform JS for define:vars compatibility.
|
|
279
|
+
* Astro's define:vars injects each prop as a script-scope variable, not a `props` object.
|
|
280
|
+
* This function:
|
|
281
|
+
* 1. Removes `const/let/var { x, y } = props;` destructuring lines
|
|
282
|
+
* 2. Replaces `props.X` references with direct `X` variable access
|
|
283
|
+
* 3. Drops `var/let/const` from redeclarations of define:vars variables
|
|
284
|
+
*/
|
|
285
|
+
function transformDefineVarsJS(js: string, varNames: string[]): string {
|
|
286
|
+
let result = js;
|
|
287
|
+
|
|
288
|
+
// 1. Remove destructuring from props: `const { x, y } = props;`
|
|
289
|
+
result = result.replace(
|
|
290
|
+
/^\s*(const|let|var)\s+\{([^}]+)\}\s*=\s*props\s*;?\s*$/gm,
|
|
291
|
+
(match, _keyword, inner) => {
|
|
292
|
+
const names = inner.split(',').map((s: string) => s.trim()).filter(Boolean);
|
|
293
|
+
if (names.every((n: string) => varNames.includes(n))) return '';
|
|
294
|
+
return match;
|
|
295
|
+
}
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
// 2. Replace `props.X` with `X` (longest names first to avoid substring conflicts)
|
|
299
|
+
const sorted = [...varNames].sort((a, b) => b.length - a.length);
|
|
300
|
+
for (const name of sorted) {
|
|
301
|
+
result = result.replace(new RegExp(`props\\.${name}\\b`, 'g'), name);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// 3. Remove redeclarations of define:vars variables (already injected as const by Astro)
|
|
305
|
+
for (const name of varNames) {
|
|
306
|
+
result = result.replace(
|
|
307
|
+
new RegExp(`^\\s*(var|let|const)\\s+${name}\\s*=[^;]*;?\\s*$`, 'gm'),
|
|
308
|
+
''
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Build the script section with proper el/props initialization.
|
|
317
|
+
* - defineVars components: use Astro's define:vars to pass props into inline script
|
|
318
|
+
* - other components: use is:inline to avoid module bundling
|
|
319
|
+
* Both cases use document.currentScript.previousElementSibling to get el.
|
|
320
|
+
*/
|
|
321
|
+
function buildScriptSection(
|
|
322
|
+
js: string,
|
|
323
|
+
comp: StructuredComponentDefinition,
|
|
324
|
+
propDefs: Record<string, PropDefinition>
|
|
325
|
+
): string {
|
|
326
|
+
const elInit = 'const el = document.currentScript.previousElementSibling;';
|
|
327
|
+
|
|
328
|
+
if (comp.defineVars) {
|
|
329
|
+
const vars = comp.defineVars === true
|
|
330
|
+
? Object.keys(propDefs).filter(k => k !== 'children')
|
|
331
|
+
: comp.defineVars;
|
|
332
|
+
|
|
333
|
+
if (vars.length > 0) {
|
|
334
|
+
const transformedJS = transformDefineVarsJS(js, vars);
|
|
335
|
+
const defineVarsObj = `{ ${vars.join(', ')} }`;
|
|
336
|
+
return `\n<script define:vars={${defineVarsObj}}>\n${elInit}\n${transformedJS}\n</script>\n`;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return `\n<script is:inline>\n${elInit}\n${js}\n</script>\n`;
|
|
341
|
+
}
|