index.mjs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import valueParser from 'postcss-value-parser';
  2. import { atRuleRegexes, functionRegexes } from '../../utils/regexes.mjs';
  3. import { isRegExp, isString } from '../../utils/validateTypes.mjs';
  4. import { atRuleParamIndex } from '../../utils/nodeFieldIndices.mjs';
  5. import report from '../../utils/report.mjs';
  6. import ruleMessages from '../../utils/ruleMessages.mjs';
  7. import validateOptions from '../../utils/validateOptions.mjs';
  8. const ruleName = 'layer-name-pattern';
  9. const messages = ruleMessages(ruleName, {
  10. expected: (name, pattern) => `Expected "${name}" to match pattern "${pattern}"`,
  11. });
  12. const meta = {
  13. url: 'https://stylelint.io/user-guide/rules/layer-name-pattern',
  14. };
  15. /** @type {import('stylelint').CoreRules[ruleName]} */
  16. const rule = (primary) => {
  17. return (root, result) => {
  18. const validOptions = validateOptions(result, ruleName, {
  19. actual: primary,
  20. possible: [isRegExp, isString],
  21. });
  22. if (!validOptions) return;
  23. const pattern = isString(primary) ? new RegExp(primary) : primary;
  24. root.walkAtRules(atRuleRegexes.layerName, (atRule) => {
  25. const { params } = atRule;
  26. if (!params) return;
  27. const parsedParams = valueParser(params);
  28. parsedParams.walk((node) => {
  29. check(node.type, node.value, node.sourceIndex, atRule);
  30. });
  31. });
  32. root.walkAtRules(atRuleRegexes.importName, (atRule) => {
  33. const { params } = atRule;
  34. if (!functionRegexes.layer.test(params)) return;
  35. const parsedParams = valueParser(atRule.params);
  36. parsedParams.walk((node) => {
  37. if (node.type !== 'function' || node.value.toLowerCase() !== 'layer') return;
  38. for (const child of node.nodes) {
  39. check(child.type, child.value, child.sourceIndex, atRule);
  40. }
  41. });
  42. });
  43. /**
  44. * @param {string} type
  45. * @param {string} value
  46. * @param {number} sourceIndex
  47. * @param {import('postcss').AtRule} atRule
  48. */
  49. function check(type, value, sourceIndex, atRule) {
  50. if (type !== 'word') return;
  51. if (pattern.test(value)) return;
  52. const index = atRuleParamIndex(atRule) + sourceIndex;
  53. const endIndex = index + value.length;
  54. report({
  55. message: messages.expected,
  56. messageArgs: [value, primary],
  57. node: atRule,
  58. index,
  59. endIndex,
  60. ruleName,
  61. result,
  62. });
  63. }
  64. };
  65. };
  66. rule.ruleName = ruleName;
  67. rule.messages = messages;
  68. rule.meta = meta;
  69. export default rule;