UNPKG

2.42 kBJavaScriptView Raw
1'use strict';
2
3const _ = require('lodash');
4const eachDeclarationBlock = require('../../utils/eachDeclarationBlock');
5const optionsMatches = require('../../utils/optionsMatches');
6const postcss = require('postcss');
7const report = require('../../utils/report');
8const ruleMessages = require('../../utils/ruleMessages');
9const shorthandData = require('../../reference/shorthandData');
10const validateOptions = require('../../utils/validateOptions');
11
12const ruleName = 'declaration-block-no-redundant-longhand-properties';
13
14const messages = ruleMessages(ruleName, {
15 expected: (props) => `Expected shorthand property "${props}"`,
16});
17
18function rule(actual, options) {
19 return (root, result) => {
20 const validOptions = validateOptions(
21 result,
22 ruleName,
23 { actual },
24 {
25 actual: options,
26 possible: {
27 ignoreShorthands: [_.isString, _.isRegExp],
28 },
29 optional: true,
30 },
31 );
32
33 if (!validOptions) {
34 return;
35 }
36
37 const longhandProperties = _.transform(shorthandData, (result, values, key) => {
38 if (optionsMatches(options, 'ignoreShorthands', key)) {
39 return;
40 }
41
42 values.forEach((value) => {
43 (result[value] || (result[value] = [])).push(key);
44 });
45 });
46
47 eachDeclarationBlock(root, (eachDecl) => {
48 const longhandDeclarations = {};
49
50 eachDecl((decl) => {
51 const prop = decl.prop.toLowerCase();
52 const unprefixedProp = postcss.vendor.unprefixed(prop);
53 const prefix = postcss.vendor.prefix(prop);
54
55 const shorthandProperties = longhandProperties[unprefixedProp];
56
57 if (!shorthandProperties) {
58 return;
59 }
60
61 shorthandProperties.forEach((shorthandProperty) => {
62 const prefixedShorthandProperty = prefix + shorthandProperty;
63
64 if (!longhandDeclarations[prefixedShorthandProperty]) {
65 longhandDeclarations[prefixedShorthandProperty] = [];
66 }
67
68 longhandDeclarations[prefixedShorthandProperty].push(prop);
69
70 const prefixedShorthandData = shorthandData[shorthandProperty].map((item) => {
71 return prefix + item;
72 });
73
74 if (
75 !_.isEqual(
76 prefixedShorthandData.sort(),
77 longhandDeclarations[prefixedShorthandProperty].sort(),
78 )
79 ) {
80 return;
81 }
82
83 report({
84 ruleName,
85 result,
86 node: decl,
87 message: messages.expected(prefixedShorthandProperty),
88 });
89 });
90 });
91 });
92 };
93}
94
95rule.ruleName = ruleName;
96rule.messages = messages;
97module.exports = rule;