UNPKG

2.52 kBJavaScriptView Raw
1'use strict';
2
3const _ = require('lodash');
4const atRuleParamIndex = require('../../utils/atRuleParamIndex');
5const isCustomMediaQuery = require('../../utils/isCustomMediaQuery');
6const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature');
7const isStandardSyntaxMediaFeatureName = require('../../utils/isStandardSyntaxMediaFeatureName');
8const keywordSets = require('../../reference/keywordSets');
9const mediaParser = require('postcss-media-query-parser').default;
10const optionsMatches = require('../../utils/optionsMatches');
11const postcss = require('postcss');
12const rangeContextNodeParser = require('../rangeContextNodeParser');
13const report = require('../../utils/report');
14const ruleMessages = require('../../utils/ruleMessages');
15const validateOptions = require('../../utils/validateOptions');
16
17const ruleName = 'media-feature-name-no-unknown';
18
19const messages = ruleMessages(ruleName, {
20 rejected: (mediaFeatureName) => `Unexpected unknown media feature name "${mediaFeatureName}"`,
21});
22
23function rule(actual, options) {
24 return (root, result) => {
25 const validOptions = validateOptions(
26 result,
27 ruleName,
28 { actual },
29 {
30 actual: options,
31 possible: {
32 ignoreMediaFeatureNames: [_.isString, _.isRegExp],
33 },
34 optional: true,
35 },
36 );
37
38 if (!validOptions) {
39 return;
40 }
41
42 root.walkAtRules(/^media$/i, (atRule) => {
43 mediaParser(atRule.params).walk(/^media-feature$/i, (mediaFeatureNode) => {
44 const parent = mediaFeatureNode.parent;
45 const mediaFeatureRangeContext = isRangeContextMediaFeature(parent.value);
46
47 let value;
48 let sourceIndex;
49
50 if (mediaFeatureRangeContext) {
51 const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode);
52
53 value = parsedRangeContext.name.value;
54 sourceIndex = parsedRangeContext.name.sourceIndex;
55 } else {
56 value = mediaFeatureNode.value;
57 sourceIndex = mediaFeatureNode.sourceIndex;
58 }
59
60 if (!isStandardSyntaxMediaFeatureName(value) || isCustomMediaQuery(value)) {
61 return;
62 }
63
64 if (optionsMatches(options, 'ignoreMediaFeatureNames', value)) {
65 return;
66 }
67
68 if (
69 postcss.vendor.prefix(value) ||
70 keywordSets.mediaFeatureNames.has(value.toLowerCase())
71 ) {
72 return;
73 }
74
75 report({
76 index: atRuleParamIndex(atRule) + sourceIndex,
77 message: messages.rejected(value),
78 node: atRule,
79 ruleName,
80 result,
81 });
82 });
83 });
84 };
85}
86
87rule.ruleName = ruleName;
88rule.messages = messages;
89module.exports = rule;