@variance-authority/core 0.10.0 → 0.11.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/CHANGELOG.md
CHANGED
|
@@ -26,7 +26,7 @@ export type Observability = 'full' | 'structural-only' | 'declared-only' | 'none
|
|
|
26
26
|
* process.** A role, an accessible name, an ARIA state and a text node are facts
|
|
27
27
|
* about a document, so a dropped `aria-label` and a changed string are settled at
|
|
28
28
|
* the cheapest tier this project has — no browser, no screenshot, no baseline
|
|
29
|
-
* image. That is the concrete form of `docs/
|
|
29
|
+
* image. That is the concrete form of `docs/compare-visual-review.md` §3.3: the category no
|
|
30
30
|
* raster comparison can reach is also the category that costs least to reach.
|
|
31
31
|
*
|
|
32
32
|
* The return type is `Record<Band, …>` on purpose. Declaring a new band and
|
|
@@ -23,7 +23,7 @@ import { BANDS } from './band.js';
|
|
|
23
23
|
* process.** A role, an accessible name, an ARIA state and a text node are facts
|
|
24
24
|
* about a document, so a dropped `aria-label` and a changed string are settled at
|
|
25
25
|
* the cheapest tier this project has — no browser, no screenshot, no baseline
|
|
26
|
-
* image. That is the concrete form of `docs/
|
|
26
|
+
* image. That is the concrete form of `docs/compare-visual-review.md` §3.3: the category no
|
|
27
27
|
* raster comparison can reach is also the category that costs least to reach.
|
|
28
28
|
*
|
|
29
29
|
* The return type is `Record<Band, …>` on purpose. Declaring a new band and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observability.js","sourceRoot":"","sources":["../../src/compare/observability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,KAAK,EAAa,MAAM,WAAW,CAAC;AAK7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAAC,OAA2B;IACzD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QACxC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM;QACjF,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM;QACxF,0EAA0E;QAC1E,gDAAgD;QAChD,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;KAC1C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,IAAU,EAAE,KAAoB;IAC1D,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC;AACnE,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAA4C;IACpD,IAAI,EAAE,CAAC;IACP,iBAAiB,EAAE,CAAC;IACpB,eAAe,EAAE,CAAC;IAClB,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,MAAM,UAAU,MAAM,CAAC,CAAgB,EAAE,CAAgB;IACvD,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,mBAAmB,CACjC,CAAqB,EACrB,CAAqB;IAErB,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAEjC,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAC9B,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,MAA6C;IAC3E,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,MAA6C;IACzE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;AAC5F,CAAC","sourcesContent":["/**\n * What a profile can decide, band by band.\n *\n * This lives in `compare` rather than beside `ObservationProfile` in `format`\n * because it is a statement about *bands*, and a band classifies a delta. Core's\n * entrypoints run format → rules → compare → attribute → judge → plan, and a\n * `format` module importing `Band` would point that arrow backwards. The profile\n * describes a collector's capability; mapping that capability onto what can be\n * settled is the comparison layer's question.\n */\n\nimport type { ObservationProfile } from '../format/profile.js';\nimport { BANDS, type Band } from './band.js';\n\n/** How completely a profile can decide one band. */\nexport type Observability = 'full' | 'structural-only' | 'declared-only' | 'none';\n\n/**\n * Bands a profile is able to decide. A band this returns `none` for can never\n * resolve to `unchanged` under that profile — it resolves to `unobserved`.\n *\n * JSDOM sees structural geometry (nodes appearing, disappearing, reordering)\n * because that is tree shape, but not metric geometry (moves, resizes) because\n * that requires an engine. `geometry` is therefore only partially observable,\n * and partial observation of a blocking band is reported, never assumed away.\n *\n * The two bands that need no engine are worth stating rather than leaving to be\n * inferred: **`a11y` and `content` are fully decidable in the unit-test\n * process.** A role, an accessible name, an ARIA state and a text node are facts\n * about a document, so a dropped `aria-label` and a changed string are settled at\n * the cheapest tier this project has — no browser, no screenshot, no baseline\n * image. That is the concrete form of `docs/
|
|
1
|
+
{"version":3,"file":"observability.js","sourceRoot":"","sources":["../../src/compare/observability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,KAAK,EAAa,MAAM,WAAW,CAAC;AAK7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAAC,OAA2B;IACzD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QACxC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM;QACjF,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM;QACxF,0EAA0E;QAC1E,gDAAgD;QAChD,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;KAC1C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,IAAU,EAAE,KAAoB;IAC1D,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC;AACnE,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAA4C;IACpD,IAAI,EAAE,CAAC;IACP,iBAAiB,EAAE,CAAC;IACpB,eAAe,EAAE,CAAC;IAClB,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,MAAM,UAAU,MAAM,CAAC,CAAgB,EAAE,CAAgB;IACvD,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,mBAAmB,CACjC,CAAqB,EACrB,CAAqB;IAErB,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAEjC,OAAO,MAAM,CAAC,WAAW,CACvB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAC9B,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,MAA6C;IAC3E,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,MAA6C;IACzE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;AAC5F,CAAC","sourcesContent":["/**\n * What a profile can decide, band by band.\n *\n * This lives in `compare` rather than beside `ObservationProfile` in `format`\n * because it is a statement about *bands*, and a band classifies a delta. Core's\n * entrypoints run format → rules → compare → attribute → judge → plan, and a\n * `format` module importing `Band` would point that arrow backwards. The profile\n * describes a collector's capability; mapping that capability onto what can be\n * settled is the comparison layer's question.\n */\n\nimport type { ObservationProfile } from '../format/profile.js';\nimport { BANDS, type Band } from './band.js';\n\n/** How completely a profile can decide one band. */\nexport type Observability = 'full' | 'structural-only' | 'declared-only' | 'none';\n\n/**\n * Bands a profile is able to decide. A band this returns `none` for can never\n * resolve to `unchanged` under that profile — it resolves to `unobserved`.\n *\n * JSDOM sees structural geometry (nodes appearing, disappearing, reordering)\n * because that is tree shape, but not metric geometry (moves, resizes) because\n * that requires an engine. `geometry` is therefore only partially observable,\n * and partial observation of a blocking band is reported, never assumed away.\n *\n * The two bands that need no engine are worth stating rather than leaving to be\n * inferred: **`a11y` and `content` are fully decidable in the unit-test\n * process.** A role, an accessible name, an ARIA state and a text node are facts\n * about a document, so a dropped `aria-label` and a changed string are settled at\n * the cheapest tier this project has — no browser, no screenshot, no baseline\n * image. That is the concrete form of `docs/compare-visual-review.md` §3.3: the category no\n * raster comparison can reach is also the category that costs least to reach.\n *\n * The return type is `Record<Band, …>` on purpose. Declaring a new band and\n * forgetting to say whether a profile can observe it is a compile error, not a\n * silent `undefined` that a truthiness check reads as \"no\".\n */\nexport function observableBands(profile: ObservationProfile): Record<Band, Observability> {\n return {\n a11y: profile.ariaTree ? 'full' : 'none',\n geometry: profile.layout ? 'full' : profile.ariaTree ? 'structural-only' : 'none',\n token: profile.computedStyle ? 'full' : profile.declaredStyle ? 'declared-only' : 'none',\n // Text is the one band no collector can fail at: having a document is the\n // precondition for producing a snapshot at all.\n content: 'full',\n texture: profile.raster ? 'full' : 'none',\n };\n}\n\n/**\n * Whether a level is enough to settle its band, or whether the band must be\n * reported `unobserved`.\n *\n * The asymmetry between `geometry` and everything else is ADR-0002 and is\n * deliberate. `structural-only` geometry is *not* enough: a profile that sees\n * tree shape but not metrics would report a box that moved as `unchanged`, which\n * is the one failure this product must never produce. `declared-only` style *is*\n * enough — an author's declaration is a real answer about the token band, just a\n * narrower one than a resolved cascade.\n */\nexport function decidesBand(band: Band, level: Observability): boolean {\n return band === 'geometry' ? level === 'full' : level !== 'none';\n}\n\n/**\n * How completely a band was decided when two profiles both had to decide it.\n *\n * The weaker reading wins, which is the same union rule `unobserved` is built\n * from carried one value further. A pair is only as well observed as its blinder\n * side, and reporting the better side's level would describe a reading nobody\n * took.\n *\n * The two partial levels never meet: `structural-only` is a geometry answer and\n * `declared-only` a token one, and a band produces at most one of them. So the\n * ranking needs no tie-break between them, and a tie is two spellings of one\n * level.\n */\nconst RANK: Readonly<Record<Observability, number>> = {\n none: 0,\n 'structural-only': 1,\n 'declared-only': 1,\n full: 2,\n};\n\nexport function weaker(a: Observability, b: Observability): Observability {\n return RANK[a] <= RANK[b] ? a : b;\n}\n\n/** The weaker of two profiles' readings, band by band. */\nexport function sharedObservability(\n a: ObservationProfile,\n b: ObservationProfile,\n): Record<Band, Observability> {\n const here = observableBands(a);\n const there = observableBands(b);\n\n return Object.fromEntries(\n BANDS.map((band) => [band, weaker(here[band], there[band])]),\n ) as Record<Band, Observability>;\n}\n\n/**\n * Bands a comparison could not decide at all.\n *\n * Derived from {@link sharedObservability} rather than computed beside it: a band\n * is unobserved exactly when the weaker of the two levels does not decide it, and\n * two expressions of one rule are two things that can disagree.\n */\nexport function unobservedBands(levels: Readonly<Record<Band, Observability>>): readonly Band[] {\n return BANDS.filter((band) => !decidesBand(band, levels[band]));\n}\n\n/**\n * Bands that were decided, but on less than the evidence the band is made of.\n *\n * The half of observability that has no verdict to hide behind. `unobserved` is\n * loud — a band with no answer is reported as having none — while a band decided\n * `declared-only` returns `unchanged`, in the same word a resolved cascade\n * returns, over a narrower question: JSDOM compares what an author wrote, so\n * `padding: 1rem` stays `1rem` and a root font-size that moved underneath it is\n * not in the comparison. That is a real answer and the reason the level decides\n * its band at all — but it is not the answer the word `unchanged` promises, and\n * a reader given the word without the level cannot tell which one they have.\n */\nexport function narrowedBands(levels: Readonly<Record<Band, Observability>>): readonly Band[] {\n return BANDS.filter((band) => decidesBand(band, levels[band]) && levels[band] !== 'full');\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@variance-authority/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "The Variance Authority format, rules, comparison, attribution and verdicts. Pure data in, pure data out, no DOM and no I/O.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"variance-authority",
|