@markuplint/rules 2.0.0-dev.2021117.3 → 2.0.0-dev.20211213.2

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.
@@ -1,8 +1,14 @@
1
1
  import type { Translator } from '@markuplint/i18n';
2
- import type { Attribute as AttrSpec } from '@markuplint/ml-spec';
2
+ import type { Attribute as AttrSpec, AttributeType } from '@markuplint/ml-spec';
3
3
  declare type Invalid = {
4
4
  invalidType: 'non-existent' | 'invalid-value';
5
5
  message: string;
6
+ loc?: Loc;
7
+ };
8
+ declare type Loc = {
9
+ raw: string;
10
+ line: number;
11
+ col: number;
6
12
  };
7
13
  /**
8
14
  * Use in rules `invalid-attr` and `wai-aria`
@@ -13,4 +19,5 @@ declare type Invalid = {
13
19
  * @param spec
14
20
  */
15
21
  export declare function attrCheck(t: Translator, name: string, value: string, isCustomRule: boolean, spec?: AttrSpec): Invalid | false;
22
+ export declare function valueCheck(t: Translator, name: string, value: string, type: AttributeType): string | [string, Loc] | false;
16
23
  export {};
package/lib/attr-check.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.attrCheck = void 0;
4
- const primitive_check_1 = require("./primitive-check");
3
+ exports.valueCheck = exports.attrCheck = void 0;
4
+ const types_1 = require("@markuplint/types");
5
+ const create_message_1 = require("./create-message");
6
+ const debug_1 = require("./debug");
5
7
  /**
6
8
  * Use in rules `invalid-attr` and `wai-aria`
7
9
  *
@@ -23,476 +25,70 @@ function attrCheck(t, name, value, isCustomRule, spec) {
23
25
  }
24
26
  // Existance
25
27
  if (!spec) {
28
+ (0, debug_1.log)('The "%s" attribute DOES\'NT EXIST in the spec', name);
26
29
  return {
27
30
  invalidType: 'non-existent',
28
31
  message: t('{0} is {1:c}', t('the "{0}" {1}', name, 'attribute'), 'disallowed'),
29
32
  };
30
33
  }
31
- const invalid = valueCheck(t, name, value, spec);
32
- if (invalid) {
34
+ const nameCaseSensitive = /[A-Z]/.test(spec.name);
35
+ if (nameCaseSensitive && name !== spec.name) {
36
+ (0, debug_1.log)('The "%s" attribute name is unmatched in case-sensitive', name);
33
37
  return {
34
- invalidType: 'invalid-value',
35
- message: invalid,
38
+ invalidType: 'non-existent',
39
+ message: t('{0} is {1:c}', t('the "{0}" {1}', name, 'attribute'), 'disallowed') +
40
+ t('. ') +
41
+ t('Did you mean "{0*}"?', spec.name),
36
42
  };
37
43
  }
38
- return false;
39
- }
40
- exports.attrCheck = attrCheck;
41
- function valueCheck(t, name, value, spec) {
42
- // Valid because any string value is acceptable
43
- if (typeof spec.type !== 'string' && 'enum' in spec.type) {
44
- // has "enum"
45
- return includesEnum(t, name, value, spec.type.enum);
46
- }
47
- const t_theNameAttribute = t('the "{0}" {1}', name, 'attribute');
48
- if (spec.type === 'NonEmptyString' && value === '') {
49
- return t('{0} must not be {1}', t('{0} of {1}', t('the {0}', 'value'), t_theNameAttribute), 'empty string');
50
- }
51
- if (spec.type === 'Boolean') {
52
- // Valid because an attribute is exist
53
- return false;
54
- }
55
- if (spec.type === 'Function') {
56
- // TODO: To eval function-body string
57
- return false;
58
- }
59
- if (spec.type === 'Date') {
60
- // TODO: https://html.spec.whatwg.org/multipage/text-level-semantics.html#datetime-value
61
- return false;
62
- }
63
- if (spec.type === 'Int') {
64
- if ((0, primitive_check_1.intCheck)(value)) {
65
- return false;
66
- }
67
- return t('{0} expects {1}', t_theNameAttribute, 'integer');
68
- }
69
- if (spec.type === 'Uint') {
70
- if ((0, primitive_check_1.uintCheck)(value)) {
71
- return false;
72
- }
73
- return t('{0} expects {1}', t_theNameAttribute, 'non-negative integer');
74
- }
75
- if (spec.type === 'Float') {
76
- if ((0, primitive_check_1.floatCheck)(value)) {
77
- return false;
78
- }
79
- return t('{0} expects {1}', t_theNameAttribute, 'floating-point number');
80
- }
81
- if (spec.type === 'NonZeroUint') {
82
- if ((0, primitive_check_1.nonZeroUintCheck)(value)) {
83
- return false;
84
- }
85
- return t('{0} expects {1}', t_theNameAttribute, t('{0} greater than {1}', 'floating-point number', 'zero'));
86
- }
87
- if (spec.type === 'ZeroToOne') {
88
- if ((0, primitive_check_1.range)(value, 0, 1)) {
89
- return false;
90
- }
91
- return t('{0} expects {1:c}', t_theNameAttribute, t('in the range between {0} and {1}', 'zero', 'one'));
92
- }
93
- if (spec.type === 'AcceptList') {
94
- // TODO: https://html.spec.whatwg.org/multipage/input.html#attr-input-accept
95
- return false;
96
- }
97
- if (spec.type === 'AutoComplete') {
98
- // TODO: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-detail-tokens
99
- return false;
100
- }
101
- if (spec.type === 'BCP47') {
102
- // TODO: https://tools.ietf.org/html/bcp47
103
- return false;
104
- }
105
- if (spec.type === 'Color') {
106
- // TODO: https://drafts.csswg.org/css-color/#typedef-color
107
- return false;
108
- }
109
- if (spec.type === 'ColSpan') {
110
- /**
111
- * > value must be a valid non-negative integer greater than zero and less than or equal to 1000.
112
- *
113
- * @see https://html.spec.whatwg.org/multipage/tables.html#attr-tdth-colspan
114
- */
115
- if ((0, primitive_check_1.intCheck)(value) && (0, primitive_check_1.range)(value, 0, 1000)) {
116
- return false;
44
+ const types = Array.isArray(spec.type) ? spec.type : [spec.type];
45
+ const invalidList = types.map(type => {
46
+ if (!type) {
47
+ (0, debug_1.log)('attrCheck: %o', arguments);
48
+ throw new Error('type is empty in spec');
117
49
  }
118
- return t('{0} expects {1:c}', t_theNameAttribute, t('{0:c} and {1:c}', t('{0} greater than {1}', 'non-negative integer', 'zero'), t('less than or equal to {0}', 1000)));
119
- }
120
- if (spec.type === 'Coords') {
121
- // TODO: https://html.spec.whatwg.org/multipage/image-maps.html#attr-area-coords
122
- return false;
123
- }
124
- if (spec.type === 'Crossorigin') {
125
- // TODO: https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes
126
- return false;
127
- }
128
- if (spec.type === 'DateTime') {
129
- // TODO: https://html.spec.whatwg.org/multipage/text-level-semantics.html#datetime-value
130
- return false;
131
- }
132
- if (spec.type === 'Destination') {
133
- // TODO: https://html.spec.whatwg.org/multipage/semantics.html#attr-link-as
134
- return false;
135
- }
136
- if (spec.type === 'DOMID') {
137
- // TODO: Searching ID in Document
138
- return false;
139
- }
140
- if (spec.type === 'DOMIDList') {
141
- // TODO: Searching ID in Document
142
- return false;
143
- }
144
- if (spec.type === 'IRI') {
145
- // TODO: https://developer.mozilla.org/ja/docs/Web/SVG/Content_type#iri
146
- return false;
147
- }
148
- if (spec.type === 'ItemType') {
149
- // TODO: https://html.spec.whatwg.org/multipage/microdata.html#attr-itemtype
150
- return false;
151
- }
152
- if (spec.type === 'LinkSizes') {
153
- // TODO: https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes
154
- return false;
155
- }
156
- if (spec.type === 'LinkType') {
157
- // TODO: https://html.spec.whatwg.org/multipage/links.html#linkTypes
158
- return false;
159
- }
160
- if (spec.type === 'LinkTypeList') {
161
- // TODO: https://html.spec.whatwg.org/multipage/links.html#linkTypes
162
- return false;
163
- }
164
- if (spec.type === 'MediaQuery') {
165
- // TODO: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-media-query-list
166
- return false;
167
- }
168
- if (spec.type === 'MediaQueryList') {
169
- // TODO: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-media-query-list
170
- return false;
171
- }
172
- if (spec.type === 'MIMEType') {
173
- // TODO: https://mimesniff.spec.whatwg.org/#valid-mime-type
174
- return false;
175
- }
176
- if (spec.type === 'ReferrerPolicy') {
177
- /**
178
- * @see https://html.spec.whatwg.org/multipage/urls-and-fetching.html#referrer-policy-attributes
179
- */
180
- return includesEnum(t, name, value, [
181
- '',
182
- 'no-referrer',
183
- 'no-referrer-when-downgrade',
184
- 'same-origin',
185
- 'origin',
186
- 'strict-origin',
187
- 'origin-when-cross-origin',
188
- 'strict-origin-when-cross-origin',
189
- 'unsafe-url',
190
- ]);
191
- }
192
- if (spec.type === 'RowSpan') {
193
- /**
194
- * > value must be a valid non-negative integer less than or equal to 65534.
195
- *
196
- * @see https://html.spec.whatwg.org/multipage/tables.html#attr-tdth-rowspan
197
- */
198
- if ((0, primitive_check_1.intCheck)(value) && (0, primitive_check_1.range)(value, 0, 65534)) {
199
- return false;
200
- }
201
- return t('{0} expects {1:c}', t_theNameAttribute, t('{0:c} and {1:c}', t('{0} greater than {1}', 'non-negative integer', 'zero'), t('less than or equal to {0}', 65534)));
202
- }
203
- if (spec.type === 'SourceSizeList') {
204
- // TODO: https://html.spec.whatwg.org/multipage/images.html#sizes-attributes
205
- return false;
206
- }
207
- if (spec.type === 'SrcSet') {
208
- // TODO: https://html.spec.whatwg.org/multipage/images.html#srcset-attribute
209
- return false;
210
- }
211
- if (spec.type === 'TabIndex') {
212
- /**
213
- * > ## omitted (or non-integer values)
214
- * >
215
- * > The user agent will decide whether the element is focusable, and if it is, whether it is sequentially focusable or click focusable (or both).
216
- * >
217
- * > ## −1 (or other negative integer values)
218
- * >
219
- * > Causes the element to be focusable, and indicates that the author would prefer the element to be click focusable but not sequentially focusable. The user agent might ignore this preference for click and sequential focusability, e.g., for specific element types according to platform conventions, or for keyboard-only users.
220
- * >
221
- * > ## 0
222
- * >
223
- * > Causes the element to be focusable, and indicates that the author would prefer the element to be both click focusable and sequentially focusable. The user agent might ignore this preference for click and sequential focusabiity.
224
- * >
225
- * > ## positive integer values
226
- * >
227
- * > Behaves the same as 0, but in addition creates a relative ordering within a tabindex-ordered focus navigation scope, so that elements with higher tabindex attribute value come later.
228
- *
229
- * @see https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex
230
- */
231
- if ((0, primitive_check_1.intCheck)(value)) {
232
- const i = parseInt(value);
233
- if (-1 <= i) {
234
- return false;
50
+ const invalid = valueCheck(t, name, value, type);
51
+ if (invalid) {
52
+ if (typeof invalid === 'string') {
53
+ return {
54
+ invalidType: 'invalid-value',
55
+ message: invalid,
56
+ };
235
57
  }
236
- if (-1 > i) {
237
- return t('{0} behaves the same as {1} if {2}', t_theNameAttribute, '-1', t('less than {0}', '-1'));
58
+ else {
59
+ return {
60
+ invalidType: 'invalid-value',
61
+ message: invalid[0],
62
+ loc: invalid[1],
63
+ };
238
64
  }
239
65
  }
240
- return t('{0} expects {1:c}', t_theNameAttribute, t('either {0}', t(['-1', 'zero', 'non-negative integer'])));
241
- }
242
- if (spec.type === 'Target') {
243
- // TODO: https://html.spec.whatwg.org/multipage/links.html#attr-hyperlink-target
244
- return false;
245
- }
246
- if (spec.type === 'URL') {
247
- // TODO: https://html.spec.whatwg.org/multipage/urls-and-fetching.html#valid-url-potentially-surrounded-by-spaces
248
66
  return false;
249
- }
250
- if (spec.type === 'URLHash') {
251
- /**
252
- * https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-hash-name-reference
253
- */
254
- const valid = value[0] === '#';
255
- if (valid) {
256
- return false;
257
- }
258
- return t('{0} expects {1:c}', t_theNameAttribute, t('valid {0}', 'hash-name reference'));
259
- }
260
- if (spec.type === 'URLList') {
261
- // TODO: https://html.spec.whatwg.org/multipage/urls-and-fetching.html#valid-url-potentially-surrounded-by-spaces
262
- return false;
263
- }
264
- if (spec.type === 'CSSAngle') {
265
- /**
266
- * @see https://drafts.csswg.org/css-values/#angles
267
- */
268
- const valid = (0, primitive_check_1.numberCheckWithUnit)(value, ['deg', 'grad', 'rad', 'turn']);
269
- if (valid) {
270
- return false;
271
- }
272
- return t('{0} expects {1}', t_theNameAttribute, 'angle');
273
- }
274
- if (spec.type === 'CSSBlendMode') {
275
- /**
276
- * @see https://drafts.fxtf.org/compositing/#ltblendmodegt
277
- */
278
- return includesEnum(t, name, value, [
279
- 'normal',
280
- 'multiply',
281
- 'screen',
282
- 'overlay',
283
- 'darken',
284
- 'lighten',
285
- 'color-dodge',
286
- 'color-burn',
287
- 'hard-light',
288
- 'soft-light',
289
- 'difference',
290
- 'exclusion',
291
- 'hue',
292
- 'saturation',
293
- 'color',
294
- 'luminosity',
295
- ]);
296
- }
297
- if (spec.type === 'CSSClipPath') {
298
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path
67
+ });
68
+ if (invalidList.some(i => !i)) {
299
69
  return false;
300
70
  }
301
- if (spec.type === 'CSSCustomIdent') {
302
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
303
- return false;
304
- }
305
- if (spec.type === 'CSSDisplay') {
306
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/display
307
- return false;
308
- }
309
- if (spec.type === 'CSSFilter') {
310
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/filter
311
- return false;
312
- }
313
- if (spec.type === 'CSSFontFamily') {
314
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family
315
- return false;
316
- }
317
- if (spec.type === 'CSSFontSize') {
318
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size
319
- return false;
320
- }
321
- if (spec.type === 'CSSFontVariant') {
322
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant
323
- return false;
324
- }
325
- if (spec.type === 'CSSFontWeight') {
326
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight
327
- return false;
328
- }
329
- if (spec.type === 'CSSMask') {
330
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/mask
331
- return false;
332
- }
333
- if (spec.type === 'CSSOpacity') {
334
- /**
335
- * @see https://drafts.csswg.org/css-color/#typedef-alpha-value
336
- */
337
- const { num, unit } = (0, primitive_check_1.splitUnit)(value);
338
- if (unit === '%') {
339
- const vaild = (0, primitive_check_1.range)(num, 0, 100);
340
- if (vaild) {
341
- return false;
342
- }
343
- return t('{0} expects {1:c}', t_theNameAttribute, t('{0} as {1}', t('{0} to {1}', '0%', '100%'), 'alpha channel value'));
344
- }
345
- const vaild = (0, primitive_check_1.range)(num, 0, 1);
346
- if (vaild) {
347
- return false;
348
- }
349
- return t('{0} expects {1:c}', t_theNameAttribute, t('{0} as {1}', t('{0} to {1}', '0', '1'), 'alpha channel value'));
350
- }
351
- if (spec.type === 'CSSTextDecoration') {
352
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration
353
- return false;
354
- }
355
- if (spec.type === 'CSSTransformList') {
356
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function
357
- return false;
358
- }
359
- if (spec.type === 'CSSTransformOrigin') {
360
- // TODO: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
361
- return false;
362
- }
363
- if (spec.type === 'CSSURL') {
364
- // TODO: https://www.w3.org/TR/css3-values/#url-value
365
- return false;
366
- }
367
- if (spec.type === 'SVGAnimatableValue') {
368
- // TODO
369
- /**
370
- * The exact value type for this attribute depends on the value of the attribute
371
- * that will be animated.
372
- *
373
- * ```svg
374
- * <rect x="10" y="10" height="100">
375
- * <animate attributeName="width" fill="freeze" from="100" to="150" dur="3s"/>
376
- * </rect>
377
- * ```
378
- *
379
- * The `from` and `to` attributes of the `animate` element are SVGAnimatableValue.
380
- */
381
- return false;
382
- }
383
- if (spec.type === 'SVGBeginValueList') {
384
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/begin
385
- return false;
386
- }
387
- if (spec.type === 'SVGClockValue') {
388
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#clock-value
389
- return false;
390
- }
391
- if (spec.type === 'SVGColorMatrix') {
392
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feColorMatrix
393
- return false;
394
- }
395
- if (spec.type === 'SVGDashArray') {
396
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
397
- return false;
398
- }
399
- if (spec.type === 'SVGEndValueList') {
400
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/end
401
- return false;
402
- }
403
- if (spec.type === 'SVGFilterPrimitiveReference') {
404
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/result#usage_notes
405
- return false;
406
- }
407
- if (spec.type === 'SVGKernelMatrix') {
408
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/kernelMatrix
409
- return false;
410
- }
411
- if (spec.type === 'SVGKeyPoints') {
412
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/keyPoints
413
- return false;
414
- }
415
- if (spec.type === 'SVGKeySplines') {
416
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/keySplines
417
- return false;
418
- }
419
- if (spec.type === 'SVGKeyTimes') {
420
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/keyTimes
421
- return false;
422
- }
423
- if (spec.type === 'SVGLanguageTags') {
424
- /**
425
- * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/systemLanguage
426
- */
427
- // TODO: List of BCP47
428
- return false;
429
- }
430
- if (spec.type === 'SVGLength') {
431
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#length
432
- return false;
433
- }
434
- if (spec.type === 'SVGLengthList') {
435
- /**
436
- * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#length
437
- */
438
- // TODO: List of SVGLength
439
- return false;
440
- }
441
- if (spec.type === 'SVGNumberList') {
442
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/tableValues#usage_notes
443
- return false;
444
- }
445
- if (spec.type === 'SVGNumberOptionalNumber') {
446
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#number-optional-number
447
- return false;
448
- }
449
- if (spec.type === 'SVGOrigin') {
450
- // TODO: https://www.w3.org/TR/2001/REC-smil-animation-20010904/#MotionOriginAttribute
451
- return false;
452
- }
453
- if (spec.type === 'SVGPaint') {
454
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#paint
455
- return false;
456
- }
457
- if (spec.type === 'SVGPathCommands') {
458
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#path_commands
459
- return false;
460
- }
461
- if (spec.type === 'SVGPercentage') {
462
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#percentage
463
- return false;
464
- }
465
- if (spec.type === 'SVGPercentageList') {
466
- /**
467
- * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#percentage
468
- */
469
- // TODO: List of SVGPercentage
470
- return false;
471
- }
472
- if (spec.type === 'SVGPoints') {
473
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/points
474
- return false;
475
- }
476
- if (spec.type === 'SVGPreserveAspectRatio') {
477
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio
71
+ const invalid = invalidList.find(i => i);
72
+ return invalid || false;
73
+ }
74
+ exports.attrCheck = attrCheck;
75
+ function valueCheck(t, name, value, type) {
76
+ if (type === 'Boolean') {
77
+ // Valid because an attribute is exist
478
78
  return false;
479
79
  }
480
- if (spec.type === 'SVGViewBox') {
481
- // TODO: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox
482
- return false;
80
+ const matches = (0, types_1.check)(value, type);
81
+ (0, debug_1.log)(`Result ([${name}="${value}"]): %O`, { ...matches, type });
82
+ if (!matches.matched) {
83
+ const location = {
84
+ raw: matches.raw,
85
+ line: matches.line - 1,
86
+ col: matches.column - 1,
87
+ };
88
+ const base = t('the "{0*}" {1}', name, 'attribute');
89
+ const message = (0, create_message_1.createMessageValueExpected)(t, base, type, matches);
90
+ return [message, location];
483
91
  }
484
92
  return false;
485
93
  }
486
- /**
487
- *
488
- * @param name
489
- * @param value
490
- * @param enumValues
491
- */
492
- function includesEnum(t, name, value, enumValues) {
493
- const valid = enumValues.includes(value.toLowerCase());
494
- if (valid) {
495
- return false;
496
- }
497
- return t('{0} expects {1:c}', t('the "{0}" {1}', name, 'attribute'), t('either {0}', t(enumValues)));
498
- }
94
+ exports.valueCheck = valueCheck;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ml_core_1 = require("@markuplint/ml-core");
4
- const helpers_1 = require("../helpers");
5
4
  exports.default = (0, ml_core_1.createRule)({
6
5
  defaultServerity: 'warning',
7
6
  defaultValue: 'no-upper',
@@ -15,7 +14,7 @@ exports.default = (0, ml_core_1.createRule)({
15
14
  const deny = node.rule.value === 'no-upper' ? /[A-Z]/ : /[a-z]/;
16
15
  const cases = node.rule.value === 'no-upper' ? 'lower' : 'upper';
17
16
  const message = t(`{0} ${ms} be {1}`, t('{0} of {1}', 'attribute names', 'HTML elements'), `${cases}case`);
18
- const attrSpecs = (0, helpers_1.getAttrSpecs)(node.nameWithNS, document.specs);
17
+ const attrSpecs = (0, ml_core_1.getAttrSpecs)(node.nameWithNS, document.specs);
19
18
  for (const attr of node.attributes) {
20
19
  if (attr.attrType === 'ps-attr') {
21
20
  continue;
@@ -51,7 +50,7 @@ exports.default = (0, ml_core_1.createRule)({
51
50
  if (node.isForeignElement || node.isCustomElement) {
52
51
  return;
53
52
  }
54
- const attrSpecs = (0, helpers_1.getAttrSpecs)(node.nameWithNS, document.specs);
53
+ const attrSpecs = (0, ml_core_1.getAttrSpecs)(node.nameWithNS, document.specs);
55
54
  if (node.attributes) {
56
55
  for (const attr of node.attributes) {
57
56
  if (attr.attrType === 'ps-attr') {
@@ -0,0 +1,5 @@
1
+ import type { Translator } from '@markuplint/i18n';
2
+ import type { AttributeType } from '@markuplint/ml-spec';
3
+ import type { UnmatchedResult } from '@markuplint/types';
4
+ export declare function createMessageValueExpected(t: Translator, baseTarget: string, type: AttributeType, matches: UnmatchedResult): string;
5
+ export declare function __createMessageValueExpected(t: Translator, baseTarget: string, expected: string | null, matches: Pick<UnmatchedResult, 'partName' | 'reason' | 'raw' | 'candicate' | 'ref' | 'extra'>): string;