ecss/docs/architecture.en.md

59 lines
4.9 KiB
Markdown

# ecss Architecture
[中文](architecture.zh.md)
## Position
`ecss` is the generic pure-computation layer that answers which rule wins and what each final property value is. It transforms consumer-provided property schemas, subjects, stylesheets, inline declarations, and a parent computed style into computed values, custom properties, active properties, specified properties, provenance, and diagnostics.
```text
consumer schemas + subject adapter + stylesheet + parent style
selector match → candidate collection → cascade winner
CSS-wide/custom-property resolution → normalize/validate
computed style + specified properties + provenance + diagnostics
```
`ecss` does not know how computed values are displayed. TP may convert final text-property contributions into retained surface patches. Ebox may interpret final Box/Flex/Grid properties as measurement, layout, and painting consequences. Ordinary callers may use `ecss` without either package.
## Package schemas and explicit surfaces
Each owning package creates one immutable `ecss-schema-package`. A concrete surface then atomically composes the required packages with `ecss-schema-set-compose`. Composition rejects duplicate packages and canonical/canonical, canonical/alias, and alias/alias collisions. There is no process-global mutable registry and no last-wins registration, so applications can compose different property vocabularies in one Emacs process without interference.
Aliases exist only at declaration normalization and disappear before cascade. An alias/canonical duplicate or a shorthand/owned-longhand conflict inside one declaration fails immediately. The schema set retains owner, impact, and projection facts, and a computed style references that set instead of building a second computed tree. Packages and schema sets expose no mutator; public queries return detached data.
Stylesheets remain explicitly owned mutable authoring objects. UA, user, and author origins inside one stylesheet keep independent layer orders. Rule addition is atomic, so failure cannot leave a half-added layer or an incorrect source order.
## Subjects and adapters
Simple callers use `ecss-subject` directly. Existing tree models use `ecss-subject-adapter-create` to provide type, id, classes, attributes, states, parent, and children callbacks without copying business nodes into ECSS nodes. Selector queries and stylesheets share one parser, matcher, and specificity implementation, so query matching cannot drift from rule matching.
## Cascade order
Candidates compare by CSS order: relevance and matching, origin plus importance, cascade layer, specificity, scope proximity, source order, and declaration order. Standard origin levels are UA normal, user normal, author normal, animation, author important, user important, UA important, and transition. Later normal layers win and unlayered normal declarations beat layered ones. Important layers reverse order. Inline author declarations retain the highest priority inside the author origin.
`revert` removes the entire current origin, across normal and important declarations, before choosing again. `revert-layer` removes the entire current layer inside that origin. An invalid-at-computed-value winner never recascades to a lower candidate; it uses the inherited or initial fallback and records the invalid winner in provenance.
## Value-source boundary
ECSS never calls an ordinary function stored in a property and defines no reactive or computed wrapper. A caller that needs evaluation explicitly passes `:value-resolver` to `ecss-compute-style`. The resolver receives value, property, and subject. ECSS invokes it once for each selected source and never executes its result a second time. Resolver errors propagate. Because computation is pure, ECSS has no buffer or runtime state to roll back.
## Custom properties
Custom properties use `--name` symbols. Their raw values first pass through ordinary cascade, inherit from the parent computed style by default, and then resolve through `ecss-var`. References may occur inside lists or vectors. Missing values and cycles can use fallback at the reference site. A cycle does not destroy the whole computed style: it creates a deterministic diagnostic and makes the affected value invalid at computed-value time.
## Three-package boundary
```text
ecss: selector / stylesheet / cascade / computed values
tp: text-property contributions / reactive runtime / diff / transaction / buffer commit
ebox: box semantics / measurement / flex-grid layout / painting / dirty ownership
```
Ebox may consume both `ecss` and TP. `ecss` and TP remain independently usable and do not depend on each other. The `ecss` public API contains no TP object, binding, or mount; no Ebox node; and no marker, patch, or buffer mutation.