@salesforce-ux/eslint-plugin-slds 1.0.8-internal → 1.0.9-internal

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/build/config/rule-messages.d.ts +2 -0
  2. package/build/config/rule-messages.js +197 -0
  3. package/build/config/rule-messages.js.map +7 -0
  4. package/build/index.js +40 -2471
  5. package/build/index.js.map +4 -4
  6. package/build/rules/enforce-bem-usage.js +16 -232
  7. package/build/rules/enforce-bem-usage.js.map +4 -4
  8. package/build/rules/modal-close-button-issue.js +11 -183
  9. package/build/rules/modal-close-button-issue.js.map +4 -4
  10. package/build/rules/no-deprecated-classes-slds2.js +4 -176
  11. package/build/rules/no-deprecated-classes-slds2.js.map +4 -4
  12. package/build/rules/v9/enforce-bem-usage.js +1 -161
  13. package/build/rules/v9/enforce-bem-usage.js.map +4 -4
  14. package/build/rules/v9/enforce-component-hook-naming-convention.js +1 -161
  15. package/build/rules/v9/enforce-component-hook-naming-convention.js.map +4 -4
  16. package/build/rules/v9/enforce-sds-to-slds-hooks.js +1 -161
  17. package/build/rules/v9/enforce-sds-to-slds-hooks.js.map +4 -4
  18. package/build/rules/v9/lwc-token-to-slds-hook.js +4 -262
  19. package/build/rules/v9/lwc-token-to-slds-hook.js.map +4 -4
  20. package/build/rules/v9/no-deprecated-slds-classes.js +1 -161
  21. package/build/rules/v9/no-deprecated-slds-classes.js.map +4 -4
  22. package/build/rules/v9/no-deprecated-tokens-slds1.js +29 -168
  23. package/build/rules/v9/no-deprecated-tokens-slds1.js.map +4 -4
  24. package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js +9 -289
  25. package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js.map +4 -4
  26. package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js +13 -283
  27. package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js.map +4 -4
  28. package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js +12 -328
  29. package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js.map +4 -4
  30. package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js +13 -309
  31. package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js.map +4 -4
  32. package/build/rules/v9/no-hardcoded-values/handlers/index.js +8 -875
  33. package/build/rules/v9/no-hardcoded-values/handlers/index.js.map +4 -4
  34. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js +3 -1208
  35. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js.map +4 -4
  36. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js +3 -1208
  37. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js.map +4 -4
  38. package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js +22 -993
  39. package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js.map +4 -4
  40. package/build/rules/v9/no-slds-class-overrides.js +1 -161
  41. package/build/rules/v9/no-slds-class-overrides.js.map +4 -4
  42. package/build/rules/v9/no-slds-namespace-for-custom-hooks.js +3 -252
  43. package/build/rules/v9/no-slds-namespace-for-custom-hooks.js.map +4 -4
  44. package/build/rules/v9/no-slds-private-var.js +1 -161
  45. package/build/rules/v9/no-slds-private-var.js.map +4 -4
  46. package/build/rules/v9/no-slds-var-without-fallback.js +3 -255
  47. package/build/rules/v9/no-slds-var-without-fallback.js.map +4 -4
  48. package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js +1 -161
  49. package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js.map +4 -4
  50. package/build/rules/v9/no-unsupported-hooks-slds2.js +1 -161
  51. package/build/rules/v9/no-unsupported-hooks-slds2.js.map +4 -4
  52. package/build/rules/v9/reduce-annotations.js +1 -161
  53. package/build/rules/v9/reduce-annotations.js.map +4 -4
  54. package/build/{src/utils → utils}/boxShadowValueParser.d.ts +1 -1
  55. package/build/utils/boxShadowValueParser.js +63 -93
  56. package/build/utils/boxShadowValueParser.js.map +4 -4
  57. package/build/utils/color-lib-utils.js +2 -29
  58. package/build/utils/color-lib-utils.js.map +3 -3
  59. package/build/{src/utils → utils}/css-utils.d.ts +7 -0
  60. package/build/utils/css-utils.js +10 -71
  61. package/build/utils/css-utils.js.map +4 -4
  62. package/build/utils/hardcoded-shared-utils.js +17 -82
  63. package/build/utils/hardcoded-shared-utils.js.map +4 -4
  64. package/build/utils/property-matcher.js +2 -2
  65. package/build/utils/property-matcher.js.map +2 -2
  66. package/build/utils/styling-hook-utils.js +16 -39
  67. package/build/utils/styling-hook-utils.js.map +3 -3
  68. package/build/{src/utils → utils}/value-utils.d.ts +2 -2
  69. package/build/utils/value-utils.js +8 -8
  70. package/build/utils/value-utils.js.map +2 -2
  71. package/package.json +5 -10
  72. package/src/config/rule-messages.yml +0 -143
  73. /package/build/{src/index.d.ts → index.d.ts} +0 -0
  74. /package/build/{src/rules → rules}/enforce-bem-usage.d.ts +0 -0
  75. /package/build/{src/rules → rules}/modal-close-button-issue.d.ts +0 -0
  76. /package/build/{src/rules → rules}/no-deprecated-classes-slds2.d.ts +0 -0
  77. /package/build/{src/rules → rules}/v9/enforce-bem-usage.d.ts +0 -0
  78. /package/build/{src/rules → rules}/v9/enforce-component-hook-naming-convention.d.ts +0 -0
  79. /package/build/{src/rules → rules}/v9/enforce-sds-to-slds-hooks.d.ts +0 -0
  80. /package/build/{src/rules → rules}/v9/lwc-token-to-slds-hook.d.ts +0 -0
  81. /package/build/{src/rules → rules}/v9/no-deprecated-slds-classes.d.ts +0 -0
  82. /package/build/{src/rules → rules}/v9/no-deprecated-tokens-slds1.d.ts +0 -0
  83. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/boxShadowHandler.d.ts +0 -0
  84. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/colorHandler.d.ts +0 -0
  85. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/densityHandler.d.ts +0 -0
  86. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/fontHandler.d.ts +0 -0
  87. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/index.d.ts +0 -0
  88. /package/build/{src/rules → rules}/v9/no-hardcoded-values/no-hardcoded-values-slds1.d.ts +0 -0
  89. /package/build/{src/rules → rules}/v9/no-hardcoded-values/no-hardcoded-values-slds2.d.ts +0 -0
  90. /package/build/{src/rules → rules}/v9/no-hardcoded-values/noHardcodedValueRule.d.ts +0 -0
  91. /package/build/{src/rules → rules}/v9/no-hardcoded-values/ruleOptionsSchema.d.ts +0 -0
  92. /package/build/{src/rules → rules}/v9/no-slds-class-overrides.d.ts +0 -0
  93. /package/build/{src/rules → rules}/v9/no-slds-namespace-for-custom-hooks.d.ts +0 -0
  94. /package/build/{src/rules → rules}/v9/no-slds-private-var.d.ts +0 -0
  95. /package/build/{src/rules → rules}/v9/no-slds-var-without-fallback.d.ts +0 -0
  96. /package/build/{src/rules → rules}/v9/no-sldshook-fallback-for-lwctoken.d.ts +0 -0
  97. /package/build/{src/rules → rules}/v9/no-unsupported-hooks-slds2.d.ts +0 -0
  98. /package/build/{src/rules → rules}/v9/reduce-annotations.d.ts +0 -0
  99. /package/build/{src/types → types}/index.d.ts +0 -0
  100. /package/build/{src/utils → utils}/color-lib-utils.d.ts +0 -0
  101. /package/build/{src/utils → utils}/css-functions.d.ts +0 -0
  102. /package/build/{src/utils → utils}/custom-mapping-utils.d.ts +0 -0
  103. /package/build/{src/utils → utils}/hardcoded-shared-utils.d.ts +0 -0
  104. /package/build/{src/utils → utils}/node.d.ts +0 -0
  105. /package/build/{src/utils → utils}/property-matcher.d.ts +0 -0
  106. /package/build/{src/utils → utils}/rule-utils.d.ts +0 -0
  107. /package/build/{src/utils → utils}/styling-hook-utils.d.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/color-lib-utils.ts", "../../src/utils/css-functions.ts"],
