UNPKG

2.74 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
23const meta = {
24 url: 'https://stylelint.io/user-guide/rules/list/media-feature-name-no-unknown',
25};
26
27/** @type {import('stylelint').Rule} */
28const rule = (primary, secondaryOptions) => {
29 return (root, result) => {
30 const validOptions = validateOptions(
31 result,
32 ruleName,
33 { actual: primary },
34 {
35 actual: secondaryOptions,
36 possible: {
37 ignoreMediaFeatureNames: [isString, isRegExp],
38 },
39 optional: true,
40 },
41 );
42
43 if (!validOptions) {
44 return;
45 }
46
47 root.walkAtRules(/^media$/i, (atRule) => {
48 mediaParser(atRule.params).walk(/^media-feature$/i, (mediaFeatureNode) => {
49 const parent = mediaFeatureNode.parent;
50 const mediaFeatureRangeContext = isRangeContextMediaFeature(parent.value);
51
52 let value;
53 let sourceIndex;
54
55 if (mediaFeatureRangeContext) {
56 const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode);
57
58 value = parsedRangeContext.name.value;
59 sourceIndex = parsedRangeContext.name.sourceIndex;
60 } else {
61 value = mediaFeatureNode.value;
62 sourceIndex = mediaFeatureNode.sourceIndex;
63 }
64
65 if (!isStandardSyntaxMediaFeatureName(value) || isCustomMediaQuery(value)) {
66 return;
67 }
68
69 if (optionsMatches(secondaryOptions, 'ignoreMediaFeatureNames', value)) {
70 return;
71 }
72
73 if (vendor.prefix(value) || keywordSets.mediaFeatureNames.has(value.toLowerCase())) {
74 return;
75 }
76
77 report({
78 index: atRuleParamIndex(atRule) + sourceIndex,
79 message: messages.rejected(value),
80 node: atRule,
81 ruleName,
82 result,
83 });
84 });
85 });
86 };
87};
88
89rule.ruleName = ruleName;
90rule.messages = messages;
91rule.meta = meta;
92module.exports = rule;