sheetom 0.1.0-rc.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SheetOM contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # SheetOM
2
+
3
+ SheetOM is a mutable, browser-shaped CSS authoring object model for Node.js,
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.
6
+
7
+ It is intended for server-side stylesheet editing and serialization. It does
8
+ not implement the DOM, cascade, selector matching, layout, or computed styles.
9
+
10
+ ## Install
11
+
12
+ SheetOM is not published yet. The first registry release will be
13
+ `0.1.0-rc.0` under the `next` dist-tag after the complete conformance gate
14
+ passes. Once published:
15
+
16
+ ```sh
17
+ npm install sheetom@next
18
+ ```
19
+
20
+ `lightningcss`, `css-tree`, `cssstyle`, and the CSS Tools tokenizer are regular
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:
29
+
30
+ ```sh
31
+ deno run --node-modules-dir=manual --allow-ffi --allow-sys app.ts
32
+ ```
33
+
34
+ SheetOM exports browser-named classes but never modifies `globalThis`.
35
+
36
+ ## Use
37
+
38
+ ```ts
39
+ import { CSSStyleRule, CSSStyleSheet, parseStyleSheet } from "sheetom";
40
+
41
+ const sheet = new CSSStyleSheet({ diagnostics: true });
42
+ sheet.replaceSync(".card { width: 12px; }");
43
+
44
+ const rule = sheet.cssRules[0];
45
+ if (rule instanceof CSSStyleRule) {
46
+ rule.style.setProperty("padding", "8px 16px");
47
+ Reflect.set(rule.style, "backgroundColor", "rebeccapurple");
48
+ }
49
+
50
+ console.log(sheet.serialize());
51
+
52
+ const existing = parseStyleSheet('@import "theme.css"; .card { color: red; }', {
53
+ href: "https://example.com/assets/app.css",
54
+ });
55
+ console.log(existing.cssRules.length); // 2
56
+ ```
57
+
58
+ Constructed sheets follow browser replacement behavior and strip `@import`.
59
+ `parseStyleSheet` creates a regular authoring sheet and preserves valid imports
60
+ without loading them.
61
+
62
+ ## Recovered values and safe serialization
63
+
64
+ SheetOM distinguishes the browser-facing CSSOM text from safe output. Chromium
65
+ accepts some values using CSS Syntax end-of-input recovery while preserving the
66
+ unclosed input in `getPropertyValue()` and `cssText`:
67
+
68
+ ```ts
69
+ const sheet = new CSSStyleSheet();
70
+ sheet.insertRule(".card {}");
71
+
72
+ const rule = sheet.cssRules[0] as CSSStyleRule;
73
+ rule.style.setProperty("padding", "72px var(--space, var(--space,");
74
+
75
+ rule.style.getPropertyValue("padding");
76
+ // "72px var(--space, var(--space,"
77
+
78
+ rule.style.cssText;
79
+ // "padding: 72px var(--space, var(--space,;"
80
+
81
+ sheet.serialize();
82
+ // reparsable CSS with the missing syntax repaired
83
+ ```
84
+
85
+ Invalid `setProperty` values and priorities are atomic no-ops, matching browser
86
+ behavior. Opt into mutation diagnostics with `{ diagnostics: true }` and drain
87
+ them using `takeDiagnostics()`.
88
+
89
+ ## API scope
90
+
91
+ - `CSSStyleSheet`, live `CSSRuleList`, `CSSRule`, and `MediaList`
92
+ - nested `CSSStyleRule`, `CSSGroupingRule`, and `CSSConditionRule`
93
+ - media, supports, container, layer, scope, and starting-style rules
94
+ - import, font-face, page/margin, nested-declaration, and position-try rules
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
102
+
103
+ SheetOM targets standards and shared browser behavior first, with Chromium
104
+ behavior used only as the final measured divergence fallback. Versioned JSON
105
+ Operation Fixtures execute through SheetOM and native browser adapters;
106
+ applicable WPT subtests retain their pinned source path, title, and blob SHA.
107
+ Every release ships its machine-readable Compatibility Report.
108
+
109
+ See [the behavioral API reference](./docs/api.md) for return, exception,
110
+ identity, and detachment contracts. Maintainers use the separately reviewed
111
+ [release procedure](./docs/releasing.md); Changesets never publishes by itself.
112
+
113
+ The checked-in ordinary-property manifest was generated against Chromium
114
+ 151.0.7922.34. Run `npm run generate:properties` only when intentionally
115
+ advancing the Compatibility Baseline.
116
+
117
+ ## Security and resource boundaries
118
+
119
+ SheetOM does not fetch `@import` targets or URLs and does not execute CSS. It is
120
+ also not a sanitizer: valid authored URLs, imports, and browser features remain
121
+ in serialized output. Callers must sanitize untrusted output before attaching
122
+ it to a document or another rendering environment.
123
+
124
+ The browser-shaped interface has no implicit input-size, nesting-depth, or
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.
128
+
129
+ ## Development
130
+
131
+ ```sh
132
+ npm test
133
+ npm run typecheck
134
+ npm run build
135
+ npm run conformance:validate
136
+ npm run conformance:drift
137
+ npm run fuzz
138
+ npm run benchmark
139
+ npm run pack:test
140
+ ```
141
+
142
+ `npm test` runs unit, deterministic fuzz, and local Chromium projects. Use
143
+ `npm run test:browser:matrix` on a machine with all Playwright dependencies to
144
+ run Chromium, Firefox, and WebKit. `npm run docs:build` generates the TypeDoc
145
+ reference under `site/api`.
146
+
147
+ Only the latest published `0.x` minor and its active prereleases receive fixes
148
+ before 1.0. During `0.x`, observable compatibility corrections and interface
149
+ breaks require a new minor version and migration note; patches remain backward
150
+ compatible.
151
+
152
+ ## License
153
+
154
+ MIT
package/SECURITY.md ADDED
@@ -0,0 +1,13 @@
1
+ # Security policy
2
+
3
+ ## Supported releases
4
+
5
+ Before 1.0, only the latest published `0.x` minor and its active prereleases receive security fixes.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Use GitHub's **Report a vulnerability** form in the repository Security tab. Do not open a public issue for a suspected vulnerability.
10
+
11
+ Reports should include the affected SheetOM version, impact, reproduction steps, and any known mitigations. You can expect an initial acknowledgement within seven days when practical, but this is a maintainer response target rather than a contractual service-level agreement.
12
+
13
+ SheetOM parses and serializes CSS but is not a sanitizer. It does not fetch resources or execute CSS; callers are responsible for validating untrusted output before it crosses a rendering boundary.
@@ -0,0 +1,15 @@
1
+ # The 3-Clause BSD License
2
+
3
+ Copyright © web-platform-tests contributors
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12
+
13
+ This text is copied from Web Platform Tests revision
14
+ `54f8f933629e7c010ae98a246729af01f8abcda5`. SheetOM records every adapted
15
+ scenario's exact source path and subtest title in `wpt-mappings.json`.
@@ -0,0 +1,70 @@
1
+ {
2
+ "$schema": "../schemas/compatibility-report.schema.json",
3
+ "schemaVersion": 1,
4
+ "packageVersion": "0.1.0-rc.0",
5
+ "baseline": {
6
+ "wptCommit": "54f8f933629e7c010ae98a246729af01f8abcda5",
7
+ "lightningcss": "1.33.0",
8
+ "cssTree": "3.2.1",
9
+ "runtimes": {
10
+ "node": "v24.18.0",
11
+ "bun": "1.3.1",
12
+ "deno": "2.9.5"
13
+ },
14
+ "browsers": {
15
+ "chromium": "151.0.7922.34 (revision 1234)",
16
+ "firefox": "153.0 (revision 1538)",
17
+ "webkit": "26.5 (revision 2336)"
18
+ }
19
+ },
20
+ "summary": {
21
+ "passed": 3,
22
+ "divergences": 1,
23
+ "excluded": 0,
24
+ "unexplained": 0
25
+ },
26
+ "evidence": {
27
+ "operationFixtures": {
28
+ "passed": 4,
29
+ "total": 4
30
+ },
31
+ "nativeWpt": [
32
+ {
33
+ "engine": "chrome",
34
+ "version": "150.0.7871.128",
35
+ "sha256": "93b768eb22570bb5d0b2ce26ec3a6df1576f5bb410b0d9c4a59b7913326e8a5d",
36
+ "passed": 4,
37
+ "total": 4
38
+ },
39
+ {
40
+ "engine": "firefox",
41
+ "version": "153.0.3",
42
+ "sha256": "64d86d8096a586634b6522b010960d29a487fc40e33d8a419907f924b2633ca0",
43
+ "passed": 4,
44
+ "total": 4
45
+ }
46
+ ]
47
+ },
48
+ "resolutions": [
49
+ {
50
+ "fixtureId": "declarations.basic-set-property",
51
+ "decision": "shared",
52
+ "rationale": "The observable declaration state is shared by the pinned browser engines."
53
+ },
54
+ {
55
+ "fixtureId": "declarations.malformed-padding",
56
+ "decision": "chromium-fallback",
57
+ "rationale": "CSS Syntax accepts the EOF-recovered value; Chromium preserves the unclosed observable spelling while Firefox materializes closing parentheses."
58
+ },
59
+ {
60
+ "fixtureId": "declarations.setproperty-null-undefined",
61
+ "decision": "shared",
62
+ "rationale": "The four adapted WPT subtests define the shared null and undefined conversion behavior."
63
+ },
64
+ {
65
+ "fixtureId": "declarations.required-arguments",
66
+ "decision": "shared",
67
+ "rationale": "Required WebIDL arguments throw TypeError before string conversion in the pinned browser engines."
68
+ }
69
+ ]
70
+ }
@@ -0,0 +1,3 @@
1
+ # Compatibility baselines
2
+
3
+ Release pull requests add one immutable, schema-validated `<version>.json` report here. `0.0.0` is an unpublished implementation version and intentionally has no report.
@@ -0,0 +1,68 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/leo91000/sheetom/compatibility/schemas/compatibility-report.schema.json",
4
+ "title": "SheetOM Compatibility Report",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "packageVersion", "baseline", "summary", "evidence", "resolutions"],
8
+ "properties": {
9
+ "$schema": { "type": "string" },
10
+ "schemaVersion": { "const": 1 },
11
+ "packageVersion": { "type": "string" },
12
+ "baseline": {
13
+ "type": "object",
14
+ "additionalProperties": false,
15
+ "required": ["wptCommit", "lightningcss", "cssTree", "runtimes", "browsers"],
16
+ "properties": {
17
+ "wptCommit": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
18
+ "lightningcss": { "type": "string" },
19
+ "cssTree": { "type": "string" },
20
+ "runtimes": { "type": "object" },
21
+ "browsers": { "type": "object" }
22
+ }
23
+ },
24
+ "summary": {
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": ["passed", "divergences", "excluded", "unexplained"],
28
+ "properties": {
29
+ "passed": { "type": "integer", "minimum": 0 },
30
+ "divergences": { "type": "integer", "minimum": 0 },
31
+ "excluded": { "type": "integer", "minimum": 0 },
32
+ "unexplained": { "const": 0 }
33
+ }
34
+ },
35
+ "evidence": {
36
+ "type": "object",
37
+ "additionalProperties": false,
38
+ "required": ["operationFixtures", "nativeWpt"],
39
+ "properties": {
40
+ "operationFixtures": {
41
+ "type": "object",
42
+ "additionalProperties": false,
43
+ "required": ["passed", "total"],
44
+ "properties": {
45
+ "passed": { "type": "integer", "minimum": 0 },
46
+ "total": { "type": "integer", "minimum": 0 }
47
+ }
48
+ },
49
+ "nativeWpt": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "object",
53
+ "additionalProperties": false,
54
+ "required": ["engine", "version", "sha256", "passed", "total"],
55
+ "properties": {
56
+ "engine": { "enum": ["chrome", "firefox", "safari"] },
57
+ "version": { "type": "string" },
58
+ "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
59
+ "passed": { "type": "integer", "minimum": 0 },
60
+ "total": { "type": "integer", "minimum": 0 }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ },
66
+ "resolutions": { "type": "array" }
67
+ }
68
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/leo91000/sheetom/compatibility/schemas/compatibility-resolutions.schema.json",
4
+ "title": "SheetOM Compatibility Resolutions",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "resolutions"],
8
+ "properties": {
9
+ "$schema": { "type": "string" },
10
+ "schemaVersion": { "const": 1 },
11
+ "resolutions": {
12
+ "type": "array",
13
+ "items": {
14
+ "type": "object",
15
+ "additionalProperties": false,
16
+ "required": ["fixtureId", "decision", "rationale", "expected"],
17
+ "properties": {
18
+ "fixtureId": { "type": "string" },
19
+ "decision": {
20
+ "enum": ["shared", "specification", "chromium-fallback", "scope-exclusion"]
21
+ },
22
+ "rationale": { "type": "string", "minLength": 1 },
23
+ "expected": { "type": "array" }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,87 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/leo91000/sheetom/compatibility/schemas/operation-fixture.schema.json",
4
+ "title": "SheetOM Operation Fixture",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "id", "operations"],
8
+ "properties": {
9
+ "$schema": { "type": "string" },
10
+ "schemaVersion": { "const": 1 },
11
+ "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
12
+ "provenanceIds": {
13
+ "type": "array",
14
+ "items": { "type": "string" },
15
+ "uniqueItems": true
16
+ },
17
+ "operations": {
18
+ "type": "array",
19
+ "minItems": 1,
20
+ "items": { "$ref": "#/$defs/operation" }
21
+ }
22
+ },
23
+ "$defs": {
24
+ "boundaryValue": {
25
+ "oneOf": [
26
+ {
27
+ "anyOf": [
28
+ { "type": "string" },
29
+ { "type": "number" },
30
+ { "type": "boolean" },
31
+ { "type": "null" }
32
+ ]
33
+ },
34
+ {
35
+ "type": "object",
36
+ "additionalProperties": false,
37
+ "required": ["$type"],
38
+ "properties": {
39
+ "$type": {
40
+ "enum": [
41
+ "undefined",
42
+ "nan",
43
+ "positive-infinity",
44
+ "negative-infinity",
45
+ "bigint",
46
+ "symbol",
47
+ "throwing-string-coercion"
48
+ ]
49
+ },
50
+ "value": { "type": "string" }
51
+ }
52
+ }
53
+ ]
54
+ },
55
+ "operation": {
56
+ "type": "object",
57
+ "additionalProperties": false,
58
+ "required": ["op", "target", "args"],
59
+ "properties": {
60
+ "op": { "type": "string" },
61
+ "target": { "type": "string" },
62
+ "handle": { "type": "string" },
63
+ "args": {
64
+ "type": "array",
65
+ "items": { "$ref": "#/$defs/boundaryValue" }
66
+ },
67
+ "observe": {
68
+ "type": "array",
69
+ "items": {
70
+ "type": "string",
71
+ "enum": [
72
+ "return",
73
+ "exception",
74
+ "cssText",
75
+ "length",
76
+ "items",
77
+ "parentRule",
78
+ "parentStyleSheet",
79
+ "serialize"
80
+ ]
81
+ },
82
+ "uniqueItems": true
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/leo91000/sheetom/compatibility/schemas/wpt-mappings.schema.json",
4
+ "title": "SheetOM WPT mappings",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "wptCommit", "mappings", "tombstones"],
8
+ "properties": {
9
+ "$schema": { "type": "string" },
10
+ "schemaVersion": { "const": 1 },
11
+ "wptCommit": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
12
+ "mappings": {
13
+ "type": "array",
14
+ "items": {
15
+ "type": "object",
16
+ "additionalProperties": false,
17
+ "required": ["id", "path", "subtest", "blobSha", "disposition", "coverage", "translation", "fixtureIds"],
18
+ "properties": {
19
+ "id": { "type": "string" },
20
+ "path": { "type": "string" },
21
+ "subtest": { "type": "string" },
22
+ "blobSha": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
23
+ "disposition": { "enum": ["applicable", "partial", "excluded"] },
24
+ "coverage": { "enum": ["full", "partial", "none"] },
25
+ "translation": { "type": "string" },
26
+ "fixtureIds": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
27
+ "reason": { "type": "string" },
28
+ "selectionNote": { "type": "string" }
29
+ }
30
+ }
31
+ },
32
+ "tombstones": {
33
+ "type": "array",
34
+ "items": {
35
+ "type": "object",
36
+ "additionalProperties": false,
37
+ "required": ["id", "path", "subtest", "reason"],
38
+ "properties": {
39
+ "id": { "type": "string" },
40
+ "path": { "type": "string" },
41
+ "subtest": { "type": "string" },
42
+ "reason": { "type": "string" }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }