index.cjs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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 validateTypes = require('../../utils/validateTypes.cjs');
  7. const regexes = require('../../utils/regexes.cjs');
  8. const isCustomProperty = require('../../utils/isCustomProperty.cjs');
  9. const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty.cjs');
  10. const isVarFunction = require('../../utils/isVarFunction.cjs');
  11. const report = require('../../utils/report.cjs');
  12. const ruleMessages = require('../../utils/ruleMessages.cjs');
  13. const validateOptions = require('../../utils/validateOptions.cjs');
  14. const ruleName = 'custom-property-pattern';
  15. const messages = ruleMessages(ruleName, {
  16. expected: (property, pattern) => `Expected "${property}" to match pattern "${pattern}"`,
  17. });
  18. const meta = {
  19. url: 'https://stylelint.io/user-guide/rules/custom-property-pattern',
  20. };
  21. const VAR_FUNC_REGEX = /var\(/i;
  22. /** @type {import('stylelint').CoreRules[ruleName]} */
  23. const rule = (primary) => {
  24. return (root, result) => {
  25. const validOptions = validateOptions(result, ruleName, {
  26. actual: primary,
  27. possible: [validateTypes.isRegExp, validateTypes.isString],
  28. });
  29. if (!validOptions) return;
  30. const regexpPattern = validateTypes.isString(primary) ? new RegExp(primary) : primary;
  31. /**
  32. * @param {string} property
  33. * @returns {boolean}
  34. */
  35. function check(property) {
  36. return (
  37. !isCustomProperty(property) ||
  38. !isStandardSyntaxProperty(property) ||
  39. regexpPattern.test(property.slice(2))
  40. );
  41. }
  42. root.walkDecls((decl) => {
  43. const { prop, value } = decl;
  44. if (VAR_FUNC_REGEX.test(value)) {
  45. const parsedValue = valueParser(value);
  46. parsedValue.walk((node) => {
  47. if (!isVarFunction(node)) return;
  48. const { nodes } = node;
  49. const firstNode = nodes[0];
  50. if (!firstNode || check(firstNode.value)) return;
  51. complain(nodeFieldIndices.declarationValueIndex(decl) + firstNode.sourceIndex, firstNode.value, decl);
  52. });
  53. }
  54. if (check(prop)) return;
  55. complain(0, prop, decl);
  56. });
  57. root.walkAtRules(regexes.atRuleRegexes.propertyName, (atRule) => {
  58. const { params: propName } = atRule;
  59. if (check(propName)) return;
  60. complain(nodeFieldIndices.atRuleParamIndex(atRule), propName, atRule);
  61. });
  62. /**
  63. * @param {number} index
  64. * @param {string} propName
  65. * @param {import('postcss').Declaration|import('postcss').AtRule} node
  66. */
  67. function complain(index, propName, node) {
  68. report({
  69. result,
  70. ruleName,
  71. message: messages.expected,
  72. messageArgs: [propName, primary],
  73. node,
  74. index,
  75. endIndex: index + propName.length,
  76. });
  77. }
  78. };
  79. };
  80. rule.ruleName = ruleName;
  81. rule.messages = messages;
  82. rule.meta = meta;
  83. module.exports = rule;