@webability/core 1.17.1 → 1.18.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/dist/dom.cjs +31 -31
- package/dist/dom.js +31 -31
- package/dist/engine.cjs +32 -32
- package/dist/engine.d.cts +98 -84
- package/dist/engine.d.ts +98 -84
- package/dist/engine.js +32 -32
- package/dist/index.cjs +39 -39
- package/dist/index.js +39 -39
- package/dist/playwright.cjs +31 -31
- package/dist/playwright.js +31 -31
- package/package.json +1 -1
package/dist/engine.d.cts
CHANGED
|
@@ -37,6 +37,96 @@ declare function htmlRequestPolicy(target: string, opts?: {
|
|
|
37
37
|
scripts?: boolean;
|
|
38
38
|
}): HtmlRequestPolicy;
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Fix Manifest Validator — Three-Layer Safety Architecture
|
|
42
|
+
*
|
|
43
|
+
* Every fix passes through three layers before reaching the DB:
|
|
44
|
+
*
|
|
45
|
+
* Layer 1: Structural validation (selector, attribute, value safety)
|
|
46
|
+
* Layer 2: Protected element check (don't touch third-party/admin/consent UI)
|
|
47
|
+
* Layer 3: Risk classification (additive vs modifier vs destructive)
|
|
48
|
+
*
|
|
49
|
+
* Layer 3 output feeds into the repository's status logic:
|
|
50
|
+
* - additive → normal confidence gate (>= 0.85 → approved)
|
|
51
|
+
* - modifier → always 'pending' (human review required)
|
|
52
|
+
* - destructive → rejected (unless source is 'manual')
|
|
53
|
+
*/
|
|
54
|
+
interface ValidationResult {
|
|
55
|
+
ok: boolean;
|
|
56
|
+
reason?: string;
|
|
57
|
+
}
|
|
58
|
+
type FixRiskTier = 'additive' | 'modifier' | 'destructive';
|
|
59
|
+
interface FixClassification {
|
|
60
|
+
tier: FixRiskTier;
|
|
61
|
+
reason: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validate a `role` attribute value.
|
|
65
|
+
* - case-sensitive: must be lowercase (rejects "Main", "Breadcrumb", "Navigation")
|
|
66
|
+
* - every space-separated token must be a real concrete ARIA role
|
|
67
|
+
* - empty / whitespace-only is invalid
|
|
68
|
+
*/
|
|
69
|
+
declare function validateRoleValue(value: string): ValidationResult;
|
|
70
|
+
/**
|
|
71
|
+
* The one fix the `<html>` root takes: `lang` (WCAG 3.1.1 — the document
|
|
72
|
+
* language lives on `<html>` and nowhere else). afe1654ed rejected every bare
|
|
73
|
+
* `html` selector as structural hardening (its case: `html { style:
|
|
74
|
+
* filter:invert(1) }` repaints every page); `lang` writes no style, no markup
|
|
75
|
+
* and no behaviour, so it is the single exception. Every other attribute on
|
|
76
|
+
* `html` stays rejected. Exact attribute name, no case folding.
|
|
77
|
+
*/
|
|
78
|
+
declare function isHtmlLangFix(selector: string | null | undefined, attribute: string | null | undefined): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Selector check for a fix whose attribute is known. `html` + `lang` passes
|
|
81
|
+
* (the root is one element, never protected UI); everything else takes
|
|
82
|
+
* validateSelector, where a bare `html` is still rejected.
|
|
83
|
+
*/
|
|
84
|
+
declare function validateSelectorForAttribute(selector: string, attribute: string, protectedScope?: ProtectedScope): ValidationResult;
|
|
85
|
+
/**
|
|
86
|
+
* Would the browser's querySelectorAll parse this selector? (LEDGER row 78 —
|
|
87
|
+
* served selectors that throw are swallowed per fix by the widget and stay
|
|
88
|
+
* approved forever.) Two layers: the character/escape rules below refuse an
|
|
89
|
+
* unescaped `/`, `%`, `!` or a Tailwind `:variant` exactly as the browser
|
|
90
|
+
* does; then a real tokeniser (css-what) refuses unbalanced brackets, an
|
|
91
|
+
* unterminated string, an empty `:not()`, a dangling `#`, and `astParses`
|
|
92
|
+
* refuses what css-what tolerates but the browser does not (`#hero >`,
|
|
93
|
+
* `a||b`, `li:nth-child(2n+)`, `button::part()`).
|
|
94
|
+
*/
|
|
95
|
+
declare function selectorParses(selector: string): boolean;
|
|
96
|
+
/** Which protected-element registry a writer consults. The scan path runs the
|
|
97
|
+
* full registry against a DOM it rendered; the ingest path keeps the narrower
|
|
98
|
+
* admin/overlay check because the full registry's SUBSTRING vendor patterns
|
|
99
|
+
* (crisp-, hubspot-) false-match attribute VALUES in live approved fixes
|
|
100
|
+
* (img[src=".../apple-cranberry-crisp-…jpg"], body.hubspot-disable-focus-styles). */
|
|
101
|
+
type ProtectedScope = 'full' | 'dead-region';
|
|
102
|
+
declare function validateSelector(selector: string, protectedScope?: ProtectedScope): ValidationResult;
|
|
103
|
+
declare function validateAttribute(attr: string): ValidationResult;
|
|
104
|
+
/**
|
|
105
|
+
* Hint codes from simple checks on an aria-label or alt value. A hint is a reason for an agent to look closer, never
|
|
106
|
+
* a verdict: the agent reads the element and decides (a hint alone never rejects, its absence never approves).
|
|
107
|
+
* validateTextValue never rejects a label for a hint: only injection, the size cap and the HTML spec checks block.
|
|
108
|
+
*/
|
|
109
|
+
type LabelSignal = 'markup' | 'url_like' | 'mailto' | 'tel_uri' | 'long_label' | 'no_letters' | 'filename' | 'field_index' | 'generic_field' | 'dimension_suffix' | 'query_or_hash' | 'ip_like' | 'no_destination' | 'vague_word';
|
|
110
|
+
declare function labelSignals(value: string, attribute?: string): LabelSignal[];
|
|
111
|
+
declare function validateTextValue(value: string, attribute?: string): ValidationResult;
|
|
112
|
+
/**
|
|
113
|
+
* Classify a fix into a risk tier:
|
|
114
|
+
* - additive: adds information that wasn't there (aria-label, alt, role, scope, etc.)
|
|
115
|
+
* - modifier: changes visibility/interactivity (aria-hidden, tabindex, style)
|
|
116
|
+
* - destructive: removes or empties functional attributes
|
|
117
|
+
*/
|
|
118
|
+
declare function classifyFixRisk(fix: {
|
|
119
|
+
attribute: string;
|
|
120
|
+
value: string;
|
|
121
|
+
}): FixClassification;
|
|
122
|
+
declare function validateFix(fix: {
|
|
123
|
+
selector: string;
|
|
124
|
+
attribute: string;
|
|
125
|
+
value: string;
|
|
126
|
+
issueType?: string | null;
|
|
127
|
+
context?: string | null;
|
|
128
|
+
}, protectedScope?: ProtectedScope): ValidationResult;
|
|
129
|
+
|
|
40
130
|
/**
|
|
41
131
|
* The one engine's contract: two injected drivers in, one result out.
|
|
42
132
|
*
|
|
@@ -278,6 +368,13 @@ interface EngineFix {
|
|
|
278
368
|
/** What the fix rests on: the finding's message and the element markup. */
|
|
279
369
|
evidence: string;
|
|
280
370
|
engineVersion: string;
|
|
371
|
+
/**
|
|
372
|
+
* Label hint codes for the caller's judge (see `labelSignals`): the value of
|
|
373
|
+
* an aria-label or alt write that looks off (a vague word, a URL, a very long
|
|
374
|
+
* label...). A hint is not a verdict. A fix with signals should not auto-apply
|
|
375
|
+
* without a judge reading the element. Absent when there are none.
|
|
376
|
+
*/
|
|
377
|
+
signals?: LabelSignal[];
|
|
281
378
|
/**
|
|
282
379
|
* Post-fix verification: 'verified' (applied on the page, axe found no new
|
|
283
380
|
* violation on it, its ancestors or descendants); 'not_verifiable' (a
|
|
@@ -578,89 +675,6 @@ declare function fromPuppeteer(p: PuppeteerPageLike, opts?: {
|
|
|
578
675
|
interceptDocument?: boolean;
|
|
579
676
|
}): Page;
|
|
580
677
|
|
|
581
|
-
/**
|
|
582
|
-
* Fix Manifest Validator — Three-Layer Safety Architecture
|
|
583
|
-
*
|
|
584
|
-
* Every fix passes through three layers before reaching the DB:
|
|
585
|
-
*
|
|
586
|
-
* Layer 1: Structural validation (selector, attribute, value safety)
|
|
587
|
-
* Layer 2: Protected element check (don't touch third-party/admin/consent UI)
|
|
588
|
-
* Layer 3: Risk classification (additive vs modifier vs destructive)
|
|
589
|
-
*
|
|
590
|
-
* Layer 3 output feeds into the repository's status logic:
|
|
591
|
-
* - additive → normal confidence gate (>= 0.85 → approved)
|
|
592
|
-
* - modifier → always 'pending' (human review required)
|
|
593
|
-
* - destructive → rejected (unless source is 'manual')
|
|
594
|
-
*/
|
|
595
|
-
interface ValidationResult {
|
|
596
|
-
ok: boolean;
|
|
597
|
-
reason?: string;
|
|
598
|
-
}
|
|
599
|
-
type FixRiskTier = 'additive' | 'modifier' | 'destructive';
|
|
600
|
-
interface FixClassification {
|
|
601
|
-
tier: FixRiskTier;
|
|
602
|
-
reason: string;
|
|
603
|
-
}
|
|
604
|
-
/**
|
|
605
|
-
* Validate a `role` attribute value.
|
|
606
|
-
* - case-sensitive: must be lowercase (rejects "Main", "Breadcrumb", "Navigation")
|
|
607
|
-
* - every space-separated token must be a real concrete ARIA role
|
|
608
|
-
* - empty / whitespace-only is invalid
|
|
609
|
-
*/
|
|
610
|
-
declare function validateRoleValue(value: string): ValidationResult;
|
|
611
|
-
/**
|
|
612
|
-
* The one fix the `<html>` root takes: `lang` (WCAG 3.1.1 — the document
|
|
613
|
-
* language lives on `<html>` and nowhere else). afe1654ed rejected every bare
|
|
614
|
-
* `html` selector as structural hardening (its case: `html { style:
|
|
615
|
-
* filter:invert(1) }` repaints every page); `lang` writes no style, no markup
|
|
616
|
-
* and no behaviour, so it is the single exception. Every other attribute on
|
|
617
|
-
* `html` stays rejected. Exact attribute name, no case folding.
|
|
618
|
-
*/
|
|
619
|
-
declare function isHtmlLangFix(selector: string | null | undefined, attribute: string | null | undefined): boolean;
|
|
620
|
-
/**
|
|
621
|
-
* Selector check for a fix whose attribute is known. `html` + `lang` passes
|
|
622
|
-
* (the root is one element, never protected UI); everything else takes
|
|
623
|
-
* validateSelector, where a bare `html` is still rejected.
|
|
624
|
-
*/
|
|
625
|
-
declare function validateSelectorForAttribute(selector: string, attribute: string, protectedScope?: ProtectedScope): ValidationResult;
|
|
626
|
-
/**
|
|
627
|
-
* Would the browser's querySelectorAll parse this selector? (LEDGER row 78 —
|
|
628
|
-
* served selectors that throw are swallowed per fix by the widget and stay
|
|
629
|
-
* approved forever.) Two layers: the character/escape rules below refuse an
|
|
630
|
-
* unescaped `/`, `%`, `!` or a Tailwind `:variant` exactly as the browser
|
|
631
|
-
* does; then a real tokeniser (css-what) refuses unbalanced brackets, an
|
|
632
|
-
* unterminated string, an empty `:not()`, a dangling `#`, and `astParses`
|
|
633
|
-
* refuses what css-what tolerates but the browser does not (`#hero >`,
|
|
634
|
-
* `a||b`, `li:nth-child(2n+)`, `button::part()`).
|
|
635
|
-
*/
|
|
636
|
-
declare function selectorParses(selector: string): boolean;
|
|
637
|
-
/** Which protected-element registry a writer consults. The scan path runs the
|
|
638
|
-
* full registry against a DOM it rendered; the ingest path keeps the narrower
|
|
639
|
-
* admin/overlay check because the full registry's SUBSTRING vendor patterns
|
|
640
|
-
* (crisp-, hubspot-) false-match attribute VALUES in live approved fixes
|
|
641
|
-
* (img[src=".../apple-cranberry-crisp-…jpg"], body.hubspot-disable-focus-styles). */
|
|
642
|
-
type ProtectedScope = 'full' | 'dead-region';
|
|
643
|
-
declare function validateSelector(selector: string, protectedScope?: ProtectedScope): ValidationResult;
|
|
644
|
-
declare function validateAttribute(attr: string): ValidationResult;
|
|
645
|
-
declare function validateTextValue(value: string, attribute?: string): ValidationResult;
|
|
646
|
-
/**
|
|
647
|
-
* Classify a fix into a risk tier:
|
|
648
|
-
* - additive: adds information that wasn't there (aria-label, alt, role, scope, etc.)
|
|
649
|
-
* - modifier: changes visibility/interactivity (aria-hidden, tabindex, style)
|
|
650
|
-
* - destructive: removes or empties functional attributes
|
|
651
|
-
*/
|
|
652
|
-
declare function classifyFixRisk(fix: {
|
|
653
|
-
attribute: string;
|
|
654
|
-
value: string;
|
|
655
|
-
}): FixClassification;
|
|
656
|
-
declare function validateFix(fix: {
|
|
657
|
-
selector: string;
|
|
658
|
-
attribute: string;
|
|
659
|
-
value: string;
|
|
660
|
-
issueType?: string | null;
|
|
661
|
-
context?: string | null;
|
|
662
|
-
}, protectedScope?: ProtectedScope): ValidationResult;
|
|
663
|
-
|
|
664
678
|
/**
|
|
665
679
|
* Hiding-hazard guard
|
|
666
680
|
* ───────────────────
|
|
@@ -959,4 +973,4 @@ declare function listHiddenCandidates(page: PageLike, opts?: {
|
|
|
959
973
|
max?: number;
|
|
960
974
|
}): Promise<HiddenCandidateList>;
|
|
961
975
|
|
|
962
|
-
export { BARE_TAGS, type BackdropKind, DEFAULT_MAX_CANDIDATES, type EngineFinding, type EngineFix, type EngineInput, type EngineIssue, type EngineOptions, type EngineResult, type EngineStats, FORM_CONTROL_ROLES, type HazardElementView, type HiddenCandidate, type HiddenCandidateList, type HiddenCause, type HiddenKind, type HiddenText, type HtmlDecision, type HtmlRequest, type HtmlRequestPolicy, InternalBug, type JudgedFix, LABEL_IN_NAME_JS, type Model, type ModelRequest, type ModelResponse, type NearbyInteractive, type Page, type PlaywrightPageLike, type ProtectedScope, type PuppeteerPageLike, SERVED_FIX_KEYS, TOKEN_QUERY_KEY, classifyFixRisk, detectPageLanguage, dropHazardousHidingFixes, foldContains, foldLabel, fromPlaywright, fromPuppeteer, htmlRequestPolicy, isHidingFix, isHtmlLangFix, isInteractiveOrContainsFocusable, isLabelText, labelContainsText, labelInNameCheck, languageFromText, languageFromUrl, listHiddenCandidates, loadSnapshot, normalizeVisibleText, parseContext, primaryLanguage, runEngine, scoreSelectorQuality, selectorParses, toPageLike, validateAttribute, validateFix, validateRoleValue, validateSelector, validateSelectorForAttribute, validateTextValue };
|
|
976
|
+
export { BARE_TAGS, type BackdropKind, DEFAULT_MAX_CANDIDATES, type EngineFinding, type EngineFix, type EngineInput, type EngineIssue, type EngineOptions, type EngineResult, type EngineStats, FORM_CONTROL_ROLES, type HazardElementView, type HiddenCandidate, type HiddenCandidateList, type HiddenCause, type HiddenKind, type HiddenText, type HtmlDecision, type HtmlRequest, type HtmlRequestPolicy, InternalBug, type JudgedFix, LABEL_IN_NAME_JS, type LabelSignal, type Model, type ModelRequest, type ModelResponse, type NearbyInteractive, type Page, type PlaywrightPageLike, type ProtectedScope, type PuppeteerPageLike, SERVED_FIX_KEYS, TOKEN_QUERY_KEY, classifyFixRisk, detectPageLanguage, dropHazardousHidingFixes, foldContains, foldLabel, fromPlaywright, fromPuppeteer, htmlRequestPolicy, isHidingFix, isHtmlLangFix, isInteractiveOrContainsFocusable, isLabelText, labelContainsText, labelInNameCheck, labelSignals, languageFromText, languageFromUrl, listHiddenCandidates, loadSnapshot, normalizeVisibleText, parseContext, primaryLanguage, runEngine, scoreSelectorQuality, selectorParses, toPageLike, validateAttribute, validateFix, validateRoleValue, validateSelector, validateSelectorForAttribute, validateTextValue };
|
package/dist/engine.d.ts
CHANGED
|
@@ -37,6 +37,96 @@ declare function htmlRequestPolicy(target: string, opts?: {
|
|
|
37
37
|
scripts?: boolean;
|
|
38
38
|
}): HtmlRequestPolicy;
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Fix Manifest Validator — Three-Layer Safety Architecture
|
|
42
|
+
*
|
|
43
|
+
* Every fix passes through three layers before reaching the DB:
|
|
44
|
+
*
|
|
45
|
+
* Layer 1: Structural validation (selector, attribute, value safety)
|
|
46
|
+
* Layer 2: Protected element check (don't touch third-party/admin/consent UI)
|
|
47
|
+
* Layer 3: Risk classification (additive vs modifier vs destructive)
|
|
48
|
+
*
|
|
49
|
+
* Layer 3 output feeds into the repository's status logic:
|
|
50
|
+
* - additive → normal confidence gate (>= 0.85 → approved)
|
|
51
|
+
* - modifier → always 'pending' (human review required)
|
|
52
|
+
* - destructive → rejected (unless source is 'manual')
|
|
53
|
+
*/
|
|
54
|
+
interface ValidationResult {
|
|
55
|
+
ok: boolean;
|
|
56
|
+
reason?: string;
|
|
57
|
+
}
|
|
58
|
+
type FixRiskTier = 'additive' | 'modifier' | 'destructive';
|
|
59
|
+
interface FixClassification {
|
|
60
|
+
tier: FixRiskTier;
|
|
61
|
+
reason: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validate a `role` attribute value.
|
|
65
|
+
* - case-sensitive: must be lowercase (rejects "Main", "Breadcrumb", "Navigation")
|
|
66
|
+
* - every space-separated token must be a real concrete ARIA role
|
|
67
|
+
* - empty / whitespace-only is invalid
|
|
68
|
+
*/
|
|
69
|
+
declare function validateRoleValue(value: string): ValidationResult;
|
|
70
|
+
/**
|
|
71
|
+
* The one fix the `<html>` root takes: `lang` (WCAG 3.1.1 — the document
|
|
72
|
+
* language lives on `<html>` and nowhere else). afe1654ed rejected every bare
|
|
73
|
+
* `html` selector as structural hardening (its case: `html { style:
|
|
74
|
+
* filter:invert(1) }` repaints every page); `lang` writes no style, no markup
|
|
75
|
+
* and no behaviour, so it is the single exception. Every other attribute on
|
|
76
|
+
* `html` stays rejected. Exact attribute name, no case folding.
|
|
77
|
+
*/
|
|
78
|
+
declare function isHtmlLangFix(selector: string | null | undefined, attribute: string | null | undefined): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Selector check for a fix whose attribute is known. `html` + `lang` passes
|
|
81
|
+
* (the root is one element, never protected UI); everything else takes
|
|
82
|
+
* validateSelector, where a bare `html` is still rejected.
|
|
83
|
+
*/
|
|
84
|
+
declare function validateSelectorForAttribute(selector: string, attribute: string, protectedScope?: ProtectedScope): ValidationResult;
|
|
85
|
+
/**
|
|
86
|
+
* Would the browser's querySelectorAll parse this selector? (LEDGER row 78 —
|
|
87
|
+
* served selectors that throw are swallowed per fix by the widget and stay
|
|
88
|
+
* approved forever.) Two layers: the character/escape rules below refuse an
|
|
89
|
+
* unescaped `/`, `%`, `!` or a Tailwind `:variant` exactly as the browser
|
|
90
|
+
* does; then a real tokeniser (css-what) refuses unbalanced brackets, an
|
|
91
|
+
* unterminated string, an empty `:not()`, a dangling `#`, and `astParses`
|
|
92
|
+
* refuses what css-what tolerates but the browser does not (`#hero >`,
|
|
93
|
+
* `a||b`, `li:nth-child(2n+)`, `button::part()`).
|
|
94
|
+
*/
|
|
95
|
+
declare function selectorParses(selector: string): boolean;
|
|
96
|
+
/** Which protected-element registry a writer consults. The scan path runs the
|
|
97
|
+
* full registry against a DOM it rendered; the ingest path keeps the narrower
|
|
98
|
+
* admin/overlay check because the full registry's SUBSTRING vendor patterns
|
|
99
|
+
* (crisp-, hubspot-) false-match attribute VALUES in live approved fixes
|
|
100
|
+
* (img[src=".../apple-cranberry-crisp-…jpg"], body.hubspot-disable-focus-styles). */
|
|
101
|
+
type ProtectedScope = 'full' | 'dead-region';
|
|
102
|
+
declare function validateSelector(selector: string, protectedScope?: ProtectedScope): ValidationResult;
|
|
103
|
+
declare function validateAttribute(attr: string): ValidationResult;
|
|
104
|
+
/**
|
|
105
|
+
* Hint codes from simple checks on an aria-label or alt value. A hint is a reason for an agent to look closer, never
|
|
106
|
+
* a verdict: the agent reads the element and decides (a hint alone never rejects, its absence never approves).
|
|
107
|
+
* validateTextValue never rejects a label for a hint: only injection, the size cap and the HTML spec checks block.
|
|
108
|
+
*/
|
|
109
|
+
type LabelSignal = 'markup' | 'url_like' | 'mailto' | 'tel_uri' | 'long_label' | 'no_letters' | 'filename' | 'field_index' | 'generic_field' | 'dimension_suffix' | 'query_or_hash' | 'ip_like' | 'no_destination' | 'vague_word';
|
|
110
|
+
declare function labelSignals(value: string, attribute?: string): LabelSignal[];
|
|
111
|
+
declare function validateTextValue(value: string, attribute?: string): ValidationResult;
|
|
112
|
+
/**
|
|
113
|
+
* Classify a fix into a risk tier:
|
|
114
|
+
* - additive: adds information that wasn't there (aria-label, alt, role, scope, etc.)
|
|
115
|
+
* - modifier: changes visibility/interactivity (aria-hidden, tabindex, style)
|
|
116
|
+
* - destructive: removes or empties functional attributes
|
|
117
|
+
*/
|
|
118
|
+
declare function classifyFixRisk(fix: {
|
|
119
|
+
attribute: string;
|
|
120
|
+
value: string;
|
|
121
|
+
}): FixClassification;
|
|
122
|
+
declare function validateFix(fix: {
|
|
123
|
+
selector: string;
|
|
124
|
+
attribute: string;
|
|
125
|
+
value: string;
|
|
126
|
+
issueType?: string | null;
|
|
127
|
+
context?: string | null;
|
|
128
|
+
}, protectedScope?: ProtectedScope): ValidationResult;
|
|
129
|
+
|
|
40
130
|
/**
|
|
41
131
|
* The one engine's contract: two injected drivers in, one result out.
|
|
42
132
|
*
|
|
@@ -278,6 +368,13 @@ interface EngineFix {
|
|
|
278
368
|
/** What the fix rests on: the finding's message and the element markup. */
|
|
279
369
|
evidence: string;
|
|
280
370
|
engineVersion: string;
|
|
371
|
+
/**
|
|
372
|
+
* Label hint codes for the caller's judge (see `labelSignals`): the value of
|
|
373
|
+
* an aria-label or alt write that looks off (a vague word, a URL, a very long
|
|
374
|
+
* label...). A hint is not a verdict. A fix with signals should not auto-apply
|
|
375
|
+
* without a judge reading the element. Absent when there are none.
|
|
376
|
+
*/
|
|
377
|
+
signals?: LabelSignal[];
|
|
281
378
|
/**
|
|
282
379
|
* Post-fix verification: 'verified' (applied on the page, axe found no new
|
|
283
380
|
* violation on it, its ancestors or descendants); 'not_verifiable' (a
|
|
@@ -578,89 +675,6 @@ declare function fromPuppeteer(p: PuppeteerPageLike, opts?: {
|
|
|
578
675
|
interceptDocument?: boolean;
|
|
579
676
|
}): Page;
|
|
580
677
|
|
|
581
|
-
/**
|
|
582
|
-
* Fix Manifest Validator — Three-Layer Safety Architecture
|
|
583
|
-
*
|
|
584
|
-
* Every fix passes through three layers before reaching the DB:
|
|
585
|
-
*
|
|
586
|
-
* Layer 1: Structural validation (selector, attribute, value safety)
|
|
587
|
-
* Layer 2: Protected element check (don't touch third-party/admin/consent UI)
|
|
588
|
-
* Layer 3: Risk classification (additive vs modifier vs destructive)
|
|
589
|
-
*
|
|
590
|
-
* Layer 3 output feeds into the repository's status logic:
|
|
591
|
-
* - additive → normal confidence gate (>= 0.85 → approved)
|
|
592
|
-
* - modifier → always 'pending' (human review required)
|
|
593
|
-
* - destructive → rejected (unless source is 'manual')
|
|
594
|
-
*/
|
|
595
|
-
interface ValidationResult {
|
|
596
|
-
ok: boolean;
|
|
597
|
-
reason?: string;
|
|
598
|
-
}
|
|
599
|
-
type FixRiskTier = 'additive' | 'modifier' | 'destructive';
|
|
600
|
-
interface FixClassification {
|
|
601
|
-
tier: FixRiskTier;
|
|
602
|
-
reason: string;
|
|
603
|
-
}
|
|
604
|
-
/**
|
|
605
|
-
* Validate a `role` attribute value.
|
|
606
|
-
* - case-sensitive: must be lowercase (rejects "Main", "Breadcrumb", "Navigation")
|
|
607
|
-
* - every space-separated token must be a real concrete ARIA role
|
|
608
|
-
* - empty / whitespace-only is invalid
|
|
609
|
-
*/
|
|
610
|
-
declare function validateRoleValue(value: string): ValidationResult;
|
|
611
|
-
/**
|
|
612
|
-
* The one fix the `<html>` root takes: `lang` (WCAG 3.1.1 — the document
|
|
613
|
-
* language lives on `<html>` and nowhere else). afe1654ed rejected every bare
|
|
614
|
-
* `html` selector as structural hardening (its case: `html { style:
|
|
615
|
-
* filter:invert(1) }` repaints every page); `lang` writes no style, no markup
|
|
616
|
-
* and no behaviour, so it is the single exception. Every other attribute on
|
|
617
|
-
* `html` stays rejected. Exact attribute name, no case folding.
|
|
618
|
-
*/
|
|
619
|
-
declare function isHtmlLangFix(selector: string | null | undefined, attribute: string | null | undefined): boolean;
|
|
620
|
-
/**
|
|
621
|
-
* Selector check for a fix whose attribute is known. `html` + `lang` passes
|
|
622
|
-
* (the root is one element, never protected UI); everything else takes
|
|
623
|
-
* validateSelector, where a bare `html` is still rejected.
|
|
624
|
-
*/
|
|
625
|
-
declare function validateSelectorForAttribute(selector: string, attribute: string, protectedScope?: ProtectedScope): ValidationResult;
|
|
626
|
-
/**
|
|
627
|
-
* Would the browser's querySelectorAll parse this selector? (LEDGER row 78 —
|
|
628
|
-
* served selectors that throw are swallowed per fix by the widget and stay
|
|
629
|
-
* approved forever.) Two layers: the character/escape rules below refuse an
|
|
630
|
-
* unescaped `/`, `%`, `!` or a Tailwind `:variant` exactly as the browser
|
|
631
|
-
* does; then a real tokeniser (css-what) refuses unbalanced brackets, an
|
|
632
|
-
* unterminated string, an empty `:not()`, a dangling `#`, and `astParses`
|
|
633
|
-
* refuses what css-what tolerates but the browser does not (`#hero >`,
|
|
634
|
-
* `a||b`, `li:nth-child(2n+)`, `button::part()`).
|
|
635
|
-
*/
|
|
636
|
-
declare function selectorParses(selector: string): boolean;
|
|
637
|
-
/** Which protected-element registry a writer consults. The scan path runs the
|
|
638
|
-
* full registry against a DOM it rendered; the ingest path keeps the narrower
|
|
639
|
-
* admin/overlay check because the full registry's SUBSTRING vendor patterns
|
|
640
|
-
* (crisp-, hubspot-) false-match attribute VALUES in live approved fixes
|
|
641
|
-
* (img[src=".../apple-cranberry-crisp-…jpg"], body.hubspot-disable-focus-styles). */
|
|
642
|
-
type ProtectedScope = 'full' | 'dead-region';
|
|
643
|
-
declare function validateSelector(selector: string, protectedScope?: ProtectedScope): ValidationResult;
|
|
644
|
-
declare function validateAttribute(attr: string): ValidationResult;
|
|
645
|
-
declare function validateTextValue(value: string, attribute?: string): ValidationResult;
|
|
646
|
-
/**
|
|
647
|
-
* Classify a fix into a risk tier:
|
|
648
|
-
* - additive: adds information that wasn't there (aria-label, alt, role, scope, etc.)
|
|
649
|
-
* - modifier: changes visibility/interactivity (aria-hidden, tabindex, style)
|
|
650
|
-
* - destructive: removes or empties functional attributes
|
|
651
|
-
*/
|
|
652
|
-
declare function classifyFixRisk(fix: {
|
|
653
|
-
attribute: string;
|
|
654
|
-
value: string;
|
|
655
|
-
}): FixClassification;
|
|
656
|
-
declare function validateFix(fix: {
|
|
657
|
-
selector: string;
|
|
658
|
-
attribute: string;
|
|
659
|
-
value: string;
|
|
660
|
-
issueType?: string | null;
|
|
661
|
-
context?: string | null;
|
|
662
|
-
}, protectedScope?: ProtectedScope): ValidationResult;
|
|
663
|
-
|
|
664
678
|
/**
|
|
665
679
|
* Hiding-hazard guard
|
|
666
680
|
* ───────────────────
|
|
@@ -959,4 +973,4 @@ declare function listHiddenCandidates(page: PageLike, opts?: {
|
|
|
959
973
|
max?: number;
|
|
960
974
|
}): Promise<HiddenCandidateList>;
|
|
961
975
|
|
|
962
|
-
export { BARE_TAGS, type BackdropKind, DEFAULT_MAX_CANDIDATES, type EngineFinding, type EngineFix, type EngineInput, type EngineIssue, type EngineOptions, type EngineResult, type EngineStats, FORM_CONTROL_ROLES, type HazardElementView, type HiddenCandidate, type HiddenCandidateList, type HiddenCause, type HiddenKind, type HiddenText, type HtmlDecision, type HtmlRequest, type HtmlRequestPolicy, InternalBug, type JudgedFix, LABEL_IN_NAME_JS, type Model, type ModelRequest, type ModelResponse, type NearbyInteractive, type Page, type PlaywrightPageLike, type ProtectedScope, type PuppeteerPageLike, SERVED_FIX_KEYS, TOKEN_QUERY_KEY, classifyFixRisk, detectPageLanguage, dropHazardousHidingFixes, foldContains, foldLabel, fromPlaywright, fromPuppeteer, htmlRequestPolicy, isHidingFix, isHtmlLangFix, isInteractiveOrContainsFocusable, isLabelText, labelContainsText, labelInNameCheck, languageFromText, languageFromUrl, listHiddenCandidates, loadSnapshot, normalizeVisibleText, parseContext, primaryLanguage, runEngine, scoreSelectorQuality, selectorParses, toPageLike, validateAttribute, validateFix, validateRoleValue, validateSelector, validateSelectorForAttribute, validateTextValue };
|
|
976
|
+
export { BARE_TAGS, type BackdropKind, DEFAULT_MAX_CANDIDATES, type EngineFinding, type EngineFix, type EngineInput, type EngineIssue, type EngineOptions, type EngineResult, type EngineStats, FORM_CONTROL_ROLES, type HazardElementView, type HiddenCandidate, type HiddenCandidateList, type HiddenCause, type HiddenKind, type HiddenText, type HtmlDecision, type HtmlRequest, type HtmlRequestPolicy, InternalBug, type JudgedFix, LABEL_IN_NAME_JS, type LabelSignal, type Model, type ModelRequest, type ModelResponse, type NearbyInteractive, type Page, type PlaywrightPageLike, type ProtectedScope, type PuppeteerPageLike, SERVED_FIX_KEYS, TOKEN_QUERY_KEY, classifyFixRisk, detectPageLanguage, dropHazardousHidingFixes, foldContains, foldLabel, fromPlaywright, fromPuppeteer, htmlRequestPolicy, isHidingFix, isHtmlLangFix, isInteractiveOrContainsFocusable, isLabelText, labelContainsText, labelInNameCheck, labelSignals, languageFromText, languageFromUrl, listHiddenCandidates, loadSnapshot, normalizeVisibleText, parseContext, primaryLanguage, runEngine, scoreSelectorQuality, selectorParses, toPageLike, validateAttribute, validateFix, validateRoleValue, validateSelector, validateSelectorForAttribute, validateTextValue };
|