Complete ECSS cascade and selector contracts
This commit is contained in:
parent
0e6d76801a
commit
1275322d6c
@ -49,6 +49,7 @@ Do not pass both `:stylesheet` and `:rules`. `:rules` accepts the rule list retu
|
|||||||
- `(ecss-computed-style-custom-properties STYLE)` returns a deterministic custom-property plist.
|
- `(ecss-computed-style-custom-properties STYLE)` returns a deterministic custom-property plist.
|
||||||
- `(ecss-computed-style-active-properties STYLE)` returns property IDs supplied by valid declarations or active inheritance, preserving explicit nil versus absence. An invalid winner falling back to the initial value is not presented as an active declaration.
|
- `(ecss-computed-style-active-properties STYLE)` returns property IDs supplied by valid declarations or active inheritance, preserving explicit nil versus absence. An invalid winner falling back to the initial value is not presented as an active declaration.
|
||||||
- `(ecss-computed-style-specified-properties STYLE)` returns longhand property IDs that have cascade winners, independent of whether provenance was requested.
|
- `(ecss-computed-style-specified-properties STYLE)` returns longhand property IDs that have cascade winners, independent of whether provenance was requested.
|
||||||
|
- `(ecss-computed-style-copy-with-values STYLE VALUES &key active-properties specified-properties)` returns an immutable-style copy for a consumer that has already proved selector/cascade facts unchanged and only needs to replace computed values.
|
||||||
- `(ecss-computed-style-provenance STYLE)` returns winner, origin, importance, layer, specificity, scope/source/declaration order, validity, and fallback facts.
|
- `(ecss-computed-style-provenance STYLE)` returns winner, origin, importance, layer, specificity, scope/source/declaration order, validity, and fallback facts.
|
||||||
- `(ecss-computed-style-diagnostics STYLE)` returns deterministic diagnostics such as custom-property cycles.
|
- `(ecss-computed-style-diagnostics STYLE)` returns deterministic diagnostics such as custom-property cycles.
|
||||||
- `(ecss-computed-style-value STYLE PROPERTY &optional FALLBACK)` reads one value.
|
- `(ecss-computed-style-value STYLE PROPERTY &optional FALLBACK)` reads one value.
|
||||||
|
|||||||
@ -49,6 +49,7 @@ ORIGIN 是 `ua`、`user`、`author`、`animation` 或 `transition`。Inline decl
|
|||||||
- `(ecss-computed-style-custom-properties STYLE)` 返回 deterministic custom-property plist。
|
- `(ecss-computed-style-custom-properties STYLE)` 返回 deterministic custom-property plist。
|
||||||
- `(ecss-computed-style-active-properties STYLE)` 返回由有效 declaration 或 active inheritance 实际提供的 property ids,保留 explicit nil 与 absence 的区别;invalid winner 回退到 initial 时不伪装成 active declaration。
|
- `(ecss-computed-style-active-properties STYLE)` 返回由有效 declaration 或 active inheritance 实际提供的 property ids,保留 explicit nil 与 absence 的区别;invalid winner 回退到 initial 时不伪装成 active declaration。
|
||||||
- `(ecss-computed-style-specified-properties STYLE)` 返回存在 cascade winner 的长手 property ids,独立于是否请求 provenance。
|
- `(ecss-computed-style-specified-properties STYLE)` 返回存在 cascade winner 的长手 property ids,独立于是否请求 provenance。
|
||||||
|
- `(ecss-computed-style-copy-with-values STYLE VALUES &key active-properties specified-properties)` 在 selector/cascade 事实已证明不变、只需替换 computed values 时返回新的 immutable-style copy。
|
||||||
- `(ecss-computed-style-provenance STYLE)` 返回 winner、origin、important、layer、specificity、scope/source/declaration order、valid/fallback 等事实。
|
- `(ecss-computed-style-provenance STYLE)` 返回 winner、origin、important、layer、specificity、scope/source/declaration order、valid/fallback 等事实。
|
||||||
- `(ecss-computed-style-diagnostics STYLE)` 返回 custom-property cycle 等 deterministic diagnostics。
|
- `(ecss-computed-style-diagnostics STYLE)` 返回 custom-property cycle 等 deterministic diagnostics。
|
||||||
- `(ecss-computed-style-value STYLE PROPERTY &optional FALLBACK)` 读取单值。
|
- `(ecss-computed-style-value STYLE PROPERTY &optional FALLBACK)` 读取单值。
|
||||||
|
|||||||
@ -801,7 +801,7 @@ STACK detects cycles and DIAGNOSTICS records them."
|
|||||||
|
|
||||||
(defun ecss--resolve-property-value
|
(defun ecss--resolve-property-value
|
||||||
(value schema parent-style custom-tables diagnostics)
|
(value schema parent-style custom-tables diagnostics)
|
||||||
"Resolve VALUE for SCHEMA using PARENT-STYLE, CUSTOM, and DIAGNOSTICS."
|
"Resolve VALUE for SCHEMA using PARENT-STYLE, CUSTOM-TABLES, and DIAGNOSTICS."
|
||||||
(cond ((and (ecss--wide-p value)
|
(cond ((and (ecss--wide-p value)
|
||||||
(memq (ecss--wide-kind value) '(initial inherit unset)))
|
(memq (ecss--wide-kind value) '(initial inherit unset)))
|
||||||
(ecss--wide-default value schema parent-style))
|
(ecss--wide-default value schema parent-style))
|
||||||
@ -826,10 +826,10 @@ STACK detects cycles and DIAGNOSTICS records them."
|
|||||||
(defun ecss--compute-candidate-value
|
(defun ecss--compute-candidate-value
|
||||||
(candidate schema source parent-style custom-tables diagnostics)
|
(candidate schema source parent-style custom-tables diagnostics)
|
||||||
"Resolve CANDIDATE for SCHEMA and computation context.
|
"Resolve CANDIDATE for SCHEMA and computation context.
|
||||||
SOURCE is the already resolved candidate value. PARENT-STYLE and CUSTOM
|
SOURCE is the already resolved candidate value. PARENT-STYLE and CUSTOM-TABLES
|
||||||
supply inherited values, and DIAGNOSTICS records variable failures."
|
supply inherited values, and DIAGNOSTICS records variable failures."
|
||||||
(let* ((property (ecss-property-schema-id schema))
|
(ignore candidate)
|
||||||
(resolved (ecss--resolve-property-value
|
(let* ((resolved (ecss--resolve-property-value
|
||||||
source schema parent-style custom-tables diagnostics)))
|
source schema parent-style custom-tables diagnostics)))
|
||||||
(cons (if (eq (cdr resolved) 'declaration)
|
(cons (if (eq (cdr resolved) 'declaration)
|
||||||
(ecss--normalize-property-value schema (car resolved))
|
(ecss--normalize-property-value schema (car resolved))
|
||||||
@ -845,8 +845,8 @@ supply inherited values, and DIAGNOSTICS records variable failures."
|
|||||||
(defun ecss--resolve-property-candidates
|
(defun ecss--resolve-property-candidates
|
||||||
(schema candidates parent-style custom-tables subject resolver diagnostics)
|
(schema candidates parent-style custom-tables subject resolver diagnostics)
|
||||||
"Resolve SCHEMA from ordered CANDIDATES.
|
"Resolve SCHEMA from ordered CANDIDATES.
|
||||||
PARENT-STYLE and CUSTOM supply inherited values. SUBJECT and RESOLVER handle
|
PARENT-STYLE and CUSTOM-TABLES supply inherited values. SUBJECT and RESOLVER
|
||||||
explicit sources, and DIAGNOSTICS records variable failures."
|
handle explicit sources, and DIAGNOSTICS records variable failures."
|
||||||
(let ((remaining candidates) winner resolved)
|
(let ((remaining candidates) winner resolved)
|
||||||
(while (and remaining (null winner))
|
(while (and remaining (null winner))
|
||||||
(let* ((candidate (pop remaining))
|
(let* ((candidate (pop remaining))
|
||||||
@ -885,8 +885,9 @@ explicit sources, and DIAGNOSTICS records variable failures."
|
|||||||
(schemas table parent-style custom-tables subject resolver diagnostics
|
(schemas table parent-style custom-tables subject resolver diagnostics
|
||||||
provenance-p)
|
provenance-p)
|
||||||
"Compute SCHEMAS property values from TABLE and context.
|
"Compute SCHEMAS property values from TABLE and context.
|
||||||
PARENT-STYLE and CUSTOM-TABLES supply inherited values. SUBJECT and RESOLVER handle
|
PARENT-STYLE and CUSTOM-TABLES supply inherited values. SUBJECT and RESOLVER
|
||||||
explicit sources. DIAGNOSTICS records failures; PROVENANCE-P retains facts."
|
handle explicit sources. DIAGNOSTICS records failures; PROVENANCE-P retains
|
||||||
|
facts."
|
||||||
(let (values active specified provenance)
|
(let (values active specified provenance)
|
||||||
(dolist (property (ecss--schema-set-order schemas))
|
(dolist (property (ecss--schema-set-order schemas))
|
||||||
(let ((schema (ecss--schema-for schemas property)))
|
(let ((schema (ecss--schema-for schemas property)))
|
||||||
@ -980,6 +981,29 @@ non-nil, is the only function allowed to evaluate caller-owned value sources;
|
|||||||
(append (cadr raw-facts) property-facts))
|
(append (cadr raw-facts) property-facts))
|
||||||
:diagnostics (nreverse (car diagnostics))))))))
|
:diagnostics (nreverse (car diagnostics))))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(cl-defun ecss-computed-style-copy-with-values
|
||||||
|
(style values &key active-properties specified-properties)
|
||||||
|
"Return STYLE copied with replacement VALUES and optional metadata.
|
||||||
|
|
||||||
|
This is a narrow immutable-style transformation for consumers that have
|
||||||
|
already proved selector/cascade facts unchanged and only need to propagate a
|
||||||
|
safe computed-value delta. Omitted ACTIVE-PROPERTIES and
|
||||||
|
SPECIFIED-PROPERTIES retain STYLE's metadata; all mutable values are copied at
|
||||||
|
the public boundary."
|
||||||
|
(unless (ecss-computed-style-p style)
|
||||||
|
(signal 'wrong-type-argument (list 'ecss-computed-style-p style)))
|
||||||
|
(let ((copy (copy-ecss-computed-style style)))
|
||||||
|
(setf (ecss--computed-style-values copy)
|
||||||
|
(ecss--copy-boundary-data values))
|
||||||
|
(when active-properties
|
||||||
|
(setf (ecss--computed-style-active-properties copy)
|
||||||
|
(ecss--copy-boundary-data active-properties)))
|
||||||
|
(when specified-properties
|
||||||
|
(setf (ecss--computed-style-specified-properties copy)
|
||||||
|
(ecss--copy-boundary-data specified-properties)))
|
||||||
|
copy))
|
||||||
|
|
||||||
(defun ecss--computed-style-check (style)
|
(defun ecss--computed-style-check (style)
|
||||||
"Return STYLE or signal when it is not a computed style."
|
"Return STYLE or signal when it is not a computed style."
|
||||||
(unless (ecss-computed-style-p style)
|
(unless (ecss-computed-style-p style)
|
||||||
|
|||||||
@ -38,6 +38,27 @@
|
|||||||
"Return PROPERTY from computed STYLE."
|
"Return PROPERTY from computed STYLE."
|
||||||
(ecss-computed-style-value style property :absent))
|
(ecss-computed-style-value style property :absent))
|
||||||
|
|
||||||
|
(ert-deftest ecss-cascade-test-computed-style-copy-with-values-is-defensive ()
|
||||||
|
"Copy computed STYLE while replacing values and preserving metadata."
|
||||||
|
(let* ((schemas (ecss-cascade-test--schemas))
|
||||||
|
(subject (ecss-cascade-test--subject))
|
||||||
|
(style (ecss-compute-style schemas subject
|
||||||
|
:declarations '(app/color "red")))
|
||||||
|
(copy (ecss-computed-style-copy-with-values
|
||||||
|
style '(app/color "blue")
|
||||||
|
:active-properties '(app/color)
|
||||||
|
:specified-properties '(app/color)))
|
||||||
|
(values (ecss-computed-style-values copy)))
|
||||||
|
(should-not (eq style copy))
|
||||||
|
(should (equal "blue" (plist-get values 'app/color)))
|
||||||
|
(should (equal '(app/color)
|
||||||
|
(ecss-computed-style-active-properties copy)))
|
||||||
|
(should (equal '(app/color)
|
||||||
|
(ecss-computed-style-specified-properties copy)))
|
||||||
|
(setf (plist-get values 'app/color) "mutated")
|
||||||
|
(should (equal "blue"
|
||||||
|
(ecss-computed-style-value copy 'app/color)))))
|
||||||
|
|
||||||
(ert-deftest ecss-cascade-test-schema-registration-is-atomic ()
|
(ert-deftest ecss-cascade-test-schema-registration-is-atomic ()
|
||||||
(let ((schemas (ecss-schema-set-create)))
|
(let ((schemas (ecss-schema-set-create)))
|
||||||
(ecss-schema-set-define schemas 'app/width :initial 4 :validator #'integerp)
|
(ecss-schema-set-define schemas 'app/width :initial 4 :validator #'integerp)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user