@templatical/quality 0.7.2 → 0.8.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/index.d.ts +168 -63
- package/dist/index.js +643 -253
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -4,44 +4,7 @@ import { TemplateContent } from '../../../types/src/index.ts';
|
|
|
4
4
|
import { TemplateContent as TemplateContent_2 } from '../../types/src/index.ts';
|
|
5
5
|
import { TemplateSettings } from '../../types/src/index.ts';
|
|
6
6
|
|
|
7
|
-
export declare
|
|
8
|
-
/** Block id, or null for template-level issues. */
|
|
9
|
-
blockId: string | null;
|
|
10
|
-
ruleId: string;
|
|
11
|
-
severity: Exclude<Severity, "off">;
|
|
12
|
-
message: string;
|
|
13
|
-
fix?: A11yPatch;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export declare interface A11yOptions {
|
|
17
|
-
/**
|
|
18
|
-
* Fully disable linting. When true, the editor skips lazy-loading the
|
|
19
|
-
* package, hides the sidebar tab, and suppresses inline badges.
|
|
20
|
-
*/
|
|
21
|
-
disabled?: boolean;
|
|
22
|
-
/** Locale for vague-text dictionaries and message text. Falls back to `en`. */
|
|
23
|
-
locale?: string;
|
|
24
|
-
/** Per-rule severity override. Set to `'off'` to disable a specific rule. */
|
|
25
|
-
rules?: Record<string, Severity>;
|
|
26
|
-
thresholds?: Partial<A11yThresholds>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export declare interface A11yPatch {
|
|
30
|
-
description: string;
|
|
31
|
-
apply: (ctx: A11yPatchContext) => void;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export declare interface A11yPatchContext {
|
|
35
|
-
updateBlock: (blockId: string, patch: Partial<Block>) => void;
|
|
36
|
-
updateSettings: (patch: Partial<TemplateSettings>) => void;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export declare interface A11yThresholds {
|
|
40
|
-
altMaxLength: number;
|
|
41
|
-
minFontSize: number;
|
|
42
|
-
allCapsMinLength: number;
|
|
43
|
-
minTouchTargetPx: number;
|
|
44
|
-
}
|
|
7
|
+
export declare const ACCESSIBILITY_RULES: Rule[];
|
|
45
8
|
|
|
46
9
|
export declare interface AnchorInfo {
|
|
47
10
|
href: string;
|
|
@@ -52,7 +15,9 @@ export declare interface AnchorInfo {
|
|
|
52
15
|
hasImageWithAlt: boolean;
|
|
53
16
|
}
|
|
54
17
|
|
|
55
|
-
export declare const
|
|
18
|
+
export declare const DEFAULT_A11Y_THRESHOLDS: LintThresholds;
|
|
19
|
+
|
|
20
|
+
export declare const DEFAULT_NON_PRODUCTION_HOSTS: string[];
|
|
56
21
|
|
|
57
22
|
export declare type Dictionary = typeof en;
|
|
58
23
|
|
|
@@ -81,25 +46,53 @@ declare const en: {
|
|
|
81
46
|
* Templates use `{name}` placeholders, interpolated by `formatMessage`.
|
|
82
47
|
*/
|
|
83
48
|
declare const en_2: {
|
|
84
|
-
"img-missing-alt": string;
|
|
85
|
-
"img-alt-is-filename": string;
|
|
86
|
-
"img-alt-too-long": string;
|
|
87
|
-
"img-decorative-needs-empty-alt": string;
|
|
88
|
-
"img-linked-no-context": string;
|
|
89
|
-
"heading-empty": string;
|
|
90
|
-
"heading-skip-level": string;
|
|
91
|
-
"heading-multiple-h1": string;
|
|
92
|
-
"link-empty": string;
|
|
93
|
-
"link-vague-text": string;
|
|
94
|
-
"link-href-empty": string;
|
|
95
|
-
"link-target-blank-no-rel": string;
|
|
96
|
-
"text-all-caps": string;
|
|
97
|
-
"text-low-contrast": string;
|
|
98
|
-
"text-too-small": string;
|
|
99
|
-
"button-vague-label": string;
|
|
100
|
-
"button-touch-target": string;
|
|
101
|
-
"button-low-contrast": string;
|
|
102
|
-
"missing-preheader": string;
|
|
49
|
+
"a11y.img-missing-alt": string;
|
|
50
|
+
"a11y.img-alt-is-filename": string;
|
|
51
|
+
"a11y.img-alt-too-long": string;
|
|
52
|
+
"a11y.img-decorative-needs-empty-alt": string;
|
|
53
|
+
"a11y.img-linked-no-context": string;
|
|
54
|
+
"a11y.heading-empty": string;
|
|
55
|
+
"a11y.heading-skip-level": string;
|
|
56
|
+
"a11y.heading-multiple-h1": string;
|
|
57
|
+
"a11y.link-empty": string;
|
|
58
|
+
"a11y.link-vague-text": string;
|
|
59
|
+
"a11y.link-href-empty": string;
|
|
60
|
+
"a11y.link-target-blank-no-rel": string;
|
|
61
|
+
"a11y.text-all-caps": string;
|
|
62
|
+
"a11y.text-low-contrast": string;
|
|
63
|
+
"a11y.text-too-small": string;
|
|
64
|
+
"a11y.button-vague-label": string;
|
|
65
|
+
"a11y.button-touch-target": string;
|
|
66
|
+
"a11y.button-low-contrast": string;
|
|
67
|
+
"a11y.missing-preheader": string;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* English structure-rule messages. The source of truth — other locales
|
|
72
|
+
* annotate themselves `typeof en` so missing or extra keys fail typecheck.
|
|
73
|
+
*
|
|
74
|
+
* Templates use `{name}` placeholders, interpolated by `formatMessage`.
|
|
75
|
+
*/
|
|
76
|
+
declare const en_3: {
|
|
77
|
+
"structure.duplicate-block-id": string;
|
|
78
|
+
"structure.section-column-mismatch": string;
|
|
79
|
+
"structure.nested-section": string;
|
|
80
|
+
"structure.empty-section": string;
|
|
81
|
+
"structure.empty-column": string;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* English link-rule messages. The source of truth — other locales annotate
|
|
86
|
+
* themselves `typeof en` so missing or extra keys fail typecheck.
|
|
87
|
+
*
|
|
88
|
+
* Templates use `{name}` placeholders, interpolated by `formatLinkMessage`.
|
|
89
|
+
*/
|
|
90
|
+
declare const en_4: {
|
|
91
|
+
"link.javascript-protocol": string;
|
|
92
|
+
"link.unsupported-protocol": string;
|
|
93
|
+
"link.malformed-mailto": string;
|
|
94
|
+
"link.malformed-tel": string;
|
|
95
|
+
"link.localhost-or-staging": string;
|
|
103
96
|
};
|
|
104
97
|
|
|
105
98
|
/**
|
|
@@ -115,6 +108,8 @@ export declare function extractAnchors(html: string): AnchorInfo[];
|
|
|
115
108
|
*/
|
|
116
109
|
export declare function extractText(html: string): string;
|
|
117
110
|
|
|
111
|
+
export declare function formatLinkMessage(locale: string, ruleId: LinkRuleMessageId, params?: Record<string, string | number>): string;
|
|
112
|
+
|
|
118
113
|
/**
|
|
119
114
|
* Resolve a localized message for a rule. `params` interpolate `{name}`
|
|
120
115
|
* placeholders. Falls back to English when the locale doesn't ship the
|
|
@@ -122,6 +117,8 @@ export declare function extractText(html: string): string;
|
|
|
122
117
|
*/
|
|
123
118
|
export declare function formatMessage(locale: string, ruleId: RuleMessageId, params?: Record<string, string | number>): string;
|
|
124
119
|
|
|
120
|
+
export declare function formatStructureMessage(locale: string, ruleId: StructureRuleMessageId, params?: Record<string, string | number>): string;
|
|
121
|
+
|
|
125
122
|
/**
|
|
126
123
|
* WCAG 2.1 sRGB relative-luminance contrast.
|
|
127
124
|
*
|
|
@@ -145,20 +142,94 @@ export declare function getContrastRatio(fg: string, bg: string): number;
|
|
|
145
142
|
*/
|
|
146
143
|
export declare function getDictionary(_locale: string): Dictionary;
|
|
147
144
|
|
|
145
|
+
export declare function getLinkMessages(locale: string): LinkMessageMap;
|
|
146
|
+
|
|
148
147
|
export declare function getMessages(locale: string): MessageMap;
|
|
149
148
|
|
|
149
|
+
export declare function getStructureMessages(locale: string): StructureMessageMap;
|
|
150
|
+
|
|
150
151
|
export declare function isOpaqueHex(input: string | undefined | null): boolean;
|
|
151
152
|
|
|
152
|
-
export declare
|
|
153
|
+
export declare const LINK_RULES: Rule[];
|
|
154
|
+
|
|
155
|
+
export declare type LinkMessageMap = typeof en_4;
|
|
156
|
+
|
|
157
|
+
export declare type LinkRuleMessageId = keyof LinkMessageMap;
|
|
158
|
+
|
|
159
|
+
export declare function lintAccessibility(content: TemplateContent, options?: LintOptions): LintIssue[];
|
|
160
|
+
|
|
161
|
+
export declare interface LintIssue {
|
|
162
|
+
/** Block id, or null for template-level issues. */
|
|
163
|
+
blockId: string | null;
|
|
164
|
+
ruleId: string;
|
|
165
|
+
severity: Exclude<Severity, "off">;
|
|
166
|
+
message: string;
|
|
167
|
+
fix?: LintPatch;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export declare function lintLinks(content: TemplateContent, options?: LintOptions): LintIssue[];
|
|
171
|
+
|
|
172
|
+
export declare interface LintLinksOptions {
|
|
173
|
+
/**
|
|
174
|
+
* Host patterns that should flag as "staging / non-production".
|
|
175
|
+
* Each entry is a glob-style pattern matched against the URL host.
|
|
176
|
+
* `*` matches any run of characters (including `.`), so `*.staging.*`
|
|
177
|
+
* matches `app.staging.example.com`.
|
|
178
|
+
*
|
|
179
|
+
* Default: ['localhost', '127.0.0.1', '0.0.0.0', '*.local',
|
|
180
|
+
* '*.staging.*', '*.dev.*']
|
|
181
|
+
*/
|
|
182
|
+
nonProductionHosts?: string[];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export declare interface LintOptions {
|
|
186
|
+
/**
|
|
187
|
+
* Fully disable linting. When true, the editor skips lazy-loading the
|
|
188
|
+
* package, hides the sidebar tab, and suppresses inline badges.
|
|
189
|
+
*/
|
|
190
|
+
disabled?: boolean;
|
|
191
|
+
/** Locale for vague-text dictionaries and message text. Falls back to `en`. */
|
|
192
|
+
locale?: string;
|
|
193
|
+
/** Per-rule severity override. Set to `'off'` to disable a specific rule. */
|
|
194
|
+
rules?: Record<string, Severity>;
|
|
195
|
+
thresholds?: Partial<LintThresholds>;
|
|
196
|
+
/** Per-linter knobs. Only `lintLinks` reads `links` today. */
|
|
197
|
+
links?: LintLinksOptions;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export declare interface LintPatch {
|
|
201
|
+
description: string;
|
|
202
|
+
apply: (ctx: LintPatchContext) => void;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export declare interface LintPatchContext {
|
|
206
|
+
updateBlock: (blockId: string, patch: Partial<Block>) => void;
|
|
207
|
+
updateSettings: (patch: Partial<TemplateSettings>) => void;
|
|
208
|
+
removeBlock: (blockId: string) => void;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export declare function lintStructure(content: TemplateContent, options?: LintOptions): LintIssue[];
|
|
212
|
+
|
|
213
|
+
export declare interface LintThresholds {
|
|
214
|
+
altMaxLength: number;
|
|
215
|
+
minFontSize: number;
|
|
216
|
+
allCapsMinLength: number;
|
|
217
|
+
minTouchTargetPx: number;
|
|
218
|
+
}
|
|
153
219
|
|
|
154
220
|
export declare type MessageMap = typeof en_2;
|
|
155
221
|
|
|
156
222
|
export declare function parseHex(input: string | undefined | null): Rgb | null;
|
|
157
223
|
|
|
224
|
+
export declare interface ResolvedLinksOptions {
|
|
225
|
+
nonProductionHosts: string[];
|
|
226
|
+
}
|
|
227
|
+
|
|
158
228
|
export declare interface ResolvedOptions {
|
|
159
229
|
locale: string;
|
|
160
230
|
rules: Record<string, Severity>;
|
|
161
|
-
thresholds:
|
|
231
|
+
thresholds: LintThresholds;
|
|
232
|
+
links: ResolvedLinksOptions;
|
|
162
233
|
/** Returns the effective severity for a rule (override or default). */
|
|
163
234
|
severity: (ruleId: string) => Severity;
|
|
164
235
|
}
|
|
@@ -186,7 +257,7 @@ export declare interface RuleHit {
|
|
|
186
257
|
blockId: string | null;
|
|
187
258
|
/** Interpolation values for the rule's localized message template. */
|
|
188
259
|
params?: Record<string, string | number>;
|
|
189
|
-
fix?:
|
|
260
|
+
fix?: LintPatch;
|
|
190
261
|
}
|
|
191
262
|
|
|
192
263
|
export declare type RuleMessageId = keyof MessageMap;
|
|
@@ -198,14 +269,32 @@ export declare interface RuleMeta {
|
|
|
198
269
|
severity: Exclude<Severity, "off">;
|
|
199
270
|
}
|
|
200
271
|
|
|
201
|
-
export declare const RULES: Rule[];
|
|
202
|
-
|
|
203
272
|
export declare type Severity = "error" | "warning" | "info" | "off";
|
|
204
273
|
|
|
274
|
+
export declare const STRUCTURE_RULES: Rule[];
|
|
275
|
+
|
|
276
|
+
export declare type StructureMessageMap = typeof en_3;
|
|
277
|
+
|
|
278
|
+
export declare type StructureRuleMessageId = keyof StructureMessageMap;
|
|
279
|
+
|
|
205
280
|
export declare const SUPPORTED_DICTIONARY_LOCALES: string[];
|
|
206
281
|
|
|
282
|
+
export declare const SUPPORTED_LINK_MESSAGE_LOCALES: string[];
|
|
283
|
+
|
|
207
284
|
export declare const SUPPORTED_MESSAGE_LOCALES: string[];
|
|
208
285
|
|
|
286
|
+
export declare const SUPPORTED_STRUCTURE_MESSAGE_LOCALES: string[];
|
|
287
|
+
|
|
288
|
+
export declare interface UrlOccurrence {
|
|
289
|
+
url: string;
|
|
290
|
+
blockId: string;
|
|
291
|
+
source: UrlSource;
|
|
292
|
+
/** Anchor text or block-derived label, if applicable. */
|
|
293
|
+
label?: string;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export declare type UrlSource = "anchor" | "button" | "image-link" | "video" | "menu-item" | "social-icon";
|
|
297
|
+
|
|
209
298
|
export declare type Visitor = (block: Block, ctx: WalkContext) => void;
|
|
210
299
|
|
|
211
300
|
/**
|
|
@@ -231,4 +320,20 @@ export declare interface WalkContext {
|
|
|
231
320
|
resolvedBackgroundColor: string;
|
|
232
321
|
}
|
|
233
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Visit every URL-bearing field in the template tree.
|
|
325
|
+
*
|
|
326
|
+
* Sources covered:
|
|
327
|
+
* - anchor — `<a href>` inside `title.content`, `paragraph.content`,
|
|
328
|
+
* `html.content` (parsed via extractAnchors)
|
|
329
|
+
* - button — `button.url`
|
|
330
|
+
* - image-link — `image.linkUrl` (only when present + non-empty)
|
|
331
|
+
* - video — `video.url`
|
|
332
|
+
* - menu-item — `menu.items[i].url`
|
|
333
|
+
* - social-icon — `social.icons[i].url`
|
|
334
|
+
*
|
|
335
|
+
* Each rule iterates this list once and decides per occurrence.
|
|
336
|
+
*/
|
|
337
|
+
export declare function walkUrls(content: TemplateContent_2): UrlOccurrence[];
|
|
338
|
+
|
|
234
339
|
export { }
|