UNPKG

2.38 kBJavaScriptView Raw
1// @ts-nocheck
2
3'use strict';
4
5const _ = require('lodash');
6const isCustomProperty = require('../../utils/isCustomProperty');
7const isStandardSyntaxDeclaration = require('../../utils/isStandardSyntaxDeclaration');
8const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty');
9const optionsMatches = require('../../utils/optionsMatches');
10const properties = require('known-css-properties').all;
11const report = require('../../utils/report');
12const ruleMessages = require('../../utils/ruleMessages');
13const validateOptions = require('../../utils/validateOptions');
14const vendor = require('../../utils/vendor');
15
16const ruleName = 'property-no-unknown';
17
18const messages = ruleMessages(ruleName, {
19 rejected: (property) => `Unexpected unknown property "${property}"`,
20});
21
22function rule(actual, options) {
23 const allValidProperties = new Set(properties);
24
25 return (root, result) => {
26 const validOptions = validateOptions(
27 result,
28 ruleName,
29 { actual },
30 {
31 actual: options,
32 possible: {
33 ignoreProperties: [_.isString, _.isRegExp],
34 checkPrefixed: _.isBoolean,
35 ignoreSelectors: [_.isString, _.isRegExp],
36 ignoreAtRules: [_.isString, _.isRegExp],
37 },
38 optional: true,
39 },
40 );
41
42 if (!validOptions) {
43 return;
44 }
45
46 const shouldCheckPrefixed = _.get(options, 'checkPrefixed');
47
48 root.walkDecls(checkStatement);
49
50 function checkStatement(decl) {
51 const prop = decl.prop;
52
53 if (!isStandardSyntaxProperty(prop)) {
54 return;
55 }
56
57 if (!isStandardSyntaxDeclaration(decl)) {
58 return;
59 }
60
61 if (isCustomProperty(prop)) {
62 return;
63 }
64
65 if (!shouldCheckPrefixed && vendor.prefix(prop)) {
66 return;
67 }
68
69 if (optionsMatches(options, 'ignoreProperties', prop)) {
70 return;
71 }
72
73 const { selector } = decl.parent;
74
75 if (selector && optionsMatches(options, 'ignoreSelectors', selector)) {
76 return;
77 }
78
79 let node = decl.parent;
80
81 while (node && node.type !== 'root') {
82 const { type, name } = node;
83
84 if (type === 'atrule' && optionsMatches(options, 'ignoreAtRules', name)) {
85 return;
86 }
87
88 node = node.parent;
89 }
90
91 if (allValidProperties.has(prop.toLowerCase())) {
92 return;
93 }
94
95 report({
96 message: messages.rejected(prop),
97 node: decl,
98 result,
99 ruleName,
100 });
101 }
102 };
103}
104
105rule.ruleName = ruleName;
106rule.messages = messages;
107module.exports = rule;