meno-core 1.1.3 → 1.1.4
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/dist/chunks/{chunk-LOZL5HOF.js → chunk-UOF4MCAD.js} +64 -2
- package/dist/chunks/chunk-UOF4MCAD.js.map +7 -0
- package/dist/chunks/{chunk-3JXK2QFU.js → chunk-ZEDLSHYQ.js} +2 -2
- package/dist/lib/client/index.js +46 -28
- package/dist/lib/client/index.js.map +2 -2
- package/dist/lib/server/index.js +1267 -233
- package/dist/lib/server/index.js.map +4 -4
- package/dist/lib/shared/index.js +3 -1
- package/dist/lib/shared/index.js.map +1 -1
- package/lib/client/core/ComponentBuilder.test.ts +32 -0
- package/lib/client/core/ComponentBuilder.ts +30 -0
- package/lib/client/theme.test.ts +2 -2
- package/lib/client/theme.ts +28 -26
- package/lib/server/createServer.ts +5 -1
- package/lib/server/cssAudit.test.ts +270 -0
- package/lib/server/cssAudit.ts +815 -0
- package/lib/server/deMirror.test.ts +61 -0
- package/lib/server/deMirror.ts +317 -0
- package/lib/server/fileWatcher.test.ts +23 -0
- package/lib/server/fileWatcher.ts +6 -1
- package/lib/server/index.ts +19 -0
- package/lib/server/routes/api/core-routes.ts +18 -0
- package/lib/server/routes/api/cssAudit.test.ts +101 -0
- package/lib/server/routes/api/cssAudit.ts +138 -0
- package/lib/server/routes/api/deMirror.test.ts +105 -0
- package/lib/server/routes/api/deMirror.ts +127 -0
- package/lib/server/routes/api/pages.ts +2 -2
- package/lib/server/services/componentService.test.ts +43 -0
- package/lib/server/services/componentService.ts +49 -12
- package/lib/server/services/pageService.test.ts +15 -0
- package/lib/server/services/pageService.ts +44 -22
- package/lib/server/ssr/htmlGenerator.test.ts +29 -0
- package/lib/server/ssr/htmlGenerator.ts +83 -3
- package/lib/server/themeCssCodec.test.ts +67 -0
- package/lib/server/themeCssCodec.ts +67 -5
- package/lib/server/webflow/templateWrapper.ts +54 -0
- package/lib/shared/cssGeneration.test.ts +28 -0
- package/lib/shared/interfaces/contentProvider.ts +9 -0
- package/lib/shared/types/cms.ts +1 -0
- package/lib/shared/utilityClassConfig.ts +2 -0
- package/lib/shared/utilityClassMapper.test.ts +53 -0
- package/lib/shared/utilityClassNames.ts +74 -0
- package/lib/shared/utils/fileUtils.ts +11 -0
- package/lib/shared/validation/schemas.ts +1 -0
- package/lib/shared/viewportUnits.test.ts +34 -1
- package/lib/shared/viewportUnits.ts +43 -0
- package/package.json +3 -1
- package/vite.config.ts +4 -1
- package/dist/chunks/chunk-LOZL5HOF.js.map +0 -7
- /package/dist/chunks/{chunk-3JXK2QFU.js.map → chunk-ZEDLSHYQ.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from 'bun:test';
|
|
2
|
-
import { rewriteViewportUnits } from './viewportUnits';
|
|
2
|
+
import { rewriteViewportUnits, rewriteViewportUnitsInStylesheet } from './viewportUnits';
|
|
3
3
|
|
|
4
4
|
describe('rewriteViewportUnits', () => {
|
|
5
5
|
it('rewrites basic vh values in declarations', () => {
|
|
@@ -102,3 +102,36 @@ describe('rewriteViewportUnits', () => {
|
|
|
102
102
|
expect(rewriteViewportUnits('top: 0vh;')).toBe('top: calc(var(--design-vh, 1vh) * 0);');
|
|
103
103
|
});
|
|
104
104
|
});
|
|
105
|
+
|
|
106
|
+
describe('rewriteViewportUnitsInStylesheet', () => {
|
|
107
|
+
it('preserves an escaped selector carrying a DECIMAL viewport unit', () => {
|
|
108
|
+
// `text-[clamp(56px,9.5vw,150px)]` escapes to `…9\.5vw…`; the value-level
|
|
109
|
+
// rewriter matches `.5vw` after the backslash and corrupts the selector, so
|
|
110
|
+
// the browser drops the rule. Stylesheet-scoped rewrite touches only bodies.
|
|
111
|
+
const rule = '.text-\\[clamp\\(56px\\,9\\.5vw\\,150px\\)\\] { font-size: clamp(56px,9.5vw,150px); }';
|
|
112
|
+
expect(rewriteViewportUnitsInStylesheet(rule)).toBe(
|
|
113
|
+
'.text-\\[clamp\\(56px\\,9\\.5vw\\,150px\\)\\] { font-size: clamp(56px,calc(var(--design-vw, 1vw) * 9.5),150px); }',
|
|
114
|
+
);
|
|
115
|
+
// Rationale guard: the raw value rewriter alone corrupts this selector.
|
|
116
|
+
expect(rewriteViewportUnits(rule).split('{')[0]).toContain('calc(');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('preserves an escaped selector when a viewport unit follows a no-space comma', () => {
|
|
120
|
+
const rule = '.p-\\[80px_clamp\\(20px\\,5vw\\,64px\\)\\] { padding: 80px clamp(20px,5vw,64px); }';
|
|
121
|
+
expect(rewriteViewportUnitsInStylesheet(rule)).toBe(
|
|
122
|
+
'.p-\\[80px_clamp\\(20px\\,5vw\\,64px\\)\\] { padding: 80px clamp(20px,calc(var(--design-vw, 1vw) * 5),64px); }',
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('rewrites declaration values inside @media blocks while keeping nested selectors literal', () => {
|
|
127
|
+
const sheet = '@media (max-width: 767px) { .h-\\[50dvh\\] { height: 50dvh; } }';
|
|
128
|
+
expect(rewriteViewportUnitsInStylesheet(sheet)).toBe(
|
|
129
|
+
'@media (max-width: 767px) { .h-\\[50dvh\\] { height: calc(var(--design-dvh, 1dvh) * 50); } }',
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('is a no-op on empty / brace-free input', () => {
|
|
134
|
+
expect(rewriteViewportUnitsInStylesheet('')).toBe('');
|
|
135
|
+
expect(rewriteViewportUnitsInStylesheet('.a { color: red; }')).toBe('.a { color: red; }');
|
|
136
|
+
});
|
|
137
|
+
});
|
|
@@ -53,6 +53,49 @@ export function rewriteViewportUnits(input: string): string {
|
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Apply {@link rewriteViewportUnits} to a whole stylesheet, rewriting ONLY the
|
|
58
|
+
* declaration bodies — never the selectors or at-rule preludes.
|
|
59
|
+
*
|
|
60
|
+
* {@link rewriteViewportUnits} is regex-based and can't reliably tell a
|
|
61
|
+
* declaration value's viewport unit from one buried in an *escaped*
|
|
62
|
+
* arbitrary-value class SELECTOR. The `VIEWPORT_UNIT_RE` lookbehind guards the
|
|
63
|
+
* common selector shapes (`.mh-100vh`, `.min-h-[100svh]`), but a class whose
|
|
64
|
+
* arbitrary value carries a viewport unit after an escaped `.` or `,` slips
|
|
65
|
+
* through — e.g. `text-[clamp(56px,9.5vw,150px)]` escapes to
|
|
66
|
+
* `.text-\[clamp\(56px\,9\.5vw\,150px\)\]`, where the `.5vw` sits right after a
|
|
67
|
+
* backslash and the rewriter injects `calc(...)` INTO the selector. The result
|
|
68
|
+
* is invalid CSS the browser drops entirely, so the rule — and the design-mode
|
|
69
|
+
* viewport pin it carries — silently vanishes and the element renders unstyled.
|
|
70
|
+
*
|
|
71
|
+
* Splitting selector text from declaration bodies at brace boundaries removes
|
|
72
|
+
* the ambiguity: every selector / prelude ends at a `{`, every declaration body
|
|
73
|
+
* ends at a `}`, so only body text is handed to the value rewriter. Correct
|
|
74
|
+
* through `@media` nesting too (a nested rule's selector still ends at its own
|
|
75
|
+
* `{`). Assumes braces only ever delimit blocks — true for the generated
|
|
76
|
+
* utility/interactive/theme sheets (none emit literal `{`/`}` inside a value or
|
|
77
|
+
* string). Mirror of meno-astro's `rewriteViewportUnitsInStylesheet` (keep in
|
|
78
|
+
* sync — see packages/astro/lib/integration/viewportUnits.ts).
|
|
79
|
+
*/
|
|
80
|
+
export function rewriteViewportUnitsInStylesheet(css: string): string {
|
|
81
|
+
if (!css) return css;
|
|
82
|
+
let out = '';
|
|
83
|
+
let seg = '';
|
|
84
|
+
for (let i = 0; i < css.length; i++) {
|
|
85
|
+
const ch = css[i];
|
|
86
|
+
if (ch === '{') {
|
|
87
|
+
out += seg + ch; // `seg` is a selector / at-rule prelude — keep it literal
|
|
88
|
+
seg = '';
|
|
89
|
+
} else if (ch === '}') {
|
|
90
|
+
out += rewriteViewportUnits(seg) + ch; // `seg` is a declaration body — rewrite its values
|
|
91
|
+
seg = '';
|
|
92
|
+
} else {
|
|
93
|
+
seg += ch;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return out + seg; // trailing text outside any block — never a declaration value
|
|
97
|
+
}
|
|
98
|
+
|
|
56
99
|
/**
|
|
57
100
|
* Names of the CSS custom properties the runtime sets/clears to switch
|
|
58
101
|
* between design-mode (stable px) and page-mode (no override, vh = actual
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meno-core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"meno": "./dist/bin/cli.js"
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@emotion/css": "^11.13.5",
|
|
26
|
+
"css-tree": "^3.2.1",
|
|
26
27
|
"esbuild": "^0.25.0",
|
|
27
28
|
"isomorphic-dompurify": "^2.32.0",
|
|
28
29
|
"jsep": "^1.4.0",
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
"zod": "^3.22.4"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
37
|
+
"@types/css-tree": "^2.3.11",
|
|
36
38
|
"@types/markdown-it": "^14.1.2",
|
|
37
39
|
"@types/react": "^18.2.0",
|
|
38
40
|
"@types/react-dom": "^18.2.0",
|
package/vite.config.ts
CHANGED
|
@@ -19,7 +19,10 @@ export default defineConfig({
|
|
|
19
19
|
'react',
|
|
20
20
|
'react-dom',
|
|
21
21
|
'bun',
|
|
22
|
-
// Node.js built-ins (server code)
|
|
22
|
+
// Node.js built-ins (server code) — bare and node:-prefixed specifiers.
|
|
23
|
+
// The regex covers all `node:`-prefixed imports (e.g. `node:path`) so they
|
|
24
|
+
// stay external instead of being browser-stubbed by Vite.
|
|
25
|
+
/^node:/,
|
|
23
26
|
'path',
|
|
24
27
|
'fs',
|
|
25
28
|
'fs/promises',
|