@csszyx/mcp-server 0.10.0 → 0.10.2
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/llms-full.txt +94 -13
- package/package.json +4 -4
package/llms-full.txt
CHANGED
|
@@ -248,11 +248,15 @@ compile error, so typos and legacy CSS-property names are caught by `tsc` (run
|
|
|
248
248
|
`tsc --noEmit` in CI to enforce it).
|
|
249
249
|
|
|
250
250
|
```tsx
|
|
251
|
-
{
|
|
251
|
+
{
|
|
252
|
+
bgColor: "red-500";
|
|
253
|
+
} // ❌ tsc error — unknown key; canonical is { bg: 'red-500' }
|
|
252
254
|
|
|
253
255
|
// Forcing a brand-new Tailwind utility csszyx has no key for yet — opt out explicitly:
|
|
254
256
|
// @ts-expect-error - forward-compat utility not yet in csszyx
|
|
255
|
-
{
|
|
257
|
+
{
|
|
258
|
+
someNewUtility: "x";
|
|
259
|
+
} // ✅ allowed; the runtime still emits the class
|
|
256
260
|
```
|
|
257
261
|
|
|
258
262
|
Arbitrary variants are allowed by pattern: `{ '@container': {…} }`, `{ 'min-[320px]': {…} }`,
|
|
@@ -260,7 +264,9 @@ Arbitrary variants are allowed by pattern: `{ '@container': {…} }`, `{ 'min-[3
|
|
|
260
264
|
Tailwind `@theme` and csszyx auto-generates the type:
|
|
261
265
|
|
|
262
266
|
```css
|
|
263
|
-
@theme {
|
|
267
|
+
@theme {
|
|
268
|
+
--breakpoint-tablet: 40rem;
|
|
269
|
+
} /* → { tablet: { p: 6 } } now type-checks */
|
|
264
270
|
```
|
|
265
271
|
|
|
266
272
|
## Full Snippets Reference
|
|
@@ -3511,37 +3517,112 @@ import { __szColorVar } from "csszyx/lite";
|
|
|
3511
3517
|
When a caller passes one flat `className` to a component that renders nested elements, `splitBox` partitions it at the CSS box-model border line so each element gets the classes that act on it. Pure string functions, framework-agnostic. The class-token → box-role map is generated from the compiler's property tables (never drifts).
|
|
3512
3518
|
|
|
3513
3519
|
```tsx
|
|
3514
|
-
import {
|
|
3520
|
+
import {
|
|
3521
|
+
splitBox,
|
|
3522
|
+
splitBoxSz,
|
|
3523
|
+
classify,
|
|
3524
|
+
has,
|
|
3525
|
+
pick,
|
|
3526
|
+
omit,
|
|
3527
|
+
stripSzProps,
|
|
3528
|
+
} from "@csszyx/runtime";
|
|
3515
3529
|
|
|
3516
3530
|
// Partition: outer = border-outward (margin/position/border/sizing/bg/shadow/transform/visibility),
|
|
3517
3531
|
// inner = border-inward (padding/overflow/display/layout/gap/text/paint-inside/interactivity)
|
|
3518
|
-
const { outer, inner } = splitBox(
|
|
3532
|
+
const { outer, inner } = splitBox("m-4 px-2 md:flex");
|
|
3519
3533
|
// outer: "m-4" inner: "px-2 md:flex"
|
|
3520
3534
|
|
|
3521
3535
|
// Override any default per call (BoxSelector = box-role | category | class-prefix | { category: value })
|
|
3522
|
-
splitBox(
|
|
3536
|
+
splitBox("overflow-hidden p-4", { outer: ["overflow"] });
|
|
3523
3537
|
// outer: "overflow-hidden" inner: "p-4"
|
|
3524
3538
|
|
|
3525
3539
|
// Toolkit: csszyx owns the truth (box-role/category), your project owns the rule
|
|
3526
|
-
classify(
|
|
3527
|
-
has(
|
|
3528
|
-
pick(
|
|
3529
|
-
omit(
|
|
3540
|
+
classify("inset-ring-2"); // { role: 'inner', category: 'ring' }
|
|
3541
|
+
has("p-2 overflow-y-auto", "overflow"); // true
|
|
3542
|
+
pick("m-4 text-sm", "text"); // "text-sm"
|
|
3543
|
+
omit("p-2 overflow-y-auto flex", "overflow"); // "p-2 flex"
|
|
3530
3544
|
|
|
3531
3545
|
// A scroller scrolls only when the outer frame clips (project-owned dependency rule)
|
|
3532
|
-
const dep = has(outer, { overflow:
|
|
3546
|
+
const dep = has(outer, { overflow: "hidden" }) ? "overflow-y-auto h-full" : "";
|
|
3547
|
+
|
|
3548
|
+
// sz-OBJECT routing: splitBoxSz partitions an sz OBJECT (not a className) into
|
|
3549
|
+
// { outer, inner } sz objects — keeps a szv-based component sz-native and routes
|
|
3550
|
+
// each key to the same side its class would (splitBoxSz(x) ≡ splitBox(compile(x))).
|
|
3551
|
+
splitBoxSz({ m: 4, px: 2 }); // { outer: { m: 4 }, inner: { px: 2 } }
|
|
3552
|
+
splitBoxSz({ gap: 2, hover: { px: 1 }, md: { m: 4 } }); // variants route by inner prop; split when they disagree
|
|
3553
|
+
splitBoxSz({ grow: 2, self: "center" }, { outer: ["grow", "self"] }); // force flex-item utils to the frame
|
|
3554
|
+
// classifySzKey(key) / hasSz / pickSz / omitSz — the sz-object toolkit twins
|
|
3533
3555
|
|
|
3534
3556
|
// stripSzProps: drop sz before forwarding ...rest to the DOM (guards uncompiled files
|
|
3535
3557
|
// whose raw sz would leak as sz="[object Object]"; dev-warns once on a raw-object sz)
|
|
3536
|
-
function Box({ sz, ...rest }) {
|
|
3558
|
+
function Box({ sz, ...rest }) {
|
|
3559
|
+
return <div {...stripSzProps(rest)} />;
|
|
3560
|
+
}
|
|
3537
3561
|
```
|
|
3538
3562
|
|
|
3563
|
+
## Build-time vs runtime (when does sz become CSS)
|
|
3564
|
+
|
|
3565
|
+
csszyx has two worlds; pick by "is the value set finite and known at build time?".
|
|
3566
|
+
|
|
3567
|
+
- **Static (build-time, default):** literals + `szv` variants. The compiler lowers
|
|
3568
|
+
sz → Tailwind classes and safelists them; Tailwind generates CSS at build. Zero
|
|
3569
|
+
runtime, SSR-safe.
|
|
3570
|
+
- **Runtime (`dynamic()`):** unbounded values (CMS color, user `#hex`). CSS is
|
|
3571
|
+
generated + injected in the browser via insertRule. Escape hatch only.
|
|
3572
|
+
|
|
3573
|
+
Engines (BUILD-TIME parse of JSX source only): Rust native (default) → oxc (JS
|
|
3574
|
+
fallback) → babel (last resort). The RUNTIME has no parser: `_sz`/`szv`/`splitBox`
|
|
3575
|
+
are plain JS; `dynamic()` lowers an sz OBJECT via `@csszyx/compiler/browser` (pure
|
|
3576
|
+
JS, no JSX parsing).
|
|
3577
|
+
|
|
3578
|
+
Helper build-time/runtime:
|
|
3579
|
+
|
|
3580
|
+
- `sz={{…}}` literal → build-time (extracted + safelisted).
|
|
3581
|
+
- `szv` → build-time: the compiler extracts the `szv({…})` config from its
|
|
3582
|
+
DECLARATION, regardless of how the factory output is used (direct sz=, through
|
|
3583
|
+
splitBoxSz, or unused). Indirection does NOT break safelisting.
|
|
3584
|
+
- `splitBox`/`splitBoxSz` → RUNTIME routing only (pure JS). They re-partition
|
|
3585
|
+
existing classes; they emit no new CSS and do NOT force `dynamic()`. CSS comes
|
|
3586
|
+
from the static source (a literal or a szv config).
|
|
3587
|
+
- `dynamic()` → the only helper that generates CSS at runtime, and only for a
|
|
3588
|
+
class not already in the built CSS.
|
|
3589
|
+
|
|
3590
|
+
Safelist requires a statically analyzable position (a literal sz, or a szv config
|
|
3591
|
+
literal). File-discovery gap: the prescan only scans files containing `sz=`/`sz:`,
|
|
3592
|
+
so a standalone szv-config file (no JSX) is skipped → co-locate szv in the
|
|
3593
|
+
component file that has a `sz=` usage. For a sibling workspace package, opt it in
|
|
3594
|
+
with `compilePackages: ['name']`.
|
|
3595
|
+
|
|
3596
|
+
Tree-shaking is content-presence (same as Tailwind), not import-graph. Co-locating
|
|
3597
|
+
szv makes the component the shaking unit.
|
|
3598
|
+
|
|
3599
|
+
Specificity: a `dynamic()`-injected rule is UNLAYERED → beats static sz / Tailwind
|
|
3600
|
+
`@layer utilities` at equal specificity (CSS Cascade Level 5). They don't collide
|
|
3601
|
+
by design (dynamic injects only not-yet-built classes); prefer all-static in a
|
|
3602
|
+
component.
|
|
3603
|
+
|
|
3604
|
+
CRITICAL — sz on an HTML tag vs a component: the compiler rewrites `sz=` to
|
|
3605
|
+
`className=` on ANY element. On an html tag (`<div sz>`) the class lands on the DOM
|
|
3606
|
+
and applies. On a COMPONENT (`<Box sz={{p:4}}>` → `<Box className="p-4">`) the
|
|
3607
|
+
class becomes a `className` PROP — the component does NOT receive an sz object and
|
|
3608
|
+
MUST forward `className` onto a real html tag, else the style is lost. Putting sz
|
|
3609
|
+
on a component is NOT enough; every style must reach an html tag.
|
|
3610
|
+
|
|
3611
|
+
Design-system rules: (1) a component is styled from the app via the `className` it
|
|
3612
|
+
receives (the compiled app sz); forward it to a DOM tag
|
|
3613
|
+
(`function Box({className}) { return <div className={className}/> }`). NEVER
|
|
3614
|
+
`dynamic(sz)` inside a component (makes every consumer runtime). (2) a multi-part
|
|
3615
|
+
component receives ONE className and routes it with `splitBox(className)` (STRING),
|
|
3616
|
+
combining with its own base classes on plain className (don't mix sz= and
|
|
3617
|
+
className= on one element). `splitBoxSz` (object) is only for routing an sz object
|
|
3618
|
+
the component builds internally (e.g. from szv) onto nested sz= props.
|
|
3619
|
+
|
|
3539
3620
|
## Security — untrusted sz
|
|
3540
3621
|
|
|
3541
3622
|
csszyx is safe-by-default for AUTHORED sz (compiled to class strings at build time). When sz comes from UNTRUSTED input (JSON-driven UI, CMS, user data), it controls keys and values that reach the runtime CSS pipeline — purify it.
|
|
3542
3623
|
|
|
3543
3624
|
```tsx
|
|
3544
|
-
import { dynamic, purifySz } from
|
|
3625
|
+
import { dynamic, purifySz } from "@csszyx/dynamic";
|
|
3545
3626
|
// stripSzProps is exported from '@csszyx/runtime'
|
|
3546
3627
|
|
|
3547
3628
|
// Untrusted sz → dynamic() runtime CSS: purify first (allowlist + value sanitize + proto guard)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csszyx/mcp-server",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for csszyx — enables AI agents to understand and generate sz props",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
32
32
|
"zod": "^3.23.8",
|
|
33
|
-
"@csszyx/cli": "0.10.
|
|
34
|
-
"@csszyx/
|
|
35
|
-
"@csszyx/
|
|
33
|
+
"@csszyx/cli": "0.10.2",
|
|
34
|
+
"@csszyx/compiler": "0.10.2",
|
|
35
|
+
"@csszyx/unplugin": "0.10.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"typescript": "^6.0.3",
|