index.cjs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // NOTICE: This file is generated by Rollup. To modify it,
  2. // please instead edit the ESM counterpart and rebuild with Rollup (npm run build).
  3. 'use strict';
  4. const valueParser = require('postcss-value-parser');
  5. const nodeFieldIndices = require('../../utils/nodeFieldIndices.cjs');
  6. const regexes = require('../../utils/regexes.cjs');
  7. const validateTypes = require('../../utils/validateTypes.cjs');
  8. const keywords = require('../../reference/keywords.cjs');
  9. const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule.cjs');
  10. const isStandardSyntaxDeclaration = require('../../utils/isStandardSyntaxDeclaration.cjs');
  11. const isStandardSyntaxValue = require('../../utils/isStandardSyntaxValue.cjs');
  12. const report = require('../../utils/report.cjs');
  13. const ruleMessages = require('../../utils/ruleMessages.cjs');
  14. const validateOptions = require('../../utils/validateOptions.cjs');
  15. const ruleName = 'container-name-pattern';
  16. const messages = ruleMessages(ruleName, {
  17. expected: (containerName, pattern) => `Expected "${containerName}" to match pattern "${pattern}"`,
  18. });
  19. const meta = {
  20. url: 'https://stylelint.io/user-guide/rules/container-name-pattern',
  21. };
  22. const KEYWORDS = new Set(['and', 'or', 'none', 'not']);
  23. /** @type {import('stylelint').CoreRules[ruleName]} */
  24. const rule = (primary) => {
  25. return (root, result) => {
  26. const validOptions = validateOptions(result, ruleName, {
  27. actual: primary,
  28. possible: [validateTypes.isRegExp, validateTypes.isString],
  29. });
  30. if (!validOptions) return;
  31. const regex = validateTypes.isString(primary) ? new RegExp(primary) : primary;
  32. const languageCssWideKeywords =
  33. result.stylelint.config?.languageOptions?.syntax?.cssWideKeywords ?? [];
  34. const cssWideKeywords = new Set([...keywords.basicKeywords, ...languageCssWideKeywords]);
  35. root.walkDecls(regexes.propertyRegexes.containerNameAndShorthandName, (decl) => {
  36. if (!isStandardSyntaxDeclaration(decl)) return;
  37. const parsedValue = valueParser(decl.value);
  38. let isContainerType = false;
  39. parsedValue.walk(({ sourceIndex, type, value }) => {
  40. if (isContainerType) return;
  41. if (type === 'div' && value === '/') isContainerType = true;
  42. if (type !== 'word') return false;
  43. if (cssWideKeywords.has(value.toLowerCase())) return;
  44. if (!isStandardSyntaxValue(value)) return;
  45. if (regex.test(value)) return;
  46. complain(nodeFieldIndices.declarationValueIndex(decl) + sourceIndex, value, decl);
  47. });
  48. });
  49. root.walkAtRules(regexes.atRuleRegexes.containerName, (atRule) => {
  50. if (!isStandardSyntaxAtRule(atRule)) return;
  51. const { params } = atRule;
  52. const parsedValue = valueParser(params);
  53. parsedValue.walk(({ sourceIndex, type, value }) => {
  54. if (type !== 'word') return false;
  55. if (KEYWORDS.has(value.toLowerCase())) return;
  56. if (regex.test(value)) return;
  57. complain(nodeFieldIndices.atRuleParamIndex(atRule) + sourceIndex, value, atRule);
  58. });
  59. });
  60. /**
  61. * @param {number} index
  62. * @param {string} containerName
  63. * @param {import('postcss').Declaration|import('postcss').AtRule} node
  64. */
  65. function complain(index, containerName, node) {
  66. report({
  67. result,
  68. ruleName,
  69. message: messages.expected,
  70. messageArgs: [containerName, primary],
  71. node,
  72. index,
  73. endIndex: index + containerName.length,
  74. });
  75. }
  76. };
  77. };
  78. rule.ruleName = ruleName;
  79. rule.messages = messages;
  80. rule.meta = meta;
  81. module.exports = rule;