UNPKG

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