@cassida/compiler 0.1.0

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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/config.schema.json +88 -0
  3. package/dist/canonicalizer.d.ts +42 -0
  4. package/dist/canonicalizer.d.ts.map +1 -0
  5. package/dist/canonicalizer.js +185 -0
  6. package/dist/canonicalizer.js.map +1 -0
  7. package/dist/compile.d.ts +46 -0
  8. package/dist/compile.d.ts.map +1 -0
  9. package/dist/compile.js +84 -0
  10. package/dist/compile.js.map +1 -0
  11. package/dist/config.d.ts +182 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +150 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/emitter.d.ts +44 -0
  16. package/dist/emitter.d.ts.map +1 -0
  17. package/dist/emitter.js +189 -0
  18. package/dist/emitter.js.map +1 -0
  19. package/dist/generated-property-specs.d.ts +3193 -0
  20. package/dist/generated-property-specs.d.ts.map +1 -0
  21. package/dist/generated-property-specs.js +472 -0
  22. package/dist/generated-property-specs.js.map +1 -0
  23. package/dist/hasher.d.ts +8 -0
  24. package/dist/hasher.d.ts.map +1 -0
  25. package/dist/hasher.js +10 -0
  26. package/dist/hasher.js.map +1 -0
  27. package/dist/index.d.ts +23 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +13 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/modifier-spec.d.ts +104 -0
  32. package/dist/modifier-spec.d.ts.map +1 -0
  33. package/dist/modifier-spec.js +52 -0
  34. package/dist/modifier-spec.js.map +1 -0
  35. package/dist/plugin.d.ts +66 -0
  36. package/dist/plugin.d.ts.map +1 -0
  37. package/dist/plugin.js +65 -0
  38. package/dist/plugin.js.map +1 -0
  39. package/dist/property-spec.d.ts +321 -0
  40. package/dist/property-spec.d.ts.map +1 -0
  41. package/dist/property-spec.js +382 -0
  42. package/dist/property-spec.js.map +1 -0
  43. package/dist/registry.d.ts +71 -0
  44. package/dist/registry.d.ts.map +1 -0
  45. package/dist/registry.js +123 -0
  46. package/dist/registry.js.map +1 -0
  47. package/dist/types.d.ts +135 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +28 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/util.d.ts +6 -0
  52. package/dist/util.d.ts.map +1 -0
  53. package/dist/util.js +6 -0
  54. package/dist/util.js.map +1 -0
  55. package/package.json +60 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Marker for arguments the parser could not statically evaluate. The
