UNPKG

2.9 kBJavaScriptView Raw
1// @ts-nocheck
2
3'use strict';
4
5const _ = require('lodash');
6const htmlTags = require('html-tags');
7const isCustomElement = require('../../utils/isCustomElement');
8const isKeyframeSelector = require('../../utils/isKeyframeSelector');
9const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
10const isStandardSyntaxTypeSelector = require('../../utils/isStandardSyntaxTypeSelector');
11const keywordSets = require('../../reference/keywordSets');
12const mathMLTags = require('mathml-tag-names');
13const optionsMatches = require('../../utils/optionsMatches');
14const parseSelector = require('../../utils/parseSelector');
15const report = require('../../utils/report');
16const ruleMessages = require('../../utils/ruleMessages');
17const svgTags = require('svg-tags');
18const validateOptions = require('../../utils/validateOptions');
19
20const ruleName = 'selector-type-no-unknown';
21
22const messages = ruleMessages(ruleName, {
23 rejected: (selector) => `Unexpected unknown type selector "${selector}"`,
24});
25
26function rule(actual, options) {
27 return (root, result) => {
28 const validOptions = validateOptions(
29 result,
30 ruleName,
31 { actual },
32 {
33 actual: options,
34 possible: {
35 ignore: ['custom-elements', 'default-namespace'],
36 ignoreNamespaces: [_.isString, _.isRegExp],
37 ignoreTypes: [_.isString, _.isRegExp],
38 },
39 optional: true,
40 },
41 );
42
43 if (!validOptions) {
44 return;
45 }
46
47 root.walkRules((rule) => {
48 const selector = rule.selector;
49 const selectors = rule.selectors;
50
51 if (!isStandardSyntaxRule(rule)) {
52 return;
53 }
54
55 if (selectors.some((s) => isKeyframeSelector(s))) {
56 return;
57 }
58
59 parseSelector(selector, result, rule, (selectorTree) => {
60 selectorTree.walkTags((tagNode) => {
61 if (!isStandardSyntaxTypeSelector(tagNode)) {
62 return;
63 }
64
65 if (
66 optionsMatches(options, 'ignore', 'custom-elements') &&
67 isCustomElement(tagNode.value)
68 ) {
69 return;
70 }
71
72 if (
73 optionsMatches(options, 'ignore', 'default-namespace') &&
74 !(typeof tagNode.namespace === 'string')
75 ) {
76 return;
77 }
78
79 if (optionsMatches(options, 'ignoreNamespaces', tagNode.namespace)) {
80 return;
81 }
82
83 if (optionsMatches(options, 'ignoreTypes', tagNode.value)) {
84 return;
85 }
86
87 const tagName = tagNode.value;
88 const tagNameLowerCase = tagName.toLowerCase();
89
90 if (
91 htmlTags.includes(tagNameLowerCase) ||
92 // SVG tags are case-sensitive
93 svgTags.includes(tagName) ||
94 keywordSets.nonStandardHtmlTags.has(tagNameLowerCase) ||
95 mathMLTags.includes(tagNameLowerCase)
96 ) {
97 return;
98 }
99
100 report({
101 message: messages.rejected(tagName),
102 node: rule,
103 index: tagNode.sourceIndex,
104 ruleName,
105 result,
106 });
107 });
108 });
109 });
110 };
111}
112
113rule.ruleName = ruleName;
114rule.messages = messages;
115module.exports = rule;