@salesforce-ux/eslint-plugin-slds 0.5.3 → 1.0.0-internal-alpha.0

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 (114) hide show
  1. package/build/index.js +2309 -50
  2. package/build/index.js.map +4 -4
  3. package/build/rules/enforce-bem-usage.js +325 -85
  4. package/build/rules/enforce-bem-usage.js.map +4 -4
  5. package/build/rules/modal-close-button-issue.js +324 -179
  6. package/build/rules/modal-close-button-issue.js.map +4 -4
  7. package/build/rules/no-deprecated-classes-slds2.js +247 -53
  8. package/build/rules/no-deprecated-classes-slds2.js.map +4 -4
  9. package/build/rules/v9/enforce-bem-usage.js +236 -0
  10. package/build/rules/v9/enforce-bem-usage.js.map +7 -0
  11. package/build/rules/v9/enforce-component-hook-naming-convention.js +262 -0
  12. package/build/rules/v9/enforce-component-hook-naming-convention.js.map +7 -0
  13. package/build/rules/v9/enforce-sds-to-slds-hooks.js +260 -0
  14. package/build/rules/v9/enforce-sds-to-slds-hooks.js.map +7 -0
  15. package/build/rules/v9/lwc-token-to-slds-hook.js +330 -0
  16. package/build/rules/v9/lwc-token-to-slds-hook.js.map +7 -0
  17. package/build/rules/v9/no-deprecated-slds-classes.js +227 -0
  18. package/build/rules/v9/no-deprecated-slds-classes.js.map +7 -0
  19. package/build/rules/v9/no-deprecated-tokens-slds1.js +270 -0
  20. package/build/rules/v9/no-deprecated-tokens-slds1.js.map +7 -0
  21. package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js +339 -0
  22. package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js.map +7 -0
  23. package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js +348 -0
  24. package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js.map +7 -0
  25. package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js +344 -0
  26. package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js.map +7 -0
  27. package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js +388 -0
  28. package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js.map +7 -0
  29. package/build/rules/v9/no-hardcoded-values/handlers/index.js +834 -0
  30. package/build/rules/v9/no-hardcoded-values/handlers/index.js.map +7 -0
  31. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js +1112 -0
  32. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js.map +7 -0
  33. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js +1112 -0
  34. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js.map +7 -0
  35. package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js +945 -0
  36. package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js.map +7 -0
  37. package/build/rules/v9/no-slds-class-overrides.js +233 -0
  38. package/build/rules/v9/no-slds-class-overrides.js.map +7 -0
  39. package/build/rules/v9/no-slds-namespace-for-custom-hooks.js +250 -0
  40. package/build/rules/v9/no-slds-namespace-for-custom-hooks.js.map +7 -0
  41. package/build/rules/v9/no-slds-private-var.js +230 -0
  42. package/build/rules/v9/no-slds-private-var.js.map +7 -0
  43. package/build/rules/v9/no-slds-var-without-fallback.js +253 -0
  44. package/build/rules/v9/no-slds-var-without-fallback.js.map +7 -0
  45. package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js +253 -0
  46. package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js.map +7 -0
  47. package/build/rules/v9/no-unsupported-hooks-slds2.js +243 -0
  48. package/build/rules/v9/no-unsupported-hooks-slds2.js.map +7 -0
  49. package/build/rules/v9/reduce-annotations.js +234 -0
  50. package/build/rules/v9/reduce-annotations.js.map +7 -0
  51. package/build/src/rules/enforce-bem-usage.d.ts +17 -0
  52. package/build/{rules → src/rules}/modal-close-button-issue.d.ts +2 -1
  53. package/build/{rules → src/rules}/no-deprecated-classes-slds2.d.ts +2 -1
  54. package/build/src/rules/v9/enforce-bem-usage.d.ts +3 -0
  55. package/build/src/rules/v9/enforce-component-hook-naming-convention.d.ts +3 -0
  56. package/build/src/rules/v9/enforce-sds-to-slds-hooks.d.ts +3 -0
  57. package/build/src/rules/v9/lwc-token-to-slds-hook.d.ts +3 -0
  58. package/build/src/rules/v9/no-deprecated-slds-classes.d.ts +3 -0
  59. package/build/src/rules/v9/no-deprecated-tokens-slds1.d.ts +3 -0
  60. package/build/src/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.d.ts +5 -0
  61. package/build/src/rules/v9/no-hardcoded-values/handlers/colorHandler.d.ts +7 -0
  62. package/build/src/rules/v9/no-hardcoded-values/handlers/densityHandler.d.ts +7 -0
  63. package/build/src/rules/v9/no-hardcoded-values/handlers/fontHandler.d.ts +6 -0
  64. package/build/src/rules/v9/no-hardcoded-values/handlers/index.d.ts +8 -0
  65. package/build/src/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.d.ts +3 -0
  66. package/build/src/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.d.ts +3 -0
  67. package/build/src/rules/v9/no-hardcoded-values/noHardcodedValueRule.d.ts +9 -0
  68. package/build/src/rules/v9/no-slds-class-overrides.d.ts +8 -0
  69. package/build/src/rules/v9/no-slds-namespace-for-custom-hooks.d.ts +3 -0
  70. package/build/src/rules/v9/no-slds-private-var.d.ts +3 -0
  71. package/build/src/rules/v9/no-slds-var-without-fallback.d.ts +3 -0
  72. package/build/src/rules/v9/no-sldshook-fallback-for-lwctoken.d.ts +3 -0
  73. package/build/src/rules/v9/no-unsupported-hooks-slds2.d.ts +3 -0
  74. package/build/src/rules/v9/reduce-annotations.d.ts +3 -0
  75. package/build/src/types/index.d.ts +26 -0
  76. package/build/src/utils/boxShadowValueParser.d.ts +17 -0
  77. package/build/src/utils/color-lib-utils.d.ts +18 -0
  78. package/build/src/utils/css-functions.d.ts +7 -0
  79. package/build/src/utils/css-utils.d.ts +7 -0
  80. package/build/src/utils/hardcoded-shared-utils.d.ts +60 -0
  81. package/build/src/utils/property-matcher.d.ts +23 -0
  82. package/build/src/utils/styling-hook-utils.d.ts +7 -0
  83. package/build/src/utils/value-utils.d.ts +40 -0
  84. package/build/types/index.js +18 -0
  85. package/build/types/index.js.map +7 -0
  86. package/build/types/yaml.d.js +1 -0
  87. package/build/types/yaml.d.js.map +7 -0
  88. package/build/utils/boxShadowValueParser.js +197 -0
  89. package/build/utils/boxShadowValueParser.js.map +7 -0
  90. package/build/utils/color-lib-utils.js +160 -0
  91. package/build/utils/color-lib-utils.js.map +7 -0
  92. package/build/utils/css-functions.js +68 -0
  93. package/build/utils/css-functions.js.map +7 -0
  94. package/build/utils/css-utils.js +33 -0
  95. package/build/utils/css-utils.js.map +7 -0
  96. package/build/utils/hardcoded-shared-utils.js +300 -0
  97. package/build/utils/hardcoded-shared-utils.js.map +7 -0
  98. package/build/utils/node.js +158 -0
  99. package/build/{rules/utils → utils}/node.js.map +2 -2
  100. package/build/utils/property-matcher.js +159 -0
  101. package/build/utils/property-matcher.js.map +7 -0
  102. package/build/utils/styling-hook-utils.js +80 -0
  103. package/build/utils/styling-hook-utils.js.map +7 -0
  104. package/build/utils/value-utils.js +65 -0
  105. package/build/utils/value-utils.js.map +7 -0
  106. package/package.json +9 -4
  107. package/src/config/rule-messages.yml +143 -0
  108. package/build/rules/enforce-bem-usage.d.ts +0 -28
  109. package/build/rules/utils/node.js +0 -197
  110. package/build/rules/utils/rule.d.ts +0 -7
  111. package/build/rules/utils/rule.js +0 -10
  112. package/build/rules/utils/rule.js.map +0 -7
  113. /package/build/{index.d.ts → src/index.d.ts} +0 -0
  114. /package/build/{rules → src}/utils/node.d.ts +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["yaml-file:/Users/ritesh.kumar2/Documents/projects/stylelint-sds/packages/eslint-plugin-slds/src/config/rule-messages.yml", "../../../src/rules/v9/no-deprecated-tokens-slds1.ts"],
