@ploaness/governance 1.11.0 → 1.13.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/a11y-focus-guard.d.ts +18 -0
- package/dist/a11y-focus-guard.d.ts.map +1 -0
- package/dist/a11y-focus-guard.js +17 -0
- package/dist/a11y-focus-guard.js.map +1 -0
- package/dist/a11y-hit-target.d.ts +7 -1
- package/dist/a11y-hit-target.d.ts.map +1 -1
- package/dist/a11y-hit-target.js +11 -0
- package/dist/a11y-hit-target.js.map +1 -1
- package/dist/asset-policy.d.ts +8 -4
- package/dist/asset-policy.d.ts.map +1 -1
- package/dist/asset-policy.js +28 -19
- package/dist/asset-policy.js.map +1 -1
- package/dist/browser-discovery.d.ts +116 -0
- package/dist/browser-discovery.d.ts.map +1 -0
- package/dist/browser-discovery.js +161 -0
- package/dist/browser-discovery.js.map +1 -0
- package/dist/browser-exemptions.d.ts +107 -0
- package/dist/browser-exemptions.d.ts.map +1 -0
- package/dist/browser-exemptions.js +163 -0
- package/dist/browser-exemptions.js.map +1 -0
- package/dist/browser-findings.d.ts +54 -0
- package/dist/browser-findings.d.ts.map +1 -0
- package/dist/browser-findings.js +52 -0
- package/dist/browser-findings.js.map +1 -0
- package/dist/browser-health.d.ts +45 -0
- package/dist/browser-health.d.ts.map +1 -0
- package/dist/browser-health.js +80 -0
- package/dist/browser-health.js.map +1 -0
- package/dist/browser-rules.d.ts +169 -0
- package/dist/browser-rules.d.ts.map +1 -0
- package/dist/browser-rules.js +345 -0
- package/dist/browser-rules.js.map +1 -0
- package/dist/browser-run.d.ts +110 -0
- package/dist/browser-run.d.ts.map +1 -0
- package/dist/browser-run.js +125 -0
- package/dist/browser-run.js.map +1 -0
- package/dist/browser-viewports.d.ts +77 -0
- package/dist/browser-viewports.d.ts.map +1 -0
- package/dist/browser-viewports.js +139 -0
- package/dist/browser-viewports.js.map +1 -0
- package/dist/change-scope.d.ts +158 -0
- package/dist/change-scope.d.ts.map +1 -0
- package/dist/change-scope.js +340 -0
- package/dist/change-scope.js.map +1 -0
- package/dist/cloudfront-functions.d.ts +34 -0
- package/dist/cloudfront-functions.d.ts.map +1 -0
- package/dist/cloudfront-functions.js +124 -0
- package/dist/cloudfront-functions.js.map +1 -0
- package/dist/generated-denial.d.ts +4 -1
- package/dist/generated-denial.d.ts.map +1 -1
- package/dist/generated-denial.js +10 -3
- package/dist/generated-denial.js.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/javascript-runtimes.d.ts +36 -0
- package/dist/javascript-runtimes.d.ts.map +1 -0
- package/dist/javascript-runtimes.js +40 -0
- package/dist/javascript-runtimes.js.map +1 -0
- package/dist/jsx-accessibility-scope.d.ts.map +1 -1
- package/dist/jsx-accessibility-scope.js +3 -0
- package/dist/jsx-accessibility-scope.js.map +1 -1
- package/dist/layout-boxes.d.ts.map +1 -1
- package/dist/layout-boxes.js +12 -14
- package/dist/layout-boxes.js.map +1 -1
- package/dist/layout-clip.d.ts +24 -0
- package/dist/layout-clip.d.ts.map +1 -0
- package/dist/layout-clip.js +82 -0
- package/dist/layout-clip.js.map +1 -0
- package/dist/layout-defects.d.ts +47 -4
- package/dist/layout-defects.d.ts.map +1 -1
- package/dist/layout-defects.js +94 -76
- package/dist/layout-defects.js.map +1 -1
- package/dist/layout-snapshot.d.ts +60 -2
- package/dist/layout-snapshot.d.ts.map +1 -1
- package/dist/layout-snapshot.js +65 -1
- package/dist/layout-snapshot.js.map +1 -1
- package/dist/layout-text.d.ts +4 -1
- package/dist/layout-text.d.ts.map +1 -1
- package/dist/layout-text.js +56 -7
- package/dist/layout-text.js.map +1 -1
- package/dist/route-map.d.ts +13 -0
- package/dist/route-map.d.ts.map +1 -1
- package/dist/route-map.js +13 -6
- package/dist/route-map.js.map +1 -1
- package/dist/run-plan.d.ts +27 -3
- package/dist/run-plan.d.ts.map +1 -1
- package/dist/run-plan.js +20 -3
- package/dist/run-plan.js.map +1 -1
- package/dist/settings-layering.d.ts.map +1 -1
- package/dist/settings-layering.js +6 -4
- package/dist/settings-layering.js.map +1 -1
- package/dist/settings.d.ts +32 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +51 -12
- package/dist/settings.js.map +1 -1
- package/dist/terraform-blocks.d.ts +13 -0
- package/dist/terraform-blocks.d.ts.map +1 -0
- package/dist/terraform-blocks.js +27 -0
- package/dist/terraform-blocks.js.map +1 -0
- package/dist/terraform-policy.d.ts.map +1 -1
- package/dist/terraform-policy.js +3 -14
- package/dist/terraform-policy.js.map +1 -1
- package/dist/wiring-policy.d.ts +5 -2
- package/dist/wiring-policy.d.ts.map +1 -1
- package/dist/wiring-policy.js +16 -6
- package/dist/wiring-policy.js.map +1 -1
- package/package.json +1 -1
package/dist/layout-defects.js
CHANGED
|
@@ -1,110 +1,128 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// where to look without a screenshot. Exemptions are judged across all the viewports of a page at once:
|
|
5
|
-
// an edge attached at a phone width and apart at a desktop one is the ordinary shape of a responsive
|
|
6
|
-
// layout, so an exemption is stale only when it excuses nothing at any of them.
|
|
1
|
+
import { applyExemptions, declaredExemptions, EXEMPTION_ATTRIBUTE, EXEMPTION_REASON_ATTRIBUTE, malformedExemptions, staleExemptions, } from './browser-exemptions.js';
|
|
2
|
+
import { findingAt, findingLine } from './browser-findings.js';
|
|
3
|
+
import { BASELINE_VIEWPORTS } from './browser-viewports.js';
|
|
7
4
|
import { findTouchingBoxes } from './layout-boxes.js';
|
|
8
5
|
import { ATTACHED_EXEMPTION, keyOf } from './layout-snapshot.js';
|
|
9
6
|
import { findClippedText, findOverflowingElements, findOverlappingText, } from './layout-text.js';
|
|
10
|
-
/** The viewports the harness requires
|
|
11
|
-
export const LAYOUT_VIEWPORTS =
|
|
12
|
-
{ width: 390, height: 844 },
|
|
13
|
-
{ width: 1280, height: 800 },
|
|
14
|
-
];
|
|
7
|
+
/** The viewports the harness requires. A project may add more, never remove any. */
|
|
8
|
+
export const LAYOUT_VIEWPORTS = BASELINE_VIEWPORTS;
|
|
15
9
|
/** The smallest gap, in CSS pixels, between a boxed element and its sibling. A project may raise it. */
|
|
16
10
|
export const LAYOUT_MINIMUM_GAP = 4;
|
|
17
|
-
/** The attribute a project writes on an element
|
|
18
|
-
export const LAYOUT_EXEMPTION_ATTRIBUTE =
|
|
11
|
+
/** The attribute a project writes on an element exempt from a rule. */
|
|
12
|
+
export const LAYOUT_EXEMPTION_ATTRIBUTE = EXEMPTION_ATTRIBUTE;
|
|
19
13
|
/** The attribute carrying the reason for that exemption. */
|
|
20
|
-
export const LAYOUT_REASON_ATTRIBUTE =
|
|
14
|
+
export const LAYOUT_REASON_ATTRIBUTE = EXEMPTION_REASON_ATTRIBUTE;
|
|
15
|
+
/** The geometry rules the width sweep and the text-stress passes apply: L1 to L3. */
|
|
16
|
+
export const REFLOW_RULES = ['overflow', 'text-overlap', 'clipped-text'];
|
|
17
|
+
/** Every geometry rule of the layout scan: L1 to L4. */
|
|
18
|
+
export const LAYOUT_RULES = [...REFLOW_RULES, ATTACHED_EXEMPTION];
|
|
21
19
|
const PAIR_SEPARATOR = ' <-> ';
|
|
22
|
-
const
|
|
23
|
-
const boxLine = (snapshot, finding) => {
|
|
20
|
+
const boxMessage = (finding) => {
|
|
24
21
|
const kind = finding.isOverlap
|
|
25
22
|
? 'overlapping boxes'
|
|
26
23
|
: `touching boxes (gap ${String(Math.max(0, finding.gap))}px)`;
|
|
27
|
-
return `${
|
|
24
|
+
return `${kind}: ${finding.first.label}${PAIR_SEPARATOR}${finding.second.label}`;
|
|
28
25
|
};
|
|
29
|
-
const
|
|
30
|
-
const clipLine = (snapshot, finding) => {
|
|
26
|
+
const clipMessage = (finding) => {
|
|
31
27
|
const node = finding.node;
|
|
32
28
|
const kind = finding.isUnnamedTruncation
|
|
33
29
|
? 'truncated text without its full text in title or aria-label'
|
|
34
30
|
: `clipped text (content ${String(node.scrollWidth)}x${String(node.scrollHeight)}px in a ` +
|
|
35
31
|
`${String(node.clientWidth)}x${String(node.clientHeight)}px box)`;
|
|
36
|
-
return `${
|
|
32
|
+
return `${kind}: ${node.label}`;
|
|
37
33
|
};
|
|
38
|
-
const
|
|
34
|
+
const overflowCandidates = (snapshot) => {
|
|
39
35
|
if (snapshot.scrollWidth <= snapshot.viewportWidth) {
|
|
40
36
|
return [];
|
|
41
37
|
}
|
|
42
|
-
const prefix =
|
|
38
|
+
const prefix = `horizontal overflow (page ${String(snapshot.scrollWidth)}px wide ` +
|
|
43
39
|
`in a ${String(snapshot.viewportWidth)}px viewport)`;
|
|
44
40
|
const culprits = findOverflowingElements(snapshot);
|
|
45
41
|
return culprits.length === 0
|
|
46
|
-
? [`${prefix}: document`]
|
|
47
|
-
: culprits.map((node) =>
|
|
42
|
+
? [{ rule: 'overflow', subjects: [], message: `${prefix}: document` }]
|
|
43
|
+
: culprits.map((node) => ({
|
|
44
|
+
rule: 'overflow',
|
|
45
|
+
subjects: [node],
|
|
46
|
+
message: `${prefix}: ${node.label}`,
|
|
47
|
+
}));
|
|
48
48
|
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
...
|
|
56
|
-
|
|
49
|
+
/**
|
|
50
|
+
* The reflow rules' candidates on one measured page, before exemptions: L1 to L3.
|
|
51
|
+
* @param snapshot the measured page.
|
|
52
|
+
* @returns one candidate per defect.
|
|
53
|
+
*/
|
|
54
|
+
export const reflowCandidates = (snapshot) => [
|
|
55
|
+
...findOverlappingText(snapshot).map((finding) => ({
|
|
56
|
+
rule: 'text-overlap',
|
|
57
|
+
subjects: [finding.first, finding.second],
|
|
58
|
+
message: `overlapping text: ${finding.first.label}${PAIR_SEPARATOR}${finding.second.label}`,
|
|
59
|
+
})),
|
|
60
|
+
...findClippedText(snapshot).map((finding) => ({
|
|
61
|
+
rule: 'clipped-text',
|
|
62
|
+
subjects: [finding.node],
|
|
63
|
+
message: clipMessage(finding),
|
|
64
|
+
})),
|
|
65
|
+
...overflowCandidates(snapshot),
|
|
57
66
|
];
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Judge one measured page by the geometry rules, with exemptions applied.
|
|
69
|
+
*
|
|
70
|
+
* Touching boxes are excused only by an exemption on one of the two boxes. Every other rule is excused
|
|
71
|
+
* by an exemption on the element it judges or on an ancestor of it.
|
|
72
|
+
* @param snapshot the measured page.
|
|
73
|
+
* @param place where it was measured.
|
|
74
|
+
* @param judgement the gap and rules to judge it by, and the candidates of further rules.
|
|
75
|
+
* @param judgement.minimumGap the smallest gap, in CSS pixels, between a boxed element and its sibling.
|
|
76
|
+
* @param judgement.extra candidates of further rules measured on the same page.
|
|
77
|
+
* @param judgement.rules the geometry rules to apply.
|
|
78
|
+
* @returns the findings, the exemptions used, and the exemptions declared.
|
|
79
|
+
*/
|
|
80
|
+
export const judgeLayout = (snapshot, place, { minimumGap, extra = [], rules = LAYOUT_RULES }) => {
|
|
81
|
+
const boxes = rules.includes(ATTACHED_EXEMPTION) ? findTouchingBoxes(snapshot, minimumGap) : [];
|
|
82
|
+
const candidates = [
|
|
83
|
+
...reflowCandidates(snapshot).filter((candidate) => rules.includes(candidate.rule)),
|
|
84
|
+
...extra,
|
|
85
|
+
];
|
|
86
|
+
const judged = applyExemptions(snapshot, place, candidates);
|
|
87
|
+
return {
|
|
88
|
+
findings: [
|
|
89
|
+
...boxes
|
|
90
|
+
.filter((finding) => finding.exemptedBy.length === 0)
|
|
91
|
+
.map((finding) => findingAt(place, ATTACHED_EXEMPTION, boxMessage(finding), [finding.first.index, finding.second.index])),
|
|
92
|
+
...judged.findings,
|
|
93
|
+
...malformedExemptions(snapshot, place),
|
|
94
|
+
],
|
|
95
|
+
used: [
|
|
96
|
+
...boxes.flatMap((finding) => finding.exemptedBy.map((node) => ({
|
|
97
|
+
location: place.location,
|
|
98
|
+
key: keyOf(snapshot, node),
|
|
99
|
+
rule: ATTACHED_EXEMPTION,
|
|
100
|
+
}))),
|
|
101
|
+
...judged.used,
|
|
102
|
+
],
|
|
103
|
+
declared: declaredExemptions(snapshot, place.location),
|
|
104
|
+
};
|
|
92
105
|
};
|
|
93
106
|
/**
|
|
94
|
-
* Every layout defect on one page, across the viewports it was measured at.
|
|
107
|
+
* Every layout defect on one page, across the viewports it was measured at, as report lines.
|
|
95
108
|
* @param snapshots the same page measured at each required viewport.
|
|
96
109
|
* @param minimumGap the smallest gap, in CSS pixels, between a boxed element and its sibling.
|
|
110
|
+
* @param engine the engine it was measured in.
|
|
111
|
+
* @param state the state it was measured in.
|
|
97
112
|
* @returns one line per defect, without duplicates, in the order the viewports were measured.
|
|
98
113
|
*/
|
|
99
|
-
export const findLayoutDefects = (snapshots, minimumGap) =>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
114
|
+
export const findLayoutDefects = (snapshots, minimumGap, engine = 'chromium', state = 'resting') => {
|
|
115
|
+
const judged = snapshots.map((snapshot) => judgeLayout(snapshot, {
|
|
116
|
+
location: snapshot.route,
|
|
117
|
+
state,
|
|
118
|
+
engine,
|
|
119
|
+
viewport: { width: snapshot.viewportWidth, height: snapshot.viewportHeight },
|
|
120
|
+
}, { minimumGap }));
|
|
121
|
+
const stale = staleExemptions(judged.flatMap((page) => page.declared), judged.flatMap((page) => page.used), LAYOUT_RULES, engine);
|
|
122
|
+
return [
|
|
123
|
+
...new Set([...judged.flatMap((page) => page.findings), ...stale].map((finding) => findingLine(finding))),
|
|
124
|
+
];
|
|
125
|
+
};
|
|
108
126
|
/**
|
|
109
127
|
* The viewports a scan must run at: the harness's own, then any a project adds.
|
|
110
128
|
* @param declared the viewports a project declared.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-defects.js","sourceRoot":"","sources":["../src/layout-defects.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"layout-defects.js","sourceRoot":"","sources":["../src/layout-defects.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,6 +41,12 @@ export interface LayoutNode {
|
|
|
41
41
|
readonly display: string;
|
|
42
42
|
readonly visibility: string;
|
|
43
43
|
readonly position: string;
|
|
44
|
+
/** The computed `z-index`: `auto` or an integer. */
|
|
45
|
+
readonly zIndex: string;
|
|
46
|
+
/** The computed `transform`: `none` or a `matrix()` or `matrix3d()`. */
|
|
47
|
+
readonly transform: string;
|
|
48
|
+
/** The computed `rotate` property, which `transform` does not include: `none` or an angle. */
|
|
49
|
+
readonly rotate: string;
|
|
44
50
|
readonly backgroundColor: string;
|
|
45
51
|
readonly backgroundImage: string;
|
|
46
52
|
readonly boxShadow: string;
|
|
@@ -59,10 +65,40 @@ export interface LayoutNode {
|
|
|
59
65
|
readonly clientHeight: number;
|
|
60
66
|
readonly title: string;
|
|
61
67
|
readonly ariaLabel: string;
|
|
62
|
-
/** The value of `data-ploaness-layout
|
|
68
|
+
/** The value of `data-ploaness-layout`: the rule names it exempts, or undefined when it is absent. */
|
|
63
69
|
readonly exemption: string | undefined;
|
|
64
70
|
/** The value of `data-ploaness-layout-reason`, trimmed. */
|
|
65
71
|
readonly exemptionReason: string;
|
|
72
|
+
/** The computed `font-size` in CSS pixels. */
|
|
73
|
+
readonly fontSize: number;
|
|
74
|
+
/** The computed `font-family` stack. */
|
|
75
|
+
readonly fontFamily: string;
|
|
76
|
+
/** What a replaced element reports about its content, or undefined for any other element. */
|
|
77
|
+
readonly media: MediaFacts | undefined;
|
|
78
|
+
}
|
|
79
|
+
/** What an image, video, frame or embed reports about the content it shows. */
|
|
80
|
+
export interface MediaFacts {
|
|
81
|
+
/** Whether an image has finished loading; always true for an element that is not an image. */
|
|
82
|
+
readonly isComplete: boolean;
|
|
83
|
+
/** Whether the source is a vector image, which has no fixed resolution to judge. */
|
|
84
|
+
readonly isVector: boolean;
|
|
85
|
+
/** The pixel size of the loaded source file, unscaled by a `srcset` density; 0 when it has none. */
|
|
86
|
+
readonly naturalWidth: number;
|
|
87
|
+
readonly naturalHeight: number;
|
|
88
|
+
/** The content box, inside padding and border. */
|
|
89
|
+
readonly contentWidth: number;
|
|
90
|
+
readonly contentHeight: number;
|
|
91
|
+
readonly objectFit: string;
|
|
92
|
+
/** The box the same element takes with no source loaded: the space it reserves before loading. */
|
|
93
|
+
readonly reservedWidth: number;
|
|
94
|
+
readonly reservedHeight: number;
|
|
95
|
+
}
|
|
96
|
+
/** One `@font-face` the document declares, and how far it got. */
|
|
97
|
+
export interface FontFaceFacts {
|
|
98
|
+
readonly family: string;
|
|
99
|
+
readonly status: string;
|
|
100
|
+
readonly weight: string;
|
|
101
|
+
readonly style: string;
|
|
66
102
|
}
|
|
67
103
|
/** One page measured at one viewport. */
|
|
68
104
|
export interface LayoutSnapshot {
|
|
@@ -74,15 +110,29 @@ export interface LayoutSnapshot {
|
|
|
74
110
|
/** The computed background of `<html>`, which is what `<body>` sits on. */
|
|
75
111
|
readonly rootBackground: string;
|
|
76
112
|
readonly nodes: readonly LayoutNode[];
|
|
113
|
+
/** Every `@font-face` the document declares. */
|
|
114
|
+
readonly fontFaces: readonly FontFaceFacts[];
|
|
77
115
|
}
|
|
78
|
-
/** The
|
|
116
|
+
/** The touching-boxes rule's name, which exempts an edge shared on purpose, such as a tab joined to its panel. */
|
|
79
117
|
export declare const ATTACHED_EXEMPTION: string;
|
|
118
|
+
/**
|
|
119
|
+
* Whether a computed colour hides what lies beneath it.
|
|
120
|
+
* @param color a computed colour string.
|
|
121
|
+
* @returns true for a colour with no alpha or a full one.
|
|
122
|
+
*/
|
|
123
|
+
export declare const isOpaqueColor: (color: string) => boolean;
|
|
80
124
|
/**
|
|
81
125
|
* Whether a computed colour draws anything.
|
|
82
126
|
* @param color a computed colour string.
|
|
83
127
|
* @returns false for `transparent` and any colour whose alpha is zero.
|
|
84
128
|
*/
|
|
85
129
|
export declare const isVisibleColor: (color: string) => boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Whether an element's own background hides what lies beneath its box.
|
|
132
|
+
* @param node the element.
|
|
133
|
+
* @returns true for an opaque background colour, or a gradient of opaque stops only.
|
|
134
|
+
*/
|
|
135
|
+
export declare const isOpaqueBackground: (node: LayoutNode) => boolean;
|
|
86
136
|
/**
|
|
87
137
|
* The background an element sits on: the nearest ancestor that paints one, or the page canvas.
|
|
88
138
|
* @param snapshot the measured page.
|
|
@@ -125,6 +175,14 @@ export declare const isInAriaHidden: (snapshot: LayoutSnapshot, node: LayoutNode
|
|
|
125
175
|
* @returns true inside a clipped subtree.
|
|
126
176
|
*/
|
|
127
177
|
export declare const isInClip: (snapshot: LayoutSnapshot, node: LayoutNode) => boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Whether an element or an ancestor is rotated or skewed. Its bounding rectangles are then the upright
|
|
180
|
+
* boxes around a turned shape, larger than what it paints, so no gap or overlap measured on them is real.
|
|
181
|
+
* @param snapshot the measured page.
|
|
182
|
+
* @param node the element.
|
|
183
|
+
* @returns true inside a turned subtree.
|
|
184
|
+
*/
|
|
185
|
+
export declare const isInTurn: (snapshot: LayoutSnapshot, node: LayoutNode) => boolean;
|
|
128
186
|
/**
|
|
129
187
|
* Whether `ancestor` contains `node`.
|
|
130
188
|
* @param snapshot the measured page.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-snapshot.d.ts","sourceRoot":"","sources":["../src/layout-snapshot.ts"],"names":[],"mappings":"AAMA,kEAAkE;AAClE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,gDAAgD;AAChD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAC5B;AAED,gDAAgD;AAChD,MAAM,MAAM,UAAU,GAAG,MAAM,aAAa,CAAA;AAE5C,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,sCAAsC;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,uFAAuF;IACvF,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAA;IACrC,oFAAoF;IACpF,QAAQ,CAAC,SAAS,EAAE,SAAS,UAAU,EAAE,CAAA;IACzC,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;IAC9B,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,
|
|
1
|
+
{"version":3,"file":"layout-snapshot.d.ts","sourceRoot":"","sources":["../src/layout-snapshot.ts"],"names":[],"mappings":"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"}
|
package/dist/layout-snapshot.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// The layout sweep measures inside the page and judges here. Everything a rule needs crosses the
|
|
4
4
|
// boundary as data - whole CSS pixels and computed style strings - so the rules run without a browser
|
|
5
5
|
// and a spec can state a defect as the numbers that make it one.
|
|
6
|
-
/** The
|
|
6
|
+
/** The touching-boxes rule's name, which exempts an edge shared on purpose, such as a tab joined to its panel. */
|
|
7
7
|
export const ATTACHED_EXEMPTION = 'attached';
|
|
8
8
|
// The canvas a page is drawn on when neither `<html>` nor any ancestor paints a background.
|
|
9
9
|
const CANVAS_BACKGROUND = 'rgb(255, 255, 255)';
|
|
@@ -14,6 +14,16 @@ const COMMA_ALPHA = /^rgba\([^,]+,[^,]+,[^,]+,\s*([\d.]+)\)$/u;
|
|
|
14
14
|
const SLASH_ALPHA = /\/\s*([\d.]+%?)\s*\)$/u;
|
|
15
15
|
const PERCENT = '%';
|
|
16
16
|
const alphaText = (color) => COMMA_ALPHA.exec(color)?.[1] ?? SLASH_ALPHA.exec(color)?.[1];
|
|
17
|
+
const FULL_ALPHAS = new Set(['1', `100${PERCENT}`]);
|
|
18
|
+
/**
|
|
19
|
+
* Whether a computed colour hides what lies beneath it.
|
|
20
|
+
* @param color a computed colour string.
|
|
21
|
+
* @returns true for a colour with no alpha or a full one.
|
|
22
|
+
*/
|
|
23
|
+
export const isOpaqueColor = (color) => {
|
|
24
|
+
const alpha = alphaText(color.trim());
|
|
25
|
+
return isVisibleColor(color) && (alpha === undefined || FULL_ALPHAS.has(alpha));
|
|
26
|
+
};
|
|
17
27
|
/**
|
|
18
28
|
* Whether a computed colour draws anything.
|
|
19
29
|
* @param color a computed colour string.
|
|
@@ -27,6 +37,24 @@ export const isVisibleColor = (color) => {
|
|
|
27
37
|
const alpha = alphaText(trimmed);
|
|
28
38
|
return alpha === undefined || Number(alpha.replace(PERCENT, '')) > 0;
|
|
29
39
|
};
|
|
40
|
+
// A computed gradient spells each colour stop as a colour function. An image, a keyword left in the
|
|
41
|
+
// value, or a stop of partial alpha may let what lies beneath show through, so only a gradient whose
|
|
42
|
+
// every stop is an opaque colour function hides it.
|
|
43
|
+
const COLOR_FUNCTION = /(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)\([^()]*\)/gu;
|
|
44
|
+
const UNKNOWN_PAINT = /url\(|transparent|currentcolor/u;
|
|
45
|
+
const isOpaqueGradient = (image) => {
|
|
46
|
+
const stops = image.match(COLOR_FUNCTION) ?? [];
|
|
47
|
+
return (image.includes('gradient(') &&
|
|
48
|
+
!UNKNOWN_PAINT.test(image) &&
|
|
49
|
+
stops.length > 0 &&
|
|
50
|
+
stops.every((stop) => isOpaqueColor(stop)));
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Whether an element's own background hides what lies beneath its box.
|
|
54
|
+
* @param node the element.
|
|
55
|
+
* @returns true for an opaque background colour, or a gradient of opaque stops only.
|
|
56
|
+
*/
|
|
57
|
+
export const isOpaqueBackground = (node) => isOpaqueColor(node.backgroundColor) || isOpaqueGradient(node.backgroundImage);
|
|
30
58
|
/**
|
|
31
59
|
* The background an element sits on: the nearest ancestor that paints one, or the page canvas.
|
|
32
60
|
* @param snapshot the measured page.
|
|
@@ -88,6 +116,42 @@ export const isInClip = (snapshot, node) => {
|
|
|
88
116
|
const parent = snapshot.nodes[node.parent];
|
|
89
117
|
return node.isClipped || (parent !== undefined && isInClip(snapshot, parent));
|
|
90
118
|
};
|
|
119
|
+
// A matrix turns a box when it moves either axis toward the other: `b` and `c` of `matrix(a, b, c, d, e,
|
|
120
|
+
// f)`, and the six off-diagonal terms of the column-major `matrix3d`. What is left is scaling and
|
|
121
|
+
// translation, under which a bounding rectangle is still the painted box.
|
|
122
|
+
const MATRIX = /^matrix(3d)?\((.*)\)$/u;
|
|
123
|
+
const TURN_EPSILON = 1e-6;
|
|
124
|
+
const turnTermsOf = (terms, isSpatial) => {
|
|
125
|
+
const [, m12, m13, , m21, , m23, , m31, m32] = terms;
|
|
126
|
+
return isSpatial ? [m12, m13, m21, m23, m31, m32] : [m12, m13];
|
|
127
|
+
};
|
|
128
|
+
const isTurnedTransform = (transform) => {
|
|
129
|
+
const match = MATRIX.exec(transform.trim());
|
|
130
|
+
if (match === null) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
const terms = (match[2] ?? '').split(',').map(Number);
|
|
134
|
+
return turnTermsOf(terms, match[1] !== undefined).some((term) => Math.abs(term ?? 0) > TURN_EPSILON);
|
|
135
|
+
};
|
|
136
|
+
// The angle is the last word of the computed value, after any axis: `3deg`, `x 10deg`, `0 0 1 3deg`.
|
|
137
|
+
const ANGLE_UNIT = /(?:deg|g?rad|turn)$/u;
|
|
138
|
+
const isTurnedRotate = (rotate) => {
|
|
139
|
+
const angle = Number((rotate.trim().split(/\s+/u).at(-1) ?? '').replace(ANGLE_UNIT, ''));
|
|
140
|
+
return Number.isFinite(angle) && angle !== 0;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Whether an element or an ancestor is rotated or skewed. Its bounding rectangles are then the upright
|
|
144
|
+
* boxes around a turned shape, larger than what it paints, so no gap or overlap measured on them is real.
|
|
145
|
+
* @param snapshot the measured page.
|
|
146
|
+
* @param node the element.
|
|
147
|
+
* @returns true inside a turned subtree.
|
|
148
|
+
*/
|
|
149
|
+
export const isInTurn = (snapshot, node) => {
|
|
150
|
+
const parent = snapshot.nodes[node.parent];
|
|
151
|
+
return (isTurnedTransform(node.transform) ||
|
|
152
|
+
isTurnedRotate(node.rotate) ||
|
|
153
|
+
(parent !== undefined && isInTurn(snapshot, parent)));
|
|
154
|
+
};
|
|
91
155
|
/**
|
|
92
156
|
* Whether `ancestor` contains `node`.
|
|
93
157
|
* @param snapshot the measured page.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-snapshot.js","sourceRoot":"","sources":["../src/layout-snapshot.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,EAAE;AACF,iGAAiG;AACjG,sGAAsG;AACtG,iEAAiE;
|
|
1
|
+
{"version":3,"file":"layout-snapshot.js","sourceRoot":"","sources":["../src/layout-snapshot.ts"],"names":[],"mappings":"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"}
|
package/dist/layout-text.d.ts
CHANGED
|
@@ -10,7 +10,10 @@ export interface TextFinding {
|
|
|
10
10
|
readonly second: LayoutNode;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Every pair of unrelated elements whose
|
|
13
|
+
* Every pair of unrelated elements whose visible text overlaps.
|
|
14
|
+
*
|
|
15
|
+
* Text inside a rotated or skewed subtree is not compared: its rects are the upright boxes around the
|
|
16
|
+
* turned lines, which meet where the glyphs do not.
|
|
14
17
|
* @param snapshot the measured page.
|
|
15
18
|
* @returns one finding per pair, in document order.
|
|
16
19
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-text.d.ts","sourceRoot":"","sources":["../src/layout-text.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"layout-text.d.ts","sourceRoot":"","sources":["../src/layout-text.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,UAAU,EAEf,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAA;AAE7B;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAU,CAAA;AAwH/C,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,cAAc,KAAG,SAAS,WAAW,EAclF,CAAA;AAED,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,oGAAoG;IACpG,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAA;CACtC;AAiBD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,cAAc,KAAG,SAAS,WAAW,EAazE,CAAA;AAgBN;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,cAAc,KAAG,SAAS,UAAU,EASlF,CAAA"}
|
package/dist/layout-text.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Text that overlaps other text, text cut off by its own box, and a page wider than its viewport.
|
|
2
|
-
import {
|
|
2
|
+
import { intersectionOf, outerBoxOf, visibleRectsOf } from './layout-clip.js';
|
|
3
|
+
import { hasArea, isAncestorOf, isInAriaHidden, isInClip, isInTurn, isOpaqueBackground, } from './layout-snapshot.js';
|
|
3
4
|
/**
|
|
4
5
|
* How far two text rects may intersect, in CSS pixels, before they overlap. Glyph boxes of adjacent
|
|
5
6
|
* lines share a pixel row after rounding, which is a rounding artefact rather than a collision.
|
|
@@ -33,20 +34,68 @@ const lineBoxOf = (rect, lineHeight) => {
|
|
|
33
34
|
return { ...rect, top: Math.round(rect.top + inset), bottom: Math.round(rect.bottom - inset) };
|
|
34
35
|
};
|
|
35
36
|
const lineBoxesOf = (node) => node.textRects.map((rect) => lineBoxOf(rect, node.lineHeight));
|
|
36
|
-
const isIntersecting = (first, second) =>
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const isIntersecting = (first, second) => {
|
|
38
|
+
const shared = intersectionOf(first, second);
|
|
39
|
+
return shared.right - shared.left > TEXT_OVERLAP_TOLERANCE && shared.bottom - shared.top > TEXT_OVERLAP_TOLERANCE;
|
|
40
|
+
};
|
|
41
|
+
const STATIC = 'static';
|
|
42
|
+
// What of an element's text a reader can see: each line box, cut by every ancestor that clips it.
|
|
43
|
+
const visibleLineBoxesOf = (snapshot, node) => visibleRectsOf(snapshot, node, lineBoxesOf(node));
|
|
44
|
+
const ancestorsOf = (snapshot, node) => {
|
|
45
|
+
const parent = snapshot.nodes[node.parent];
|
|
46
|
+
return parent === undefined ? [] : [parent, ...ancestorsOf(snapshot, parent)];
|
|
47
|
+
};
|
|
48
|
+
const isSelfOrAncestorOf = (snapshot, candidate, node) => candidate === node || isAncestorOf(snapshot, candidate, node);
|
|
49
|
+
const stackLevelOf = (node) => (node.zIndex === 'auto' ? 0 : Number(node.zIndex) || 0);
|
|
50
|
+
const nearestPositioned = (snapshot, node, other) => [node, ...ancestorsOf(snapshot, node)].find((candidate) => candidate.position !== STATIC && !isSelfOrAncestorOf(snapshot, candidate, other));
|
|
51
|
+
const coversRegion = (outer, inner) => outer.left <= inner.left && outer.top <= inner.top && outer.right >= inner.right && outer.bottom >= inner.bottom;
|
|
52
|
+
// Whether `cover` paints an opaque background over all of `region` without containing `under`.
|
|
53
|
+
const isOpaqueOver = (snapshot, cover, under, region) => {
|
|
54
|
+
const box = outerBoxOf(cover);
|
|
55
|
+
return (box !== undefined &&
|
|
56
|
+
isOpaqueBackground(cover) &&
|
|
57
|
+
coversRegion(box, region) &&
|
|
58
|
+
!isSelfOrAncestorOf(snapshot, cover, under));
|
|
59
|
+
};
|
|
60
|
+
// Whether the positioned layer `cover` is painted in is painted after `under`'s text.
|
|
61
|
+
const isPaintedAfter = (snapshot, cover, under) => {
|
|
62
|
+
const layer = nearestPositioned(snapshot, cover, under);
|
|
63
|
+
if (layer === undefined) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const beneath = nearestPositioned(snapshot, under, cover);
|
|
67
|
+
if (beneath === undefined) {
|
|
68
|
+
return stackLevelOf(layer) >= 0;
|
|
69
|
+
}
|
|
70
|
+
return (stackLevelOf(layer) > stackLevelOf(beneath) ||
|
|
71
|
+
(stackLevelOf(layer) === stackLevelOf(beneath) && layer.index > beneath.index));
|
|
72
|
+
};
|
|
73
|
+
// Whether `under`'s text at `region` is painted beneath an opaque background of `over` or of one of its
|
|
74
|
+
// ancestors, such as an open menu panel laid over the page. In one stacking context every in-flow
|
|
75
|
+
// background is painted before any text, so only a positioned layer covers text: it is painted after
|
|
76
|
+
// the in-flow content beside it, and after another positioned layer of no higher `z-index` before it in
|
|
77
|
+
// the document.
|
|
78
|
+
const isCoveredBy = (snapshot, under, over, region) => [over, ...ancestorsOf(snapshot, over)].some((cover) => isOpaqueOver(snapshot, cover, under, region) && isPaintedAfter(snapshot, cover, under));
|
|
79
|
+
const hasCollidingText = (snapshot, first, second) => visibleLineBoxesOf(snapshot, first).some((left) => visibleLineBoxesOf(snapshot, second).some((right) => {
|
|
80
|
+
const region = intersectionOf(left, right);
|
|
81
|
+
return (isIntersecting(left, right) &&
|
|
82
|
+
!isCoveredBy(snapshot, first, second, region) &&
|
|
83
|
+
!isCoveredBy(snapshot, second, first, region));
|
|
84
|
+
}));
|
|
39
85
|
/**
|
|
40
|
-
* Every pair of unrelated elements whose
|
|
86
|
+
* Every pair of unrelated elements whose visible text overlaps.
|
|
87
|
+
*
|
|
88
|
+
* Text inside a rotated or skewed subtree is not compared: its rects are the upright boxes around the
|
|
89
|
+
* turned lines, which meet where the glyphs do not.
|
|
41
90
|
* @param snapshot the measured page.
|
|
42
91
|
* @returns one finding per pair, in document order.
|
|
43
92
|
*/
|
|
44
93
|
export const findOverlappingText = (snapshot) => {
|
|
45
|
-
const readable = snapshot.nodes.filter((node) => isReadableText(snapshot, node));
|
|
94
|
+
const readable = snapshot.nodes.filter((node) => isReadableText(snapshot, node) && !isInTurn(snapshot, node));
|
|
46
95
|
return readable.flatMap((first, index) => readable
|
|
47
96
|
.slice(index + 1)
|
|
48
97
|
.filter((second) => !(isAncestorOf(snapshot, first, second) || isAncestorOf(snapshot, second, first)) &&
|
|
49
|
-
hasCollidingText(first, second))
|
|
98
|
+
hasCollidingText(snapshot, first, second))
|
|
50
99
|
.map((second) => ({ first, second })));
|
|
51
100
|
};
|
|
52
101
|
const hasHiddenOverflowX = (node) => CLIPPING_OVERFLOW.has(node.overflowX) && node.scrollWidth > node.clientWidth;
|