Skip to content

Commit

Permalink
Add rule to require specific attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Edwards committed Aug 4, 2015
1 parent a9de52b commit 93a9fe3
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 0 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,20 @@ p= 'This code is <escaped>'
p!= 'This code is <strong>not</strong> escaped'
```

### requireSpecificAttributes: `Array`

#### e.g.: [ { img: [ "alt" ] } ]

`img` tags must contain all of the attributes specified.

```jade
//- Invalid
img(src='src')
//- Valid
img(src='src' alt='alt')
```

### validateAttributeQuoteMarks: `"\""` | `"'"` | `true`

#### e.g.: "'"
Expand Down
60 changes: 60 additions & 0 deletions lib/rules/require-specific-attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
var assert = require('assert')
, utils = require('../utils')

module.exports = function () {}

module.exports.prototype =
{ name: 'requireSpecificAttributes'

, configure: function (options) {

assert(typeof options === 'object'
, this.name + ' option requires array value or should be removed')

this._requiredAttributes = options
}

, lint: function (file, errors) {

this._requiredAttributes.forEach(function (attribute) {
file.iterateTokensByFilter(function (token) {
return token.type === 'tag' && utils.ownProperty(attribute, token.val)
}, function (token) {
var lineNumber = token.line
, tag = token.val
, requiredAttributes = utils.ownProperty(attribute, tag)
, hasAttributes

if (typeof requiredAttributes === 'string') {
requiredAttributes = [ requiredAttributes ]
}

file.iterateTokensByFilter(function (token) {
if (token.type === 'attrs' && token.line === lineNumber) {
hasAttributes = true
return true
}

return false
}, function (token) {
var attributeNames = []

token.attrs.forEach(function (attribute) {
attributeNames.push(attribute.name.toLowerCase())
})

requiredAttributes.forEach(function (attribute) {
if (attributeNames.indexOf(attribute.toLowerCase()) === -1) {
errors.add('Tag "' + tag + '" must have attribute "' + attribute + '"', lineNumber)
}
})
})

if (!hasAttributes) {
errors.add('Tag "' + tag + '" must has attributes "' + requiredAttributes.join('", "') + '"', lineNumber)
}
})
})

}
}
3 changes: 3 additions & 0 deletions presets/clock.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
, "requireLowerCaseAttributes": true
, "requireLowerCaseTags": true
, "requireSpaceAfterCodeOperator": true
, "requireSpecificAttributes":
{ "img": "alt"
}
, "validateAttributeQuoteMarks": "'"
, "validateAttributeSeparator": ", "
, "validateIndentation": 2
Expand Down
5 changes: 5 additions & 0 deletions test/fixtures/rules/require-specific-attributes.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
abbr(title='title', lang='en-gb')
img(title='title')
abbr
img(alt='alt')
abbr(title='title')
42 changes: 42 additions & 0 deletions test/rules/require-specific-attributes.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module.exports = createTest

var assert = require('assert')

function createTest(linter, fixturesPath) {

describe('requireSpecificAttributes', function () {

describe('object', function () {

var options =
[ { 'img': 'alT' }
, { 'Abbr': [ 'title', 'laNg' ] }
]

before(function () {
linter.configure({ requireSpecificAttributes: options })
})

it('should report missing required attributes', function () {
assert.equal(linter.checkString('img(title=\'title\')').length, 1)
})

it('should not report existing attributes', function () {
assert.equal(linter.checkString('img(alt=\'alt\')').length, 0)
})

it('should report multiple errors found in file', function () {
var result = linter.checkFile(fixturesPath + 'require-specific-attributes.jade')

assert.equal(result.length, 3)
assert.equal(result[0].code, 'JADE:LINT_REQUIRESPECIFICATTRIBUTES')
assert.equal(result[0].line, 2)
assert.equal(result[1].line, 3)
assert.equal(result[2].line, 5)
})

})

})

}

0 comments on commit 93a9fe3

Please sign in to comment.