sheetom 0.1.0-rc.0 → 0.1.0-rc.10
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/README.md +151 -90
- package/dist/index.cjs +1074 -2443
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +856 -24
- package/dist/index.d.ts +856 -24
- package/dist/index.js +1066 -2443
- package/dist/index.js.map +1 -1
- package/docs/api.md +124 -4
- package/engine-abi.json +5 -0
- package/native/index.cjs +44 -0
- package/native/resolve-target.cjs +85 -0
- package/package.json +119 -26
- package/compatibility/WPT-LICENSE.md +0 -15
- package/compatibility/baselines/0.1.0-rc.0.json +0 -70
- package/compatibility/baselines/README.md +0 -3
- package/compatibility/schemas/compatibility-report.schema.json +0 -68
- package/compatibility/schemas/compatibility-resolutions.schema.json +0 -28
- package/compatibility/schemas/operation-fixture.schema.json +0 -87
- package/compatibility/schemas/wpt-mappings.schema.json +0 -47
- package/docs/releasing.md +0 -56
package/README.md
CHANGED
|
@@ -1,39 +1,36 @@
|
|
|
1
1
|
# SheetOM
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Bun, and Deno. It uses Lightning CSS for property parsing and canonicalization
|
|
5
|
-
while keeping declaration state and CSSOM serialization under its own control.
|
|
3
|
+
**A browser-compatible, mutable CSSOM for JavaScript outside the browser.**
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
SheetOM lets build tools, publishers, and server applications parse, inspect,
|
|
6
|
+
mutate, and serialize stylesheets with familiar browser APIs. It preserves
|
|
7
|
+
browser recovery behavior for malformed-but-accepted CSS while still producing
|
|
8
|
+
deterministic, reparsable stylesheet output.
|
|
9
|
+
|
|
10
|
+
- Browser-shaped `CSSStyleSheet`, rules, and declarations
|
|
11
|
+
- Transactional `setProperty()` behavior and correct shorthand/longhand state
|
|
12
|
+
- Forgiving whole-sheet parsing without a DOM or global installation
|
|
13
|
+
- One repository-owned Rust engine for native and WebAssembly backends
|
|
14
|
+
- ESM, CommonJS, TypeScript, Node.js, Bun, Deno, browsers, and workers
|
|
15
|
+
|
|
16
|
+
SheetOM focuses on the **Authoring CSSOM**. It does not implement the cascade,
|
|
17
|
+
selector matching, layout, computed styles, fetching, or DOM attachment.
|
|
9
18
|
|
|
10
19
|
## Install
|
|
11
20
|
|
|
12
|
-
|
|
13
|
-
`0.1.0-rc.0` under the `next` dist-tag after the complete conformance gate
|
|
14
|
-
passes. Once published:
|
|
21
|
+
For Node.js, Bun, or Deno:
|
|
15
22
|
|
|
16
23
|
```sh
|
|
17
|
-
npm install sheetom
|
|
24
|
+
npm install sheetom
|
|
18
25
|
```
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
dependencies; consumers do not need to install peer dependencies or globals.
|
|
22
|
-
SheetOM validates values before using `cssstyle` only as a static shorthand
|
|
23
|
-
expander, and uses the tokenizer for lossless recovered-rule spans.
|
|
24
|
-
|
|
25
|
-
Node.js 22 and 24 are tested on Linux x64, Windows x64, and macOS arm64. Bun
|
|
26
|
-
1.3.1 and Deno 2.9.5 are tested on Linux x64. Deno must use a local
|
|
27
|
-
`node_modules` directory and grant the native Lightning CSS binding FFI and
|
|
28
|
-
system-information permissions:
|
|
27
|
+
For browsers and compatible JavaScript isolates:
|
|
29
28
|
|
|
30
29
|
```sh
|
|
31
|
-
|
|
30
|
+
npm install @sheetom/wasm
|
|
32
31
|
```
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## Use
|
|
33
|
+
## Quick start
|
|
37
34
|
|
|
38
35
|
```ts
|
|
39
36
|
import { CSSStyleRule, CSSStyleSheet, parseStyleSheet } from "sheetom";
|
|
@@ -43,33 +40,68 @@ sheet.replaceSync(".card { width: 12px; }");
|
|
|
43
40
|
|
|
44
41
|
const rule = sheet.cssRules[0];
|
|
45
42
|
if (rule instanceof CSSStyleRule) {
|
|
46
|
-
rule.style.
|
|
47
|
-
|
|
43
|
+
rule.style.padding = "8px 16px";
|
|
44
|
+
rule.style.backgroundColor = "rebeccapurple";
|
|
45
|
+
rule.style.setProperty("--card-gap", "12px");
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
console.log(sheet.serialize());
|
|
51
49
|
|
|
52
|
-
const existing = parseStyleSheet(
|
|
53
|
-
|
|
54
|
-
}
|
|
50
|
+
const existing = parseStyleSheet(
|
|
51
|
+
'@import "theme.css"; .card { color: red; }',
|
|
52
|
+
{ href: "https://example.com/assets/app.css" },
|
|
53
|
+
);
|
|
54
|
+
|
|
55
55
|
console.log(existing.cssRules.length); // 2
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
Named CSS properties are typed and assignable directly. Use `setProperty()`
|
|
59
|
+
when a property name is dynamic, custom, or hyphenated. `CSSStyleSheet` is the
|
|
60
|
+
only public CSSOM constructor; rules and declarations come from a sheet, just
|
|
61
|
+
as they do in browsers.
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
Constructed sheets strip `@import` during replacement. `parseStyleSheet()` is a
|
|
64
|
+
SheetOM extension for existing regular stylesheets and preserves valid imports
|
|
65
|
+
without fetching them.
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
Compilers can apply all known mutations for one rule with one engine crossing
|
|
68
|
+
and still receive one acceptance result per operation:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
function applyCompilerDeclarations(rule: CSSStyleRule, dynamicWidth: string) {
|
|
72
|
+
const results = rule.style.applyMutations([
|
|
73
|
+
{ kind: "set", property: "display", value: "grid" },
|
|
74
|
+
{ kind: "set", property: "width", value: dynamicWidth },
|
|
75
|
+
{ kind: "remove", property: "margin-left" },
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
for (const result of results) {
|
|
79
|
+
if (result.kind === "set" && !result.accepted) {
|
|
80
|
+
console.warn(result.diagnostic);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Operations run in order through the same validation and shorthand/longhand
|
|
87
|
+
state machine as individual calls. Group one batch per declaration block;
|
|
88
|
+
never combine values into declaration text. Batch results already include
|
|
89
|
+
rejection diagnostics, so high-volume callers can leave the sheet diagnostic
|
|
90
|
+
queue disabled unless they also need diagnostics from other APIs.
|
|
91
|
+
|
|
92
|
+
## Browser recovery, safe output
|
|
93
|
+
|
|
94
|
+
Browsers accept some CSS using end-of-input recovery and expose the incomplete
|
|
95
|
+
spelling through CSSOM. SheetOM keeps that observable behavior separate from
|
|
96
|
+
whole-sheet output:
|
|
67
97
|
|
|
68
98
|
```ts
|
|
69
99
|
const sheet = new CSSStyleSheet();
|
|
70
100
|
sheet.insertRule(".card {}");
|
|
71
101
|
|
|
72
|
-
const rule = sheet.cssRules[0]
|
|
102
|
+
const rule = sheet.cssRules[0];
|
|
103
|
+
if (!(rule instanceof CSSStyleRule)) throw new TypeError("Expected a style rule");
|
|
104
|
+
|
|
73
105
|
rule.style.setProperty("padding", "72px var(--space, var(--space,");
|
|
74
106
|
|
|
75
107
|
rule.style.getPropertyValue("padding");
|
|
@@ -79,76 +111,105 @@ rule.style.cssText;
|
|
|
79
111
|
// "padding: 72px var(--space, var(--space,;"
|
|
80
112
|
|
|
81
113
|
sheet.serialize();
|
|
82
|
-
// reparsable CSS with the missing syntax repaired
|
|
114
|
+
// reparsable CSS with the missing syntax safely confined and repaired
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
| Surface | Purpose |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| `style.cssText` | Browser-compatible declaration text, including measured recovery quirks. |
|
|
120
|
+
| `rule.cssText` | Browser-compatible text for the current rule. |
|
|
121
|
+
| `sheet.serialize()` | Deterministic, reparsable CSS for a complete stylesheet. |
|
|
122
|
+
|
|
123
|
+
Invalid property values and priorities are atomic no-ops: the previous state
|
|
124
|
+
survives unchanged. Static shorthands are stored as canonical longhands, so
|
|
125
|
+
editing and then removing one longhand cannot accidentally reactivate an old
|
|
126
|
+
shorthand value.
|
|
127
|
+
|
|
128
|
+
Reparsable output prevents malformed input from leaking into a following
|
|
129
|
+
declaration or rule. It is not a CSS sanitizer, URL policy, CSP, or rendering
|
|
130
|
+
sandbox.
|
|
131
|
+
|
|
132
|
+
## Native and WebAssembly runtimes
|
|
133
|
+
|
|
134
|
+
The `sheetom` package contains the JavaScript facade and selects one exact
|
|
135
|
+
`@sheetom/native-*` optional package for the current platform. It installs no
|
|
136
|
+
JavaScript parser dependency, downloads no binary at install time, and never
|
|
137
|
+
falls back to a different engine. Omitting optional dependencies is unsupported
|
|
138
|
+
and fails explicitly.
|
|
139
|
+
|
|
140
|
+
| Runtime | Entry point | Notes |
|
|
141
|
+
| --- | --- | --- |
|
|
142
|
+
| Node.js 22+ | `sheetom` | ESM and CommonJS; prebuilt native packages for macOS, Windows, GNU Linux, and musl Linux targets. |
|
|
143
|
+
| Bun | `sheetom` | Tested through the npm package on Linux x64. |
|
|
144
|
+
| Deno | `sheetom` | Uses npm resolution and requires native FFI/system permissions. |
|
|
145
|
+
| Browsers and workers | `@sheetom/wasm` | ESM-only asynchronous factory; no WASI or global installation. |
|
|
146
|
+
|
|
147
|
+
Deno example:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
deno run --node-modules-dir=manual --allow-ffi --allow-sys app.ts
|
|
83
151
|
```
|
|
84
152
|
|
|
85
|
-
|
|
86
|
-
behavior. Opt into mutation diagnostics with `{ diagnostics: true }` and drain
|
|
87
|
-
them using `takeDiagnostics()`.
|
|
153
|
+
WebAssembly example:
|
|
88
154
|
|
|
89
|
-
|
|
155
|
+
```ts
|
|
156
|
+
import { createSheetOM } from "@sheetom/wasm";
|
|
90
157
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
- keyframes and mutable keyframe rules
|
|
96
|
-
- counter-style descriptors and font-feature-value maps
|
|
97
|
-
- live indexed and named `CSSStyleDeclaration`
|
|
98
|
-
- `insertRule`, `deleteRule`, `replace`, and `replaceSync`
|
|
99
|
-
- `parseStyleSheet` for forgiving regular-sheet parsing
|
|
100
|
-
- browser-facing `cssText` and reparsable `serialize()` output
|
|
101
|
-
- generic retention of read-only metadata rules and experimental/future rules
|
|
158
|
+
const { CSSStyleSheet } = await createSheetOM();
|
|
159
|
+
const sheet = new CSSStyleSheet();
|
|
160
|
+
sheet.replaceSync(".card { color: red; }");
|
|
161
|
+
```
|
|
102
162
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
163
|
+
The native and WebAssembly packages execute the same Rust engine and verify an
|
|
164
|
+
exact engine ABI identity before exposing CSSOM objects. `createSheetOM()`
|
|
165
|
+
shares default initialization within one JavaScript realm; passing an explicit
|
|
166
|
+
`URL`, `Response`, `ArrayBuffer`, or `WebAssembly.Module` creates an isolated
|
|
167
|
+
facade with its own class identity.
|
|
108
168
|
|
|
109
|
-
|
|
110
|
-
identity, and detachment contracts. Maintainers use the separately reviewed
|
|
111
|
-
[release procedure](./docs/releasing.md); Changesets never publishes by itself.
|
|
169
|
+
## Compatibility contract
|
|
112
170
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
171
|
+
SheetOM tests complete observable state—not only whether serialized CSS looks
|
|
172
|
+
similar. Its versioned evidence covers getters, `cssText`, indexed property
|
|
173
|
+
order, priorities, invalid-mutation atomicity, live identity, shorthand
|
|
174
|
+
sequences, recovery, native-browser reparsing, subprocess crash safety,
|
|
175
|
+
grammar-oriented fuzzing, and Publisher-shaped performance workloads.
|
|
116
176
|
|
|
117
|
-
|
|
177
|
+
Standards and shared browser behavior take precedence. When browser engines
|
|
178
|
+
genuinely differ, SheetOM records the result and follows the pinned Chromium
|
|
179
|
+
baseline as its final fallback. Browser observations and WPT mappings remain
|
|
180
|
+
test evidence; they are never imported as runtime authority.
|
|
118
181
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
in serialized output. Callers must sanitize untrusted output before attaching
|
|
122
|
-
it to a document or another rendering environment.
|
|
182
|
+
See [Compatibility](./docs/compatibility.md) for the exact promise, evidence,
|
|
183
|
+
and exclusions.
|
|
123
184
|
|
|
124
|
-
|
|
125
|
-
mutation-count limits. Isolate or bound untrusted workloads according to your
|
|
126
|
-
application's resource policy. See [SECURITY.md](./SECURITY.md) for private
|
|
127
|
-
vulnerability reporting and supported-release policy.
|
|
185
|
+
## Resource limits and diagnostics
|
|
128
186
|
|
|
129
|
-
|
|
187
|
+
Each sheet has configurable limits for stylesheet bytes, declaration-value
|
|
188
|
+
bytes, syntax depth, rule count, and declarations per block. A limit violation
|
|
189
|
+
throws `RangeError` before mutation. These budgets protect the host process;
|
|
190
|
+
they are not content policy.
|
|
130
191
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
npm run fuzz
|
|
138
|
-
npm run benchmark
|
|
139
|
-
npm run pack:test
|
|
192
|
+
Mutation diagnostics are opt-in:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
const sheet = new CSSStyleSheet({ diagnostics: true });
|
|
196
|
+
// ...mutate the sheet...
|
|
197
|
+
const diagnostics = sheet.takeDiagnostics();
|
|
140
198
|
```
|
|
141
199
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
200
|
+
Diagnostics retain rejected inputs until drained. Leave them disabled or drain
|
|
201
|
+
them promptly when handling untrusted or unusually large source.
|
|
202
|
+
|
|
203
|
+
## Documentation
|
|
146
204
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
205
|
+
- [API behavior](./docs/api.md)
|
|
206
|
+
- [Architecture](https://github.com/leo91000/sheetom/blob/main/docs/architecture.md)
|
|
207
|
+
- [Compatibility](https://github.com/leo91000/sheetom/blob/main/docs/compatibility.md)
|
|
208
|
+
- [Contributing](https://github.com/leo91000/sheetom/blob/main/CONTRIBUTING.md)
|
|
209
|
+
- [Release process](https://github.com/leo91000/sheetom/blob/main/docs/releasing.md)
|
|
210
|
+
- [Architecture decisions](https://github.com/leo91000/sheetom/blob/main/docs/adr/README.md)
|
|
211
|
+
- [Security policy](./SECURITY.md)
|
|
151
212
|
|
|
152
213
|
## License
|
|
153
214
|
|
|
154
|
-
MIT
|
|
215
|
+
MIT. Vendored parser sources retain their upstream licenses and provenance.
|