index.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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-disallowed-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-disallowed-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. const index = atRuleParamIndex(atRule) + sourceIndex;
  51. const endIndex = index + value.length;
  52. report({
  53. index,
  54. endIndex,
  55. message: messages.rejected(value),
  56. node: atRule,
  57. ruleName,
  58. result,
  59. });
  60. });
  61. });
  62. };
  63. };
  64. rule.primaryOptionArray = true;
  65. rule.ruleName = ruleName;
  66. rule.messages = messages;
  67. rule.meta = meta;
  68. module.exports = rule;