Skip to content

Commit aa16722

Browse files
committed
feat(attr-lowercase): ignore camelCase SVG attributes
Closes #542
1 parent 989d0eb commit aa16722

File tree

6 files changed

+252
-7
lines changed

6 files changed

+252
-7
lines changed

dist/core/rules/attr-lowercase.js

+75-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/htmlhint.js

+74-1
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,79 @@
336336
var attrLowercase = {};
337337

338338
Object.defineProperty(attrLowercase, "__esModule", { value: true });
339+
const svgIgnores = [
340+
'allowReorder',
341+
'attributeName',
342+
'attributeType',
343+
'autoReverse',
344+
'baseFrequency',
345+
'baseProfile',
346+
'calcMode',
347+
'clipPath',
348+
'clipPathUnits',
349+
'contentScriptType',
350+
'contentStyleType',
351+
'diffuseConstant',
352+
'edgeMode',
353+
'externalResourcesRequired',
354+
'filterRes',
355+
'filterUnits',
356+
'glyphRef',
357+
'gradientTransform',
358+
'gradientUnits',
359+
'kernelMatrix',
360+
'kernelUnitLength',
361+
'keyPoints',
362+
'keySplines',
363+
'keyTimes',
364+
'lengthAdjust',
365+
'limitingConeAngle',
366+
'markerHeight',
367+
'markerUnits',
368+
'markerWidth',
369+
'maskContentUnits',
370+
'maskUnits',
371+
'numOctaves',
372+
'onBlur',
373+
'onChange',
374+
'onClick',
375+
'onFocus',
376+
'onKeyUp',
377+
'onLoad',
378+
'pathLength',
379+
'patternContentUnits',
380+
'patternTransform',
381+
'patternUnits',
382+
'pointsAtX',
383+
'pointsAtY',
384+
'pointsAtZ',
385+
'preserveAlpha',
386+
'preserveAspectRatio',
387+
'primitiveUnits',
388+
'refX',
389+
'refY',
390+
'repeatCount',
391+
'repeatDur',
392+
'requiredExtensions',
393+
'requiredFeatures',
394+
'specularConstant',
395+
'specularExponent',
396+
'spreadMethod',
397+
'startOffset',
398+
'stdDeviation',
399+
'stitchTiles',
400+
'surfaceScale',
401+
'systemLanguage',
402+
'tableValues',
403+
'targetX',
404+
'targetY',
405+
'textLength',
406+
'viewBox',
407+
'viewTarget',
408+
'xChannelSelector',
409+
'yChannelSelector',
410+
'zoomAndPan',
411+
];
339412
function testAgainstStringOrRegExp(value, comparison) {
340413
if (comparison instanceof RegExp) {
341414
return comparison.test(value)
@@ -361,7 +434,7 @@
361434
id: 'attr-lowercase',
362435
description: 'All attribute names must be in lowercase.',
363436
init(parser, reporter, options) {
364-
const exceptions = Array.isArray(options) ? options : [];
437+
const exceptions = (Array.isArray(options) ? options : []).concat(svgIgnores);
365438
parser.addListener('tagstart', (event) => {
366439
const attrs = event.attrs;
367440
let attr;

dist/htmlhint.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/user-guide/rules/attr-lowercase.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ Level: `error`
1111

1212
1. true: enable rule
1313
2. false: disable rule
14-
3. ['viewBox', 'Test']: enable rule except for the given attribute names
14+
3. ['fooBar', 'Test']: enable rule except for the given attribute names. All SVG camelCase properties are included, for example `viewBox`
1515

1616
### Example
1717

1818
```json
1919
{
2020
...
21-
"attr-lowercase": ['viewBox']
21+
"attr-lowercase": ['fooBar']
2222
...
2323
}
2424
```
@@ -28,6 +28,9 @@ The following pattern is **not** considered a rule violation:
2828
<!-- prettier-ignore -->
2929
```html
3030
<img src="test.png" alt="test" />
31+
32+
<!-- known SVG attributes are ignored -->
33+
<svg width="200" height="200" viewBox="0 0 200 200" />
3134
```
3235

3336
The following pattern is considered a rule violation:

src/core/rules/attr-lowercase.ts

+77-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,79 @@
11
import { Rule } from '../types'
22

3+
const svgIgnores = [
4+
'allowReorder',
5+
'attributeName',
6+
'attributeType',
7+
'autoReverse',
8+
'baseFrequency',
9+
'baseProfile',
10+
'calcMode',
11+
'clipPath',
12+
'clipPathUnits',
13+
'contentScriptType',
14+
'contentStyleType',
15+
'diffuseConstant',
16+
'edgeMode',
17+
'externalResourcesRequired',
18+
'filterRes',
19+
'filterUnits',
20+
'glyphRef',
21+
'gradientTransform',
22+
'gradientUnits',
23+
'kernelMatrix',
24+
'kernelUnitLength',
25+
'keyPoints',
26+
'keySplines',
27+
'keyTimes',
28+
'lengthAdjust',
29+
'limitingConeAngle',
30+
'markerHeight',
31+
'markerUnits',
32+
'markerWidth',
33+
'maskContentUnits',
34+
'maskUnits',
35+
'numOctaves',
36+
'onBlur',
37+
'onChange',
38+
'onClick',
39+
'onFocus',
40+
'onKeyUp',
41+
'onLoad',
42+
'pathLength',
43+
'patternContentUnits',
44+
'patternTransform',
45+
'patternUnits',
46+
'pointsAtX',
47+
'pointsAtY',
48+
'pointsAtZ',
49+
'preserveAlpha',
50+
'preserveAspectRatio',
51+
'primitiveUnits',
52+
'refX',
53+
'refY',
54+
'repeatCount',
55+
'repeatDur',
56+
'requiredExtensions',
57+
'requiredFeatures',
58+
'specularConstant',
59+
'specularExponent',
60+
'spreadMethod',
61+
'startOffset',
62+
'stdDeviation',
63+
'stitchTiles',
64+
'surfaceScale',
65+
'systemLanguage',
66+
'tableValues',
67+
'targetX',
68+
'targetY',
69+
'textLength',
70+
'viewBox',
71+
'viewTarget',
72+
'xChannelSelector',
73+
'yChannelSelector',
74+
'zoomAndPan',
75+
]
76+
377
/**
478
* testAgainstStringOrRegExp
579
*
@@ -43,7 +117,9 @@ export default {
43117
id: 'attr-lowercase',
44118
description: 'All attribute names must be in lowercase.',
45119
init(parser, reporter, options) {
46-
const exceptions = Array.isArray(options) ? options : []
120+
const exceptions = (Array.isArray(options) ? options : []).concat(
121+
svgIgnores
122+
)
47123

48124
parser.addListener('tagstart', (event) => {
49125
const attrs = event.attrs

test/rules/attr-lowercase.spec.js

+20
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,24 @@ describe(`Rules: ${ruleId}`, () => {
6060
const messages = HTMLHint.verify(code, ruleOptions)
6161
expect(messages.length).to.be(0)
6262
})
63+
64+
it('Known SVG properties should be ignored with no config', () => {
65+
const code = '<svg width="200" height="200" viewBox="0 0 200 200" />'
66+
const messages = HTMLHint.verify(code, ruleOptions)
67+
expect(messages.length).to.be(0)
68+
})
69+
70+
it('Known SVG properties should be ignored with a config override', () => {
71+
const code = '<svg width="200" height="200" viewBox="0 0 200 200" />'
72+
ruleOptions[ruleId] = ['testBox']
73+
const messages = HTMLHint.verify(code, ruleOptions)
74+
expect(messages.length).to.be(0)
75+
})
76+
77+
it('Double ignored SVG properties should not cause issues', () => {
78+
const code = '<svg width="200" height="200" viewBox="0 0 200 200" />'
79+
ruleOptions[ruleId] = ['viewBox']
80+
const messages = HTMLHint.verify(code, ruleOptions)
81+
expect(messages.length).to.be(0)
82+
})
6383
})

0 commit comments

Comments
 (0)