sheetom 0.1.0-rc.1 → 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 +158 -109
- package/dist/index.cjs +1073 -2607
- 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 +1065 -2607
- package/dist/index.js.map +1 -1
- package/docs/api.md +113 -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/0.1.0-rc.1.json +0 -108
- package/compatibility/baselines/README.md +0 -3
- package/compatibility/schemas/compatibility-report.schema.json +0 -84
- 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 -60
package/README.md
CHANGED
|
@@ -1,37 +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
|
-
|
|
21
|
+
For Node.js, Bun, or Deno:
|
|
13
22
|
|
|
14
23
|
```sh
|
|
15
|
-
npm install sheetom
|
|
24
|
+
npm install sheetom
|
|
16
25
|
```
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
dependencies; consumers do not need to install peer dependencies or globals.
|
|
20
|
-
SheetOM validates values before using `cssstyle` only as a static shorthand
|
|
21
|
-
expander, and uses the tokenizer for lossless recovered-rule spans.
|
|
22
|
-
|
|
23
|
-
Node.js 22 and 24 are tested on Linux x64, Windows x64, and macOS arm64. Bun
|
|
24
|
-
1.3.1 and Deno 2.9.5 are tested on Linux x64. Deno must use a local
|
|
25
|
-
`node_modules` directory and grant the native Lightning CSS binding FFI and
|
|
26
|
-
system-information permissions:
|
|
27
|
+
For browsers and compatible JavaScript isolates:
|
|
27
28
|
|
|
28
29
|
```sh
|
|
29
|
-
|
|
30
|
+
npm install @sheetom/wasm
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
## Use
|
|
33
|
+
## Quick start
|
|
35
34
|
|
|
36
35
|
```ts
|
|
37
36
|
import { CSSStyleRule, CSSStyleSheet, parseStyleSheet } from "sheetom";
|
|
@@ -41,34 +40,68 @@ sheet.replaceSync(".card { width: 12px; }");
|
|
|
41
40
|
|
|
42
41
|
const rule = sheet.cssRules[0];
|
|
43
42
|
if (rule instanceof CSSStyleRule) {
|
|
44
|
-
rule.style.
|
|
45
|
-
|
|
43
|
+
rule.style.padding = "8px 16px";
|
|
44
|
+
rule.style.backgroundColor = "rebeccapurple";
|
|
45
|
+
rule.style.setProperty("--card-gap", "12px");
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
console.log(sheet.serialize());
|
|
49
49
|
|
|
50
|
-
const existing = parseStyleSheet(
|
|
51
|
-
|
|
52
|
-
}
|
|
50
|
+
const existing = parseStyleSheet(
|
|
51
|
+
'@import "theme.css"; .card { color: red; }',
|
|
52
|
+
{ href: "https://example.com/assets/app.css" },
|
|
53
|
+
);
|
|
54
|
+
|
|
53
55
|
console.log(existing.cssRules.length); // 2
|
|
54
56
|
```
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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.
|
|
59
62
|
|
|
60
|
-
|
|
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.
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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:
|
|
66
97
|
|
|
67
98
|
```ts
|
|
68
99
|
const sheet = new CSSStyleSheet();
|
|
69
100
|
sheet.insertRule(".card {}");
|
|
70
101
|
|
|
71
|
-
const rule = sheet.cssRules[0]
|
|
102
|
+
const rule = sheet.cssRules[0];
|
|
103
|
+
if (!(rule instanceof CSSStyleRule)) throw new TypeError("Expected a style rule");
|
|
104
|
+
|
|
72
105
|
rule.style.setProperty("padding", "72px var(--space, var(--space,");
|
|
73
106
|
|
|
74
107
|
rule.style.getPropertyValue("padding");
|
|
@@ -78,89 +111,105 @@ rule.style.cssText;
|
|
|
78
111
|
// "padding: 72px var(--space, var(--space,;"
|
|
79
112
|
|
|
80
113
|
sheet.serialize();
|
|
81
|
-
// reparsable CSS with the missing syntax repaired
|
|
114
|
+
// reparsable CSS with the missing syntax safely confined and repaired
|
|
82
115
|
```
|
|
83
116
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
| Surface | Contract |
|
|
117
|
+
| Surface | Purpose |
|
|
87
118
|
| --- | --- |
|
|
88
|
-
| `
|
|
89
|
-
| `rule.cssText` | Browser-compatible
|
|
90
|
-
| `sheet.serialize()` | Deterministic, reparsable
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
##
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
Operation Fixtures execute through SheetOM and native browser adapters;
|
|
118
|
-
applicable WPT subtests retain their pinned source path, title, and blob SHA.
|
|
119
|
-
Every release ships its machine-readable Compatibility Report.
|
|
120
|
-
|
|
121
|
-
See [the behavioral API reference](./docs/api.md) for return, exception,
|
|
122
|
-
identity, and detachment contracts. Maintainers use the separately reviewed
|
|
123
|
-
[release procedure](./docs/releasing.md); Changesets never publishes by itself.
|
|
124
|
-
|
|
125
|
-
The checked-in ordinary-property manifest was generated against Chromium
|
|
126
|
-
151.0.7922.34. Run `npm run generate:properties` only when intentionally
|
|
127
|
-
advancing the Compatibility Baseline.
|
|
128
|
-
|
|
129
|
-
## Security and resource boundaries
|
|
130
|
-
|
|
131
|
-
SheetOM does not fetch `@import` targets or URLs and does not execute CSS. It is
|
|
132
|
-
also not a sanitizer: valid authored URLs, imports, and browser features remain
|
|
133
|
-
in serialized output. Callers must sanitize untrusted output before attaching
|
|
134
|
-
it to a document or another rendering environment.
|
|
135
|
-
|
|
136
|
-
The browser-shaped interface has no implicit input-size, nesting-depth, or
|
|
137
|
-
mutation-count limits. Isolate or bound untrusted workloads according to your
|
|
138
|
-
application's resource policy. See [SECURITY.md](./SECURITY.md) for private
|
|
139
|
-
vulnerability reporting and supported-release policy.
|
|
140
|
-
|
|
141
|
-
## Development
|
|
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:
|
|
142
148
|
|
|
143
149
|
```sh
|
|
144
|
-
|
|
145
|
-
npm run typecheck
|
|
146
|
-
npm run build
|
|
147
|
-
npm run conformance:validate
|
|
148
|
-
npm run conformance:drift
|
|
149
|
-
npm run fuzz
|
|
150
|
-
npm run benchmark
|
|
151
|
-
npm run pack:test
|
|
150
|
+
deno run --node-modules-dir=manual --allow-ffi --allow-sys app.ts
|
|
152
151
|
```
|
|
153
152
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
WebAssembly example:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { createSheetOM } from "@sheetom/wasm";
|
|
157
|
+
|
|
158
|
+
const { CSSStyleSheet } = await createSheetOM();
|
|
159
|
+
const sheet = new CSSStyleSheet();
|
|
160
|
+
sheet.replaceSync(".card { color: red; }");
|
|
161
|
+
```
|
|
162
|
+
|
|
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.
|
|
168
|
+
|
|
169
|
+
## Compatibility contract
|
|
170
|
+
|
|
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.
|
|
176
|
+
|
|
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.
|
|
181
|
+
|
|
182
|
+
See [Compatibility](./docs/compatibility.md) for the exact promise, evidence,
|
|
183
|
+
and exclusions.
|
|
184
|
+
|
|
185
|
+
## Resource limits and diagnostics
|
|
186
|
+
|
|
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.
|
|
191
|
+
|
|
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();
|
|
198
|
+
```
|
|
199
|
+
|
|
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
|
|
158
204
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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)
|
|
163
212
|
|
|
164
213
|
## License
|
|
165
214
|
|
|
166
|
-
MIT
|
|
215
|
+
MIT. Vendored parser sources retain their upstream licenses and provenance.
|