4
- "sourcesContent": ["import { ValueToStylingHooksMapping, ValueToStylingHookEntry } from '@salesforce-ux/sds-metadata/next';\nimport chroma from 'chroma-js';\nimport { generate } from '@eslint/css-tree';\nimport { isCssColorFunction } from './css-functions';\n\n/**\n * Perceptual color difference threshold (Delta E, CIEDE2000 via chroma.deltaE).\n * Lower values are stricter matches. Used to decide which hooks are \"close enough\".\n */\nconst DELTAE_THRESHOLD = 10;\n\n/**\n * Convert any valid CSS color (named, hex, rgb(a), hsl(a), etc.) to hex.\n * Returns null if the value is not a valid color.\n */\nconst convertToHex = (color: string): string | null => {\n try {\n // Try converting the color using chroma-js, which handles both named and hex colors\n return chroma(color).hex();\n } catch (e) {\n // If chroma can't process the color, it's likely invalid\n return null;\n }\n};\n\nconst isHookPropertyMatch = (hook: ValueToStylingHookEntry, cssProperty: string): boolean => {\n return hook.properties.includes(cssProperty) || hook.properties.includes(\"*\");\n}\n\nfunction getOrderByCssProp(cssProperty: string): string[] {\n if(cssProperty === 'color' || cssProperty === 'fill') {\n return [\"surface\", \"theme\", \"feedback\", \"reference\"];\n } else if(cssProperty.match(/background/)){\n return [\"surface\", \"surface-inverse\", \"theme\", \"feedback\", \"reference\"];\n } else if(cssProperty.match(/border/) || cssProperty.match(/outline/) || cssProperty.match(/stroke/)) {\n return [\"borders\", \"borders-inverse\", \"feedback\", \"theme\", \"reference\"];\n }\n return [\"surface\", \"surface-inverse\", \"borders\", \"borders-inverse\", \"theme\", \"feedback\", \"reference\"];\n}\n\n\n/**\n * Given an input color and the metadata mapping of supported colors to hooks,\n * suggest up to 5 styling hook names ordered by:\n * 1) Category priority: semantic -> system -> palette\n * 2) Perceptual distance (Delta E)\n * Also prioritizes exact color matches (distance 0).\n */\nconst findClosestColorHook = (\n color: string,\n supportedColors:ValueToStylingHooksMapping,\n cssProperty: string\n): string[] => {\n const closestHooks: Array<{distance: number, group: string, name: string}> = [];\n Object.entries(supportedColors).forEach(([sldsValue, data]) => {\n if (sldsValue && isValidColor(sldsValue)) {\n const hooks = data as ValueToStylingHookEntry[]; // Get the hooks for the sldsValue\n\n hooks.forEach((hook) => {\n // Exact match shortcut to avoid floating rounding noise\n const distance = (sldsValue.toLowerCase() === color.toLowerCase())\n ? 0\n : chroma.deltaE(sldsValue, color);\n \n // Check if the hook has the same property or universal selector\n if (isHookPropertyMatch(hook, cssProperty) && distance <= DELTAE_THRESHOLD) {\n // Add to same property hooks if within threshold\n closestHooks.push({ distance, group: hook.group, name: hook.name });\n }\n });\n }\n });\n\n const hooksByGroupMap:Record<string, string[]> = closestHooks.sort((a, b) => a.distance - b.distance).reduce((acc, hook) => {\n if (!acc[hook.group]) {\n acc[hook.group] = [];\n }\n acc[hook.group].push(hook.name);\n return acc;\n }, {});\n\n return getOrderByCssProp(cssProperty)\n .map(group => hooksByGroupMap[group]||[])\n .flat().slice(0, 5);\n};\n\n/**\n * Check if a value is any valid CSS color string (delegates to chroma-js).\n */\nconst isValidColor = (val:string):boolean => chroma.valid(val);\n\n/**\n * Extract a color string from a CSS AST node produced by @eslint/css-tree.\n * Supports Hash (#rrggbb), Identifier (named colors), and color Function nodes.\n * Returns null if the extracted value is not a valid color.\n */\nconst extractColorValue = (node: any): string | null => {\n let colorValue: string | null = null;\n \n switch (node.type) {\n case 'Hash':\n colorValue = `#${node.value}`;\n break;\n case 'Identifier':\n colorValue = node.name;\n break;\n case 'Function':\n // Only extract color functions\n if (isCssColorFunction(node.name)) {\n colorValue = generate(node);\n }\n break;\n }\n \n return colorValue && isValidColor(colorValue) ? colorValue : null;\n};\n\nexport { findClosestColorHook, convertToHex, isValidColor, extractColorValue };\n", "//stylelint-sds/packages/stylelint-plugin-slds/src/utils/css-functions.ts\n/**\n * Complete list of CSS functions that should be preserved/recognized\n */\nconst CSS_FUNCTIONS = [\n 'attr',\n 'calc',\n 'color-mix',\n 'conic-gradient',\n 'counter',\n 'cubic-bezier',\n 'linear-gradient',\n 'max',\n 'min',\n 'radial-gradient',\n 'repeating-conic-gradient',\n 'repeating-linear-gradient',\n 'repeating-radial-gradient',\n 'var'\n ];\n \n \n const CSS_MATH_FUNCTIONS = ['calc', 'min', 'max'];\n \n \n const RGB_COLOR_FUNCTIONS = ['rgb', 'rgba', 'hsl', 'hsla'];\n \n /**\n * Regex for matching any CSS function (for general detection)\n * Matches function names within other text\n */\n const cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join('|')})`);\n \n \n const cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join('|')})$`);\n \n \n const cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join('|')})$`);\n \n export function containsCssFunction(value: string): boolean {\n return cssFunctionsRegex.test(value);\n }\n \n /**\n * Check if a value is exactly a CSS function name\n */\n export function isCssFunction(value: string): boolean {\n return cssFunctionsExactRegex.test(value);\n }\n \n export function isCssMathFunction(value: string): boolean {\n return cssMathFunctionsRegex.test(value);\n }\n \n export function isCssColorFunction(value: string): boolean {\n return RGB_COLOR_FUNCTIONS.includes(value);\n }"],
5
- "mappings": "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",
3
+ "sources": ["../../src/utils/color-lib-utils.ts"],
4
+ "sourcesContent": ["import { ValueToStylingHooksMapping, ValueToStylingHookEntry } from '@salesforce-ux/sds-metadata/next';\nimport chroma from 'chroma-js';\nimport { generate } from '@eslint/css-tree';\nimport { isCssColorFunction } from './css-functions';\n\n/**\n * Perceptual color difference threshold (Delta E, CIEDE2000 via chroma.deltaE).\n * Lower values are stricter matches. Used to decide which hooks are \"close enough\".\n */\nconst DELTAE_THRESHOLD = 10;\n\n/**\n * Convert any valid CSS color (named, hex, rgb(a), hsl(a), etc.) to hex.\n * Returns null if the value is not a valid color.\n */\nconst convertToHex = (color: string): string | null => {\n try {\n // Try converting the color using chroma-js, which handles both named and hex colors\n return chroma(color).hex();\n } catch (e) {\n // If chroma can't process the color, it's likely invalid\n return null;\n }\n};\n\nconst isHookPropertyMatch = (hook: ValueToStylingHookEntry, cssProperty: string): boolean => {\n return hook.properties.includes(cssProperty) || hook.properties.includes(\"*\");\n}\n\nfunction getOrderByCssProp(cssProperty: string): string[] {\n if(cssProperty === 'color' || cssProperty === 'fill') {\n return [\"surface\", \"theme\", \"feedback\", \"reference\"];\n } else if(cssProperty.match(/background/)){\n return [\"surface\", \"surface-inverse\", \"theme\", \"feedback\", \"reference\"];\n } else if(cssProperty.match(/border/) || cssProperty.match(/outline/) || cssProperty.match(/stroke/)) {\n return [\"borders\", \"borders-inverse\", \"feedback\", \"theme\", \"reference\"];\n }\n return [\"surface\", \"surface-inverse\", \"borders\", \"borders-inverse\", \"theme\", \"feedback\", \"reference\"];\n}\n\n\n/**\n * Given an input color and the metadata mapping of supported colors to hooks,\n * suggest up to 5 styling hook names ordered by:\n * 1) Category priority: semantic -> system -> palette\n * 2) Perceptual distance (Delta E)\n * Also prioritizes exact color matches (distance 0).\n */\nconst findClosestColorHook = (\n color: string,\n supportedColors:ValueToStylingHooksMapping,\n cssProperty: string\n): string[] => {\n const closestHooks: Array<{distance: number, group: string, name: string}> = [];\n Object.entries(supportedColors).forEach(([sldsValue, data]) => {\n if (sldsValue && isValidColor(sldsValue)) {\n const hooks = data as ValueToStylingHookEntry[]; // Get the hooks for the sldsValue\n\n hooks.forEach((hook) => {\n // Exact match shortcut to avoid floating rounding noise\n const distance = (sldsValue.toLowerCase() === color.toLowerCase())\n ? 0\n : chroma.deltaE(sldsValue, color);\n \n // Check if the hook has the same property or universal selector\n if (isHookPropertyMatch(hook, cssProperty) && distance <= DELTAE_THRESHOLD) {\n // Add to same property hooks if within threshold\n closestHooks.push({ distance, group: hook.group, name: hook.name });\n }\n });\n }\n });\n\n const hooksByGroupMap:Record<string, string[]> = closestHooks.sort((a, b) => a.distance - b.distance).reduce((acc, hook) => {\n if (!acc[hook.group]) {\n acc[hook.group] = [];\n }\n acc[hook.group].push(hook.name);\n return acc;\n }, {});\n\n return getOrderByCssProp(cssProperty)\n .map(group => hooksByGroupMap[group]||[])\n .flat().slice(0, 5);\n};\n\n/**\n * Check if a value is any valid CSS color string (delegates to chroma-js).\n */\nconst isValidColor = (val:string):boolean => chroma.valid(val);\n\n/**\n * Extract a color string from a CSS AST node produced by @eslint/css-tree.\n * Supports Hash (#rrggbb), Identifier (named colors), and color Function nodes.\n * Returns null if the extracted value is not a valid color.\n */\nconst extractColorValue = (node: any): string | null => {\n let colorValue: string | null = null;\n \n switch (node.type) {\n case 'Hash':\n colorValue = `#${node.value}`;\n break;\n case 'Identifier':\n colorValue = node.name;\n break;\n case 'Function':\n // Only extract color functions\n if (isCssColorFunction(node.name)) {\n colorValue = generate(node);\n }\n break;\n }\n \n return colorValue && isValidColor(colorValue) ? colorValue : null;\n};\n\nexport { findClosestColorHook, convertToHex, isValidColor, extractColorValue };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAAmB;AACnB,sBAAyB;AACzB,2BAAmC;AAMnC,IAAM,mBAAmB;AAMzB,IAAM,eAAe,CAAC,UAAiC;AACrD,MAAI;AAEF,eAAO,iBAAAA,SAAO,KAAK,EAAE,IAAI;AAAA,EAC3B,SAAS,GAAG;AAEV,WAAO;AAAA,EACT;AACF;AAEA,IAAM,sBAAsB,CAAC,MAA+B,gBAAiC;AAC3F,SAAO,KAAK,WAAW,SAAS,WAAW,KAAK,KAAK,WAAW,SAAS,GAAG;AAC9E;AAEA,SAAS,kBAAkB,aAA+B;AACxD,MAAG,gBAAgB,WAAW,gBAAgB,QAAQ;AAClD,WAAO,CAAC,WAAW,SAAU,YAAY,WAAW;AAAA,EACxD,WAAU,YAAY,MAAM,YAAY,GAAE;AACvC,WAAO,CAAC,WAAW,mBAAmB,SAAU,YAAY,WAAW;AAAA,EAC1E,WAAU,YAAY,MAAM,QAAQ,KAAK,YAAY,MAAM,SAAS,KAAK,YAAY,MAAM,QAAQ,GAAG;AAClG,WAAO,CAAC,WAAW,mBAAmB,YAAY,SAAS,WAAW;AAAA,EAC1E;AACA,SAAO,CAAC,WAAW,mBAAmB,WAAW,mBAAmB,SAAU,YAAY,WAAW;AACvG;AAUA,IAAM,uBAAuB,CAC3B,OACA,iBACA,gBACa;AACb,QAAM,eAAuE,CAAC;AAC9E,SAAO,QAAQ,eAAe,EAAE,QAAQ,CAAC,CAAC,WAAW,IAAI,MAAM;AAC7D,QAAI,aAAa,aAAa,SAAS,GAAG;AACxC,YAAM,QAAQ;AAEd,YAAM,QAAQ,CAAC,SAAS;AAEtB,cAAM,WAAY,UAAU,YAAY,MAAM,MAAM,YAAY,IAC5D,IACA,iBAAAA,QAAO,OAAO,WAAW,KAAK;AAGlC,YAAI,oBAAoB,MAAM,WAAW,KAAK,YAAY,kBAAkB;AAE1E,uBAAa,KAAK,EAAE,UAAU,OAAO,KAAK,OAAO,MAAM,KAAK,KAAK,CAAC;AAAA,QACpE;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,QAAM,kBAA2C,aAAa,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,KAAK,SAAS;AAC1H,QAAI,CAAC,IAAI,KAAK,KAAK,GAAG;AACpB,UAAI,KAAK,KAAK,IAAI,CAAC;AAAA,IACrB;AACA,QAAI,KAAK,KAAK,EAAE,KAAK,KAAK,IAAI;AAC9B,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,SAAO,kBAAkB,WAAW,EACjC,IAAI,WAAS,gBAAgB,KAAK,KAAG,CAAC,CAAC,EACvC,KAAK,EAAE,MAAM,GAAG,CAAC;AACtB;AAKA,IAAM,eAAe,CAAC,QAAuB,iBAAAA,QAAO,MAAM,GAAG;AAO7D,IAAM,oBAAoB,CAAC,SAA6B;AACtD,MAAI,aAA4B;AAEhC,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,mBAAa,IAAI,KAAK,KAAK;AAC3B;AAAA,IACF,KAAK;AACH,mBAAa,KAAK;AAClB;AAAA,IACF,KAAK;AAEH,cAAI,yCAAmB,KAAK,IAAI,GAAG;AACjC,yBAAa,0BAAS,IAAI;AAAA,MAC5B;AACA;AAAA,EACJ;AAEA,SAAO,cAAc,aAAa,UAAU,IAAI,aAAa;AAC/D;",
6
6
  "names": ["chroma"]
7
7
  }
@@ -13,6 +13,13 @@ export interface CssVariableInfo {
13
13
  name: string;
14
14
  hasFallback: boolean;
15
15
  }
