@templatical/quality 0.7.3 → 0.8.1
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 +206 -61
- package/dist/index.js +691 -258
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -4,43 +4,12 @@ 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
|
-
}
|
|
7
|
+
export declare const ACCESSIBILITY_RULES: Rule[];
|
|
38
8
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
minTouchTargetPx: number;
|
|
9
|
+
/** Options consumed only by the accessibility linter. */
|
|
10
|
+
export declare interface AccessibilityLintOptions {
|
|
11
|
+
rules?: RuleOverrides;
|
|
12
|
+
thresholds?: Partial<LintThresholds>;
|
|
44
13
|
}
|
|
45
14
|
|
|
46
15
|
export declare interface AnchorInfo {
|
|
@@ -52,7 +21,9 @@ export declare interface AnchorInfo {
|
|
|
52
21
|
hasImageWithAlt: boolean;
|
|
53
22
|
}
|
|
54
23
|
|
|
55
|
-
export declare const
|
|
24
|
+
export declare const DEFAULT_A11Y_THRESHOLDS: LintThresholds;
|
|
25
|
+
|
|
26
|
+
export declare const DEFAULT_NON_PRODUCTION_HOSTS: string[];
|
|
56
27
|
|
|
57
28
|
export declare type Dictionary = typeof en;
|
|
58
29
|
|
|
@@ -81,25 +52,53 @@ declare const en: {
|
|
|
81
52
|
* Templates use `{name}` placeholders, interpolated by `formatMessage`.
|
|
82
53
|
*/
|
|
83
54
|
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;
|
|
55
|
+
"a11y.img-missing-alt": string;
|
|
56
|
+
"a11y.img-alt-is-filename": string;
|
|
57
|
+
"a11y.img-alt-too-long": string;
|
|
58
|
+
"a11y.img-decorative-needs-empty-alt": string;
|
|
59
|
+
"a11y.img-linked-no-context": string;
|
|
60
|
+
"a11y.heading-empty": string;
|
|
61
|
+
"a11y.heading-skip-level": string;
|
|
62
|
+
"a11y.heading-multiple-h1": string;
|
|
63
|
+
"a11y.link-empty": string;
|
|
64
|
+
"a11y.link-vague-text": string;
|
|
65
|
+
"a11y.link-href-empty": string;
|
|
66
|
+
"a11y.link-target-blank-no-rel": string;
|
|
67
|
+
"a11y.text-all-caps": string;
|
|
68
|
+
"a11y.text-low-contrast": string;
|
|
69
|
+
"a11y.text-too-small": string;
|
|
70
|
+
"a11y.button-vague-label": string;
|
|
71
|
+
"a11y.button-touch-target": string;
|
|
72
|
+
"a11y.button-low-contrast": string;
|
|
73
|
+
"a11y.missing-preheader": string;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* English structure-rule messages. The source of truth — other locales
|
|
78
|
+
* annotate themselves `typeof en` so missing or extra keys fail typecheck.
|
|
79
|
+
*
|
|
80
|
+
* Templates use `{name}` placeholders, interpolated by `formatMessage`.
|
|
81
|
+
*/
|
|
82
|
+
declare const en_3: {
|
|
83
|
+
"structure.duplicate-block-id": string;
|
|
84
|
+
"structure.section-column-mismatch": string;
|
|
85
|
+
"structure.nested-section": string;
|
|
86
|
+
"structure.empty-section": string;
|
|
87
|
+
"structure.empty-column": string;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* English link-rule messages. The source of truth — other locales annotate
|
|
92
|
+
* themselves `typeof en` so missing or extra keys fail typecheck.
|
|
93
|
+
*
|
|
94
|
+
* Templates use `{name}` placeholders, interpolated by `formatLinkMessage`.
|
|
95
|
+
*/
|
|
96
|
+
declare const en_4: {
|
|
97
|
+
"link.javascript-protocol": string;
|
|
98
|
+
"link.unsupported-protocol": string;
|
|
99
|
+
"link.malformed-mailto": string;
|
|
100
|
+
"link.malformed-tel": string;
|
|
101
|
+
"link.localhost-or-staging": string;
|
|
103
102
|
};
|
|
104
103
|
|
|
105
104
|
/**
|
|
@@ -115,6 +114,8 @@ export declare function extractAnchors(html: string): AnchorInfo[];
|
|
|
115
114
|
*/
|
|
116
115
|
export declare function extractText(html: string): string;
|
|
117
116
|
|
|
117
|
+
export declare function formatLinkMessage(locale: string, ruleId: LinkRuleMessageId, params?: Record<string, string | number>): string;
|
|
118
|
+
|
|
118
119
|
/**
|
|
119
120
|
* Resolve a localized message for a rule. `params` interpolate `{name}`
|
|
120
121
|
* placeholders. Falls back to English when the locale doesn't ship the
|
|
@@ -122,6 +123,8 @@ export declare function extractText(html: string): string;
|
|
|
122
123
|
*/
|
|
123
124
|
export declare function formatMessage(locale: string, ruleId: RuleMessageId, params?: Record<string, string | number>): string;
|
|
124
125
|
|
|
126
|
+
export declare function formatStructureMessage(locale: string, ruleId: StructureRuleMessageId, params?: Record<string, string | number>): string;
|
|
127
|
+
|
|
125
128
|
/**
|
|
126
129
|
* WCAG 2.1 sRGB relative-luminance contrast.
|
|
127
130
|
*
|
|
@@ -145,20 +148,116 @@ export declare function getContrastRatio(fg: string, bg: string): number;
|
|
|
145
148
|
*/
|
|
146
149
|
export declare function getDictionary(_locale: string): Dictionary;
|
|
147
150
|
|
|
151
|
+
export declare function getLinkMessages(locale: string): LinkMessageMap;
|
|
152
|
+
|
|
148
153
|
export declare function getMessages(locale: string): MessageMap;
|
|
149
154
|
|
|
155
|
+
export declare function getStructureMessages(locale: string): StructureMessageMap;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* `true` when no linter would run for the given options — either the
|
|
159
|
+
* global `disabled` flag is set, or every per-tool key is `false`.
|
|
160
|
+
*
|
|
161
|
+
* The editor uses this to skip lazy-loading `@templatical/quality`, hide
|
|
162
|
+
* the Issues sidebar tab, and suppress inline canvas badges. Headless
|
|
163
|
+
* callers can use it to short-circuit before any linter call.
|
|
164
|
+
*/
|
|
165
|
+
export declare function isLintFullyDisabled(options: LintOptions | undefined): boolean;
|
|
166
|
+
|
|
150
167
|
export declare function isOpaqueHex(input: string | undefined | null): boolean;
|
|
151
168
|
|
|
152
|
-
export declare
|
|
169
|
+
export declare const LINK_RULES: Rule[];
|
|
170
|
+
|
|
171
|
+
export declare type LinkMessageMap = typeof en_4;
|
|
172
|
+
|
|
173
|
+
export declare type LinkRuleMessageId = keyof LinkMessageMap;
|
|
174
|
+
|
|
175
|
+
/** Options consumed only by the links linter. */
|
|
176
|
+
export declare interface LinksLintOptions {
|
|
177
|
+
rules?: RuleOverrides;
|
|
178
|
+
/**
|
|
179
|
+
* Host patterns that should flag as "staging / non-production".
|
|
180
|
+
* Each entry is a glob-style pattern matched against the URL host.
|
|
181
|
+
* `*` matches any run of characters (including `.`), so `*.staging.*`
|
|
182
|
+
* matches `app.staging.example.com`.
|
|
183
|
+
*
|
|
184
|
+
* Default: ['localhost', '127.0.0.1', '0.0.0.0', '*.local',
|
|
185
|
+
* '*.staging.*', '*.dev.*']
|
|
186
|
+
*/
|
|
187
|
+
nonProductionHosts?: string[];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export declare function lintAccessibility(content: TemplateContent, options?: LintOptions): LintIssue[];
|
|
191
|
+
|
|
192
|
+
export declare interface LintIssue {
|
|
193
|
+
/** Block id, or null for template-level issues. */
|
|
194
|
+
blockId: string | null;
|
|
195
|
+
ruleId: string;
|
|
196
|
+
severity: Exclude<Severity, "off">;
|
|
197
|
+
message: string;
|
|
198
|
+
fix?: LintPatch;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export declare function lintLinks(content: TemplateContent, options?: LintOptions): LintIssue[];
|
|
202
|
+
|
|
203
|
+
export declare interface LintOptions {
|
|
204
|
+
/**
|
|
205
|
+
* Fully disable linting. When true, the editor skips lazy-loading the
|
|
206
|
+
* package, hides the sidebar tab, and suppresses inline badges.
|
|
207
|
+
*/
|
|
208
|
+
disabled?: boolean;
|
|
209
|
+
/** Locale for vague-text dictionaries and message text. Falls back to `en`. */
|
|
210
|
+
locale?: string;
|
|
211
|
+
/**
|
|
212
|
+
* Accessibility linter config. Set to `false` to disable the whole
|
|
213
|
+
* `lintAccessibility` linter without enumerating its rules.
|
|
214
|
+
*/
|
|
215
|
+
accessibility?: false | AccessibilityLintOptions;
|
|
216
|
+
/**
|
|
217
|
+
* Structure linter config. Set to `false` to disable the whole
|
|
218
|
+
* `lintStructure` linter without enumerating its rules.
|
|
219
|
+
*/
|
|
220
|
+
structure?: false | StructureLintOptions;
|
|
221
|
+
/**
|
|
222
|
+
* Links linter config. Set to `false` to disable the whole `lintLinks`
|
|
223
|
+
* linter without enumerating its rules.
|
|
224
|
+
*/
|
|
225
|
+
links?: false | LinksLintOptions;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export declare interface LintPatch {
|
|
229
|
+
description: string;
|
|
230
|
+
apply: (ctx: LintPatchContext) => void;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export declare interface LintPatchContext {
|
|
234
|
+
updateBlock: (blockId: string, patch: Partial<Block>) => void;
|
|
235
|
+
updateSettings: (patch: Partial<TemplateSettings>) => void;
|
|
236
|
+
removeBlock: (blockId: string) => void;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export declare function lintStructure(content: TemplateContent, options?: LintOptions): LintIssue[];
|
|
240
|
+
|
|
241
|
+
export declare interface LintThresholds {
|
|
242
|
+
altMaxLength: number;
|
|
243
|
+
minFontSize: number;
|
|
244
|
+
allCapsMinLength: number;
|
|
245
|
+
minTouchTargetPx: number;
|
|
246
|
+
}
|
|
153
247
|
|
|
154
248
|
export declare type MessageMap = typeof en_2;
|
|
155
249
|
|
|
156
250
|
export declare function parseHex(input: string | undefined | null): Rgb | null;
|
|
157
251
|
|
|
252
|
+
export declare interface ResolvedLinksOptions {
|
|
253
|
+
nonProductionHosts: string[];
|
|
254
|
+
}
|
|
255
|
+
|
|
158
256
|
export declare interface ResolvedOptions {
|
|
159
257
|
locale: string;
|
|
160
|
-
rules:
|
|
161
|
-
thresholds:
|
|
258
|
+
rules: RuleOverrides;
|
|
259
|
+
thresholds: LintThresholds;
|
|
260
|
+
links: ResolvedLinksOptions;
|
|
162
261
|
/** Returns the effective severity for a rule (override or default). */
|
|
163
262
|
severity: (ruleId: string) => Severity;
|
|
164
263
|
}
|
|
@@ -186,7 +285,7 @@ export declare interface RuleHit {
|
|
|
186
285
|
blockId: string | null;
|
|
187
286
|
/** Interpolation values for the rule's localized message template. */
|
|
188
287
|
params?: Record<string, string | number>;
|
|
189
|
-
fix?:
|
|
288
|
+
fix?: LintPatch;
|
|
190
289
|
}
|
|
191
290
|
|
|
192
291
|
export declare type RuleMessageId = keyof MessageMap;
|
|
@@ -198,14 +297,44 @@ export declare interface RuleMeta {
|
|
|
198
297
|
severity: Exclude<Severity, "off">;
|
|
199
298
|
}
|
|
200
299
|
|
|
201
|
-
|
|
300
|
+
/**
|
|
301
|
+
* Per-rule severity override. Set a rule to `'off'` to disable it.
|
|
302
|
+
* Keys are the full prefixed rule IDs (`a11y.*`, `structure.*`, `link.*`)
|
|
303
|
+
* so a value copied from `LintIssue.ruleId` pastes straight in.
|
|
304
|
+
*/
|
|
305
|
+
export declare type RuleOverrides = Record<string, Severity>;
|
|
202
306
|
|
|
203
307
|
export declare type Severity = "error" | "warning" | "info" | "off";
|
|
204
308
|
|
|
309
|
+
export declare const STRUCTURE_RULES: Rule[];
|
|
310
|
+
|
|
311
|
+
/** Options consumed only by the structure linter. */
|
|
312
|
+
export declare interface StructureLintOptions {
|
|
313
|
+
rules?: RuleOverrides;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export declare type StructureMessageMap = typeof en_3;
|
|
317
|
+
|
|
318
|
+
export declare type StructureRuleMessageId = keyof StructureMessageMap;
|
|
319
|
+
|
|
205
320
|
export declare const SUPPORTED_DICTIONARY_LOCALES: string[];
|
|
206
321
|
|
|
322
|
+
export declare const SUPPORTED_LINK_MESSAGE_LOCALES: string[];
|
|
323
|
+
|
|
207
324
|
export declare const SUPPORTED_MESSAGE_LOCALES: string[];
|
|
208
325
|
|
|
326
|
+
export declare const SUPPORTED_STRUCTURE_MESSAGE_LOCALES: string[];
|
|
327
|
+
|
|
328
|
+
export declare interface UrlOccurrence {
|
|
329
|
+
url: string;
|
|
330
|
+
blockId: string;
|
|
331
|
+
source: UrlSource;
|
|
332
|
+
/** Anchor text or block-derived label, if applicable. */
|
|
333
|
+
label?: string;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export declare type UrlSource = "anchor" | "button" | "image-link" | "video" | "menu-item" | "social-icon";
|
|
337
|
+
|
|
209
338
|
export declare type Visitor = (block: Block, ctx: WalkContext) => void;
|
|
210
339
|
|
|
211
340
|
/**
|
|
@@ -231,4 +360,20 @@ export declare interface WalkContext {
|
|
|
231
360
|
resolvedBackgroundColor: string;
|
|
232
361
|
}
|
|
233
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Visit every URL-bearing field in the template tree.
|
|
365
|
+
*
|
|
366
|
+
* Sources covered:
|
|
367
|
+
* - anchor — `<a href>` inside `title.content`, `paragraph.content`,
|
|
368
|
+
* `html.content` (parsed via extractAnchors)
|
|
369
|
+
* - button — `button.url`
|
|
370
|
+
* - image-link — `image.linkUrl` (only when present + non-empty)
|
|
371
|
+
* - video — `video.url`
|
|
372
|
+
* - menu-item — `menu.items[i].url`
|
|
373
|
+
* - social-icon — `social.icons[i].url`
|
|
374
|
+
*
|
|
375
|
+
* Each rule iterates this list once and decides per occurrence.
|
|
376
|
+
*/
|
|
377
|
+
export declare function walkUrls(content: TemplateContent_2): UrlOccurrence[];
|
|
378
|
+
|
|
234
379
|
export { }
|