index.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. 'use strict';
  2. const atRuleParamIndex = require('../../utils/atRuleParamIndex');
  3. const isCustomMediaQuery = require('../../utils/isCustomMediaQuery');
  4. const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature');
  5. const isStandardSyntaxMediaFeatureName = require('../../utils/isStandardSyntaxMediaFeatureName');
  6. const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp');
  7. const mediaParser = require('postcss-media-query-parser').default;
  8. const rangeContextNodeParser = require('../rangeContextNodeParser');
  9. const report = require('../../utils/report');
  10. const ruleMessages = require('../../utils/ruleMessages');
  11. const validateOptions = require('../../utils/validateOptions');
  12. const { isRegExp, isString } = require('../../utils/validateTypes');
  13. const ruleName = 'media-feature-name-allowed-list';
  14. const messages = ruleMessages(ruleName, {
  15. rejected: (name) => `Unexpected media feature name "${name}"`,
  16. });
  17. const meta = {
  18. url: 'https://stylelint.io/user-guide/rules/list/media-feature-name-allowed-list',
  19. };
  20. /** @type {import('stylelint').Rule<string | RegExp | Array<string | RegExp>>} */
  21. const rule = (primary) => {
  22. return (root, result) => {
  23. const validOptions = validateOptions(result, ruleName, {
  24. actual: primary,
  25. possible: [isString, isRegExp],
  26. });
  27. if (!validOptions) {
  28. return;
  29. }
  30. root.walkAtRules(/^media$/i, (atRule) => {
  31. mediaParser(atRule.params).walk(/^media-feature$/i, (mediaFeatureNode) => {
  32. const parent = mediaFeatureNode.parent;
  33. const mediaFeatureRangeContext = isRangeContextMediaFeature(parent.value);
  34. let value;
  35. let sourceIndex;
  36. if (mediaFeatureRangeContext) {
  37. const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode);
  38. value = parsedRangeContext.name.value;
  39. sourceIndex = parsedRangeContext.name.sourceIndex;
  40. } else {
  41. value = mediaFeatureNode.value;
  42. sourceIndex = mediaFeatureNode.sourceIndex;
  43. }
  44. if (!isStandardSyntaxMediaFeatureName(value) || isCustomMediaQuery(value)) {
  45. return;
  46. }
  47. if (matchesStringOrRegExp(value, primary)) {
  48. return;
  49. }
  50. report({
  51. index: atRuleParamIndex(atRule) + sourceIndex,
  52. message: messages.rejected(value),
  53. node: atRule,
  54. ruleName,
  55. result,
  56. });
  57. });
  58. });
  59. };
  60. };
  61. rule.primaryOptionArray = true;
  62. rule.ruleName = ruleName;
  63. rule.messages = messages;
  64. rule.meta = meta;
  65. module.exports = rule;