Skip to content

Commit

Permalink
Enhancement: added option ignore: ["custom-elements"]. (#2366)
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi authored and davidtheclark committed Apr 16, 2017
1 parent b1aa4ed commit 95c6b17
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 30 deletions.
26 changes: 26 additions & 0 deletions lib/reference/keywordSets.js
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,32 @@ keywordSets.systemColors = new Set([
"windowtext",
])

// htmlTags includes only "standard" tags. So we augment it with older tags etc.
keywordSets.nonStandardHtmlTags = new Set([
"acronym",
"applet",
"basefont",
"big",
"blink",
"center",
"content",
"dir",
"font",
"frame",
"frameset",
"hgroup",
"isindex",
"keygen",
"listing",
"marquee",
"noembed",
"plaintext",
"spacer",
"strike",
"tt",
"xmp",
])

function uniteSets() {
const sets = Array.from(arguments)

Expand Down
22 changes: 21 additions & 1 deletion lib/rules/selector-type-no-unknown/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,27 @@ li > a {}

## Optional secondary options

### `ignore: ["default-namespace"]`
### `ignore: ["custom-elements", "default-namespace"]`

#### `"custom-elements"`

Allow custom elements.

The following patterns are considered warnings:

```css
unknown {}
```

```css
x-Foo {}
```

The following patterns are *not* considered warnings:

```css
x-foo {}
```

#### `"default-namespace"`

Expand Down
47 changes: 45 additions & 2 deletions lib/rules/selector-type-no-unknown/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ testRule(rule, {
message: messages.rejected("unknown"),
line: 1,
column: 11,
}, {
code: "x-Foo {}",
description: "invalid custom element",
message: messages.rejected("x-Foo"),
line: 1,
column: 1,
}, {
code: "X-foo {}",
description: "invalid custom element",
message: messages.rejected("X-foo"),
line: 1,
column: 1,
}, {
code: "X-FOO {}",
description: "invalid custom element",
message: messages.rejected("X-FOO"),
line: 1,
column: 1,
} ],
})

Expand Down Expand Up @@ -173,8 +191,8 @@ testRule(rule, {
line: 1,
column: 1,
}, {
code: "not-my-type {}",
message: messages.rejected("not-my-type"),
code: "notmytype {}",
message: messages.rejected("notmytype"),
line: 1,
column: 1,
} ],
Expand Down Expand Up @@ -226,3 +244,28 @@ testRule(rule, {
column: 11,
}],
})

testRule(rule, {
ruleName,
config: [ true, { ignore: ["custom-elements"] } ],

accept: [ {
code: "a {}",
}, {
code: "x-foo {}",
description: "custom element",
} ],

reject: [ {
code: "unknown {}",
message: messages.rejected("unknown"),
line: 1,
column: 1,
}, {
code: "x-Foo {}",
description: "invalid custom element",
message: messages.rejected("x-Foo"),
line: 1,
column: 1,
} ],
})
38 changes: 11 additions & 27 deletions lib/rules/selector-type-no-unknown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ const isKeyframeSelector = require("../../utils/isKeyframeSelector")
const isStandardSyntaxRule = require("../../utils/isStandardSyntaxRule")
const isStandardSyntaxSelector = require("../../utils/isStandardSyntaxSelector")
const isStandardSyntaxTypeSelector = require("../../utils/isStandardSyntaxTypeSelector")
const isCustomElement = require("../../utils/isCustomElement")
const optionsMatches = require("../../utils/optionsMatches")
const parseSelector = require("../../utils/parseSelector")
const report = require("../../utils/report")
const ruleMessages = require("../../utils/ruleMessages")
const validateOptions = require("../../utils/validateOptions")
const htmlTags = require("html-tags")
const keywordSets = require("../../reference/keywordSets")
const _ = require("lodash")
const svgTags = require("svg-tags")
const mathMLTags = require("mathml-tag-names")
Expand All @@ -20,38 +22,13 @@ const messages = ruleMessages(ruleName, {
rejected: selector => `Unexpected unknown type selector "${selector}"`,
})

