UNPKG

2.57 kBJavaScriptView Raw
1'use strict';
2
3const valueParser = require('postcss-value-parser');
4
5const isAutoprefixable = require('../../utils/isAutoprefixable');
6const isStandardSyntaxDeclaration = require('../../utils/isStandardSyntaxDeclaration');
7const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty');
8const optionsMatches = require('../../utils/optionsMatches');
9const report = require('../../utils/report');
10const ruleMessages = require('../../utils/ruleMessages');
11const setDeclarationValue = require('../../utils/setDeclarationValue');
12const validateOptions = require('../../utils/validateOptions');
13const vendor = require('../../utils/vendor');
14const { isString } = require('../../utils/validateTypes');
15
16const ruleName = 'value-no-vendor-prefix';
17
18const messages = ruleMessages(ruleName, {
19 rejected: (value) => `Unexpected vendor-prefix "${value}"`,
20});
21
22const meta = {
23 url: 'https://stylelint.io/user-guide/rules/list/value-no-vendor-prefix',
24};
25
26const valuePrefixes = ['-webkit-', '-moz-', '-ms-', '-o-'];
27
28/**
29 * @param {string} value
30 * @returns {boolean}
31 */
32const hasPrefix = (value) => {
33 const lowerValue = value.toLowerCase();
34
35 return valuePrefixes.some((prefix) => lowerValue.startsWith(prefix));
36};
37
38/** @type {import('stylelint').Rule} */
39const rule = (primary, secondaryOptions, context) => {
40 return (root, result) => {
41 const validOptions = validateOptions(
42 result,
43 ruleName,
44 { actual: primary },
45 {
46 optional: true,
47 actual: secondaryOptions,
48 possible: {
49 ignoreValues: [isString],
50 },
51 },
52 );
53
54 if (!validOptions) {
55 return;
56 }
57
58 root.walkDecls((decl) => {
59 const { value } = decl;
60
61 if (
62 !isStandardSyntaxDeclaration(decl) ||
63 !isStandardSyntaxProperty(decl.prop) ||
64 !value.startsWith('-')
65 ) {
66 return;
67 }
68
69 if (optionsMatches(secondaryOptions, 'ignoreValues', vendor.unprefixed(value))) {
70 return;
71 }
72
73 const parsedValue = valueParser(value);
74
75 parsedValue.walk((node) => {
76 if (!hasPrefix(node.value)) {
77 return;
78 }
79
80 if (!isAutoprefixable.propertyValue(node.value)) {
81 return;
82 }
83
84 if (context.fix) {
85 node.value = isAutoprefixable.unprefix(node.value);
86
87 return;
88 }
89
90 report({
91 message: messages.rejected(node.value),
92 node: decl,
93 index: decl.prop.length + (decl.raws.between || '').length + node.sourceIndex,
94 result,
95 ruleName,
96 });
97 });
98
99 setDeclarationValue(decl, parsedValue.toString());
100 });
101 };
102};
103
104rule.ruleName = ruleName;
105rule.messages = messages;
106rule.meta = meta;
107module.exports = rule;