Skip to content

Commit

Permalink
feat: move rules into dedicated attribute (#476)
Browse files Browse the repository at this point in the history
* feat: move rules into dedicated attribute

* test: update tests
  • Loading branch information
Shinigami committed Jul 10, 2020
1 parent 11311ed commit dcf5bf0
Show file tree
Hide file tree
Showing 36 changed files with 196 additions and 169 deletions.
6 changes: 3 additions & 3 deletions src/cli/htmlhint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ function hintFile(filepath: string, ruleset?: Ruleset) {
// ignore
}

return HTMLHint.verify(content, ruleset)
return HTMLHint.verify(content, { rules: ruleset })
}

// hint stdin
Expand All @@ -483,7 +483,7 @@ function hintStdin(

process.stdin.on('end', () => {
const content = buffers.join('')
const messages = HTMLHint.verify(content, ruleset)
const messages = HTMLHint.verify(content, { rules: ruleset })
callback(messages)
})
}
Expand All @@ -496,7 +496,7 @@ function hintUrl(
) {
request.get(url, (error, response, body) => {
if (!error && response.statusCode == 200) {
const messages = HTMLHint.verify(body, ruleset)
const messages = HTMLHint.verify(body, { rules: ruleset })
callback(messages)
} else {
callback([])
Expand Down
15 changes: 13 additions & 2 deletions src/core/core.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import HTMLParser from './htmlparser'
import Reporter, { ReportMessageCallback } from './reporter'
import * as HTMLRules from './rules'
import { Hint, isRuleSeverity, Rule, Ruleset, RuleSeverity } from './types'
import {
Configuration,
Hint,
isRuleSeverity,
Rule,
Ruleset,
RuleSeverity,
} from './types'

export interface FormatOptions {
colors?: boolean
Expand All @@ -27,7 +34,11 @@ class HTMLHintCore {
this.rules[rule.id] = rule
}

public verify(html: string, ruleset: Ruleset = this.defaultRuleset) {
public verify(
html: string,
config: Configuration = { rules: this.defaultRuleset }
) {
let ruleset = config.rules ?? this.defaultRuleset
if (Object.keys(ruleset).length === 0) {
ruleset = this.defaultRuleset
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { HTMLParser } from './core'
import { ReportMessageCallback } from './reporter'

export interface Configuration {
rules?: Ruleset
}

export interface Rule {
id: string
description: string
Expand Down
24 changes: 17 additions & 7 deletions test/core.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const HTMLHint = require('../dist/htmlhint.js').HTMLHint
describe('Core', () => {
it('Set false to rule no effected should result in an error', () => {
const code = '<img src="test.gif" />'
const messages = HTMLHint.verify(code, { 'alt-require': 'off' })
const messages = HTMLHint.verify(code, { rules: { 'alt-require': 'off' } })
expect(messages.length).to.be(0)
})

Expand All @@ -27,7 +27,9 @@ describe('Core', () => {
// With value = 'error'
let code = '<!-- htmlhint alt-require:error -->\r\n<img src="test.gif" />'
let messages = HTMLHint.verify(code, {
'alt-require': 'off',
rules: {
'alt-require': 'off',
},
})

expect(messages.length).to.be(1)
Expand All @@ -38,7 +40,9 @@ describe('Core', () => {
// Without value
code = '<!-- htmlhint alt-require -->\r\n<img src="test.gif" />'
messages = HTMLHint.verify(code, {
'alt-require': 'off',
rules: {
'alt-require': 'off',
},
})

expect(messages.length).to.be(1)
Expand All @@ -49,14 +53,18 @@ describe('Core', () => {
// With value = 'off'
code = '<!-- htmlhint alt-require:off -->\r\n<img src="test.gif" />'
messages = HTMLHint.verify(code, {
'alt-require': 'error',
rules: {
'alt-require': 'error',
},
})
expect(messages.length).to.be(0)

// Without rule
code = '<!-- htmlhint -->\r\n<img src="test.gif" />'
messages = HTMLHint.verify(code, {
'alt-require': 'off',
rules: {
'alt-require': 'off',
},
})

expect(messages.length).to.be(0)
Expand All @@ -66,8 +74,10 @@ describe('Core', () => {
const code =
'tttttttttttttttttttttttttttttttttttt<div>中文<img src="test.gif" />tttttttttttttttttttttttttttttttttttttttttttttt'
const messages = HTMLHint.verify(code, {
'tag-pair': 'error',
'alt-require': 'error',
rules: {
'tag-pair': 'error',
'alt-require': 'error',
},
})
let arrLogs = HTMLHint.format(messages)
expect(arrLogs.length).to.be(4)
Expand Down
26 changes: 13 additions & 13 deletions test/rules/alt-require.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ ruleOptions[ruldId] = 'warn'
describe(`Rules: ${ruldId}`, () => {
it('Img tag have empty alt attribute should not result in an error', () => {
const code = '<img width="200" height="300" alt="">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Img tag have non empty alt attribute should not result in an error', () => {
const code = '<img width="200" height="300" alt="test">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Img tag have not alt attribute should result in an error', () => {
const code = '<img width="200" height="300">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -33,19 +33,19 @@ describe(`Rules: ${ruldId}`, () => {
/* A tag can have shape and coords attributes and not have alt attribute */
it('A tag have not alt attribute should not result in an error', () => {
const code = '<a>'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Area tag have not href and alt attributes should not result in an error', () => {
const code = '<area>'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Area[href] tag have not alt attribute should result in an error', () => {
const code = '<area href="#test">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -55,7 +55,7 @@ describe(`Rules: ${ruldId}`, () => {

it('Area[href] tag have empty alt attribute should result in an error', () => {
const code = '<area href="#test" alt="">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -65,25 +65,25 @@ describe(`Rules: ${ruldId}`, () => {

it('Area[href] tag have non emtpy alt attribute should not result in an error', () => {
const code = '<area href="#test" alt="test">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Input tag have not type and alt attributes should not result in an error', () => {
const code = '<input>'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Input[type="text"] tag have not alt attribute should not result in an error', () => {
const code = '<input type="text">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Input[type="image"] tag have not alt attribute should result in an error', () => {
const code = '<input type="image">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -93,7 +93,7 @@ describe(`Rules: ${ruldId}`, () => {

it('Input[type="image"] tag have empty alt attribute should result in an error', () => {
const code = '<input type="image" alt="">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -103,7 +103,7 @@ describe(`Rules: ${ruldId}`, () => {

it('Input[type="image"] tag have non emtpy alt attribute should not result in an error', () => {
const code = '<input type="image" alt="test">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})
})
14 changes: 7 additions & 7 deletions test/rules/attr-lowercase.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ ruleOptions[ruldId] = 'error'
describe(`Rules: ${ruldId}`, () => {
it('Not all lowercase attr should result in an error', () => {
let code = '<p TEST="abc">'
let messages = HTMLHint.verify(code, ruleOptions)
let messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
expect(messages[0].col).to.be(3)

code = '<p id=""\r\n TEST1="abc" TEST2="abc">'
messages = HTMLHint.verify(code, ruleOptions)
messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(2)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(2)
Expand All @@ -29,35 +29,35 @@ describe(`Rules: ${ruldId}`, () => {

it('Lowercase attr should not result in an error', () => {
const code = '<p test="abc">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Set is false should not result in an error', () => {
const code = '<p TEST="abc">'
ruleOptions[ruldId] = 'off'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Set to array list should not result in an error', () => {
const code = '<p testBox="abc" tttAAA="ccc">'
ruleOptions[ruldId] = ['error', { exceptions: ['testBox', 'tttAAA'] }]
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Set to array list with RegExp should not result in an error', () => {
const code = '<p testBox="abc" bind:tapTop="ccc">'
ruleOptions[ruldId] = ['error', { exceptions: ['testBox', /bind:.*/] }]
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Set to array list with regex string should not result in an error', () => {
const code = '<p testBox="abc" [ngFor]="ccc">'
ruleOptions[ruldId] = ['error', { exceptions: ['testBox', '/\\[.*\\]/'] }]
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})
})
4 changes: 2 additions & 2 deletions test/rules/attr-no-duplication.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ruleOptions[ruldId] = 'error'
describe(`Rules: ${ruldId}`, () => {
it('Attribute name been duplication should result in an error', () => {
const code = '<a href="a" href="b">bbb</a>'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -19,7 +19,7 @@ describe(`Rules: ${ruldId}`, () => {

it('Attribute name not been duplication should not result in an error', () => {
const code = '<a href="a">bbb</a>'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})
})
4 changes: 2 additions & 2 deletions test/rules/attr-no-unnecessary-whitespace.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe(`Rules: ${ruldId}`, () => {
'<div title ="a" />',
]
for (let i = 0; i < codes.length; i++) {
const messages = HTMLHint.verify(codes[i], ruleOptions)
const messages = HTMLHint.verify(codes[i], { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -26,7 +26,7 @@ describe(`Rules: ${ruldId}`, () => {
it('Attribute without spaces should not result in an error', () => {
const codes = ['<div title="a" />', '<div title="a = a" />']
for (let i = 0; i < codes.length; i++) {
const messages = HTMLHint.verify(codes[i], ruleOptions)
const messages = HTMLHint.verify(codes[i], { rules: ruleOptions })
expect(messages.length).to.be(0)
}
})
Expand Down
6 changes: 3 additions & 3 deletions test/rules/attr-sort.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe(`Rules: ${ruleId}`, () => {
it('Attribute unsorted tags must result in an error', () => {
const code = '<div id="test" class="class" title="tite"></div>'

const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })

expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruleId)
Expand All @@ -21,15 +21,15 @@ describe(`Rules: ${ruleId}`, () => {
it('Attribute unsorted tags that are unrecognizable should not throw error', () => {
const code = '<div img="image" meta="meta" font="font"></div>'

const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })

expect(messages.length).to.be(0)
})

it('Attribute unsorted of tags of various types should throw error', () => {
const code = '<div type="type" img="image" id="id" font="font"></div>'

const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })

expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruleId)
Expand Down
6 changes: 3 additions & 3 deletions test/rules/attr-unsafe-chars.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe(`Rules: ${ruldId}`, () => {
it('Attribute value have unsafe chars should result in an error', () => {
const code =
'<a href="https://vimeo.com/album/1951235/video/56931059‎">Sud Web 2012</a>'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(1)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -21,14 +21,14 @@ describe(`Rules: ${ruldId}`, () => {

it('Attribute value have no unsafe chars should not result in an error', () => {
const code = '<input disabled="disabled" />'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})

it('Attribute value have \\r\\n\\t should not result in an error', () => {
const code =
'<link rel="icon" type="image/x-icon" href="data:image/x-icon;base64,R0lGODlhEAAQAKEAAAAAAICAgP///wAAACH/\nC05FVFNDQVBFMi4wAwEAAAAh/hFDcmVhdGVkIHdpdGggR0lNUAAh+QQBZAADACwAAAAAEAAQAAACJIyPacLtvp5kEUwYmL00i81VXK\neNgjiioQdeqsuakXl6tIIjBQAh+QQBZAADACwAAAAAEAAQAAACIIyPacLtvp5kcb5qG85iZ2+BkyiRV8BBaEqtrKkqslEAADs=\t"/>'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})
})
4 changes: 2 additions & 2 deletions test/rules/attr-value-double-quotes.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ruleOptions[ruldId] = 'error'
describe(`Rules: ${ruldId}`, () => {
it('Attribute value closed by single quotes should result in an error', () => {
const code = "<a href='abc' title=abc style=''>"
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(3)
expect(messages[0].rule.id).to.be(ruldId)
expect(messages[0].line).to.be(1)
Expand All @@ -25,7 +25,7 @@ describe(`Rules: ${ruldId}`, () => {

it('Attribute value no closed should not result in an error', () => {
const code = '<input type="button" disabled style="">'
const messages = HTMLHint.verify(code, ruleOptions)
const messages = HTMLHint.verify(code, { rules: ruleOptions })
expect(messages.length).to.be(0)
})
})

0 comments on commit dcf5bf0

Please sign in to comment.