// htmlTags includes only "standard" tags. So we augment it with older tags etc.
const nonStandardHtmlTags = new Set([
"acronym",
"applet",
"basefont",
"big",
"blink",
"center",
"content",
"dir",
"font",
"frame",
"frameset",
"hgroup",
"isindex",
"keygen",
"listing",
"marquee",
"noembed",
"plaintext",
"spacer",
"strike",
"tt",
"xmp",
])

const rule = function (actual, options) {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, { actual }, {
actual: options,
possible: {
ignore: [
"custom-elements",
"default-namespace",
],
ignoreNamespaces: [_.isString],
Expand Down Expand Up @@ -83,6 +60,13 @@ const rule = function (actual, options) {
return
}

if (
optionsMatches(options, "ignore", "custom-elements")
&& isCustomElement(tagNode.value)
) {
return
}

if (
optionsMatches(options, "ignore", "default-namespace")
&& !tagNode.hasOwnProperty("namespace")
Expand All @@ -103,7 +87,7 @@ const rule = function (actual, options) {

if (htmlTags.indexOf(tagNameLowerCase) !== -1
|| svgTags.indexOf(tagNameLowerCase) !== -1
|| nonStandardHtmlTags.has(tagNameLowerCase)
|| keywordSets.nonStandardHtmlTags.has(tagNameLowerCase)
|| mathMLTags.indexOf(tagNameLowerCase) !== -1
) {
return
Expand Down
36 changes: 36 additions & 0 deletions lib/utils/__tests__/isCustomElement.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict"

const isCustomElement = require("../isCustomElement")

it("isCustomElement", () => {
expect(isCustomElement("x-foo")).toBeTruthy()
expect(isCustomElement("math-α")).toBeTruthy()
expect(isCustomElement("emotion-😍")).toBeTruthy()

expect(isCustomElement("X-foo")).toBeFalsy()
expect(isCustomElement("x-Foo")).toBeFalsy()
expect(isCustomElement("X-FOO")).toBeFalsy()

// Html tags
expect(isCustomElement("div")).toBeFalsy()
expect(isCustomElement("dIv")).toBeFalsy()
expect(isCustomElement("DiV")).toBeFalsy()
expect(isCustomElement("DIV")).toBeFalsy()
expect(isCustomElement("foo")).toBeFalsy()
expect(isCustomElement("acronym")).toBeFalsy()
// Svg tags
expect(isCustomElement("font-face")).toBeFalsy()
expect(isCustomElement("clipPath")).toBeFalsy()
// Mathml tags
expect(isCustomElement("abs")).toBeFalsy()
expect(isCustomElement("annotation-xml")).toBeFalsy()

expect(isCustomElement(".foo")).toBeFalsy()
expect(isCustomElement(".foo-bar")).toBeFalsy()
expect(isCustomElement("#foo")).toBeFalsy()
expect(isCustomElement("#foo-bar")).toBeFalsy()
expect(isCustomElement(":foo")).toBeFalsy()
expect(isCustomElement(":foo-bar")).toBeFalsy()
expect(isCustomElement("::foo")).toBeFalsy()
expect(isCustomElement("::foo-bar")).toBeFalsy()
})
40 changes: 40 additions & 0 deletions lib/utils/isCustomElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* @flow */
"use strict"

const svgTags = require("svg-tags")
const htmlTags = require("html-tags")
const keywordSets = require("../reference/keywordSets")
const mathMLTags = require("mathml-tag-names")

/**
* Check whether a type selector is a custom element
*/
module.exports = function (selector/*: string*/)/*: boolean*/ {
if (!(/^[a-z]/).test(selector)) {
return false
}

if (selector.indexOf("-") === -1) {
return false
}

const selectorLowerCase = selector.toLowerCase()

if (selectorLowerCase !== selector) {
return false
}
if (svgTags.indexOf(selectorLowerCase) !== -1) {
return false
}
if (htmlTags.indexOf(selectorLowerCase) !== -1) {
return false
}
if (keywordSets.nonStandardHtmlTags.has(selectorLowerCase)) {
return false
}
if (mathMLTags.indexOf(selectorLowerCase) !== -1) {
return false
}

return true
}

0 comments on commit 95c6b17

Please sign in to comment.