3
+ * parser stashes the original AST node behind `id`; the compiler treats
4
+ * these as opaque placeholders for canonical-key purposes and wires the
5
+ * surviving slot into the resulting `CompiledRule.dynamics` list.
6
+ */
7
+ export declare const DYNAMIC_TAG = "__fss_dynamic__";
8
+ export interface DynamicArg {
9
+ readonly [DYNAMIC_TAG]: true;
10
+ readonly id: string;
11
+ }
12
+ export declare function isDynamic(v: unknown): v is DynamicArg;
13
+ /**
14
+ * Sentinel value placed in a property bag for slots whose value is
15
+ * dynamic. The choice of ` ` makes accidental collision with a
16
+ * real CSS string impossible.
17
+ */
18
+ export declare const DYNAMIC_PLACEHOLDER = " <FSS_DYN> ";
19
+ /**
20
+ * A method call captured from a `cas()` chain, e.g. `color('red')`.
21
+ */
22
+ export interface MethodOp {
23
+ readonly method: string;
24
+ readonly args: readonly unknown[];
25
+ }
26
+ /**
27
+ * A scope-introducing call (`hover(c => ...)`, `media(q, c => ...)`,
28
+ * `on(sel, c => ...)`). Inner ops are collected from the callback's
29
+ * fresh chain and nested under this scope.
30
+ */
31
+ export interface ScopedOp {
32
+ readonly scope: Scope;
33
+ readonly ops: readonly Op[];
34
+ }
35
+ /**
36
+ * A direct CSS property write that bypasses the registry — emitted
37
+ * by `fss.unsafe(preset)` for keys outside the safe canonical set.
38
+ *
39
+ * `property` is a kebab-case CSS property name; `value` is a fully
40
+ * formatted CSS value string. Shorthand-policy guards do not apply
41
+ * to RawOps (they are intentionally outside the safety net — that's
42
+ * what "unsafe" means).
43
+ */
44
+ export interface RawOp {
45
+ readonly property: string;
46
+ readonly value: string;
47
+ }
48
+ /**
49
+ * Discriminated union of chain ops. Use `isMethodOp` / `isScopedOp` /
50
+ * `isRawOp` to narrow at consumption sites.
51
+ */
52
+ export type Op = MethodOp | ScopedOp | RawOp;
53
+ export declare function isMethodOp(op: Op): op is MethodOp;
54
+ export declare function isScopedOp(op: Op): op is ScopedOp;
55
+ export declare function isRawOp(op: Op): op is RawOp;
56
+ /**
57
+ * One scoping layer in a chain. The Canonicalizer turns these into
58
+ * nested rule selectors (`& :hover { ... }`, `@media (...) { ... }`).
59
+ *
60
+ * - `pseudo`: ":hover", ":focus", "::before", etc. — always prefixed by `&`.
61
+ * - `media`: the parenthesized query body, sans `@media`.
62
+ * - `raw`: arbitrary CSS selector text appended after `&` (e.g.
63
+ * `[data-loading="true"]`, `> *`). Use sparingly.
64
+ */
65
+ export type Scope = {
66
+ readonly kind: 'pseudo';
67
+ readonly selector: string;
68
+ } | {
69
+ readonly kind: 'media';
70
+ readonly query: string;
71
+ } | {
72
+ readonly kind: 'raw';
73
+ readonly selector: string;
74
+ };
75
+ /**
76
+ * Canonical, post-LIFO property map. Keys are CSS property names
77
+ * (`margin-top`, not `marginTop`); values are CSS-ready strings or
78
+ * the dynamic placeholder.
79
+ */
80
+ export type PropertyBag = Readonly<Record<string, string>>;
81
+ /**
82
+ * Recursive scope-tree produced by `Canonicalizer.collapse`.
83
+ *
84
+ * Each node owns the declarations *directly* applied at its scope
85
+ * (e.g. the base node owns un-modified declarations; a `:hover` child
86
+ * owns declarations written inside `.hover(c => ...)`).
87
+ *
88
+ * The hash is computed over the entire tree, so two structurally
89
+ * identical chains share a class regardless of textual differences in
90
+ * the source.
91
+ */
92
+ export interface ScopeBag {
93
+ /** `null` for the root (base scope); `Scope` for any nested layer. */
94
+ readonly scope: Scope | null;
95
+ readonly bag: PropertyBag;
96
+ readonly slots: Readonly<Record<string, string>>;
97
+ readonly children: readonly ScopeBag[];
98
+ }
99
+ /**
100
+ * One dynamic slot in a compiled rule. The CSS rule emits
101
+ * `<property>: var(<varName>)`; the parser injects the source AST node
102
+ * as the value of `<varName>` in the element's inline style.
103
+ *
104
+ * `scopePath` describes where in the scope tree this slot lives; it is
105
+ * informational only (the var name already encodes uniqueness via the
106
+ * className hash).
107
+ */
108
+ export interface DynamicSlot {
109
+ readonly property: string;
110
+ readonly varName: string;
111
+ readonly sourceId: string;
112
+ readonly animatable: boolean;
113
+ readonly syntax: string | undefined;
114
+ readonly initialValue: string | undefined;
115
+ readonly scopePath: readonly Scope[];
116
+ }
117
+ /**
118
+ * Result of compiling an `Op[]` chain.
119
+ *
120
+ * - `canonical` is the deterministic key from which `className` was
121
+ * derived (placeholders for dynamics, sorted scope-tree shape).
122
+ * - `tree` is CSS-emission-ready: dynamic entries already substituted
123
+ * with `var(--<className>-<scope>-<prop>)`. The emitter walks the
124
+ * tree, builds nested CSS, and runs it through stylis.
125
+ * - `dynamics` lists every dynamic slot in source order; the parser
126
+ * maps each `sourceId` back to its AST expression to populate the
127
+ * inline style attribute.
128
+ */
129
+ export interface CompiledRule {
130
+ readonly className: string;
131
+ readonly tree: ScopeBag;
132
+ readonly canonical: string;
133
+ readonly dynamics: readonly DynamicSlot[];
134
+ }
135
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Marker for arguments the parser could not statically evaluate. The
3
+ * parser stashes the original AST node behind `id`; the compiler treats
4
+ * these as opaque placeholders for canonical-key purposes and wires the
5
+ * surviving slot into the resulting `CompiledRule.dynamics` list.
6
+ */
7
+ export const DYNAMIC_TAG = '__fss_dynamic__';
8
+ export function isDynamic(v) {
9
+ return (typeof v === 'object' &&
10
+ v !== null &&
11
+ v[DYNAMIC_TAG] === true);
12
+ }
13
+ /**
14
+ * Sentinel value placed in a property bag for slots whose value is
15
+ * dynamic. The choice of ` ` makes accidental collision with a
16
+ * real CSS string impossible.
17
+ */
18
+ export const DYNAMIC_PLACEHOLDER = ' <FSS_DYN> ';
19
+ export function isMethodOp(op) {
20
+ return 'method' in op;
21
+ }
22
+ export function isScopedOp(op) {
23
+ return 'scope' in op && 'ops' in op;
24
+ }
25
+ export function isRawOp(op) {
26
+ return 'property' in op && 'value' in op;
27
+ }
28
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAO7C,MAAM,UAAU,SAAS,CAAC,CAAU;IAClC,OAAO,CACL,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,KAAK,IAAI;QACT,CAAiC,CAAC,WAAW,CAAC,KAAK,IAAI,CACzD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAC;AAwCjD,MAAM,UAAU,UAAU,CAAC,EAAM;IAC/B,OAAO,QAAQ,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAM;IAC/B,OAAO,OAAO,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EAAM;IAC5B,OAAO,UAAU,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,CAAC;AAC3C,CAAC"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Convert kebab-case CSS property names to camelCase keys (the form used
3
+ * by React's `style` prop and `csstype.Properties`).
4
+ */
5
+ export declare const cssToCamel: (prop: string) => string;
6
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,MACiC,CAAC"}
package/dist/util.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Convert kebab-case CSS property names to camelCase keys (the form used
3
+ * by React's `style` prop and `csstype.Properties`).
4
+ */
5
+ export const cssToCamel = (prop) => prop.replace(/-([a-z])/g, (_match, c) => c.toUpperCase());
6
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE,CACjD,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,MAAc,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@cassida/compiler",
3
+ "version": "0.1.0",
4
+ "description": "Cassida build-time CSS resolver: registry, canonicalizer, hasher, emitter.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "config.schema.json"
19
+ ],
20
+ "dependencies": {
21
+ "csstype": "^3.1.3",
22
+ "stylis": "^4.3.4",
23
+ "zod": "^3.23.8"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^22.9.0",
27
+ "@types/stylis": "^4.2.7",
28
+ "mdn-data": "^2.13.0",
29
+ "tsx": "^4.19.2",
30
+ "typescript": "^5.6.3",
31
+ "vitest": "^2.1.4"
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/pishio/cassida.git",
36
+ "directory": "packages/compiler"
37
+ },
38
+ "homepage": "https://github.com/pishio/cassida/tree/main/packages/compiler#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/pishio/cassida/issues"
41
+ },
42
+ "author": "pishio",
43
+ "keywords": [
44
+ "cassida",
45
+ "css-in-js",
46
+ "compile-time",
47
+ "single-class",
48
+ "react"
49
+ ],
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "scripts": {
54
+ "build": "tsc -p tsconfig.json",
55
+ "test": "vitest run",
56
+ "test:watch": "vitest",
57
+ "typecheck": "tsc -p tsconfig.json --noEmit",
58
+ "codegen": "tsx scripts/generate-property-specs.ts"
59
+ }
60
+ }