16
+ /**
17
+ * Get the CSS variable token from a var() function node
18
+ * Extracts the custom property name from var(--custom-prop) -> "--custom-prop"
19
+ * @param node - CSS tree AST node (Function node expected)
20
+ * @returns The custom property name (e.g., "--slds-g-color-brand-base-15") or empty string
21
+ */
22
+ export declare function getVarToken(node: any): string;
16
23
  /**
17
24
  * Specialized CSS variable traversal for SLDS variables
18
25
  * Finds var(--slds-*) functions and reports their fallback status
@@ -1,8 +1,6 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
5
  var __export = (target, all) => {
8
6
  for (var name in all)
@@ -16,14 +14,6 @@ var __copyProps = (to, from, except, desc) => {
16
14
  }
17
15
  return to;
18
16
  };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
18
 
29
19
  // src/utils/css-utils.ts
@@ -33,67 +23,11 @@ __export(css_utils_exports, {
33
23
  forEachNamespacedVariable: () => forEachNamespacedVariable,
34
24
  forEachSldsVariable: () => forEachSldsVariable,
35
25
  formatSuggestionHooks: () => formatSuggestionHooks,
26
+ getVarToken: () => getVarToken,
36
27
  isTargetProperty: () => isTargetProperty
37
28
  });
38
29
  module.exports = __toCommonJS(css_utils_exports);
39
-
40
- // src/utils/hardcoded-shared-utils.ts
41
- var import_css_tree2 = require("@eslint/css-tree");
42
-
43
- // src/utils/color-lib-utils.ts
44
- var import_chroma_js = __toESM(require("chroma-js"));
45
- var import_css_tree = require("@eslint/css-tree");
46
-
47
- // src/utils/css-functions.ts
48
- var CSS_FUNCTIONS = [
49
- "attr",
50
- "calc",
51
- "color-mix",
52
- "conic-gradient",
53
- "counter",
54
- "cubic-bezier",
55
- "linear-gradient",
56
- "max",
57
- "min",
58
- "radial-gradient",
59
- "repeating-conic-gradient",
60
- "repeating-linear-gradient",
61
- "repeating-radial-gradient",
62
- "var"
63
- ];
64
- var CSS_MATH_FUNCTIONS = ["calc", "min", "max"];
65
- var cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join("|")})`);
66
- var cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join("|")})$`);
67
- var cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join("|")})$`);
68
-
69
- // src/utils/hardcoded-shared-utils.ts
70
- function forEachValue(valueText, extractValue, shouldSkipNode, callback) {
71
- if (!valueText || typeof valueText !== "string") {
72
- return;
73
- }
74
- try {
75
- const ast = (0, import_css_tree2.parse)(valueText, { context: "value", positions: true });
76
- (0, import_css_tree2.walk)(ast, {
77
- enter(node) {
78
- if (shouldSkipNode(node)) {
79
- return this.skip;
80
- }
81
- const value = extractValue(node);
82
- if (value !== null) {
83
- const positionInfo = {
84
- start: node.loc?.start,
85
- end: node.loc?.end
86
- };
87
- callback(value, positionInfo);
88
- }
89
- }
90
- });
91
- } catch (error) {
92
- return;
93
- }
94
- }
95
-
96
- // src/utils/css-utils.ts
30
+ var import_hardcoded_shared_utils = require("./hardcoded-shared-utils");
97
31
  function isTargetProperty(property, propertyTargets = []) {
98
32
  if (typeof property !== "string") return false;
99
33
  return property.startsWith("--sds-") || property.startsWith("--slds-") || property.startsWith("--lwc-") || propertyTargets.length === 0 || propertyTargets.includes(property);
@@ -119,6 +53,10 @@ function extractCssVariable(node, filter) {
119
53
  }
120
54
  return filter(variableName, childrenArray);
121
55
  }
56
+ function getVarToken(node) {
57
+ const result = extractCssVariable(node, (variableName) => variableName);
58
+ return result || "";
59
+ }
122
60
  function forEachSldsVariable(valueText, callback) {
123
61
  const extractor = (node) => extractCssVariable(node, (variableName, childrenArray) => {
124
62
  if (!variableName.startsWith("--slds-")) {
@@ -129,7 +67,7 @@ function forEachSldsVariable(valueText, callback) {
129
67
  );
130
68
  return { name: variableName, hasFallback };
131
69
  });
132
- forEachValue(valueText, extractor, () => false, callback);
70
+ (0, import_hardcoded_shared_utils.forEachValue)(valueText, extractor, () => false, callback);
133
71
  }
134
72
  function forEachNamespacedVariable(valueText, callback) {
135
73
  const extractor = (node) => extractCssVariable(node, (variableName) => {
@@ -138,7 +76,7 @@ function forEachNamespacedVariable(valueText, callback) {
138
76
  }
139
77
  return null;
140
78
  });
141
- forEachValue(valueText, extractor, () => false, callback);
79
+ (0, import_hardcoded_shared_utils.forEachValue)(valueText, extractor, () => false, callback);
142
80
  }
143
81
  function forEachLwcVariable(valueText, callback) {
144
82
  const extractor = (node) => extractCssVariable(node, (variableName, childrenArray) => {
@@ -150,7 +88,7 @@ function forEachLwcVariable(valueText, callback) {
150
88
  );
151
89
  return { name: variableName, hasFallback };
152
90
  });
153
- forEachValue(valueText, extractor, () => false, callback);
91
+ (0, import_hardcoded_shared_utils.forEachValue)(valueText, extractor, () => false, callback);
154
92
  }
155
93
  function formatSuggestionHooks(hooks) {
156
94
  if (hooks.length === 1) {
@@ -164,6 +102,7 @@ function formatSuggestionHooks(hooks) {
164
102
  forEachNamespacedVariable,
165
103
  forEachSldsVariable,
166
104
  formatSuggestionHooks,
105
+ getVarToken,
167
106
  isTargetProperty
168
107
  });
169
108
  //# sourceMappingURL=css-utils.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/css-utils.ts", "../../src/utils/hardcoded-shared-utils.ts", "../../src/utils/color-lib-utils.ts", "../../src/utils/css-functions.ts"],
4
- "sourcesContent": ["import { \n forEachValue, \n type PositionInfo \n} from './hardcoded-shared-utils';\n\n/**\n * Check if a CSS property should be targeted for linting based on prefixes or explicit targets\n * @param property - The CSS property name to check\n * @param propertyTargets - Array of specific properties to target (empty means target all)\n * @returns true if the property should be targeted\n */\nexport function isTargetProperty(property: string, propertyTargets: string[] = []): boolean {\n if (typeof property !== 'string') return false;\n return property.startsWith('--sds-')\n || property.startsWith('--slds-')\n || property.startsWith('--lwc-')\n || propertyTargets.length === 0\n || propertyTargets.includes(property);\n}\n\n/**\n * CSS Variable information for SLDS variable detection\n */\nexport interface CssVariableInfo {\n name: string; // Variable name: --slds-g-color-surface-1\n hasFallback: boolean; // Whether var() already has a fallback\n}\n\n/**\n * Generic CSS variable extractor that can be customized for different use cases\n * @param node - AST node to extract from\n * @param filter - Function to validate and extract variable information\n * @returns Extracted variable info or null\n */\nfunction extractCssVariable<T>(\n node: any,\n filter: (variableName: string, childrenArray: any[]) => T | null\n): T | null {\n if (!node || node.type !== 'Function' || node.name !== 'var') {\n return null;\n }\n\n if (!node.children) {\n return null;\n }\n\n // Convert children to array and get the first child (variable name)\n const childrenArray = Array.from(node.children);\n if (childrenArray.length === 0) {\n return null;\n }\n \n const firstChild = childrenArray[0] as any;\n if (!firstChild || firstChild.type !== 'Identifier') {\n return null;\n }\n\n const variableName = firstChild.name;\n if (!variableName) {\n return null;\n }\n\n return filter(variableName, childrenArray);\n}\n\n/**\n * Specialized CSS variable traversal for SLDS variables\n * Finds var(--slds-*) functions and reports their fallback status\n */\nexport function forEachSldsVariable(\n valueText: string,\n callback: (variableInfo: CssVariableInfo, positionInfo: PositionInfo) => void\n): void {\n const extractor = (node: any) => extractCssVariable(node, (variableName, childrenArray) => {\n if (!variableName.startsWith('--slds-')) {\n return null;\n }\n\n // Check if there's a fallback (comma separator)\n const hasFallback = childrenArray.some((child: any) => \n child.type === 'Operator' && child.value === ','\n );\n\n return { name: variableName, hasFallback };\n });\n\n forEachValue(valueText, extractor, () => false, callback);\n}\n\n/**\n * Specialized CSS variable traversal for SLDS/SDS namespace detection\n * Finds var(--slds-*) or var(--sds-*) functions in CSS values\n * Note: hasFallback is set to false as it's unused for namespace validation\n */\nexport function forEachNamespacedVariable(\n valueText: string,\n callback: (variableInfo: CssVariableInfo, positionInfo: PositionInfo) => void\n): void {\n const extractor = (node: any) => extractCssVariable(node, (variableName) => {\n // Check for SLDS or SDS namespace\n if (variableName.startsWith('--slds-') || variableName.startsWith('--sds-')) {\n return { name: variableName, hasFallback: false }; // hasFallback unused, but required by interface\n }\n return null;\n });\n\n forEachValue(valueText, extractor, () => false, callback);\n}\n\n/**\n * Specialized CSS variable traversal for LWC variables\n * Finds var(--lwc-*) functions in CSS values and reports their fallback status\n */\nexport function forEachLwcVariable(\n valueText: string,\n callback: (variableInfo: CssVariableInfo, positionInfo: PositionInfo) => void\n): void {\n const extractor = (node: any) => extractCssVariable(node, (variableName, childrenArray) => {\n if (!variableName.startsWith('--lwc-')) {\n return null;\n }\n\n // Check if there's a fallback (comma separator)\n const hasFallback = childrenArray.some((child: any) => \n child.type === 'Operator' && child.value === ','\n );\n\n return { name: variableName, hasFallback };\n });\n\n forEachValue(valueText, extractor, () => false, callback);\n}\n\n/**\n * Format multiple hook suggestions for better readability\n * @param hooks - Array of hook names to format\n * @returns Formatted string with hooks\n */\nexport function formatSuggestionHooks(hooks: string[]): string {\n if (hooks.length === 1) {\n return `${hooks[0]}`;\n }\n\n // Loop through hooks and append each as a numbered list item with line breaks\n return '\\n' + hooks.map((hook, index) => `${index + 1}. ${hook}`).join('\\n');\n}", "import { parse, walk } from '@eslint/css-tree';\nimport type { HandlerContext } from '../types';\nimport type { ParsedUnitValue } from './value-utils';\nimport { ALLOWED_UNITS } from './value-utils';\nimport { extractColorValue } from './color-lib-utils';\nimport { isCssFunction } from './css-functions';\n\n/**\n * Common replacement data structure used by both color and density handlers\n */\nexport interface ReplacementInfo {\n start: number;\n end: number;\n replacement: string; // Full CSS var: var(--hook, fallback)\n displayValue: string; // Just the hook: --hook\n hasHook: boolean;\n isNumeric?: boolean; // Whether this is a numeric (dimension) value\n}\n\n/**\n * Position information from CSS tree parsing\n */\nexport interface PositionInfo {\n start?: { offset: number; line: number; column: number };\n end?: { offset: number; line: number; column: number };\n}\n\n/**\n * Generic callback for processing values with position information\n */\nexport type ValueCallback<T> = (value: T, positionInfo?: PositionInfo) => void;\n\n/**\n * Known valid font-weight values\n */\nconst FONT_WEIGHTS = [\n 'normal',\n 'bold', \n 'bolder',\n 'lighter',\n '100',\n '200', \n '300',\n '400',\n '500',\n '600',\n '700',\n '800',\n '900'\n];\n\n/**\n * Check if a value is a known font-weight\n */\nexport function isKnownFontWeight(value: string | number): boolean {\n const stringValue = value.toString();\n return FONT_WEIGHTS.includes(stringValue.toLowerCase());\n}\n\n/**\n * Generic shorthand auto-fix handler\n * Handles the common logic for reconstructing shorthand values with replacements\n */\nexport function handleShorthandAutoFix(\n declarationNode: any,\n context: HandlerContext,\n valueText: string,\n replacements: ReplacementInfo[]\n) {\n if(!replacements || replacements.length === 0){\n return;\n }\n // Sort replacements by position for proper reconstruction\n const sortedReplacements = replacements.sort((a,b)=> b.start-a.start);\n\n // Get rule options\n const reportNumericValue = context.options?.reportNumericValue || 'always';\n\n const fixCallback = (start:number, originalValue:string, replacement:string) => {\n // Reconstruct the entire value with all replacements\n let newValue = valueText;\n\n newValue = newValue.substring(0, start) + replacement + newValue.substring(start+originalValue.length);\n\n if(newValue !== valueText){\n return (fixer:any)=>{\n return fixer.replaceText(declarationNode.value, newValue);\n }\n }\n }\n\n // Report each individual value\n sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook, isNumeric }) => {\n const originalValue = valueText.substring(start, end);\n \n // Check if we should skip reporting based on reportNumericValue option\n if (isNumeric) {\n if (reportNumericValue === 'never') {\n return; // Skip reporting numeric values\n }\n if (reportNumericValue === 'hasReplacement' && !hasHook) {\n return; // Skip reporting numeric values without replacements\n }\n }\n \n \n const valueColumnStart = declarationNode.value.loc.start.column + start;\n const valueColumnEnd = valueColumnStart + originalValue.length;\n const canAutoFix = originalValue !== replacement;\n \n // Create precise error location for this value\n const { loc: { start: locStart, end: locEnd } } = declarationNode.value;\n const reportNode = {\n ...declarationNode.value,\n loc: {\n ...declarationNode.value.loc,\n start: {\n ...locStart,\n column: valueColumnStart\n },\n end: {\n ...locEnd,\n column: valueColumnEnd\n }\n }\n };\n\n if (hasHook) {\n // Create auto-fix for the entire shorthand value\n const fix = canAutoFix ? fixCallback(start, originalValue, replacement) : undefined;\n\n context.context.report({\n node: reportNode,\n messageId: 'hardcodedValue',\n data: {\n oldValue: originalValue,\n newValue: displayValue\n },\n fix\n });\n } else {\n // No hook available\n context.context.report({\n node: reportNode,\n messageId: 'noReplacement',\n data: {\n oldValue: originalValue\n }\n });\n }\n });\n}\n\n/**\n * Generic CSS tree traversal with position tracking\n * Always provides position information since both handlers need it\n */\nexport function forEachValue<T>(\n valueText: string,\n extractValue: (node: any) => T | null,\n shouldSkipNode: (node: any) => boolean,\n callback: (value: T, positionInfo: PositionInfo) => void\n): void {\n if (!valueText || typeof valueText !== 'string') {\n return;\n }\n\n try {\n const ast = parse(valueText, { context: 'value' as const, positions: true });\n \n walk(ast, {\n enter(node: any) {\n // Skip nodes efficiently using this.skip\n if (shouldSkipNode(node)) {\n return this.skip;\n }\n \n const value = extractValue(node);\n if (value !== null) {\n const positionInfo: PositionInfo = {\n start: node.loc?.start,\n end: node.loc?.end\n };\n callback(value, positionInfo);\n }\n }\n });\n } catch (error) {\n // Silently handle parse errors\n return;\n }\n}\n\n/**\n * Check if color node should be skipped during traversal\n */\nfunction shouldSkipColorNode(node: any): boolean {\n return node.type === 'Function' && isCssFunction(node.name);\n}\n\n/**\n * Check if dimension node should be skipped during traversal\n * Skip all function nodes by default\n */\nfunction shouldSkipDimensionNode(node: any): boolean {\n return node.type === 'Function';\n}\n\n/**\n * Extract dimension value from CSS AST node\n * Returns structured data with number and unit to eliminate regex parsing\n */\nfunction extractDimensionValue(valueNode: any, cssProperty?: string): ParsedUnitValue | null {\n if (!valueNode) return null;\n \n switch (valueNode.type) {\n case 'Dimension':\n // Dimensions: 16px, 1rem -> extract value and unit directly from AST\n const numValue = Number(valueNode.value);\n if (numValue === 0) return null; // Skip zero values\n \n const unit = valueNode.unit.toLowerCase();\n if (!ALLOWED_UNITS.includes(unit)) return null; // Support only allowed units\n \n return {\n number: numValue,\n unit: unit as 'px' | 'rem' | '%' | 'em' | 'ch'\n };\n \n case 'Number':\n // Numbers: 400, 1.5 -> treat as unitless (font-weight, line-height, etc.)\n const numberValue = Number(valueNode.value);\n if (numberValue === 0) return null; // Skip zero values\n \n return {\n number: numberValue,\n unit: null\n };\n \n case 'Percentage':\n // Percentage values: 100%, 50% -> extract value and add % unit\n const percentValue = Number(valueNode.value);\n if (percentValue === 0) return null; // Skip zero values\n \n return {\n number: percentValue,\n unit: '%'\n };\n \n case 'Value':\n // Value wrapper - extract from first child\n return valueNode.children?.[0] ? extractDimensionValue(valueNode.children[0], cssProperty) : null;\n }\n \n return null;\n}\n\n/**\n * Specialized color value traversal\n * Handles color-specific extraction and skipping logic\n */\nexport function forEachColorValue(\n valueText: string,\n callback: (colorValue: string, positionInfo: PositionInfo) => void\n): void {\n forEachValue(valueText, extractColorValue, shouldSkipColorNode, callback);\n}\n\n/**\n * Specialized density value traversal\n * Handles dimension-specific extraction and skipping logic\n */\nexport function forEachDensityValue(\n valueText: string,\n cssProperty: string,\n callback: (parsedDimension: ParsedUnitValue, positionInfo: PositionInfo) => void\n): void {\n forEachValue(\n valueText, \n (node) => extractDimensionValue(node, cssProperty), \n shouldSkipDimensionNode, \n callback\n );\n}\n\n/**\n * Extract font-related values from CSS AST node\n * Handles font-size and font-weight values\n */\nfunction extractFontValue(node: any): ParsedUnitValue | null {\n if (!node) return null;\n \n switch (node.type) {\n case 'Dimension':\n // Font-size: 16px, 1rem, etc.\n const numValue = Number(node.value);\n if (numValue <= 0) return null; // Skip zero/negative values\n \n const unit = node.unit.toLowerCase();\n if (!ALLOWED_UNITS.includes(unit)) return null;\n \n return {\n number: numValue,\n unit: unit as 'px' | 'rem' | '%' | 'em' | 'ch'\n };\n \n case 'Number':\n // Font-weight: 400, 700, etc.\n const numberValue = Number(node.value);\n if (numberValue <= 0) {\n return null; // Skip zero/negative values\n }\n \n // Only accept known font-weight values for unitless numbers\n if (!isKnownFontWeight(numberValue)) {\n return null; // Skip values that aren't valid font-weights\n }\n \n return {\n number: numberValue,\n unit: null\n };\n \n case 'Identifier':\n // Font-weight keywords: normal, bold, etc.\n const namedValue = node.name.toLowerCase();\n \n // Only accept known font-weight keywords\n if (!isKnownFontWeight(namedValue)) {\n return null;\n }\n \n // Convert known keywords to numeric values\n if (namedValue === 'normal') {\n return { number: 400, unit: null };\n }\n \n // For other keywords (bolder, lighter), we can't determine exact numeric value\n // but we know they're valid font-weight values\n return { number: namedValue, unit: null };\n \n case 'Percentage':\n // Percentage values for font-size\n const percentValue = Number(node.value);\n if (percentValue === 0) return null; // Skip zero values\n \n return {\n number: percentValue,\n unit: '%'\n };\n \n case 'Value':\n // Value wrapper - extract from first child\n return node.children?.[0] ? extractFontValue(node.children[0]) : null;\n }\n \n return null;\n}\n\n/**\n * Check if font node should be skipped during traversal\n * Skip all function nodes by default\n */\nfunction shouldSkipFontNode(node: any): boolean {\n return node.type === 'Function';\n}\n\n/**\n * Specialized font value traversal\n * Handles font-specific extraction and skipping logic\n */\nexport function forEachFontValue(\n valueText: string,\n callback: (fontValue: ParsedUnitValue, positionInfo: PositionInfo) => void\n): void {\n forEachValue(valueText, extractFontValue, shouldSkipFontNode, callback);\n}\n", "import { ValueToStylingHooksMapping, ValueToStylingHookEntry } from '@salesforce-ux/sds-metadata/next';\nimport chroma from 'chroma-js';\nimport { generate } from '@eslint/css-tree';\nimport { isCssColorFunction } from './css-functions';\n\n/**\n * Perceptual color difference threshold (Delta E, CIEDE2000 via chroma.deltaE).\n * Lower values are stricter matches. Used to decide which hooks are \"close enough\".\n */\nconst DELTAE_THRESHOLD = 10;\n\n/**\n * Convert any valid CSS color (named, hex, rgb(a), hsl(a), etc.) to hex.\n * Returns null if the value is not a valid color.\n */\nconst convertToHex = (color: string): string | null => {\n try {\n // Try converting the color using chroma-js, which handles both named and hex colors\n return chroma(color).hex();\n } catch (e) {\n // If chroma can't process the color, it's likely invalid\n return null;\n }\n};\n\nconst isHookPropertyMatch = (hook: ValueToStylingHookEntry, cssProperty: string): boolean => {\n return hook.properties.includes(cssProperty) || hook.properties.includes(\"*\");\n}\n\nfunction getOrderByCssProp(cssProperty: string): string[] {\n if(cssProperty === 'color' || cssProperty === 'fill') {\n return [\"surface\", \"theme\", \"feedback\", \"reference\"];\n } else if(cssProperty.match(/background/)){\n return [\"surface\", \"surface-inverse\", \"theme\", \"feedback\", \"reference\"];\n } else if(cssProperty.match(/border/) || cssProperty.match(/outline/) || cssProperty.match(/stroke/)) {\n return [\"borders\", \"borders-inverse\", \"feedback\", \"theme\", \"reference\"];\n }\n return [\"surface\", \"surface-inverse\", \"borders\", \"borders-inverse\", \"theme\", \"feedback\", \"reference\"];\n}\n\n\n/**\n * Given an input color and the metadata mapping of supported colors to hooks,\n * suggest up to 5 styling hook names ordered by:\n * 1) Category priority: semantic -> system -> palette\n * 2) Perceptual distance (Delta E)\n * Also prioritizes exact color matches (distance 0).\n */\nconst findClosestColorHook = (\n color: string,\n supportedColors:ValueToStylingHooksMapping,\n cssProperty: string\n): string[] => {\n const closestHooks: Array<{distance: number, group: string, name: string}> = [];\n Object.entries(supportedColors).forEach(([sldsValue, data]) => {\n if (sldsValue && isValidColor(sldsValue)) {\n const hooks = data as ValueToStylingHookEntry[]; // Get the hooks for the sldsValue\n\n hooks.forEach((hook) => {\n // Exact match shortcut to avoid floating rounding noise\n const distance = (sldsValue.toLowerCase() === color.toLowerCase())\n ? 0\n : chroma.deltaE(sldsValue, color);\n \n // Check if the hook has the same property or universal selector\n if (isHookPropertyMatch(hook, cssProperty) && distance <= DELTAE_THRESHOLD) {\n // Add to same property hooks if within threshold\n closestHooks.push({ distance, group: hook.group, name: hook.name });\n }\n });\n }\n });\n\n const hooksByGroupMap:Record<string, string[]> = closestHooks.sort((a, b) => a.distance - b.distance).reduce((acc, hook) => {\n if (!acc[hook.group]) {\n acc[hook.group] = [];\n }\n acc[hook.group].push(hook.name);\n return acc;\n }, {});\n\n return getOrderByCssProp(cssProperty)\n .map(group => hooksByGroupMap[group]||[])\n .flat().slice(0, 5);\n};\n\n/**\n * Check if a value is any valid CSS color string (delegates to chroma-js).\n */\nconst isValidColor = (val:string):boolean => chroma.valid(val);\n\n/**\n * Extract a color string from a CSS AST node produced by @eslint/css-tree.\n * Supports Hash (#rrggbb), Identifier (named colors), and color Function nodes.\n * Returns null if the extracted value is not a valid color.\n */\nconst extractColorValue = (node: any): string | null => {\n let colorValue: string | null = null;\n \n switch (node.type) {\n case 'Hash':\n colorValue = `#${node.value}`;\n break;\n case 'Identifier':\n colorValue = node.name;\n break;\n case 'Function':\n // Only extract color functions\n if (isCssColorFunction(node.name)) {\n colorValue = generate(node);\n }\n break;\n }\n \n return colorValue && isValidColor(colorValue) ? colorValue : null;\n};\n\nexport { findClosestColorHook, convertToHex, isValidColor, extractColorValue };\n", "//stylelint-sds/packages/stylelint-plugin-slds/src/utils/css-functions.ts\n/**\n * Complete list of CSS functions that should be preserved/recognized\n */\nconst CSS_FUNCTIONS = [\n 'attr',\n 'calc',\n 'color-mix',\n 'conic-gradient',\n 'counter',\n 'cubic-bezier',\n 'linear-gradient',\n 'max',\n 'min',\n 'radial-gradient',\n 'repeating-conic-gradient',\n 'repeating-linear-gradient',\n 'repeating-radial-gradient',\n 'var'\n ];\n \n \n const CSS_MATH_FUNCTIONS = ['calc', 'min', 'max'];\n \n \n const RGB_COLOR_FUNCTIONS = ['rgb', 'rgba', 'hsl', 'hsla'];\n \n /**\n * Regex for matching any CSS function (for general detection)\n * Matches function names within other text\n */\n const cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join('|')})`);\n \n \n const cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join('|')})$`);\n \n \n const cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join('|')})$`);\n \n export function containsCssFunction(value: string): boolean {\n return cssFunctionsRegex.test(value);\n }\n \n /**\n * Check if a value is exactly a CSS function name\n */\n export function isCssFunction(value: string): boolean {\n return cssFunctionsExactRegex.test(value);\n }\n \n export function isCssMathFunction(value: string): boolean {\n return cssMathFunctionsRegex.test(value);\n }\n \n export function isCssColorFunction(value: string): boolean {\n return RGB_COLOR_FUNCTIONS.includes(value);\n }"],
5
- "mappings": "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",
6
- "names": ["import_css_tree"]
3
+ "sources": ["../../src/utils/css-utils.ts"],
4
+ "sourcesContent": ["import { \n forEachValue, \n type PositionInfo \n} from './hardcoded-shared-utils';\n\n/**\n * Check if a CSS property should be targeted for linting based on prefixes or explicit targets\n * @param property - The CSS property name to check\n * @param propertyTargets - Array of specific properties to target (empty means target all)\n * @returns true if the property should be targeted\n */\nexport function isTargetProperty(property: string, propertyTargets: string[] = []): boolean {\n if (typeof property !== 'string') return false;\n return property.startsWith('--sds-')\n || property.startsWith('--slds-')\n || property.startsWith('--lwc-')\n || propertyTargets.length === 0\n || propertyTargets.includes(property);\n}\n\n/**\n * CSS Variable information for SLDS variable detection\n */\nexport interface CssVariableInfo {\n name: string; // Variable name: --slds-g-color-surface-1\n hasFallback: boolean; // Whether var() already has a fallback\n}\n\n/**\n * Generic CSS variable extractor that can be customized for different use cases\n * @param node - AST node to extract from\n * @param filter - Function to validate and extract variable information\n * @returns Extracted variable info or null\n */\nfunction extractCssVariable<T>(\n node: any,\n filter: (variableName: string, childrenArray: any[]) => T | null\n): T | null {\n if (!node || node.type !== 'Function' || node.name !== 'var') {\n return null;\n }\n\n if (!node.children) {\n return null;\n }\n\n // Convert children to array and get the first child (variable name)\n const childrenArray = Array.from(node.children);\n if (childrenArray.length === 0) {\n return null;\n }\n \n const firstChild = childrenArray[0] as any;\n if (!firstChild || firstChild.type !== 'Identifier') {\n return null;\n }\n\n const variableName = firstChild.name;\n if (!variableName) {\n return null;\n }\n\n return filter(variableName, childrenArray);\n}\n\n/**\n * Get the CSS variable token from a var() function node\n * Extracts the custom property name from var(--custom-prop) -> \"--custom-prop\"\n * @param node - CSS tree AST node (Function node expected)\n * @returns The custom property name (e.g., \"--slds-g-color-brand-base-15\") or empty string\n */\nexport function getVarToken(node: any): string {\n const result = extractCssVariable(node, (variableName) => variableName);\n return result || '';\n}\n\n/**\n * Specialized CSS variable traversal for SLDS variables\n * Finds var(--slds-*) functions and reports their fallback status\n */\nexport function forEachSldsVariable(\n valueText: string,\n callback: (variableInfo: CssVariableInfo, positionInfo: PositionInfo) => void\n): void {\n const extractor = (node: any) => extractCssVariable(node, (variableName, childrenArray) => {\n if (!variableName.startsWith('--slds-')) {\n return null;\n }\n\n // Check if there's a fallback (comma separator)\n const hasFallback = childrenArray.some((child: any) => \n child.type === 'Operator' && child.value === ','\n );\n\n return { name: variableName, hasFallback };\n });\n\n forEachValue(valueText, extractor, () => false, callback);\n}\n\n/**\n * Specialized CSS variable traversal for SLDS/SDS namespace detection\n * Finds var(--slds-*) or var(--sds-*) functions in CSS values\n * Note: hasFallback is set to false as it's unused for namespace validation\n */\nexport function forEachNamespacedVariable(\n valueText: string,\n callback: (variableInfo: CssVariableInfo, positionInfo: PositionInfo) => void\n): void {\n const extractor = (node: any) => extractCssVariable(node, (variableName) => {\n // Check for SLDS or SDS namespace\n if (variableName.startsWith('--slds-') || variableName.startsWith('--sds-')) {\n return { name: variableName, hasFallback: false }; // hasFallback unused, but required by interface\n }\n return null;\n });\n\n forEachValue(valueText, extractor, () => false, callback);\n}\n\n/**\n * Specialized CSS variable traversal for LWC variables\n * Finds var(--lwc-*) functions in CSS values and reports their fallback status\n */\nexport function forEachLwcVariable(\n valueText: string,\n callback: (variableInfo: CssVariableInfo, positionInfo: PositionInfo) => void\n): void {\n const extractor = (node: any) => extractCssVariable(node, (variableName, childrenArray) => {\n if (!variableName.startsWith('--lwc-')) {\n return null;\n }\n\n // Check if there's a fallback (comma separator)\n const hasFallback = childrenArray.some((child: any) => \n child.type === 'Operator' && child.value === ','\n );\n\n return { name: variableName, hasFallback };\n });\n\n forEachValue(valueText, extractor, () => false, callback);\n}\n\n/**\n * Format multiple hook suggestions for better readability\n * @param hooks - Array of hook names to format\n * @returns Formatted string with hooks\n */\nexport function formatSuggestionHooks(hooks: string[]): string {\n if (hooks.length === 1) {\n return `${hooks[0]}`;\n }\n\n // Loop through hooks and append each as a numbered list item with line breaks\n return '\\n' + hooks.map((hook, index) => `${index + 1}. ${hook}`).join('\\n');\n}"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAGO;AAQA,SAAS,iBAAiB,UAAkB,kBAA4B,CAAC,GAAY;AAC1F,MAAI,OAAO,aAAa,SAAU,QAAO;AACzC,SAAO,SAAS,WAAW,QAAQ,KAC9B,SAAS,WAAW,SAAS,KAC7B,SAAS,WAAW,QAAQ,KAC5B,gBAAgB,WAAW,KAC3B,gBAAgB,SAAS,QAAQ;AACxC;AAgBA,SAAS,mBACP,MACA,QACU;AACV,MAAI,CAAC,QAAQ,KAAK,SAAS,cAAc,KAAK,SAAS,OAAO;AAC5D,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,KAAK,UAAU;AAClB,WAAO;AAAA,EACT;AAGA,QAAM,gBAAgB,MAAM,KAAK,KAAK,QAAQ;AAC9C,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,cAAc,CAAC;AAClC,MAAI,CAAC,cAAc,WAAW,SAAS,cAAc;AACnD,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,WAAW;AAChC,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,cAAc,aAAa;AAC3C;AAQO,SAAS,YAAY,MAAmB;AAC7C,QAAM,SAAS,mBAAmB,MAAM,CAAC,iBAAiB,YAAY;AACtE,SAAO,UAAU;AACnB;AAMO,SAAS,oBACd,WACA,UACM;AACN,QAAM,YAAY,CAAC,SAAc,mBAAmB,MAAM,CAAC,cAAc,kBAAkB;AACzF,QAAI,CAAC,aAAa,WAAW,SAAS,GAAG;AACvC,aAAO;AAAA,IACT;AAGA,UAAM,cAAc,cAAc;AAAA,MAAK,CAAC,UACtC,MAAM,SAAS,cAAc,MAAM,UAAU;AAAA,IAC/C;AAEA,WAAO,EAAE,MAAM,cAAc,YAAY;AAAA,EAC3C,CAAC;AAED,kDAAa,WAAW,WAAW,MAAM,OAAO,QAAQ;AAC1D;AAOO,SAAS,0BACd,WACA,UACM;AACN,QAAM,YAAY,CAAC,SAAc,mBAAmB,MAAM,CAAC,iBAAiB;AAE1E,QAAI,aAAa,WAAW,SAAS,KAAK,aAAa,WAAW,QAAQ,GAAG;AAC3E,aAAO,EAAE,MAAM,cAAc,aAAa,MAAM;AAAA,IAClD;AACA,WAAO;AAAA,EACT,CAAC;AAED,kDAAa,WAAW,WAAW,MAAM,OAAO,QAAQ;AAC1D;AAMO,SAAS,mBACd,WACA,UACM;AACN,QAAM,YAAY,CAAC,SAAc,mBAAmB,MAAM,CAAC,cAAc,kBAAkB;AACzF,QAAI,CAAC,aAAa,WAAW,QAAQ,GAAG;AACtC,aAAO;AAAA,IACT;AAGA,UAAM,cAAc,cAAc;AAAA,MAAK,CAAC,UACtC,MAAM,SAAS,cAAc,MAAM,UAAU;AAAA,IAC/C;AAEA,WAAO,EAAE,MAAM,cAAc,YAAY;AAAA,EAC3C,CAAC;AAED,kDAAa,WAAW,WAAW,MAAM,OAAO,QAAQ;AAC1D;AAOO,SAAS,sBAAsB,OAAyB;AAC7D,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,GAAG,MAAM,CAAC,CAAC;AAAA,EACpB;AAGA,SAAO,OAAO,MAAM,IAAI,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,IAAI,EAAE,EAAE,KAAK,IAAI;AAC7E;",
6
+ "names": []
7
7
  }
@@ -1,8 +1,6 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
5
  var __export = (target, all) => {
8
6
  for (var name in all)
@@ -16,14 +14,6 @@ var __copyProps = (to, from, except, desc) => {
16
14
  }
17
15
  return to;
18
16
  };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
18
 
29
19
  // src/utils/hardcoded-shared-utils.ts
@@ -37,65 +27,10 @@ __export(hardcoded_shared_utils_exports, {
37
27
  isKnownFontWeight: () => isKnownFontWeight
38
28
  });
39
29
  module.exports = __toCommonJS(hardcoded_shared_utils_exports);
40
- var import_css_tree2 = require("@eslint/css-tree");
41
-
42
- // src/utils/value-utils.ts
43
- var ALLOWED_UNITS = ["px", "em", "rem", "%", "ch"];
44
-
45
- // src/utils/color-lib-utils.ts
46
- var import_chroma_js = __toESM(require("chroma-js"));
47
30
  var import_css_tree = require("@eslint/css-tree");
48
-
49
- // src/utils/css-functions.ts
50
- var CSS_FUNCTIONS = [
51
- "attr",
52
- "calc",
53
- "color-mix",
54
- "conic-gradient",
55
- "counter",
56
- "cubic-bezier",
57
- "linear-gradient",
58
- "max",
59
- "min",
60
- "radial-gradient",
61
- "repeating-conic-gradient",
62
- "repeating-linear-gradient",
63
- "repeating-radial-gradient",
64
- "var"
65
- ];
66
- var CSS_MATH_FUNCTIONS = ["calc", "min", "max"];
67
- var RGB_COLOR_FUNCTIONS = ["rgb", "rgba", "hsl", "hsla"];
68
- var cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join("|")})`);
69
- var cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join("|")})$`);
70
- var cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join("|")})$`);
71
- function isCssFunction(value) {
72
- return cssFunctionsExactRegex.test(value);
73
- }
74
- function isCssColorFunction(value) {
75
- return RGB_COLOR_FUNCTIONS.includes(value);
76
- }
77
-
78
- // src/utils/color-lib-utils.ts
79
- var isValidColor = (val) => import_chroma_js.default.valid(val);
80
- var extractColorValue = (node) => {
81
- let colorValue = null;
82
- switch (node.type) {
83
- case "Hash":
84
- colorValue = `#${node.value}`;
85
- break;
86
- case "Identifier":
87
- colorValue = node.name;
88
- break;
89
- case "Function":
90
- if (isCssColorFunction(node.name)) {
91
- colorValue = (0, import_css_tree.generate)(node);
92
- }
93
- break;
94
- }
95
- return colorValue && isValidColor(colorValue) ? colorValue : null;
96
- };
97
-
98
- // src/utils/hardcoded-shared-utils.ts
31
+ var import_value_utils = require("./value-utils");
32
+ var import_color_lib_utils = require("./color-lib-utils");
33
+ var import_css_functions = require("./css-functions");
99
34
  var FONT_WEIGHTS = [
100
35
  "normal",
101
36
  "bold",
@@ -185,8 +120,8 @@ function forEachValue(valueText, extractValue, shouldSkipNode, callback) {
185
120
  return;
186
121
  }
187
122
  try {
188
- const ast = (0, import_css_tree2.parse)(valueText, { context: "value", positions: true });
189
- (0, import_css_tree2.walk)(ast, {
123
+ const ast = (0, import_css_tree.parse)(valueText, { context: "value", positions: true });
124
+ (0, import_css_tree.walk)(ast, {
190
125
  enter(node) {
191
126
  if (shouldSkipNode(node)) {
192
127
  return this.skip;
@@ -206,7 +141,7 @@ function forEachValue(valueText, extractValue, shouldSkipNode, callback) {
206
141
  }
207
142
  }
208
143
  function shouldSkipColorNode(node) {
209
- return node.type === "Function" && isCssFunction(node.name);
144
+ return node.type === "Function" && (0, import_css_functions.isCssFunction)(node.name);
210
145
  }
211
146
  function shouldSkipDimensionNode(node) {
212
147
  return node.type === "Function";
@@ -218,23 +153,23 @@ function extractDimensionValue(valueNode, cssProperty) {
218
153
  const numValue = Number(valueNode.value);
219
154
  if (numValue === 0) return null;
220
155
  const unit = valueNode.unit.toLowerCase();
221
- if (!ALLOWED_UNITS.includes(unit)) return null;
156
+ if (!import_value_utils.ALLOWED_UNITS.includes(unit)) return null;
222
157
  return {
223
- number: numValue,
158
+ value: numValue,
224
159
  unit
225
160
  };
226
161
  case "Number":
227
162
  const numberValue = Number(valueNode.value);
228
163
  if (numberValue === 0) return null;
229
164
  return {
230
- number: numberValue,
165
+ value: numberValue,
231
166
  unit: null
232
167
  };
233
168
  case "Percentage":
234
169
  const percentValue = Number(valueNode.value);
235
170
  if (percentValue === 0) return null;
236
171
  return {
237
- number: percentValue,
172
+ value: percentValue,
238
173
  unit: "%"
239
174
  };
240
175
  case "Value":
@@ -243,7 +178,7 @@ function extractDimensionValue(valueNode, cssProperty) {
243
178
  return null;
244
179
  }
245
180
  function forEachColorValue(valueText, callback) {
246
- forEachValue(valueText, extractColorValue, shouldSkipColorNode, callback);
181
+ forEachValue(valueText, import_color_lib_utils.extractColorValue, shouldSkipColorNode, callback);
247
182
  }
248
183
  function forEachDensityValue(valueText, cssProperty, callback) {
249
184
  forEachValue(
@@ -260,9 +195,9 @@ function extractFontValue(node) {
260
195
  const numValue = Number(node.value);
261
196
  if (numValue <= 0) return null;
262
197
  const unit = node.unit.toLowerCase();
263
- if (!ALLOWED_UNITS.includes(unit)) return null;
198
+ if (!import_value_utils.ALLOWED_UNITS.includes(unit)) return null;
264
199
  return {
265
- number: numValue,
200
+ value: numValue,
266
201
  unit
267
202
  };
268
203
  case "Number":
@@ -274,7 +209,7 @@ function extractFontValue(node) {
274
209
  return null;
275
210
  }
276
211
  return {
277
- number: numberValue,
212
+ value: numberValue,
278
213
  unit: null
279
214
  };
280
215
  case "Identifier":
@@ -283,14 +218,14 @@ function extractFontValue(node) {
283
218
  return null;
284
219
  }
285
220
  if (namedValue === "normal") {
286
- return { number: 400, unit: null };
221
+ return { value: 400, unit: null };
287
222
  }
288
- return { number: namedValue, unit: null };
223
+ return { value: namedValue, unit: null };
289
224
  case "Percentage":
290
225
  const percentValue = Number(node.value);
291
226
  if (percentValue === 0) return null;
292
227
  return {
293
- number: percentValue,
228
+ value: percentValue,
294
229
  unit: "%"
295
230
  };
296
231
  case "Value":
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/hardcoded-shared-utils.ts", "../../src/utils/value-utils.ts", "../../src/utils/color-lib-utils.ts", "../../src/utils/css-functions.ts"],
4
- "sourcesContent": ["import { parse, walk } from '@eslint/css-tree';\nimport type { HandlerContext } from '../types';\nimport type { ParsedUnitValue } from './value-utils';\nimport { ALLOWED_UNITS } from './value-utils';\nimport { extractColorValue } from './color-lib-utils';\nimport { isCssFunction } from './css-functions';\n\n/**\n * Common replacement data structure used by both color and density handlers\n */\nexport interface ReplacementInfo {\n start: number;\n end: number;\n replacement: string; // Full CSS var: var(--hook, fallback)\n displayValue: string; // Just the hook: --hook\n hasHook: boolean;\n isNumeric?: boolean; // Whether this is a numeric (dimension) value\n}\n\n/**\n * Position information from CSS tree parsing\n */\nexport interface PositionInfo {\n start?: { offset: number; line: number; column: number };\n end?: { offset: number; line: number; column: number };\n}\n\n/**\n * Generic callback for processing values with position information\n */\nexport type ValueCallback<T> = (value: T, positionInfo?: PositionInfo) => void;\n\n/**\n * Known valid font-weight values\n */\nconst FONT_WEIGHTS = [\n 'normal',\n 'bold', \n 'bolder',\n 'lighter',\n '100',\n '200', \n '300',\n '400',\n '500',\n '600',\n '700',\n '800',\n '900'\n];\n\n/**\n * Check if a value is a known font-weight\n */\nexport function isKnownFontWeight(value: string | number): boolean {\n const stringValue = value.toString();\n return FONT_WEIGHTS.includes(stringValue.toLowerCase());\n}\n\n/**\n * Generic shorthand auto-fix handler\n * Handles the common logic for reconstructing shorthand values with replacements\n */\nexport function handleShorthandAutoFix(\n declarationNode: any,\n context: HandlerContext,\n valueText: string,\n replacements: ReplacementInfo[]\n) {\n if(!replacements || replacements.length === 0){\n return;\n }\n // Sort replacements by position for proper reconstruction\n const sortedReplacements = replacements.sort((a,b)=> b.start-a.start);\n\n // Get rule options\n const reportNumericValue = context.options?.reportNumericValue || 'always';\n\n const fixCallback = (start:number, originalValue:string, replacement:string) => {\n // Reconstruct the entire value with all replacements\n let newValue = valueText;\n\n newValue = newValue.substring(0, start) + replacement + newValue.substring(start+originalValue.length);\n\n if(newValue !== valueText){\n return (fixer:any)=>{\n return fixer.replaceText(declarationNode.value, newValue);\n }\n }\n }\n\n // Report each individual value\n sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook, isNumeric }) => {\n const originalValue = valueText.substring(start, end);\n \n // Check if we should skip reporting based on reportNumericValue option\n if (isNumeric) {\n if (reportNumericValue === 'never') {\n return; // Skip reporting numeric values\n }\n if (reportNumericValue === 'hasReplacement' && !hasHook) {\n return; // Skip reporting numeric values without replacements\n }\n }\n \n \n const valueColumnStart = declarationNode.value.loc.start.column + start;\n const valueColumnEnd = valueColumnStart + originalValue.length;\n const canAutoFix = originalValue !== replacement;\n \n // Create precise error location for this value\n const { loc: { start: locStart, end: locEnd } } = declarationNode.value;\n const reportNode = {\n ...declarationNode.value,\n loc: {\n ...declarationNode.value.loc,\n start: {\n ...locStart,\n column: valueColumnStart\n },\n end: {\n ...locEnd,\n column: valueColumnEnd\n }\n }\n };\n\n if (hasHook) {\n // Create auto-fix for the entire shorthand value\n const fix = canAutoFix ? fixCallback(start, originalValue, replacement) : undefined;\n\n context.context.report({\n node: reportNode,\n messageId: 'hardcodedValue',\n data: {\n oldValue: originalValue,\n newValue: displayValue\n },\n fix\n });\n } else {\n // No hook available\n context.context.report({\n node: reportNode,\n messageId: 'noReplacement',\n data: {\n oldValue: originalValue\n }\n });\n }\n });\n}\n\n/**\n * Generic CSS tree traversal with position tracking\n * Always provides position information since both handlers need it\n */\nexport function forEachValue<T>(\n valueText: string,\n extractValue: (node: any) => T | null,\n shouldSkipNode: (node: any) => boolean,\n callback: (value: T, positionInfo: PositionInfo) => void\n): void {\n if (!valueText || typeof valueText !== 'string') {\n return;\n }\n\n try {\n const ast = parse(valueText, { context: 'value' as const, positions: true });\n \n walk(ast, {\n enter(node: any) {\n // Skip nodes efficiently using this.skip\n if (shouldSkipNode(node)) {\n return this.skip;\n }\n \n const value = extractValue(node);\n if (value !== null) {\n const positionInfo: PositionInfo = {\n start: node.loc?.start,\n end: node.loc?.end\n };\n callback(value, positionInfo);\n }\n }\n });\n } catch (error) {\n // Silently handle parse errors\n return;\n }\n}\n\n/**\n * Check if color node should be skipped during traversal\n */\nfunction shouldSkipColorNode(node: any): boolean {\n return node.type === 'Function' && isCssFunction(node.name);\n}\n\n/**\n * Check if dimension node should be skipped during traversal\n * Skip all function nodes by default\n */\nfunction shouldSkipDimensionNode(node: any): boolean {\n return node.type === 'Function';\n}\n\n/**\n * Extract dimension value from CSS AST node\n * Returns structured data with number and unit to eliminate regex parsing\n */\nfunction extractDimensionValue(valueNode: any, cssProperty?: string): ParsedUnitValue | null {\n if (!valueNode) return null;\n \n switch (valueNode.type) {\n case 'Dimension':\n // Dimensions: 16px, 1rem -> extract value and unit directly from AST\n const numValue = Number(valueNode.value);\n if (numValue === 0) return null; // Skip zero values\n \n const unit = valueNode.unit.toLowerCase();\n if (!ALLOWED_UNITS.includes(unit)) return null; // Support only allowed units\n \n return {\n number: numValue,\n unit: unit as 'px' | 'rem' | '%' | 'em' | 'ch'\n };\n \n case 'Number':\n // Numbers: 400, 1.5 -> treat as unitless (font-weight, line-height, etc.)\n const numberValue = Number(valueNode.value);\n if (numberValue === 0) return null; // Skip zero values\n \n return {\n number: numberValue,\n unit: null\n };\n \n case 'Percentage':\n // Percentage values: 100%, 50% -> extract value and add % unit\n const percentValue = Number(valueNode.value);\n if (percentValue === 0) return null; // Skip zero values\n \n return {\n number: percentValue,\n unit: '%'\n };\n \n case 'Value':\n // Value wrapper - extract from first child\n return valueNode.children?.[0] ? extractDimensionValue(valueNode.children[0], cssProperty) : null;\n }\n \n return null;\n}\n\n/**\n * Specialized color value traversal\n * Handles color-specific extraction and skipping logic\n */\nexport function forEachColorValue(\n valueText: string,\n callback: (colorValue: string, positionInfo: PositionInfo) => void\n): void {\n forEachValue(valueText, extractColorValue, shouldSkipColorNode, callback);\n}\n\n/**\n * Specialized density value traversal\n * Handles dimension-specific extraction and skipping logic\n */\nexport function forEachDensityValue(\n valueText: string,\n cssProperty: string,\n callback: (parsedDimension: ParsedUnitValue, positionInfo: PositionInfo) => void\n): void {\n forEachValue(\n valueText, \n (node) => extractDimensionValue(node, cssProperty), \n shouldSkipDimensionNode, \n callback\n );\n}\n\n/**\n * Extract font-related values from CSS AST node\n * Handles font-size and font-weight values\n */\nfunction extractFontValue(node: any): ParsedUnitValue | null {\n if (!node) return null;\n \n switch (node.type) {\n case 'Dimension':\n // Font-size: 16px, 1rem, etc.\n const numValue = Number(node.value);\n if (numValue <= 0) return null; // Skip zero/negative values\n \n const unit = node.unit.toLowerCase();\n if (!ALLOWED_UNITS.includes(unit)) return null;\n \n return {\n number: numValue,\n unit: unit as 'px' | 'rem' | '%' | 'em' | 'ch'\n };\n \n case 'Number':\n // Font-weight: 400, 700, etc.\n const numberValue = Number(node.value);\n if (numberValue <= 0) {\n return null; // Skip zero/negative values\n }\n \n // Only accept known font-weight values for unitless numbers\n if (!isKnownFontWeight(numberValue)) {\n return null; // Skip values that aren't valid font-weights\n }\n \n return {\n number: numberValue,\n unit: null\n };\n \n case 'Identifier':\n // Font-weight keywords: normal, bold, etc.\n const namedValue = node.name.toLowerCase();\n \n // Only accept known font-weight keywords\n if (!isKnownFontWeight(namedValue)) {\n return null;\n }\n \n // Convert known keywords to numeric values\n if (namedValue === 'normal') {\n return { number: 400, unit: null };\n }\n \n // For other keywords (bolder, lighter), we can't determine exact numeric value\n // but we know they're valid font-weight values\n return { number: namedValue, unit: null };\n \n case 'Percentage':\n // Percentage values for font-size\n const percentValue = Number(node.value);\n if (percentValue === 0) return null; // Skip zero values\n \n return {\n number: percentValue,\n unit: '%'\n };\n \n case 'Value':\n // Value wrapper - extract from first child\n return node.children?.[0] ? extractFontValue(node.children[0]) : null;\n }\n \n return null;\n}\n\n/**\n * Check if font node should be skipped during traversal\n * Skip all function nodes by default\n */\nfunction shouldSkipFontNode(node: any): boolean {\n return node.type === 'Function';\n}\n\n/**\n * Specialized font value traversal\n * Handles font-specific extraction and skipping logic\n */\nexport function forEachFontValue(\n valueText: string,\n callback: (fontValue: ParsedUnitValue, positionInfo: PositionInfo) => void\n): void {\n forEachValue(valueText, extractFontValue, shouldSkipFontNode, callback);\n}\n", "// Simplified value parsing\n\n/**\n * Checks if a value is a CSS global value.\n *\n * CSS global values are special keywords that can be used for any CSS property and have a universal meaning:\n * - initial: Resets the property to its initial value as defined by the CSS specification.\n * - inherit: Inherits the value from the parent element.\n * - unset: Acts as inherit if the property is inheritable, otherwise acts as initial.\n * - revert: Rolls back the property to the value established by the user-agent or user styles.\n * - revert-layer: Rolls back the property to the value established by the previous cascade layer.\n *\n * All CSS properties accept these global values, including but not limited to:\n * - color\n * - background\n * - font-size\n * - margin\n * - padding\n * - border\n * - display\n * - position\n * - z-index\n * - and many more\n *\n * These values are part of the CSS standard and are not considered violations, even if a rule would otherwise flag a value as invalid or non-design-token. They are always allowed for any property.\n *\n * @param value The CSS value to check.\n * @returns True if the value is a CSS global value, false otherwise.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/initial\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/inherit\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/unset\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/revert\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/revert-layer\n */\nexport function isGlobalValue(value: string): boolean {\n return value === 'initial' || value === 'inherit' || value === 'unset' || value === 'revert' || value === 'revert-layer';\n }\n\n// Configurable list of allowed CSS units\nexport const ALLOWED_UNITS = ['px', 'em', 'rem', '%', 'ch'];\n\nexport type ParsedUnitValue = {\n unit: 'px' | 'rem' | '%' | 'em' | 'ch' | null;\n number: number;\n} | null;\n\nexport function parseUnitValue(value: string): ParsedUnitValue {\n if (!value) return null;\n \n // Create regex pattern from allowed units\n const unitsPattern = ALLOWED_UNITS.join('|');\n const regex = new RegExp(`^(-?\\\\d*\\\\.?\\\\d+)(${unitsPattern})?$`);\n const match = value.match(regex);\n if (!match) return null;\n \n const number = parseFloat(match[1]);\n const unit = match[2] ? (match[2] as 'px' | 'rem' | '%' | 'em' | 'ch') : null; // Keep unitless values as null\n \n if (isNaN(number)) return null;\n \n return { number, unit };\n}\n\nexport function toAlternateUnitValue(numberVal: number, unitType: 'px' | 'rem' | '%' | 'em' | 'ch' | null): ParsedUnitValue {\n if (unitType === 'px') {\n let floatValue = parseFloat(`${numberVal / 16}`);\n if (!isNaN(floatValue)) {\n return {\n unit: 'rem',\n number: parseFloat(floatValue.toFixed(4))\n }\n }\n } else if (unitType === 'rem') {\n const intValue = parseInt(`${numberVal * 16}`);\n if (!isNaN(intValue)) {\n return {\n unit: 'px',\n number: intValue\n }\n }\n }\n // For other units (%, em, ch) and unitless values, no alternate unit conversion available\n // These units are context-dependent and don't have standard conversion ratios\n return null;\n}", "import { ValueToStylingHooksMapping, ValueToStylingHookEntry } from '@salesforce-ux/sds-metadata/next';\nimport chroma from 'chroma-js';\nimport { generate } from '@eslint/css-tree';\nimport { isCssColorFunction } from './css-functions';\n\n/**\n * Perceptual color difference threshold (Delta E, CIEDE2000 via chroma.deltaE).\n * Lower values are stricter matches. Used to decide which hooks are \"close enough\".\n */\nconst DELTAE_THRESHOLD = 10;\n\n/**\n * Convert any valid CSS color (named, hex, rgb(a), hsl(a), etc.) to hex.\n * Returns null if the value is not a valid color.\n */\nconst convertToHex = (color: string): string | null => {\n try {\n // Try converting the color using chroma-js, which handles both named and hex colors\n return chroma(color).hex();\n } catch (e) {\n // If chroma can't process the color, it's likely invalid\n return null;\n }\n};\n\nconst isHookPropertyMatch = (hook: ValueToStylingHookEntry, cssProperty: string): boolean => {\n return hook.properties.includes(cssProperty) || hook.properties.includes(\"*\");\n}\n\nfunction getOrderByCssProp(cssProperty: string): string[] {\n if(cssProperty === 'color' || cssProperty === 'fill') {\n return [\"surface\", \"theme\", \"feedback\", \"reference\"];\n } else if(cssProperty.match(/background/)){\n return [\"surface\", \"surface-inverse\", \"theme\", \"feedback\", \"reference\"];\n } else if(cssProperty.match(/border/) || cssProperty.match(/outline/) || cssProperty.match(/stroke/)) {\n return [\"borders\", \"borders-inverse\", \"feedback\", \"theme\", \"reference\"];\n }\n return [\"surface\", \"surface-inverse\", \"borders\", \"borders-inverse\", \"theme\", \"feedback\", \"reference\"];\n}\n\n\n/**\n * Given an input color and the metadata mapping of supported colors to hooks,\n * suggest up to 5 styling hook names ordered by:\n * 1) Category priority: semantic -> system -> palette\n * 2) Perceptual distance (Delta E)\n * Also prioritizes exact color matches (distance 0).\n */\nconst findClosestColorHook = (\n color: string,\n supportedColors:ValueToStylingHooksMapping,\n cssProperty: string\n): string[] => {\n const closestHooks: Array<{distance: number, group: string, name: string}> = [];\n Object.entries(supportedColors).forEach(([sldsValue, data]) => {\n if (sldsValue && isValidColor(sldsValue)) {\n const hooks = data as ValueToStylingHookEntry[]; // Get the hooks for the sldsValue\n\n hooks.forEach((hook) => {\n // Exact match shortcut to avoid floating rounding noise\n const distance = (sldsValue.toLowerCase() === color.toLowerCase())\n ? 0\n : chroma.deltaE(sldsValue, color);\n \n // Check if the hook has the same property or universal selector\n if (isHookPropertyMatch(hook, cssProperty) && distance <= DELTAE_THRESHOLD) {\n // Add to same property hooks if within threshold\n closestHooks.push({ distance, group: hook.group, name: hook.name });\n }\n });\n }\n });\n\n const hooksByGroupMap:Record<string, string[]> = closestHooks.sort((a, b) => a.distance - b.distance).reduce((acc, hook) => {\n if (!acc[hook.group]) {\n acc[hook.group] = [];\n }\n acc[hook.group].push(hook.name);\n return acc;\n }, {});\n\n return getOrderByCssProp(cssProperty)\n .map(group => hooksByGroupMap[group]||[])\n .flat().slice(0, 5);\n};\n\n/**\n * Check if a value is any valid CSS color string (delegates to chroma-js).\n */\nconst isValidColor = (val:string):boolean => chroma.valid(val);\n\n/**\n * Extract a color string from a CSS AST node produced by @eslint/css-tree.\n * Supports Hash (#rrggbb), Identifier (named colors), and color Function nodes.\n * Returns null if the extracted value is not a valid color.\n */\nconst extractColorValue = (node: any): string | null => {\n let colorValue: string | null = null;\n \n switch (node.type) {\n case 'Hash':\n colorValue = `#${node.value}`;\n break;\n case 'Identifier':\n colorValue = node.name;\n break;\n case 'Function':\n // Only extract color functions\n if (isCssColorFunction(node.name)) {\n colorValue = generate(node);\n }\n break;\n }\n \n return colorValue && isValidColor(colorValue) ? colorValue : null;\n};\n\nexport { findClosestColorHook, convertToHex, isValidColor, extractColorValue };\n", "//stylelint-sds/packages/stylelint-plugin-slds/src/utils/css-functions.ts\n/**\n * Complete list of CSS functions that should be preserved/recognized\n */\nconst CSS_FUNCTIONS = [\n 'attr',\n 'calc',\n 'color-mix',\n 'conic-gradient',\n 'counter',\n 'cubic-bezier',\n 'linear-gradient',\n 'max',\n 'min',\n 'radial-gradient',\n 'repeating-conic-gradient',\n 'repeating-linear-gradient',\n 'repeating-radial-gradient',\n 'var'\n ];\n \n \n const CSS_MATH_FUNCTIONS = ['calc', 'min', 'max'];\n \n \n const RGB_COLOR_FUNCTIONS = ['rgb', 'rgba', 'hsl', 'hsla'];\n \n /**\n * Regex for matching any CSS function (for general detection)\n * Matches function names within other text\n */\n const cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join('|')})`);\n \n \n const cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join('|')})$`);\n \n \n const cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join('|')})$`);\n \n export function containsCssFunction(value: string): boolean {\n return cssFunctionsRegex.test(value);\n }\n \n /**\n * Check if a value is exactly a CSS function name\n */\n export function isCssFunction(value: string): boolean {\n return cssFunctionsExactRegex.test(value);\n }\n \n export function isCssMathFunction(value: string): boolean {\n return cssMathFunctionsRegex.test(value);\n }\n \n export function isCssColorFunction(value: string): boolean {\n return RGB_COLOR_FUNCTIONS.includes(value);\n }"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,mBAA4B;;;ACwCrB,IAAM,gBAAgB,CAAC,MAAM,MAAM,OAAO,KAAK,IAAI;;;ACvC1D,uBAAmB;AACnB,sBAAyB;;;ACEzB,IAAM,gBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,qBAAqB,CAAC,QAAQ,OAAO,KAAK;AAGhD,IAAM,sBAAsB,CAAC,OAAO,QAAQ,OAAO,MAAM;AAMzD,IAAM,oBAAoB,IAAI,OAAO,MAAM,cAAc,KAAK,GAAG,CAAC,GAAG;AAGrE,IAAM,yBAAyB,IAAI,OAAO,OAAO,cAAc,KAAK,GAAG,CAAC,IAAI;AAG5E,IAAM,wBAAwB,IAAI,OAAO,OAAO,mBAAmB,KAAK,GAAG,CAAC,IAAI;AASzE,SAAS,cAAc,OAAwB;AACpD,SAAO,uBAAuB,KAAK,KAAK;AAC1C;AAMO,SAAS,mBAAmB,OAAwB;AACzD,SAAO,oBAAoB,SAAS,KAAK;AAC3C;;;ADiCF,IAAM,eAAe,CAAC,QAAuB,iBAAAC,QAAO,MAAM,GAAG;AAO7D,IAAM,oBAAoB,CAAC,SAA6B;AACtD,MAAI,aAA4B;AAEhC,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,mBAAa,IAAI,KAAK,KAAK;AAC3B;AAAA,IACF,KAAK;AACH,mBAAa,KAAK;AAClB;AAAA,IACF,KAAK;AAEH,UAAI,mBAAmB,KAAK,IAAI,GAAG;AACjC,yBAAa,0BAAS,IAAI;AAAA,MAC5B;AACA;AAAA,EACJ;AAEA,SAAO,cAAc,aAAa,UAAU,IAAI,aAAa;AAC/D;;;AFhFA,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,SAAS,kBAAkB,OAAiC;AACjE,QAAM,cAAc,MAAM,SAAS;AACnC,SAAO,aAAa,SAAS,YAAY,YAAY,CAAC;AACxD;AAMO,SAAS,uBACd,iBACA,SACA,WACA,cACA;AACA,MAAG,CAAC,gBAAgB,aAAa,WAAW,GAAE;AAC5C;AAAA,EACF;AAEA,QAAM,qBAAqB,aAAa,KAAK,CAAC,GAAE,MAAK,EAAE,QAAM,EAAE,KAAK;AAGpE,QAAM,qBAAqB,QAAQ,SAAS,sBAAsB;AAElE,QAAM,cAAc,CAAC,OAAc,eAAsB,gBAAuB;AAE5E,QAAI,WAAW;AAEf,eAAW,SAAS,UAAU,GAAG,KAAK,IAAI,cAAc,SAAS,UAAU,QAAM,cAAc,MAAM;AAErG,QAAG,aAAa,WAAU;AACxB,aAAO,CAAC,UAAY;AAClB,eAAO,MAAM,YAAY,gBAAgB,OAAO,QAAQ;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAGF,qBAAmB,QAAQ,CAAC,EAAE,OAAO,KAAK,aAAa,cAAc,SAAS,UAAU,MAAM;AAC5F,UAAM,gBAAgB,UAAU,UAAU,OAAO,GAAG;AAGpD,QAAI,WAAW;AACb,UAAI,uBAAuB,SAAS;AAClC;AAAA,MACF;AACA,UAAI,uBAAuB,oBAAoB,CAAC,SAAS;AACvD;AAAA,MACF;AAAA,IACF;AAGA,UAAM,mBAAmB,gBAAgB,MAAM,IAAI,MAAM,SAAS;AAClE,UAAM,iBAAiB,mBAAmB,cAAc;AACxD,UAAM,aAAa,kBAAkB;AAGrC,UAAM,EAAE,KAAK,EAAE,OAAO,UAAU,KAAK,OAAO,EAAE,IAAI,gBAAgB;AAClE,UAAM,aAAa;AAAA,MACjB,GAAG,gBAAgB;AAAA,MACnB,KAAK;AAAA,QACH,GAAG,gBAAgB,MAAM;AAAA,QACzB,OAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ;AAAA,QACV;AAAA,QACA,KAAK;AAAA,UACH,GAAG;AAAA,UACH,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS;AAEX,YAAM,MAAM,aAAa,YAAY,OAAO,eAAe,WAAW,IAAI;AAE1E,cAAQ,QAAQ,OAAO;AAAA,QACrB,MAAM;AAAA,QACN,WAAW;AAAA,QACX,MAAM;AAAA,UACJ,UAAU;AAAA,UACV,UAAU;AAAA,QACZ;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AAEL,cAAQ,QAAQ,OAAO;AAAA,QACrB,MAAM;AAAA,QACN,WAAW;AAAA,QACX,MAAM;AAAA,UACJ,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAMO,SAAS,aACd,WACA,cACA,gBACA,UACM;AACN,MAAI,CAAC,aAAa,OAAO,cAAc,UAAU;AAC/C;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAM,wBAAM,WAAW,EAAE,SAAS,SAAkB,WAAW,KAAK,CAAC;AAE3E,+BAAK,KAAK;AAAA,MACR,MAAM,MAAW;AAEf,YAAI,eAAe,IAAI,GAAG;AACxB,iBAAO,KAAK;AAAA,QACd;AAEA,cAAM,QAAQ,aAAa,IAAI;AAC/B,YAAI,UAAU,MAAM;AAClB,gBAAM,eAA6B;AAAA,YACjC,OAAO,KAAK,KAAK;AAAA,YACjB,KAAK,KAAK,KAAK;AAAA,UACjB;AACA,mBAAS,OAAO,YAAY;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AAEd;AAAA,EACF;AACF;AAKA,SAAS,oBAAoB,MAAoB;AAC/C,SAAO,KAAK,SAAS,cAAc,cAAc,KAAK,IAAI;AAC5D;AAMA,SAAS,wBAAwB,MAAoB;AACnD,SAAO,KAAK,SAAS;AACvB;AAMA,SAAS,sBAAsB,WAAgB,aAA8C;AAC3F,MAAI,CAAC,UAAW,QAAO;AAEvB,UAAQ,UAAU,MAAM;AAAA,IACtB,KAAK;AAEH,YAAM,WAAW,OAAO,UAAU,KAAK;AACvC,UAAI,aAAa,EAAG,QAAO;AAE3B,YAAM,OAAO,UAAU,KAAK,YAAY;AACxC,UAAI,CAAC,cAAc,SAAS,IAAI,EAAG,QAAO;AAE1C,aAAO;AAAA,QACL,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,IAEF,KAAK;AAEH,YAAM,cAAc,OAAO,UAAU,KAAK;AAC1C,UAAI,gBAAgB,EAAG,QAAO;AAE9B,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IAEF,KAAK;AAEH,YAAM,eAAe,OAAO,UAAU,KAAK;AAC3C,UAAI,iBAAiB,EAAG,QAAO;AAE/B,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IAEF,KAAK;AAEH,aAAO,UAAU,WAAW,CAAC,IAAI,sBAAsB,UAAU,SAAS,CAAC,GAAG,WAAW,IAAI;AAAA,EACjG;AAEA,SAAO;AACT;AAMO,SAAS,kBACd,WACA,UACM;AACN,eAAa,WAAW,mBAAmB,qBAAqB,QAAQ;AAC1E;AAMO,SAAS,oBACd,WACA,aACA,UACM;AACN;AAAA,IACE;AAAA,IACA,CAAC,SAAS,sBAAsB,MAAM,WAAW;AAAA,IACjD;AAAA,IACA;AAAA,EACF;AACF;AAMA,SAAS,iBAAiB,MAAmC;AAC3D,MAAI,CAAC,KAAM,QAAO;AAElB,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AAEH,YAAM,WAAW,OAAO,KAAK,KAAK;AAClC,UAAI,YAAY,EAAG,QAAO;AAE1B,YAAM,OAAO,KAAK,KAAK,YAAY;AACnC,UAAI,CAAC,cAAc,SAAS,IAAI,EAAG,QAAO;AAE1C,aAAO;AAAA,QACL,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,IAEF,KAAK;AAEH,YAAM,cAAc,OAAO,KAAK,KAAK;AACrC,UAAI,eAAe,GAAG;AACpB,eAAO;AAAA,MACT;AAGA,UAAI,CAAC,kBAAkB,WAAW,GAAG;AACnC,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IAEF,KAAK;AAEH,YAAM,aAAa,KAAK,KAAK,YAAY;AAGzC,UAAI,CAAC,kBAAkB,UAAU,GAAG;AAClC,eAAO;AAAA,MACT;AAGA,UAAI,eAAe,UAAU;AAC3B,eAAO,EAAE,QAAQ,KAAK,MAAM,KAAK;AAAA,MACnC;AAIA,aAAO,EAAE,QAAQ,YAAY,MAAM,KAAK;AAAA,IAE1C,KAAK;AAEH,YAAM,eAAe,OAAO,KAAK,KAAK;AACtC,UAAI,iBAAiB,EAAG,QAAO;AAE/B,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IAEF,KAAK;AAEH,aAAO,KAAK,WAAW,CAAC,IAAI,iBAAiB,KAAK,SAAS,CAAC,CAAC,IAAI;AAAA,EACrE;AAEA,SAAO;AACT;AAMA,SAAS,mBAAmB,MAAoB;AAC9C,SAAO,KAAK,SAAS;AACvB;AAMO,SAAS,iBACd,WACA,UACM;AACN,eAAa,WAAW,kBAAkB,oBAAoB,QAAQ;AACxE;",
6
- "names": ["import_css_tree", "chroma"]
3
+ "sources": ["../../src/utils/hardcoded-shared-utils.ts"],
4
+ "sourcesContent": ["import { parse, walk } from '@eslint/css-tree';\nimport type { HandlerContext } from '../types';\nimport type { ParsedUnitValue } from './value-utils';\nimport { ALLOWED_UNITS } from './value-utils';\nimport { extractColorValue } from './color-lib-utils';\nimport { isCssFunction } from './css-functions';\n\n/**\n * Common replacement data structure used by both color and density handlers\n */\nexport interface ReplacementInfo {\n start: number;\n end: number;\n replacement: string; // Full CSS var: var(--hook, fallback)\n displayValue: string; // Just the hook: --hook\n hasHook: boolean;\n isNumeric?: boolean; // Whether this is a numeric (dimension) value\n}\n\n/**\n * Position information from CSS tree parsing\n */\nexport interface PositionInfo {\n start?: { offset: number; line: number; column: number };\n end?: { offset: number; line: number; column: number };\n}\n\n/**\n * Generic callback for processing values with position information\n */\nexport type ValueCallback<T> = (value: T, positionInfo?: PositionInfo) => void;\n\n/**\n * Known valid font-weight values\n */\nconst FONT_WEIGHTS = [\n 'normal',\n 'bold', \n 'bolder',\n 'lighter',\n '100',\n '200', \n '300',\n '400',\n '500',\n '600',\n '700',\n '800',\n '900'\n];\n\n/**\n * Check if a value is a known font-weight\n */\nexport function isKnownFontWeight(value: string | number): boolean {\n const stringValue = value.toString();\n return FONT_WEIGHTS.includes(stringValue.toLowerCase());\n}\n\n/**\n * Generic shorthand auto-fix handler\n * Handles the common logic for reconstructing shorthand values with replacements\n */\nexport function handleShorthandAutoFix(\n declarationNode: any,\n context: HandlerContext,\n valueText: string,\n replacements: ReplacementInfo[]\n) {\n if(!replacements || replacements.length === 0){\n return;\n }\n // Sort replacements by position for proper reconstruction\n const sortedReplacements = replacements.sort((a,b)=> b.start-a.start);\n\n // Get rule options\n const reportNumericValue = context.options?.reportNumericValue || 'always';\n\n const fixCallback = (start:number, originalValue:string, replacement:string) => {\n // Reconstruct the entire value with all replacements\n let newValue = valueText;\n\n newValue = newValue.substring(0, start) + replacement + newValue.substring(start+originalValue.length);\n\n if(newValue !== valueText){\n return (fixer:any)=>{\n return fixer.replaceText(declarationNode.value, newValue);\n }\n }\n }\n\n // Report each individual value\n sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook, isNumeric }) => {\n const originalValue = valueText.substring(start, end);\n \n // Check if we should skip reporting based on reportNumericValue option\n if (isNumeric) {\n if (reportNumericValue === 'never') {\n return; // Skip reporting numeric values\n }\n if (reportNumericValue === 'hasReplacement' && !hasHook) {\n return; // Skip reporting numeric values without replacements\n }\n }\n \n \n const valueColumnStart = declarationNode.value.loc.start.column + start;\n const valueColumnEnd = valueColumnStart + originalValue.length;\n const canAutoFix = originalValue !== replacement;\n \n // Create precise error location for this value\n const { loc: { start: locStart, end: locEnd } } = declarationNode.value;\n const reportNode = {\n ...declarationNode.value,\n loc: {\n ...declarationNode.value.loc,\n start: {\n ...locStart,\n column: valueColumnStart\n },\n end: {\n ...locEnd,\n column: valueColumnEnd\n }\n }\n };\n\n if (hasHook) {\n // Create auto-fix for the entire shorthand value\n const fix = canAutoFix ? fixCallback(start, originalValue, replacement) : undefined;\n\n context.context.report({\n node: reportNode,\n messageId: 'hardcodedValue',\n data: {\n oldValue: originalValue,\n newValue: displayValue\n },\n fix\n });\n } else {\n // No hook available\n context.context.report({\n node: reportNode,\n messageId: 'noReplacement',\n data: {\n oldValue: originalValue\n }\n });\n }\n });\n}\n\n/**\n * Generic CSS tree traversal with position tracking\n * Always provides position information since both handlers need it\n */\nexport function forEachValue<T>(\n valueText: string,\n extractValue: (node: any) => T | null,\n shouldSkipNode: (node: any) => boolean,\n callback: (value: T, positionInfo: PositionInfo) => void\n): void {\n if (!valueText || typeof valueText !== 'string') {\n return;\n }\n\n try {\n const ast = parse(valueText, { context: 'value' as const, positions: true });\n \n walk(ast, {\n enter(node: any) {\n // Skip nodes efficiently using this.skip\n if (shouldSkipNode(node)) {\n return this.skip;\n }\n \n const value = extractValue(node);\n if (value !== null) {\n const positionInfo: PositionInfo = {\n start: node.loc?.start,\n end: node.loc?.end\n };\n callback(value, positionInfo);\n }\n }\n });\n } catch (error) {\n // Silently handle parse errors\n return;\n }\n}\n\n/**\n * Check if color node should be skipped during traversal\n */\nfunction shouldSkipColorNode(node: any): boolean {\n return node.type === 'Function' && isCssFunction(node.name);\n}\n\n/**\n * Check if dimension node should be skipped during traversal\n * Skip all function nodes by default\n */\nfunction shouldSkipDimensionNode(node: any): boolean {\n return node.type === 'Function';\n}\n\n/**\n * Extract dimension value from CSS AST node\n * Returns structured data with number and unit to eliminate regex parsing\n */\nfunction extractDimensionValue(valueNode: any, cssProperty?: string): ParsedUnitValue | null {\n if (!valueNode) return null;\n \n switch (valueNode.type) {\n case 'Dimension':\n // Dimensions: 16px, 1rem -> extract value and unit directly from AST\n const numValue = Number(valueNode.value);\n if (numValue === 0) return null; // Skip zero values\n \n const unit = valueNode.unit.toLowerCase();\n if (!ALLOWED_UNITS.includes(unit)) return null; // Support only allowed units\n \n return {\n value: numValue,\n unit: unit as 'px' | 'rem' | '%' | 'em' | 'ch'\n };\n \n case 'Number':\n // Numbers: 400, 1.5 -> treat as unitless (font-weight, line-height, etc.)\n const numberValue = Number(valueNode.value);\n if (numberValue === 0) return null; // Skip zero values\n \n return {\n value: numberValue,\n unit: null\n };\n \n case 'Percentage':\n // Percentage values: 100%, 50% -> extract value and add % unit\n const percentValue = Number(valueNode.value);\n if (percentValue === 0) return null; // Skip zero values\n \n return {\n value: percentValue,\n unit: '%'\n };\n \n case 'Value':\n // Value wrapper - extract from first child\n return valueNode.children?.[0] ? extractDimensionValue(valueNode.children[0], cssProperty) : null;\n }\n \n return null;\n}\n\n/**\n * Specialized color value traversal\n * Handles color-specific extraction and skipping logic\n */\nexport function forEachColorValue(\n valueText: string,\n callback: (colorValue: string, positionInfo: PositionInfo) => void\n): void {\n forEachValue(valueText, extractColorValue, shouldSkipColorNode, callback);\n}\n\n/**\n * Specialized density value traversal\n * Handles dimension-specific extraction and skipping logic\n */\nexport function forEachDensityValue(\n valueText: string,\n cssProperty: string,\n callback: (parsedDimension: ParsedUnitValue, positionInfo: PositionInfo) => void\n): void {\n forEachValue(\n valueText, \n (node) => extractDimensionValue(node, cssProperty), \n shouldSkipDimensionNode, \n callback\n );\n}\n\n/**\n * Extract font-related values from CSS AST node\n * Handles font-size and font-weight values\n */\nfunction extractFontValue(node: any): ParsedUnitValue | null {\n if (!node) return null;\n \n switch (node.type) {\n case 'Dimension':\n // Font-size: 16px, 1rem, etc.\n const numValue = Number(node.value);\n if (numValue <= 0) return null; // Skip zero/negative values\n \n const unit = node.unit.toLowerCase();\n if (!ALLOWED_UNITS.includes(unit)) return null;\n \n return {\n value: numValue,\n unit: unit as 'px' | 'rem' | '%' | 'em' | 'ch'\n };\n \n case 'Number':\n // Font-weight: 400, 700, etc.\n const numberValue = Number(node.value);\n if (numberValue <= 0) {\n return null; // Skip zero/negative values\n }\n \n // Only accept known font-weight values for unitless numbers\n if (!isKnownFontWeight(numberValue)) {\n return null; // Skip values that aren't valid font-weights\n }\n \n return {\n value: numberValue,\n unit: null\n };\n \n case 'Identifier':\n // Font-weight keywords: normal, bold, etc.\n const namedValue = node.name.toLowerCase();\n \n // Only accept known font-weight keywords\n if (!isKnownFontWeight(namedValue)) {\n return null;\n }\n \n // Convert known keywords to numeric values\n if (namedValue === 'normal') {\n return { value: 400, unit: null };\n }\n \n // For other keywords (bolder, lighter), we can't determine exact numeric value\n // but we know they're valid font-weight values\n return { value: namedValue, unit: null };\n \n case 'Percentage':\n // Percentage values for font-size\n const percentValue = Number(node.value);\n if (percentValue === 0) return null; // Skip zero values\n \n return {\n value: percentValue,\n unit: '%'\n };\n \n case 'Value':\n // Value wrapper - extract from first child\n return node.children?.[0] ? extractFontValue(node.children[0]) : null;\n }\n \n return null;\n}\n\n/**\n * Check if font node should be skipped during traversal\n * Skip all function nodes by default\n */\nfunction shouldSkipFontNode(node: any): boolean {\n return node.type === 'Function';\n}\n\n/**\n * Specialized font value traversal\n * Handles font-specific extraction and skipping logic\n */\nexport function forEachFontValue(\n valueText: string,\n callback: (fontValue: ParsedUnitValue, positionInfo: PositionInfo) => void\n): void {\n forEachValue(valueText, extractFontValue, shouldSkipFontNode, callback);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
7
  }
@@ -54,10 +54,10 @@ var PADDING_REGEX = new RegExp(`^padding(?:-${DIRECTION_VALUES})?$`);
54
54
  var BORDER_RADIUS_REGEX = new RegExp(`^border(?:-${CORNER_VALUES})?-radius$`);
55
55
  var INSET_REGEX = new RegExp(`^inset(?:-${INSET_VALUES})?$`);
56
56
  function isBorderColorProperty(cssProperty) {
57
- return BORDER_COLOR_REGEX.test(cssProperty);
57
+ return cssProperty === "border" || BORDER_COLOR_REGEX.test(cssProperty);
58
58
  }
59
59
  function isBorderWidthProperty(cssProperty) {
60
- return BORDER_WIDTH_REGEX.test(cssProperty);
60
+ return cssProperty === "border" || BORDER_WIDTH_REGEX.test(cssProperty);
61
61
  }
62
62
  function isMarginProperty(cssProperty) {
63
63
  return MARGIN_REGEX.test(cssProperty);