4
+ "sourcesContent": ["module.exports = {\n \"no-slds-class-overrides\": {\n \"description\": \"Create new custom CSS classes instead of overriding SLDS selectors\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-slds-class-overrides\",\n \"type\": \"problem\",\n \"messages\": {\n \"sldsClassOverride\": \"Overriding .{{className}} isn't supported. To differentiate SLDS and custom classes, create a CSS class in your namespace. Examples: myapp-input, myapp-button.\"\n }\n },\n \"no-deprecated-slds-classes\": {\n \"description\": \"Please replace the deprecated classes with a modern equivalent\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-deprecated-slds-classes\",\n \"type\": \"problem\",\n \"messages\": {\n \"deprecatedClass\": \"The class {{className}} is deprecated and not available in SLDS2. Please update to a supported class.\"\n }\n },\n \"no-deprecated-tokens-slds1\": {\n \"description\": \"Update outdated design tokens to SLDS 2 styling hooks with similar values. For more information, see Styling Hooks on lightningdesignsystem.com.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-deprecated-tokens-slds1\",\n \"type\": \"problem\",\n \"messages\": {\n \"deprecatedToken\": \"Consider removing {{oldValue}} or replacing it with {{newValue}}. Set the fallback to {{oldValue}}. For more info, see Styling Hooks on lightningdesignsystem.com.\",\n \"noReplacement\": \"Update outdated design tokens to SLDS 2 styling hooks with similar values. For more information, see Styling Hooks on lightningdesignsystem.com.\"\n }\n },\n \"enforce-sds-to-slds-hooks\": {\n \"description\": \"Convert your existing --sds styling hooks to --slds styling hooks. See lightningdesignsystem.com for more info.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#enforce-sds-to-slds-hooks\",\n \"type\": \"problem\",\n \"messages\": {\n \"replaceSdsWithSlds\": \"Replace {{oldValue}} with {{suggestedMatch}} styling hook.\"\n }\n },\n \"enforce-bem-usage\": {\n \"description\": \"Replace BEM double-dash syntax in class names with single underscore syntax\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#enforce-bem-usage\",\n \"type\": \"problem\",\n \"messages\": {\n \"bemDoubleDash\": \"{{actual}} has been retired. Update it to the new name {{newValue}}.\",\n \"fixBemNaming\": \"Update to correct BEM naming convention\"\n }\n },\n \"modal-close-button-issue\": {\n \"description\": \"Update component attributes or CSS classes for the modal close button to comply with the modal component blueprint\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#modal-close-button-issue\",\n \"type\": \"problem\",\n \"messages\": {\n \"modalCloseButtonIssue\": \"Update component attributes or CSS classes for the modal close button to comply with the modal component blueprint.\",\n \"removeClass\": \"Remove the slds-button_icon-inverse class from the modal close button in components that use the SLDS modal blueprint.\",\n \"changeVariant\": \"Change the variant attribute value from bare-inverse to bare in <lightning-button-icon> or <lightning-icon>.\",\n \"removeVariant\": \"Remove the variant attribute from the <lightning-icon> component inside the <button> element.\",\n \"ensureButtonClasses\": \"Add or move slds-button and slds-button_icon to the class attribute of the <button> element or <lightning-button-icon> component.\",\n \"ensureSizeAttribute\": \"To size icons properly, set the size attribute \u200Cto large in the <lightning-icon> and <lightning-button-icon> components.\"\n }\n },\n \"no-deprecated-classes-slds2\": {\n \"description\": \"Replace classes that aren't available with SLDS 2 classes\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-deprecated-classes-slds2\",\n \"type\": \"problem\",\n \"messages\": {\n \"deprecatedClass\": \"The class {{className}} isn't available in SLDS 2. Update it to a class supported in SLDS 2. See lightningdesignsystem.com for more information.\",\n \"updateToModernClass\": \"Replace deprecated class with modern equivalent\",\n \"checkDocumentation\": \"See lightningdesignsystem.com for SLDS 2 class alternatives\"\n }\n },\n \"lwc-token-to-slds-hook\": {\n \"description\": \"Replace the deprecated --lwc tokens with the latest --slds tokens. See lightningdesignsystem.com for more info.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#lwc-token-to-slds-hook\",\n \"type\": \"problem\",\n \"messages\": {\n \"errorWithReplacement\": \"The '{{oldValue}}' design token is deprecated. Replace it with '{{newValue}}'. For more info, see Global Styling Hooks on lightningdesignsystem.com.\",\n \"errorWithStyleHooks\": \"The '{{oldValue}}' design token is deprecated. Replace it with the SLDS 2 '{{newValue}}' styling hook and set the fallback to '{{oldValue}}'. For more info, see Global Styling Hooks on lightningdesignsystem.com.\",\n \"errorWithNoRecommendation\": \"The '{{oldValue}}' design token is deprecated. For more info, see the New Global Styling Hook Guidance on lightningdesignsystem.com.\"\n }\n },\n \"no-sldshook-fallback-for-lwctoken\": {\n \"description\": \"Avoid using --slds styling hooks as fallback values for --lwc tokens.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-sldshook-fallback-for-lwctoken\",\n \"type\": \"problem\",\n \"messages\": {\n \"unsupportedFallback\": \"Remove the {{sldsToken}} styling hook that is used as a fallback value for {{lwcToken}}.\"\n }\n },\n \"no-unsupported-hooks-slds2\": {\n \"description\": \"Identifies styling hooks that aren't present in SLDS 2. They must be replaced with styling hooks that have a similar effect, or they must be removed.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-unsupported-hooks-slds2\",\n \"type\": \"problem\",\n \"messages\": {\n \"deprecated\": \"The {{token}} styling hook isn't present in SLDS 2 and there's no equivalent replacement. Remove it or replace it with a styling hook with a similar effect.\"\n }\n },\n \"no-slds-var-without-fallback\": {\n \"description\": \"Add fallback values to SLDS styling hooks. The fallback values are used in Salesforce environments where styling hooks are unavailable.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-slds-var-without-fallback\",\n \"type\": \"problem\",\n \"messages\": {\n \"varWithoutFallback\": \"Your code uses the {{cssVar}} styling hook without a fallback value. Styling hooks are unavailable in some Salesforce environments. To render your component correctly in all environments, add this fallback value: var({{cssVar}}, {{recommendation}}). To make this fallback value brand-aware, use a branded design token instead of a static value. See Design Tokens on v1.lightningdesignsystem.com.\"\n }\n },\n \"no-slds-namespace-for-custom-hooks\": {\n \"description\": \"To differentiate custom styling hooks from SLDS styling hooks, create custom styling hooks in your namespace.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-slds-namespace-for-custom-hooks\",\n \"type\": \"problem\",\n \"messages\": {\n \"customHookNamespace\": \"Using the --slds namespace for {{token}} isn't supported. Create the custom styling hook in your namespace. Example: --myapp-{{tokenWithoutNamespace}}\"\n }\n },\n \"no-slds-private-var\": {\n \"description\": \"Some SLDS styling hooks are private and reserved only for internal Salesforce use. Private SLDS styling hooks have prefixes --_slds- and --slds-s-. For more information, look up private CSS in lightningdesignsystem.com.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-slds-private-var\",\n \"type\": \"problem\",\n \"messages\": {\n \"privateVar\": \"This styling hook is reserved for internal Salesforce use. Remove the --_slds- or \u2013slds-s private variable within selector {{prop}}. For more information, look up private CSS in lightningdesignsystem.com.\"\n }\n },\n \"enforce-component-hook-naming-convention\": {\n \"description\": \"Replace component styling hooks that use a deprecated naming convention.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#enforce-component-hook-naming-convention\",\n \"type\": \"problem\",\n \"messages\": {\n \"replace\": \"Replace the deprecated {{oldValue}} component styling hook with {{suggestedMatch}}.\"\n }\n },\n \"no-hardcoded-values-slds1\": {\n \"description\": \"Replace static values with SLDS 1 design tokens. For more information, look up design tokens on lightningdesignsystem.com.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-hardcoded-value\",\n \"type\": \"suggestion\",\n \"messages\": {\n \"hardcodedValue\": \"Replace the {{oldValue}} static value with an SLDS 1 styling hook: {{newValue}}.\",\n \"noReplacement\": \"There's no replacement styling hook for the {{oldValue}} static value. Remove the static value.\"\n }\n },\n \"no-hardcoded-values-slds2\": {\n \"description\": \"Replace static values with SLDS 2 styling hooks. For more information, look up design tokens on lightningdesignsystem.com.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-hardcoded-value\",\n \"type\": \"suggestion\",\n \"messages\": {\n \"hardcodedValue\": \"Consider replacing the {{oldValue}} static value with an SLDS 2 styling hook that has a similar value: {{newValue}}.\",\n \"noReplacement\": \"There's no replacement styling hook for the {{oldValue}} static value. Remove the static value.\"\n }\n },\n \"reduce-annotations\": {\n \"description\": \"Remove your annotations and update your code.\",\n \"url\": \"https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#reduce-annotations\",\n \"type\": \"problem\",\n \"messages\": {\n \"removeAnnotation\": \"Remove this annotation and update the code to SLDS best practices. For help, file an issue at https://github.com/salesforce-ux/slds-linter/\"\n }\n }\n};", "import { Rule } from 'eslint';\nimport metadata from '@salesforce-ux/sds-metadata/next';\nimport ruleMessages from '../../config/rule-messages.yml';\n\nconst ruleConfig = ruleMessages['no-deprecated-tokens-slds1'];\nconst { type, description, url, messages } = ruleConfig;\n\n// Get token mapping from metadata (Aura tokens to LWC tokens)\nconst tokenMapping = metadata.auraToLwcTokensMapping;\n\nexport default {\n meta: {\n type,\n docs: {\n description: description,\n recommended: true,\n url,\n },\n fixable: 'code',\n messages,\n },\n \n create(context) {\n /**\n * Check if a token should be ignored (not in mapping or not LWC token)\n */\n function shouldIgnoreDetection(token: string): boolean {\n return (!(token in tokenMapping) || !tokenMapping[token].startsWith('--lwc-'));\n }\n\n /**\n * Generate replacement suggestion for deprecated token\n */\n function generateReplacement(tokenName: string, originalFunctionCall: string): string | null {\n if (shouldIgnoreDetection(tokenName)) {\n return null;\n }\n const recommendation = tokenMapping[tokenName];\n return `var(${recommendation}, ${originalFunctionCall})`;\n }\n\n function handleTokenFunction(node, functionName) {\n // Get the token name from the identifier\n const tokenName = context.sourceCode.getText(node);\n \n // Skip if token should be ignored\n if (shouldIgnoreDetection(tokenName)) {\n return;\n }\n\n // Create original function call - mirroring stylelint's approach\n const originalFunctionCall = `${functionName}(${tokenName})`;\n const replacement = generateReplacement(tokenName, originalFunctionCall);\n \n if (replacement) {\n // Report with replacement suggestion\n context.report({\n node,\n messageId: 'deprecatedToken',\n data: { \n oldValue: originalFunctionCall,\n newValue: replacement\n },\n fix(fixer) {\n // Use node position to avoid multiple replacements of same token\n const sourceCode = context.sourceCode.getText();\n const tokenFunctionCall = `${functionName}(${tokenName})`;\n const nodeOffset = node.loc.start.offset;\n \n // Search backwards from the node position to find the function start\n const searchStart = Math.max(0, nodeOffset - functionName.length - 1);\n const searchEnd = nodeOffset + tokenName.length + 1;\n const searchArea = sourceCode.substring(searchStart, searchEnd);\n \n const functionCallIndex = searchArea.indexOf(tokenFunctionCall);\n if (functionCallIndex !== -1) {\n const actualStart = searchStart + functionCallIndex;\n const actualEnd = actualStart + tokenFunctionCall.length;\n return fixer.replaceTextRange([actualStart, actualEnd], replacement);\n }\n return null;\n }\n });\n } else {\n // Report without specific replacement\n context.report({\n node,\n messageId: 'noReplacement',\n });\n }\n }\n\n return {\n \"Function[name='token'] Identifier\"(node) {\n handleTokenFunction(node, 'token');\n },\n \"Function[name='t'] Identifier\"(node) {\n handleTokenFunction(node, 't');\n },\n };\n\n },\n} as Rule.RuleModule;\n"],
5
+ "mappings": "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",
6
+ "names": ["exports", "module", "ruleMessages", "metadata"]
7
+ }
@@ -0,0 +1,339 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
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
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.ts
30
+ var boxShadowHandler_exports = {};
31
+ __export(boxShadowHandler_exports, {
32
+ handleBoxShadowDeclaration: () => handleBoxShadowDeclaration
33
+ });
34
+ module.exports = __toCommonJS(boxShadowHandler_exports);
35
+
36
+ // src/utils/boxShadowValueParser.ts
37
+ var import_css_tree2 = require("@eslint/css-tree");
38
+
39
+ // src/utils/color-lib-utils.ts
40
+ var import_chroma_js = __toESM(require("chroma-js"));
41
+ var import_css_tree = require("@eslint/css-tree");
42
+
43
+ // src/utils/css-functions.ts
44
+ var CSS_FUNCTIONS = [
45
+ "attr",
46
+ "calc",
47
+ "color-mix",
48
+ "conic-gradient",
49
+ "counter",
50
+ "cubic-bezier",
51
+ "linear-gradient",
52
+ "max",
53
+ "min",
54
+ "radial-gradient",
55
+ "repeating-conic-gradient",
56
+ "repeating-linear-gradient",
57
+ "repeating-radial-gradient",
58
+ "var"
59
+ ];
60
+ var CSS_MATH_FUNCTIONS = ["calc", "min", "max"];
61
+ var RGB_COLOR_FUNCTIONS = ["rgb", "rgba", "hsl", "hsla"];
62
+ var cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join("|")})`);
63
+ var cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join("|")})$`);
64
+ var cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join("|")})$`);
65
+ function isCssColorFunction(value) {
66
+ return RGB_COLOR_FUNCTIONS.includes(value);
67
+ }
68
+
69
+ // src/utils/color-lib-utils.ts
70
+ var isValidColor = (val) => import_chroma_js.default.valid(val);
71
+
72
+ // src/utils/value-utils.ts
73
+ function parseUnitValue(value) {
74
+ if (!value) return null;
75
+ const match = value.match(/^(-?\d*\.?\d+)(px|rem|%)?$/);
76
+ if (!match) return null;
77
+ const number = parseFloat(match[1]);
78
+ const unit = match[2] ? match[2] : null;
79
+ if (isNaN(number)) return null;
80
+ return { number, unit };
81
+ }
82
+
83
+ // src/utils/boxShadowValueParser.ts
84
+ function isColorValue(node) {
85
+ if (!node) return false;
86
+ switch (node.type) {
87
+ case "Hash":
88
+ return true;
89
+ // #hex colors
90
+ case "Identifier":
91
+ return isValidColor(node.name);
92
+ case "Function":
93
+ return isCssColorFunction(node.name.toLowerCase());
94
+ default:
95
+ return false;
96
+ }
97
+ }
98
+ function isLengthValue(node) {
99
+ if (!node) return false;
100
+ switch (node.type) {
101
+ case "Dimension":
102
+ const dimensionStr = `${node.value}${node.unit}`;
103
+ return parseUnitValue(dimensionStr) !== null;
104
+ case "Number":
105
+ return Number(node.value) === 0;
106
+ default:
107
+ return false;
108
+ }
109
+ }
110
+ function isInsetKeyword(node) {
111
+ return node?.type === "Identifier" && node.name.toLowerCase() === "inset";
112
+ }
113
+ function extractShadowParts(valueText) {
114
+ const shadows = [];
115
+ let currentShadow = {
116
+ lengthParts: [],
117
+ colorParts: [],
118
+ inset: false
119
+ };
120
+ try {
121
+ const ast = (0, import_css_tree2.parse)(valueText, { context: "value" });
122
+ (0, import_css_tree2.walk)(ast, {
123
+ enter(node) {
124
+ if (node.type === "Function") {
125
+ return this.skip;
126
+ }
127
+ if (isInsetKeyword(node)) {
128
+ currentShadow.inset = true;
129
+ } else if (isLengthValue(node)) {
130
+ currentShadow.lengthParts.push((0, import_css_tree2.generate)(node));
131
+ } else if (isColorValue(node)) {
132
+ currentShadow.colorParts.push((0, import_css_tree2.generate)(node));
133
+ }
134
+ }
135
+ });
136
+ if (currentShadow.lengthParts.length > 0 || currentShadow.colorParts.length > 0 || currentShadow.inset) {
137
+ shadows.push(currentShadow);
138
+ }
139
+ } catch (error) {
140
+ return [];
141
+ }
142
+ return shadows;
143
+ }
144
+ function parseBoxShadowValue(value) {
145
+ const shadowStrings = value.split(",").map((s) => s.trim());
146
+ const allShadows = [];
147
+ for (const shadowString of shadowStrings) {
148
+ const shadows = extractShadowParts(shadowString);
149
+ const parsedShadows = shadows.map((shadow) => {
150
+ const shadowValue = {};
151
+ const lengthProps = ["offsetX", "offsetY", "blurRadius", "spreadRadius"];
152
+ lengthProps.forEach((prop, index) => {
153
+ if (shadow.lengthParts.length > index) {
154
+ shadowValue[prop] = shadow.lengthParts[index];
155
+ }
156
+ });
157
+ if (shadow.colorParts.length > 0) {
158
+ shadowValue.color = shadow.colorParts[0];
159
+ }
160
+ if (shadow.inset) {
161
+ shadowValue.inset = true;
162
+ }
163
+ return shadowValue;
164
+ });
165
+ allShadows.push(...parsedShadows);
166
+ }
167
+ return allShadows;
168
+ }
169
+ function normalizeLengthValue(value) {
170
+ if (!value) return "0px";
171
+ if (value === "0") return "0px";
172
+ return value;
173
+ }
174
+ function isBoxShadowMatch(parsedCssValue, parsedValueHook) {
175
+ if (parsedCssValue.length !== parsedValueHook.length) {
176
+ return false;
177
+ }
178
+ for (let i = 0; i < parsedCssValue.length; i++) {
179
+ const cssShadow = parsedCssValue[i];
180
+ const hookShadow = parsedValueHook[i];
181
+ if (cssShadow.color !== hookShadow.color || cssShadow.inset !== hookShadow.inset) {
182
+ return false;
183
+ }
184
+ const lengthProps = ["offsetX", "offsetY", "blurRadius", "spreadRadius"];
185
+ for (const prop of lengthProps) {
186
+ if (normalizeLengthValue(cssShadow[prop]) !== normalizeLengthValue(hookShadow[prop])) {
187
+ return false;
188
+ }
189
+ }
190
+ }
191
+ return true;
192
+ }
193
+
194
+ // src/utils/hardcoded-shared-utils.ts
195
+ var import_css_tree3 = require("@eslint/css-tree");
196
+ function handleShorthandAutoFix(declarationNode, context, valueText, replacements) {
197
+ const sortedReplacements = replacements.sort((a, b) => a.start - b.start);
198
+ const hasAnyHooks = sortedReplacements.some((r) => r.hasHook);
199
+ const canAutoFix = hasAnyHooks;
200
+ sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook }) => {
201
+ const originalValue = valueText.substring(start, end);
202
+ const valueStartColumn = declarationNode.value.loc.start.column;
203
+ const valueColumn = valueStartColumn + start;
204
+ const { loc: { start: locStart, end: locEnd } } = declarationNode.value;
205
+ const reportNode = {
206
+ ...declarationNode.value,
207
+ loc: {
208
+ ...declarationNode.value.loc,
209
+ start: {
210
+ ...locStart,
211
+ column: valueColumn
212
+ },
213
+ end: {
214
+ ...locEnd,
215
+ column: valueColumn + originalValue.length
216
+ }
217
+ }
218
+ };
219
+ if (hasHook) {
220
+ const fix = canAutoFix ? (fixer) => {
221
+ let newValue = valueText;
222
+ for (let i = sortedReplacements.length - 1; i >= 0; i--) {
223
+ const { start: rStart, end: rEnd, replacement: rReplacement } = sortedReplacements[i];
224
+ newValue = newValue.substring(0, rStart) + rReplacement + newValue.substring(rEnd);
225
+ }
226
+ return fixer.replaceText(declarationNode.value, newValue);
227
+ } : void 0;
228
+ context.context.report({
229
+ node: reportNode,
230
+ messageId: "hardcodedValue",
231
+ data: {
232
+ oldValue: originalValue,
233
+ newValue: displayValue
234
+ },
235
+ fix
236
+ });
237
+ } else {
238
+ context.context.report({
239
+ node: reportNode,
240
+ messageId: "noReplacement",
241
+ data: {
242
+ oldValue: originalValue
243
+ }
244
+ });
245
+ }
246
+ });
247
+ }
248
+
249
+ // src/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.ts
250
+ function containsCssVariable(valueText) {
251
+ return valueText.includes("var(");
252
+ }
253
+ var handleBoxShadowDeclaration = (node, context) => {
254
+ const cssProperty = node.property.toLowerCase();
255
+ const valueText = context.sourceCode.getText(node.value);
256
+ if (containsCssVariable(valueText)) {
257
+ return;
258
+ }
259
+ const replacements = [];
260
+ const parsedCssValue = parseAndValidateBoxShadow(valueText);
261
+ if (parsedCssValue) {
262
+ const shadowHooks = getBoxShadowHooks(context.valueToStylinghook);
263
+ const closestHooks = findMatchingBoxShadowHooks(parsedCssValue, shadowHooks);
264
+ const positionInfo = {
265
+ start: { offset: 0, line: 1, column: 1 },
266
+ end: { offset: valueText.length, line: 1, column: valueText.length + 1 }
267
+ };
268
+ const replacement = createBoxShadowReplacement(
269
+ valueText,
270
+ closestHooks,
271
+ context,
272
+ positionInfo
273
+ );
274
+ if (replacement) {
275
+ replacements.push(replacement);
276
+ }
277
+ }
278
+ handleShorthandAutoFix(node, context, valueText, replacements);
279
+ };
280
+ function getBoxShadowHooks(supportedStylinghooks) {
281
+ return Object.entries(supportedStylinghooks).filter(([key, value]) => {
282
+ return value.some((hook) => hook.properties.includes("box-shadow"));
283
+ }).map(([key, value]) => {
284
+ return [key, value.map((hook) => hook.name)];
285
+ });
286
+ }
287
+ function parseAndValidateBoxShadow(cssValue) {
288
+ const parsedCssValue = parseBoxShadowValue(cssValue).filter((shadow) => Object.keys(shadow).length > 0);
289
+ if (parsedCssValue.length === 0) {
290
+ return null;
291
+ }
292
+ return parsedCssValue;
293
+ }
294
+ function findMatchingBoxShadowHooks(parsedCssValue, shadowHooks) {
295
+ for (const [shadowHookValue, closestHooks] of shadowHooks) {
296
+ const parsedHookValue = parseAndValidateBoxShadow(shadowHookValue);
297
+ if (parsedHookValue && isBoxShadowMatch(parsedCssValue, parsedHookValue)) {
298
+ return closestHooks;
299
+ }
300
+ }
301
+ return [];
302
+ }
303
+ function createBoxShadowReplacement(originalValue, hooks, context, positionInfo) {
304
+ if (!positionInfo?.start) {
305
+ return null;
306
+ }
307
+ const start = positionInfo.start.offset;
308
+ const end = positionInfo.end.offset;
309
+ if (hooks.length === 1) {
310
+ return {
311
+ start,
312
+ end,
313
+ replacement: `var(${hooks[0]}, ${originalValue})`,
314
+ displayValue: hooks[0],
315
+ hasHook: true
316
+ };
317
+ } else if (hooks.length > 1) {
318
+ return {
319
+ start,
320
+ end,
321
+ replacement: originalValue,
322
+ displayValue: hooks.join(", "),
323
+ hasHook: true
324
+ };
325
+ } else {
326
+ return {
327
+ start,
328
+ end,
329
+ replacement: originalValue,
330
+ displayValue: originalValue,
331
+ hasHook: false
332
+ };
333
+ }
334
+ }
335
+ // Annotate the CommonJS export names for ESM import in node:
336
+ 0 && (module.exports = {
337
+ handleBoxShadowDeclaration
338
+ });
339
+ //# sourceMappingURL=boxShadowHandler.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.ts", "../../../../../src/utils/boxShadowValueParser.ts", "../../../../../src/utils/color-lib-utils.ts", "../../../../../src/utils/css-functions.ts", "../../../../../src/utils/value-utils.ts", "../../../../../src/utils/hardcoded-shared-utils.ts"],
4
+ "sourcesContent": ["import type { HandlerContext, DeclarationHandler } from '../../../../types';\nimport type { ValueToStylingHooksMapping } from '@salesforce-ux/sds-metadata/next';\nimport { parseBoxShadowValue, isBoxShadowMatch, type BoxShadowValue } from '../../../../utils/boxShadowValueParser';\n\n// Import shared utilities for common logic\nimport { \n handleShorthandAutoFix, \n type ReplacementInfo,\n type PositionInfo\n} from '../../../../utils/hardcoded-shared-utils';\n\n/**\n * Check if a CSS value contains CSS variables (var() functions)\n */\nfunction containsCssVariable(valueText: string): boolean {\n return valueText.includes('var(');\n}\n\n/**\n * Handle box-shadow declarations using CSS tree parsing\n */\nexport const handleBoxShadowDeclaration: DeclarationHandler = (node: any, context: HandlerContext) => {\n const cssProperty = node.property.toLowerCase();\n const valueText = context.sourceCode.getText(node.value);\n \n // Skip if the value contains CSS variables\n if (containsCssVariable(valueText)) {\n return;\n }\n \n // Box-shadow uses complete value matching, not individual value extraction\n const replacements: ReplacementInfo[] = [];\n \n // Parse and find matching hooks for the complete box-shadow value\n const parsedCssValue = parseAndValidateBoxShadow(valueText);\n if (parsedCssValue) {\n const shadowHooks = getBoxShadowHooks(context.valueToStylinghook);\n const closestHooks = findMatchingBoxShadowHooks(parsedCssValue, shadowHooks);\n \n // Create position info for the entire box-shadow value\n // hardcoded position is needed for string manipulation, not error reporting\n const positionInfo: PositionInfo = {\n start: { offset: 0, line: 1, column: 1 },\n end: { offset: valueText.length, line: 1, column: valueText.length + 1 }\n };\n \n const replacement = createBoxShadowReplacement(\n valueText,\n closestHooks,\n context,\n positionInfo\n );\n \n if (replacement) {\n replacements.push(replacement);\n }\n }\n \n // Apply shorthand auto-fix once processing is complete\n handleShorthandAutoFix(node, context, valueText, replacements);\n};\n\n\n/**\n * Extract box-shadow hook entries from styling hooks mapping\n */\nfunction getBoxShadowHooks(supportedStylinghooks: ValueToStylingHooksMapping): Array<[string, string[]]> {\n return Object.entries(supportedStylinghooks).filter(([key, value]) => {\n return value.some((hook) => hook.properties.includes('box-shadow'));\n }).map(([key, value]) => {\n return [key, value.map((hook) => hook.name)];\n });\n}\n\n/**\n * Parse and validate box-shadow value\n */\nfunction parseAndValidateBoxShadow(cssValue: string): BoxShadowValue[] | null {\n const parsedCssValue = parseBoxShadowValue(cssValue).filter((shadow) => Object.keys(shadow).length > 0);\n if (parsedCssValue.length === 0) {\n return null;\n }\n return parsedCssValue;\n}\n\n/**\n * Find matching hooks for a parsed box-shadow value\n */\nfunction findMatchingBoxShadowHooks(\n parsedCssValue: BoxShadowValue[], \n shadowHooks: Array<[string, string[]]>\n): string[] {\n // Try to find a matching hook for the complete box-shadow value\n for (const [shadowHookValue, closestHooks] of shadowHooks) {\n const parsedHookValue = parseAndValidateBoxShadow(shadowHookValue);\n \n if (parsedHookValue && isBoxShadowMatch(parsedCssValue, parsedHookValue)) {\n return closestHooks;\n }\n }\n \n return []; // No matching hooks found\n}\n\n/**\n * Create box-shadow replacement info for shorthand auto-fix\n * Returns replacement data or null if no valid replacement\n */\nfunction createBoxShadowReplacement(\n originalValue: string,\n hooks: string[],\n context: HandlerContext,\n positionInfo: PositionInfo\n): ReplacementInfo | null {\n if (!positionInfo?.start) {\n return null;\n }\n\n // Use position information directly from CSS tree (already 0-based offsets)\n const start = positionInfo.start.offset;\n const end = positionInfo.end.offset;\n\n if (hooks.length === 1) {\n // Has a single hook replacement - should provide autofix\n return {\n start,\n end,\n replacement: `var(${hooks[0]}, ${originalValue})`,\n displayValue: hooks[0],\n hasHook: true\n };\n } else if (hooks.length > 1) {\n // Multiple hooks - still has hooks, but no auto-fix\n return {\n start,\n end,\n replacement: originalValue,\n displayValue: hooks.join(', '),\n hasHook: true\n };\n } else {\n // No hooks - keep original value\n return {\n start,\n end,\n replacement: originalValue,\n displayValue: originalValue,\n hasHook: false\n };\n }\n}\n", "import { parse, walk, generate } from '@eslint/css-tree';\nimport { isValidColor } from './color-lib-utils';\nimport { parseUnitValue, type ParsedUnitValue } from './value-utils';\nimport { isCssColorFunction } from './css-functions';\n\nexport interface BoxShadowValue {\n offsetX?: string;\n offsetY?: string;\n blurRadius?: string;\n spreadRadius?: string;\n color?: string;\n inset?: boolean;\n}\n\ninterface ShadowParts {\n lengthParts: string[];\n colorParts: string[];\n inset: boolean;\n}\n\n/**\n * Check if a CSS tree node represents a color value\n */\nfunction isColorValue(node: any): boolean {\n if (!node) return false;\n \n switch (node.type) {\n case 'Hash':\n return true; // #hex colors\n case 'Identifier':\n return isValidColor(node.name);\n case 'Function':\n return isCssColorFunction(node.name.toLowerCase());\n default:\n return false;\n }\n}\n\n/**\n * Check if a CSS tree node represents a length value\n */\nfunction isLengthValue(node: any): boolean {\n if (!node) return false;\n \n switch (node.type) {\n case 'Dimension':\n // Use existing unit parsing to validate the unit\n const dimensionStr = `${node.value}${node.unit}`;\n return parseUnitValue(dimensionStr) !== null;\n case 'Number':\n // Zero values without units are valid lengths\n return Number(node.value) === 0;\n default:\n return false;\n }\n}\n\n/**\n * Check if a CSS tree node represents the 'inset' keyword\n */\nfunction isInsetKeyword(node: any): boolean {\n return node?.type === 'Identifier' && node.name.toLowerCase() === 'inset';\n}\n\n/**\n * Extract shadow parts from CSS tree nodes\n */\nfunction extractShadowParts(valueText: string): ShadowParts[] {\n const shadows: ShadowParts[] = [];\n let currentShadow: ShadowParts = {\n lengthParts: [],\n colorParts: [],\n inset: false\n };\n\n try {\n const ast = parse(valueText, { context: 'value' as const });\n \n walk(ast, {\n enter(node: any) {\n // Skip nested function content for now\n if (node.type === 'Function') {\n return this.skip;\n }\n \n if (isInsetKeyword(node)) {\n currentShadow.inset = true;\n } else if (isLengthValue(node)) {\n currentShadow.lengthParts.push(generate(node));\n } else if (isColorValue(node)) {\n currentShadow.colorParts.push(generate(node));\n }\n }\n });\n \n // Add the current shadow if it has any content\n if (currentShadow.lengthParts.length > 0 || currentShadow.colorParts.length > 0 || currentShadow.inset) {\n shadows.push(currentShadow);\n }\n \n } catch (error) {\n return [];\n }\n\n return shadows;\n}\n\n/**\n * Parse box-shadow value into structured format\n * Simplified version for ESLint v9 compatibility\n */\nexport function parseBoxShadowValue(value: string): BoxShadowValue[] {\n // Handle multiple shadows separated by commas\n const shadowStrings = value.split(',').map(s => s.trim());\n const allShadows: BoxShadowValue[] = [];\n \n for (const shadowString of shadowStrings) {\n const shadows = extractShadowParts(shadowString);\n \n const parsedShadows = shadows.map((shadow) => {\n /**\n * Box-shadow syntax:\n * Two, three, or four <length> values:\n * - offset-x offset-y [blur-radius] [spread-radius]\n * Optionally: inset keyword and color value\n */\n const shadowValue: BoxShadowValue = {};\n \n // Map length parts to shadow properties\n const lengthProps = ['offsetX', 'offsetY', 'blurRadius', 'spreadRadius'] as const;\n lengthProps.forEach((prop, index) => {\n if (shadow.lengthParts.length > index) {\n shadowValue[prop] = shadow.lengthParts[index];\n }\n });\n \n // Add color if present\n if (shadow.colorParts.length > 0) {\n shadowValue.color = shadow.colorParts[0];\n }\n \n // Add inset flag if present\n if (shadow.inset) {\n shadowValue.inset = true;\n }\n \n return shadowValue;\n });\n \n allShadows.push(...parsedShadows);\n }\n \n return allShadows;\n}\n\n/**\n * Normalize length value for comparison\n */\nfunction normalizeLengthValue(value: string | undefined): string {\n if (!value) return '0px';\n if (value === '0') return '0px';\n return value;\n}\n\n/**\n * Check if two parsed box-shadow values match\n */\nexport function isBoxShadowMatch(parsedCssValue: BoxShadowValue[], parsedValueHook: BoxShadowValue[]): boolean {\n // If the number of shadows doesn't match, they're not equal\n if (parsedCssValue.length !== parsedValueHook.length) {\n return false;\n }\n\n // Compare each shadow in the array\n for (let i = 0; i < parsedCssValue.length; i++) {\n const cssShadow = parsedCssValue[i];\n const hookShadow = parsedValueHook[i];\n\n // Compare color and inset properties\n if (cssShadow.color !== hookShadow.color || cssShadow.inset !== hookShadow.inset) {\n return false;\n }\n\n // Compare length properties\n const lengthProps = ['offsetX', 'offsetY', 'blurRadius', 'spreadRadius'] as const;\n for (const prop of lengthProps) {\n if (normalizeLengthValue(cssShadow[prop]) !== normalizeLengthValue(hookShadow[prop])) {\n return false;\n }\n }\n }\n\n return true;\n}\n", "//stylelint-sds/packages/stylelint-plugin-slds/src/utils/color-lib-utils.ts\nimport { 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\nconst LAB_THRESHOLD = 25; // Adjust this to set how strict the matching should be\n\nconst isHardCodedColor = (color: string): boolean => {\n const colorRegex =\n /\\b(rgb|rgba)\\((\\s*\\d{1,3}\\s*,\\s*){2,3}\\s*(0|1|0?\\.\\d+)\\s*\\)|#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\\b|[a-zA-Z]+/g;\n return colorRegex.test(color);\n};\n\nconst isHexCode = (color: string): boolean => {\n const hexPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/; // Pattern for #RGB or #RRGGBB\n return hexPattern.test(color);\n};\n\n// Convert a named color or hex code into a hex format using chroma-js\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\n// Find the closest color hook using LAB distance\nconst findClosestColorHook = (\n color: string,\n supportedColors:ValueToStylingHooksMapping,\n cssProperty: string\n): string[] => {\n const returnStylingHooks: string[] = [];\n const closestHooksWithSameProperty: { name: string; distance: number }[] = [];\n const closestHooksWithoutSameProperty: { name: string; distance: number }[] =\n [];\n const closestHooksWithAllProperty: { name: string; distance: number }[] =\n [];\n const labColor = chroma(color).lab();\n\n Object.entries(supportedColors).forEach(([sldsValue, data]) => {\n if (sldsValue && isHexCode(sldsValue)) {\n const hooks = data as ValueToStylingHookEntry[]; // Get the hooks for the sldsValue\n\n hooks.forEach((hook) => {\n const labSupportedColor = chroma(sldsValue).lab();\n const distance = (JSON.stringify(labColor) === JSON.stringify(labSupportedColor)) ? 0\n : chroma.distance(chroma.lab(...labColor), chroma.lab(...labSupportedColor), \"lab\");\n // Check if the hook has the same property\n if (hook.properties.includes(cssProperty)) {\n // Add to same property hooks if within threshold\n if (distance <= LAB_THRESHOLD) {\n closestHooksWithSameProperty.push({ name: hook.name, distance });\n }\n } \n // Check for the universal selector\n else if ( hook.properties.includes(\"*\") ){\n // Add to same property hooks if within threshold\n if (distance <= LAB_THRESHOLD) {\n closestHooksWithAllProperty.push({ name: hook.name, distance });\n }\n }\n else {\n // Add to different property hooks if within threshold\n if (distance <= LAB_THRESHOLD) {\n closestHooksWithoutSameProperty.push({ name: hook.name, distance });\n }\n }\n });\n }\n });\n\n// Group hooks by their priority\nconst closesthookGroups = [\n { hooks: closestHooksWithSameProperty, distance: 0 },\n { hooks: closestHooksWithAllProperty, distance: 0 },\n { hooks: closestHooksWithSameProperty, distance: Infinity }, // For hooks with distance > 0\n { hooks: closestHooksWithAllProperty, distance: Infinity },\n { hooks: closestHooksWithoutSameProperty, distance: Infinity },\n];\n\nfor (const group of closesthookGroups) {\n // Filter hooks based on the distance condition\n const filteredHooks = group.hooks.filter(h => \n group.distance === 0 ? h.distance === 0 : h.distance > 0\n );\n\n if (returnStylingHooks.length < 1 && filteredHooks.length > 0) {\n filteredHooks.sort((a, b) => a.distance - b.distance);\n returnStylingHooks.push(...filteredHooks.slice(0, 5).map((h) => h.name));\n }\n}\n\n\n return Array.from(new Set(returnStylingHooks));\n};\n\n/**\n * This method is usefull to identify all possible css color values.\n * - names colors\n * - 6,8 digit hex\n * - rgb and rgba\n * - hsl and hsla\n */\nconst isValidColor = (val:string):boolean => chroma.valid(val);\n\n/**\n * Extract color value from CSS AST node\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, isHexCode, isHardCodedColor, 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 }", "// 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\nexport type ParsedUnitValue = {\n unit: 'px' | 'rem' | '%' | null;\n number: number;\n} | null;\n\nexport function parseUnitValue(value: string): ParsedUnitValue {\n if (!value) return null;\n \n // Simple regex to parse number and unit\n const match = value.match(/^(-?\\d*\\.?\\d+)(px|rem|%)?$/);\n if (!match) return null;\n \n const number = parseFloat(match[1]);\n const unit = match[2] ? (match[2] as 'px' | 'rem' | '%') : 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' | '%' | 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 unitless values (font-weight, etc.), no alternate unit conversion\n return null;\n}", "import { parse, walk } from '@eslint/css-tree';\nimport type { HandlerContext } from '../types';\nimport type { ParsedUnitValue } 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}\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 // Sort replacements by position for proper reconstruction\n const sortedReplacements = replacements.sort((a, b) => a.start - b.start);\n \n // Check if we can apply auto-fix (at least one value has a hook)\n const hasAnyHooks = sortedReplacements.some(r => r.hasHook);\n const canAutoFix = hasAnyHooks;\n\n // Report each individual value\n sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook }) => {\n const originalValue = valueText.substring(start, end);\n const valueStartColumn = declarationNode.value.loc.start.column;\n const valueColumn = valueStartColumn + start;\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: valueColumn\n },\n end: {\n ...locEnd,\n column: valueColumn + originalValue.length\n }\n }\n };\n\n if (hasHook) {\n // Create auto-fix for the entire shorthand value\n const fix = canAutoFix ? (fixer: any) => {\n // Reconstruct the entire value with all replacements\n let newValue = valueText;\n \n // Apply replacements from right to left to maintain string positions\n for (let i = sortedReplacements.length - 1; i >= 0; i--) {\n const { start: rStart, end: rEnd, replacement: rReplacement } = sortedReplacements[i];\n newValue = newValue.substring(0, rStart) + rReplacement + newValue.substring(rEnd);\n }\n \n return fixer.replaceText(declarationNode.value, newValue);\n } : 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 (unit !== 'px' && unit !== 'rem' && unit !== '%') return null; // Support px, rem, and % units\n \n return {\n number: numValue,\n unit: unit as 'px' | 'rem' | '%'\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 (unit !== 'px' && unit !== 'rem' && unit !== '%') return null;\n \n return {\n number: numValue,\n unit: unit as 'px' | 'rem' | '%'\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"],
5
+ "mappings": "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",
6
+ "names": ["import_css_tree", "chroma", "import_css_tree"]
7
+ }