@salesforce-ux/eslint-plugin-slds 0.5.2 → 1.0.0-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 (117) hide show
  1. package/build/index.js +2365 -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 +369 -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 +334 -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 +355 -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 +355 -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 +399 -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 +830 -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 +1132 -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 +1132 -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 +963 -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 +339 -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 +11 -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 +7 -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 +26 -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/rule-utils.d.ts +8 -0
  83. package/build/src/utils/styling-hook-utils.d.ts +7 -0
  84. package/build/src/utils/value-utils.d.ts +41 -0
  85. package/build/types/index.js +18 -0
  86. package/build/types/index.js.map +7 -0
  87. package/build/types/yaml.d.js +1 -0
  88. package/build/types/yaml.d.js.map +7 -0
  89. package/build/utils/boxShadowValueParser.js +200 -0
  90. package/build/utils/boxShadowValueParser.js.map +7 -0
  91. package/build/utils/color-lib-utils.js +160 -0
  92. package/build/utils/color-lib-utils.js.map +7 -0
  93. package/build/utils/css-functions.js +68 -0
  94. package/build/utils/css-functions.js.map +7 -0
  95. package/build/utils/css-utils.js +141 -0
  96. package/build/utils/css-utils.js.map +7 -0
  97. package/build/utils/hardcoded-shared-utils.js +303 -0
  98. package/build/utils/hardcoded-shared-utils.js.map +7 -0
  99. package/build/utils/node.js +158 -0
  100. package/build/{rules/utils → utils}/node.js.map +2 -2
  101. package/build/utils/property-matcher.js +159 -0
  102. package/build/utils/property-matcher.js.map +7 -0
  103. package/build/utils/rule-utils.js +46 -0
  104. package/build/utils/rule-utils.js.map +7 -0
  105. package/build/utils/styling-hook-utils.js +83 -0
  106. package/build/utils/styling-hook-utils.js.map +7 -0
  107. package/build/utils/value-utils.js +70 -0
  108. package/build/utils/value-utils.js.map +7 -0
  109. package/package.json +9 -4
  110. package/src/config/rule-messages.yml +143 -0
  111. package/build/rules/enforce-bem-usage.d.ts +0 -28
  112. package/build/rules/utils/node.js +0 -197
  113. package/build/rules/utils/rule.d.ts +0 -7
  114. package/build/rules/utils/rule.js +0 -10
  115. package/build/rules/utils/rule.js.map +0 -7
  116. /package/build/{index.d.ts → src/index.d.ts} +0 -0
  117. /package/build/{rules → src}/utils/node.d.ts +0 -0
package/build/index.js CHANGED
@@ -1,58 +1,2373 @@
1
- "use strict";
2
- // Unified ESLint plugin config for both v8 (legacy) and v9+ (flat)
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const enforce_bem_usage_1 = __importDefault(require("./rules/enforce-bem-usage"));
8
- const no_deprecated_classes_slds2_1 = __importDefault(require("./rules/no-deprecated-classes-slds2"));
9
- const modal_close_button_issue_1 = __importDefault(require("./rules/modal-close-button-issue"));
10
- const parser_1 = __importDefault(require("@html-eslint/parser"));
11
- const plugin = {
12
- meta: {
13
- name: "@salesforce-ux/eslint-plugin-slds",
14
- version: process.env.PLUGIN_VERSION
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 __esm = (fn, res) => function __init() {
8
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
9
+ };
10
+ var __commonJS = (cb, mod) => function __require() {
11
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+
30
+ // src/utils/node.ts
31
+ function findAttr(node, key) {
32
+ return node.attributes.find(
33
+ (attr) => attr.key && attr.key.value.toLowerCase() === key.toLowerCase()
34
+ );
35
+ }
36
+ function isAttributesEmpty(node) {
37
+ return !node.attributes || node.attributes.length <= 0;
38
+ }
39
+ var import_parser, lineBreakPattern, lineEndingPattern;
40
+ var init_node = __esm({
41
+ "src/utils/node.ts"() {
42
+ import_parser = require("@html-eslint/parser");
43
+ lineBreakPattern = /\r\n|[\r\n\u2028\u2029]/u;
44
+ lineEndingPattern = new RegExp(lineBreakPattern.source, "gu");
45
+ }
46
+ });
47
+
48
+ // yaml-file:/Users/ritesh.kumar2/Documents/projects/stylelint-sds/packages/eslint-plugin-slds/src/config/rule-messages.yml
49
+ var require_rule_messages = __commonJS({
50
+ "yaml-file:/Users/ritesh.kumar2/Documents/projects/stylelint-sds/packages/eslint-plugin-slds/src/config/rule-messages.yml"(exports2, module2) {
51
+ module2.exports = {
52
+ "no-slds-class-overrides": {
53
+ "description": "Create new custom CSS classes instead of overriding SLDS selectors",
54
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-slds-class-overrides",
55
+ "type": "problem",
56
+ "messages": {
57
+ "sldsClassOverride": "Overriding .{{className}} isn't supported. To differentiate SLDS and custom classes, create a CSS class in your namespace. Examples: myapp-input, myapp-button."
58
+ }
59
+ },
60
+ "no-deprecated-slds-classes": {
61
+ "description": "Please replace the deprecated classes with a modern equivalent",
62
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-deprecated-slds-classes",
63
+ "type": "problem",
64
+ "messages": {
65
+ "deprecatedClass": "The class {{className}} is deprecated and not available in SLDS2. Please update to a supported class."
66
+ }
67
+ },
68
+ "no-deprecated-tokens-slds1": {
69
+ "description": "Update outdated design tokens to SLDS 2 styling hooks with similar values. For more information, see Styling Hooks on lightningdesignsystem.com.",
70
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-deprecated-tokens-slds1",
71
+ "type": "problem",
72
+ "messages": {
73
+ "deprecatedToken": "Consider removing {{oldValue}} or replacing it with {{newValue}}. Set the fallback to {{oldValue}}. For more info, see Styling Hooks on lightningdesignsystem.com.",
74
+ "noReplacement": "Update outdated design tokens to SLDS 2 styling hooks with similar values. For more information, see Styling Hooks on lightningdesignsystem.com."
75
+ }
76
+ },
77
+ "enforce-sds-to-slds-hooks": {
78
+ "description": "Convert your existing --sds styling hooks to --slds styling hooks. See lightningdesignsystem.com for more info.",
79
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#enforce-sds-to-slds-hooks",
80
+ "type": "problem",
81
+ "messages": {
82
+ "replaceSdsWithSlds": "Replace {{oldValue}} with {{suggestedMatch}} styling hook."
83
+ }
84
+ },
85
+ "enforce-bem-usage": {
86
+ "description": "Replace BEM double-dash syntax in class names with single underscore syntax",
87
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#enforce-bem-usage",
88
+ "type": "problem",
89
+ "messages": {
90
+ "bemDoubleDash": "{{actual}} has been retired. Update it to the new name {{newValue}}.",
91
+ "fixBemNaming": "Update to correct BEM naming convention"
92
+ }
93
+ },
94
+ "modal-close-button-issue": {
95
+ "description": "Update component attributes or CSS classes for the modal close button to comply with the modal component blueprint",
96
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#modal-close-button-issue",
97
+ "type": "problem",
98
+ "messages": {
99
+ "modalCloseButtonIssue": "Update component attributes or CSS classes for the modal close button to comply with the modal component blueprint.",
100
+ "removeClass": "Remove the slds-button_icon-inverse class from the modal close button in components that use the SLDS modal blueprint.",
101
+ "changeVariant": "Change the variant attribute value from bare-inverse to bare in <lightning-button-icon> or <lightning-icon>.",
102
+ "removeVariant": "Remove the variant attribute from the <lightning-icon> component inside the <button> element.",
103
+ "ensureButtonClasses": "Add or move slds-button and slds-button_icon to the class attribute of the <button> element or <lightning-button-icon> component.",
104
+ "ensureSizeAttribute": "To size icons properly, set the size attribute \u200Cto large in the <lightning-icon> and <lightning-button-icon> components."
105
+ }
106
+ },
107
+ "no-deprecated-classes-slds2": {
108
+ "description": "Replace classes that aren't available with SLDS 2 classes",
109
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-deprecated-classes-slds2",
110
+ "type": "problem",
111
+ "messages": {
112
+ "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.",
113
+ "updateToModernClass": "Replace deprecated class with modern equivalent",
114
+ "checkDocumentation": "See lightningdesignsystem.com for SLDS 2 class alternatives"
115
+ }
116
+ },
117
+ "lwc-token-to-slds-hook": {
118
+ "description": "Replace the deprecated --lwc tokens with the latest --slds tokens. See lightningdesignsystem.com for more info.",
119
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#lwc-token-to-slds-hook",
120
+ "type": "problem",
121
+ "messages": {
122
+ "errorWithReplacement": "The '{{oldValue}}' design token is deprecated. Replace it with '{{newValue}}'. For more info, see Global Styling Hooks on lightningdesignsystem.com.",
123
+ "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.",
124
+ "errorWithNoRecommendation": "The '{{oldValue}}' design token is deprecated. For more info, see the New Global Styling Hook Guidance on lightningdesignsystem.com."
125
+ }
126
+ },
127
+ "no-sldshook-fallback-for-lwctoken": {
128
+ "description": "Avoid using --slds styling hooks as fallback values for --lwc tokens.",
129
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-sldshook-fallback-for-lwctoken",
130
+ "type": "problem",
131
+ "messages": {
132
+ "unsupportedFallback": "Remove the {{sldsToken}} styling hook that is used as a fallback value for {{lwcToken}}."
133
+ }
134
+ },
135
+ "no-unsupported-hooks-slds2": {
136
+ "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.",
137
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-unsupported-hooks-slds2",
138
+ "type": "problem",
139
+ "messages": {
140
+ "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."
141
+ }
142
+ },
143
+ "no-slds-var-without-fallback": {
144
+ "description": "Add fallback values to SLDS styling hooks. The fallback values are used in Salesforce environments where styling hooks are unavailable.",
145
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-slds-var-without-fallback",
146
+ "type": "problem",
147
+ "messages": {
148
+ "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."
149
+ }
150
+ },
151
+ "no-slds-namespace-for-custom-hooks": {
152
+ "description": "To differentiate custom styling hooks from SLDS styling hooks, create custom styling hooks in your namespace.",
153
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-slds-namespace-for-custom-hooks",
154
+ "type": "problem",
155
+ "messages": {
156
+ "customHookNamespace": "Using the --slds namespace for {{token}} isn't supported. Create the custom styling hook in your namespace. Example: --myapp-{{tokenWithoutNamespace}}"
157
+ }
158
+ },
159
+ "no-slds-private-var": {
160
+ "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.",
161
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-slds-private-var",
162
+ "type": "problem",
163
+ "messages": {
164
+ "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."
165
+ }
166
+ },
167
+ "enforce-component-hook-naming-convention": {
168
+ "description": "Replace component styling hooks that use a deprecated naming convention.",
169
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#enforce-component-hook-naming-convention",
170
+ "type": "problem",
171
+ "messages": {
172
+ "replace": "Replace the deprecated {{oldValue}} component styling hook with {{suggestedMatch}}."
173
+ }
174
+ },
175
+ "no-hardcoded-values-slds1": {
176
+ "description": "Replace static values with SLDS 1 design tokens. For more information, look up design tokens on lightningdesignsystem.com.",
177
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-hardcoded-value",
178
+ "type": "suggestion",
179
+ "messages": {
180
+ "hardcodedValue": "Replace the {{oldValue}} static value with an SLDS 1 styling hook: {{newValue}}.",
181
+ "noReplacement": "There's no replacement styling hook for the {{oldValue}} static value. Remove the static value."
182
+ }
183
+ },
184
+ "no-hardcoded-values-slds2": {
185
+ "description": "Replace static values with SLDS 2 styling hooks. For more information, look up design tokens on lightningdesignsystem.com.",
186
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-hardcoded-value",
187
+ "type": "suggestion",
188
+ "messages": {
189
+ "hardcodedValue": "Consider replacing the {{oldValue}} static value with an SLDS 2 styling hook that has a similar value: {{newValue}}.",
190
+ "noReplacement": "There's no replacement styling hook for the {{oldValue}} static value. Remove the static value."
191
+ }
192
+ },
193
+ "reduce-annotations": {
194
+ "description": "Remove your annotations and update your code.",
195
+ "url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#reduce-annotations",
196
+ "type": "problem",
197
+ "messages": {
198
+ "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/"
199
+ }
200
+ }
201
+ };
202
+ }
203
+ });
204
+
205
+ // src/rules/v9/enforce-bem-usage.ts
206
+ var import_sds_metadata, import_rule_messages, type, description, url, messages, bemMapping, enforce_bem_usage_default;
207
+ var init_enforce_bem_usage = __esm({
208
+ "src/rules/v9/enforce-bem-usage.ts"() {
209
+ import_sds_metadata = __toESM(require("@salesforce-ux/sds-metadata"));
210
+ import_rule_messages = __toESM(require_rule_messages());
211
+ ({ type, description, url, messages } = import_rule_messages.default["enforce-bem-usage"]);
212
+ bemMapping = import_sds_metadata.default.bemNaming;
213
+ enforce_bem_usage_default = {
214
+ meta: {
215
+ type,
216
+ docs: {
217
+ description,
218
+ recommended: true,
219
+ url
220
+ },
221
+ fixable: "code",
222
+ messages
223
+ },
224
+ create(context) {
225
+ return {
226
+ // Check all class selectors for BEM usage
227
+ "SelectorList Selector ClassSelector"(node) {
228
+ const cssClassSelector = context.sourceCode.getText(node);
229
+ const className = cssClassSelector.substring(1);
230
+ if (className && className in bemMapping) {
231
+ const newValue = bemMapping[className];
232
+ if (typeof newValue === "string") {
233
+ context.report({
234
+ node,
235
+ messageId: "bemDoubleDash",
236
+ data: {
237
+ actual: className,
238
+ newValue
239
+ },
240
+ fix(fixer) {
241
+ return fixer.replaceText(node, `.${newValue}`);
242
+ }
243
+ });
244
+ }
245
+ }
246
+ }
247
+ };
248
+ }
249
+ };
250
+ }
251
+ });
252
+
253
+ // src/rules/enforce-bem-usage.ts
254
+ var require_enforce_bem_usage = __commonJS({
255
+ "src/rules/enforce-bem-usage.ts"(exports2, module2) {
256
+ init_node();
257
+ var import_sds_metadata14 = __toESM(require("@salesforce-ux/sds-metadata"));
258
+ var import_rule_messages16 = __toESM(require_rule_messages());
259
+ init_enforce_bem_usage();
260
+ var bemMapping2 = import_sds_metadata14.default.bemNaming;
261
+ var deprecatedClasses2 = import_sds_metadata14.default.deprecatedClasses;
262
+ var ruleConfig14 = import_rule_messages16.default["enforce-bem-usage"];
263
+ var { type: type15, description: description15, url: url15, messages: messages15 } = ruleConfig14;
264
+ var isDeprecatedClass = (className) => {
265
+ return deprecatedClasses2.includes(className) || deprecatedClasses2.includes(bemMapping2[className]);
266
+ };
267
+ var enforceBemUsageHtml = {
268
+ create(context) {
269
+ function check(node) {
270
+ if (isAttributesEmpty(node)) {
271
+ return;
272
+ }
273
+ const classAttr = findAttr(node, "class");
274
+ if (classAttr && classAttr.value) {
275
+ const classNames = classAttr.value.value.split(/\s+/);
276
+ classNames.forEach((className) => {
277
+ if (className && className in bemMapping2 && !isDeprecatedClass(className)) {
278
+ const classNameStart = classAttr.value.value.indexOf(className) + 7;
279
+ const classNameEnd = classNameStart + className.length;
280
+ const startLoc = {
281
+ line: classAttr.loc.start.line,
282
+ column: classAttr.loc.start.column + classNameStart
283
+ };
284
+ const endLoc = {
285
+ line: classAttr.loc.start.line,
286
+ column: classAttr.loc.start.column + classNameEnd
287
+ };
288
+ const newValue = bemMapping2[className];
289
+ context.report({
290
+ node,
291
+ loc: { start: startLoc, end: endLoc },
292
+ messageId: "bemDoubleDash",
293
+ data: {
294
+ actual: className,
295
+ newValue
296
+ },
297
+ fix(fixer) {
298
+ if (newValue) {
299
+ const newClassValue = classAttr.value.value.replace(
300
+ className,
301
+ newValue
302
+ );
303
+ return fixer.replaceTextRange(
304
+ [classAttr.value.range[0], classAttr.value.range[1]],
305
+ `${newClassValue}`
306
+ );
307
+ }
308
+ return null;
309
+ }
310
+ });
311
+ }
312
+ });
313
+ }
314
+ }
315
+ return {
316
+ Tag: check
317
+ };
318
+ }
319
+ };
320
+ var enforceBemUsage2 = {
321
+ meta: {
322
+ type: type15,
323
+ docs: {
324
+ recommended: true,
325
+ description: description15,
326
+ url: url15
327
+ },
328
+ fixable: "code",
329
+ messages: messages15
330
+ },
331
+ create(context) {
332
+ const filename = context.filename || context.getFilename();
333
+ if (filename.endsWith(".css") || filename.endsWith(".scss")) {
334
+ try {
335
+ return enforce_bem_usage_default.create(context);
336
+ } catch (error) {
337
+ return {};
338
+ }
339
+ } else {
340
+ return enforceBemUsageHtml.create(context);
341
+ }
342
+ }
343
+ };
344
+ module2.exports = enforceBemUsage2;
345
+ }
346
+ });
347
+
348
+ // src/rules/no-deprecated-classes-slds2.ts
349
+ var require_no_deprecated_classes_slds2 = __commonJS({
350
+ "src/rules/no-deprecated-classes-slds2.ts"(exports2, module2) {
351
+ init_node();
352
+ var import_sds_metadata14 = __toESM(require("@salesforce-ux/sds-metadata"));
353
+ var import_rule_messages16 = __toESM(require_rule_messages());
354
+ var deprecatedClasses2 = import_sds_metadata14.default.deprecatedClasses;
355
+ var ruleConfig14 = import_rule_messages16.default["no-deprecated-classes-slds2"];
356
+ module2.exports = {
357
+ meta: {
358
+ type: ruleConfig14.type,
359
+ docs: {
360
+ category: "Best Practices",
361
+ recommended: true,
362
+ description: ruleConfig14.description,
363
+ url: ruleConfig14.url
364
+ },
365
+ schema: [],
366
+ messages: ruleConfig14.messages
367
+ },
368
+ create(context) {
369
+ function check(node) {
370
+ if (isAttributesEmpty(node)) {
371
+ return;
372
+ }
373
+ const classAttr = findAttr(node, "class");
374
+ if (classAttr && classAttr.value) {
375
+ const classNames = classAttr.value.value.split(/\s+/);
376
+ classNames.forEach((className) => {
377
+ if (className && deprecatedClasses2.includes(className)) {
378
+ const classNameStart = classAttr.value.value.indexOf(className) + 7;
379
+ const classNameEnd = classNameStart + className.length;
380
+ const startLoc = {
381
+ line: classAttr.loc.start.line,
382
+ column: classAttr.loc.start.column + classNameStart
383
+ };
384
+ const endLoc = {
385
+ line: classAttr.loc.start.line,
386
+ column: classAttr.loc.start.column + classNameEnd
387
+ };
388
+ context.report({
389
+ node,
390
+ loc: { start: startLoc, end: endLoc },
391
+ messageId: "deprecatedClass",
392
+ data: {
393
+ className
394
+ }
395
+ });
396
+ }
397
+ });
398
+ }
399
+ }
400
+ return {
401
+ Tag: check
402
+ };
403
+ }
404
+ };
405
+ }
406
+ });
407
+
408
+ // src/rules/modal-close-button-issue.ts
409
+ var require_modal_close_button_issue = __commonJS({
410
+ "src/rules/modal-close-button-issue.ts"(exports2, module2) {
411
+ init_node();
412
+ var import_rule_messages16 = __toESM(require_rule_messages());
413
+ var ruleConfig14 = import_rule_messages16.default["modal-close-button-issue"];
414
+ module2.exports = {
415
+ meta: {
416
+ type: ruleConfig14.type,
417
+ docs: {
418
+ category: "Best Practices",
419
+ recommended: true,
420
+ description: ruleConfig14.description,
421
+ url: ruleConfig14.url
422
+ },
423
+ fixable: "code",
424
+ schema: [],
425
+ messages: ruleConfig14.messages
426
+ },
427
+ create(context) {
428
+ function check(node) {
429
+ if (isAttributesEmpty(node)) {
430
+ return;
431
+ }
432
+ const tagName = node.name;
433
+ if (tagName === "button") {
434
+ const classAttr = findAttr(node, "class");
435
+ if (classAttr && classAttr.value) {
436
+ const classList = classAttr.value.value.split(/\s+/);
437
+ if (!classList.includes("slds-modal__close")) {
438
+ return;
439
+ }
440
+ if (classList.includes("slds-button_icon-inverse") || classList.includes("slds-button--icon-inverse")) {
441
+ const newClassList = classList.filter((cls) => cls !== "slds-button_icon-inverse" && cls !== "slds-button--icon-inverse").join(" ");
442
+ context.report({
443
+ node,
444
+ loc: classAttr.loc,
445
+ messageId: "removeClass",
446
+ fix(fixer) {
447
+ return fixer.replaceText(
448
+ classAttr,
449
+ // Replace the full attribute
450
+ `class="${newClassList}"`
451
+ // Updated class list
452
+ );
453
+ }
454
+ });
455
+ }
456
+ }
457
+ }
458
+ if (tagName === "lightning-button-icon" || tagName === "lightning:buttonIcon") {
459
+ let validateClassAttr = function(attribute, attrName) {
460
+ if (attribute && attribute.value) {
461
+ const classList = attribute.value.value.split(/\s+/);
462
+ if (!classAttr?.value?.value?.includes("slds-modal__close")) {
463
+ return;
464
+ }
465
+ if (classList.includes("slds-button_icon-inverse") || classList.includes("slds-button--icon-inverse")) {
466
+ const newClassList = classList.filter((cls) => cls !== "slds-button_icon-inverse" && cls !== "slds-button--icon-inverse").join(" ");
467
+ context.report({
468
+ node,
469
+ loc: attribute.loc,
470
+ messageId: "removeClass",
471
+ fix(fixer) {
472
+ return fixer.replaceText(
473
+ attribute,
474
+ // Replace the full attribute
475
+ `${attrName}="${newClassList}"`
476
+ // Correctly modifies the respective attribute
477
+ );
478
+ }
479
+ });
480
+ }
481
+ if (!classList.includes("slds-button") || !classList.includes("slds-button_icon")) {
482
+ let newClassList;
483
+ if (attrName === "icon-class") {
484
+ newClassList = [
485
+ ...classList.filter((cls) => cls !== "slds-button_icon-inverse")
486
+ ].join(" ");
487
+ } else {
488
+ newClassList = [
489
+ "slds-button",
490
+ "slds-button_icon",
491
+ ...classList.filter((cls) => cls !== "slds-button_icon-inverse")
492
+ ].join(" ");
493
+ }
494
+ context.report({
495
+ node: attribute,
496
+ loc: attribute.value.loc,
497
+ messageId: "ensureButtonClasses",
498
+ fix(fixer) {
499
+ return fixer.replaceText(attribute.value, `${newClassList}`);
500
+ }
501
+ });
502
+ }
503
+ if (variantAttr && variantAttr.value && variantAttr.value.value === "bare-inverse") {
504
+ context.report({
505
+ node: variantAttr,
506
+ messageId: "changeVariant",
507
+ loc: variantAttr.value.loc,
508
+ fix(fixer) {
509
+ return fixer.replaceText(variantAttr.value, `bare`);
510
+ }
511
+ });
512
+ }
513
+ }
514
+ };
515
+ const variantAttr = findAttr(node, "variant");
516
+ const sizeAttr = findAttr(node, "size");
517
+ const classAttr = findAttr(node, "class");
518
+ const iconClassAttr = findAttr(node, "icon-class");
519
+ validateClassAttr(classAttr, "class");
520
+ validateClassAttr(iconClassAttr, "icon-class");
521
+ }
522
+ if ((tagName === "lightning-icon" || tagName === "lightning:icon") && node.parent?.name === "button") {
523
+ const parentClassAttr = findAttr(node.parent, "class");
524
+ if (parentClassAttr && parentClassAttr.value) {
525
+ const parentClassList = parentClassAttr.value.value.split(/\s+/);
526
+ if (!parentClassList.includes("slds-modal__close")) {
527
+ return;
528
+ }
529
+ const variantAttr = findAttr(node, "variant");
530
+ const sizeAttr = findAttr(node, "size");
531
+ if (variantAttr && variantAttr.value && variantAttr.value.value === "bare-inverse") {
532
+ context.report({
533
+ node: variantAttr,
534
+ messageId: "changeVariant",
535
+ loc: variantAttr.value.loc,
536
+ fix(fixer) {
537
+ return fixer.replaceText(variantAttr.value, `bare`);
538
+ }
539
+ });
540
+ }
541
+ }
542
+ }
543
+ }
544
+ return {
545
+ Tag: check
546
+ };
547
+ }
548
+ };
549
+ }
550
+ });
551
+
552
+ // src/index.ts
553
+ var import_enforce_bem_usage = __toESM(require_enforce_bem_usage());
554
+ var import_no_deprecated_classes_slds2 = __toESM(require_no_deprecated_classes_slds2());
555
+ var import_modal_close_button_issue = __toESM(require_modal_close_button_issue());
556
+
557
+ // src/rules/v9/no-slds-class-overrides.ts
558
+ var import_sds_metadata2 = __toESM(require("@salesforce-ux/sds-metadata"));
559
+ var import_rule_messages2 = __toESM(require_rule_messages());
560
+ var ruleConfig = import_rule_messages2.default["no-slds-class-overrides"];
561
+ var sldsClasses = import_sds_metadata2.default.sldsPlusClasses;
562
+ var sldsClassesSet = new Set(sldsClasses);
563
+ var no_slds_class_overrides_default = {
564
+ meta: {
565
+ type: ruleConfig.type,
566
+ docs: {
567
+ description: ruleConfig.description,
568
+ recommended: true,
569
+ //useful for plugin recommended configs
570
+ url: ruleConfig.url
571
+ },
572
+ fixable: null,
573
+ hasSuggestions: false,
574
+ schema: [],
575
+ messages: ruleConfig.messages
576
+ },
577
+ create(context) {
578
+ return {
579
+ // For no-slds-class-overrides: Only flags classes at selector end
580
+ "SelectorList Selector"(node) {
581
+ const classSelectorNode = node.children.filter((child) => child.type === "ClassSelector").at(-1);
582
+ if (classSelectorNode) {
583
+ const className = classSelectorNode.name;
584
+ if (className && className.startsWith("slds-") && sldsClassesSet.has(className)) {
585
+ context.report({
586
+ node: classSelectorNode,
587
+ messageId: "sldsClassOverride",
588
+ data: { className }
589
+ });
590
+ }
591
+ }
592
+ }
593
+ };
594
+ }
595
+ };
596
+
597
+ // src/rules/v9/no-deprecated-slds-classes.ts
598
+ var import_sds_metadata3 = __toESM(require("@salesforce-ux/sds-metadata"));
599
+ var import_rule_messages3 = __toESM(require_rule_messages());
600
+ var { type: type2, description: description2, url: url2, messages: messages2 } = import_rule_messages3.default["no-deprecated-slds-classes"];
601
+ var deprecatedClasses = import_sds_metadata3.default.deprecatedClasses;
602
+ var deprecatedClassesSet = new Set(deprecatedClasses);
603
+ var no_deprecated_slds_classes_default = {
604
+ meta: {
605
+ type: type2,
606
+ docs: {
607
+ description: description2,
608
+ recommended: true,
609
+ url: url2
15
610
  },
16
- configs: {},
17
- rules: {
18
- "enforce-bem-usage": enforce_bem_usage_1.default,
19
- "no-deprecated-classes-slds2": no_deprecated_classes_slds2_1.default,
20
- "modal-close-button-issue": modal_close_button_issue_1.default
611
+ messages: messages2
612
+ },
613
+ create(context) {
614
+ return {
615
+ // For no-deprecated-slds-classes: Check all class selectors for deprecated classes
616
+ "SelectorList Selector ClassSelector"(node) {
617
+ const cssClassSelector = context.sourceCode.getText(node);
618
+ const className = cssClassSelector.substring(1);
619
+ if (className && deprecatedClassesSet.has(className)) {
620
+ context.report({
621
+ node,
622
+ messageId: "deprecatedClass",
623
+ data: { className }
624
+ });
625
+ }
626
+ }
627
+ };
628
+ }
629
+ };
630
+
631
+ // src/rules/v9/no-deprecated-tokens-slds1.ts
632
+ var import_sds_metadata4 = __toESM(require("@salesforce-ux/sds-metadata"));
633
+ var import_rule_messages4 = __toESM(require_rule_messages());
634
+ var ruleConfig2 = import_rule_messages4.default["no-deprecated-tokens-slds1"];
635
+ var { type: type3, description: description3, url: url3, messages: messages3 } = ruleConfig2;
636
+ var tokenMapping = import_sds_metadata4.default.auraToLwcTokensMapping;
637
+ var no_deprecated_tokens_slds1_default = {
638
+ meta: {
639
+ type: type3,
640
+ docs: {
641
+ description: description3,
642
+ recommended: true,
643
+ url: url3
644
+ },
645
+ fixable: "code",
646
+ messages: messages3
647
+ },
648
+ create(context) {
649
+ function shouldIgnoreDetection6(token) {
650
+ return !(token in tokenMapping) || !tokenMapping[token].startsWith("--lwc-");
651
+ }
652
+ function generateReplacement(tokenName, originalFunctionCall) {
653
+ if (shouldIgnoreDetection6(tokenName)) {
654
+ return null;
655
+ }
656
+ const recommendation = tokenMapping[tokenName];
657
+ return `var(${recommendation}, ${originalFunctionCall})`;
21
658
  }
659
+ function handleTokenFunction(node, functionName) {
660
+ const tokenName = context.sourceCode.getText(node);
661
+ if (shouldIgnoreDetection6(tokenName)) {
662
+ return;
663
+ }
664
+ const originalFunctionCall = `${functionName}(${tokenName})`;
665
+ const replacement = generateReplacement(tokenName, originalFunctionCall);
666
+ if (replacement) {
667
+ context.report({
668
+ node,
669
+ messageId: "deprecatedToken",
670
+ data: {
671
+ oldValue: originalFunctionCall,
672
+ newValue: replacement
673
+ },
674
+ fix(fixer) {
675
+ const sourceCode = context.sourceCode.getText();
676
+ const tokenFunctionCall = `${functionName}(${tokenName})`;
677
+ const nodeOffset = node.loc.start.offset;
678
+ const searchStart = Math.max(0, nodeOffset - functionName.length - 1);
679
+ const searchEnd = nodeOffset + tokenName.length + 1;
680
+ const searchArea = sourceCode.substring(searchStart, searchEnd);
681
+ const functionCallIndex = searchArea.indexOf(tokenFunctionCall);
682
+ if (functionCallIndex !== -1) {
683
+ const actualStart = searchStart + functionCallIndex;
684
+ const actualEnd = actualStart + tokenFunctionCall.length;
685
+ return fixer.replaceTextRange([actualStart, actualEnd], replacement);
686
+ }
687
+ return null;
688
+ }
689
+ });
690
+ } else {
691
+ context.report({
692
+ node,
693
+ messageId: "noReplacement"
694
+ });
695
+ }
696
+ }
697
+ return {
698
+ "Function[name='token'] Identifier"(node) {
699
+ handleTokenFunction(node, "token");
700
+ },
701
+ "Function[name='t'] Identifier"(node) {
702
+ handleTokenFunction(node, "t");
703
+ }
704
+ };
705
+ }
22
706
  };
23
- Object.assign(plugin.configs, {
24
- // flat config format for ESLint v9+
25
- "flat/recommended": [
26
- {
27
- plugins: {
28
- "@salesforce-ux/slds": plugin,
29
- },
30
- rules: {
31
- "@salesforce-ux/slds/enforce-bem-usage": "error",
32
- "@salesforce-ux/slds/no-deprecated-classes-slds2": "error",
33
- "@salesforce-ux/slds/modal-close-button-issue": "error"
34
- },
35
- languageOptions: {
36
- parser: parser_1.default,
37
- ecmaVersion: 2021,
38
- sourceType: "module"
39
- },
40
- files: ["**/*.html", "**/*.cmp"]
41
- }
42
- ],
43
- // legacy config for ESLint v8-
44
- recommended: {
45
- plugins: ["@salesforce-ux/slds"],
46
- rules: {
47
- "@salesforce-ux/slds/enforce-bem-usage": "error",
48
- "@salesforce-ux/slds/no-deprecated-classes-slds2": "error",
49
- "@salesforce-ux/slds/modal-close-button-issue": "error"
707
+
708
+ // src/rules/v9/lwc-token-to-slds-hook.ts
709
+ var import_sds_metadata5 = __toESM(require("@salesforce-ux/sds-metadata"));
710
+ var import_rule_messages5 = __toESM(require_rule_messages());
711
+
712
+ // src/utils/hardcoded-shared-utils.ts
713
+ var import_css_tree2 = require("@eslint/css-tree");
714
+
715
+ // src/utils/value-utils.ts
716
+ var ALLOWED_UNITS = ["px", "em", "rem", "%", "ch"];
717
+ function parseUnitValue(value) {
718
+ if (!value) return null;
719
+ const unitsPattern = ALLOWED_UNITS.join("|");
720
+ const regex = new RegExp(`^(-?\\d*\\.?\\d+)(${unitsPattern})?$`);
721
+ const match = value.match(regex);
722
+ if (!match) return null;
723
+ const number = parseFloat(match[1]);
724
+ const unit = match[2] ? match[2] : null;
725
+ if (isNaN(number)) return null;
726
+ return { number, unit };
727
+ }
728
+ function toAlternateUnitValue(numberVal, unitType) {
729
+ if (unitType === "px") {
730
+ let floatValue = parseFloat(`${numberVal / 16}`);
731
+ if (!isNaN(floatValue)) {
732
+ return {
733
+ unit: "rem",
734
+ number: parseFloat(floatValue.toFixed(4))
735
+ };
736
+ }
737
+ } else if (unitType === "rem") {
738
+ const intValue = parseInt(`${numberVal * 16}`);
739
+ if (!isNaN(intValue)) {
740
+ return {
741
+ unit: "px",
742
+ number: intValue
743
+ };
744
+ }
745
+ }
746
+ return null;
747
+ }
748
+
749
+ // src/utils/color-lib-utils.ts
750
+ var import_chroma_js = __toESM(require("chroma-js"));
751
+ var import_css_tree = require("@eslint/css-tree");
752
+
753
+ // src/utils/css-functions.ts
754
+ var CSS_FUNCTIONS = [
755
+ "attr",
756
+ "calc",
757
+ "color-mix",
758
+ "conic-gradient",
759
+ "counter",
760
+ "cubic-bezier",
761
+ "linear-gradient",
762
+ "max",
763
+ "min",
764
+ "radial-gradient",
765
+ "repeating-conic-gradient",
766
+ "repeating-linear-gradient",
767
+ "repeating-radial-gradient",
768
+ "var"
769
+ ];
770
+ var CSS_MATH_FUNCTIONS = ["calc", "min", "max"];
771
+ var RGB_COLOR_FUNCTIONS = ["rgb", "rgba", "hsl", "hsla"];
772
+ var cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join("|")})`);
773
+ var cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join("|")})$`);
774
+ var cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join("|")})$`);
775
+ function isCssFunction(value) {
776
+ return cssFunctionsExactRegex.test(value);
777
+ }
778
+ function isCssColorFunction(value) {
779
+ return RGB_COLOR_FUNCTIONS.includes(value);
780
+ }
781
+
782
+ // src/utils/color-lib-utils.ts
783
+ var LAB_THRESHOLD = 25;
784
+ var isHexCode = (color) => {
785
+ const hexPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/;
786
+ return hexPattern.test(color);
787
+ };
788
+ var convertToHex = (color) => {
789
+ try {
790
+ return (0, import_chroma_js.default)(color).hex();
791
+ } catch (e) {
792
+ return null;
793
+ }
794
+ };
795
+ var findClosestColorHook = (color, supportedColors, cssProperty) => {
796
+ const returnStylingHooks = [];
797
+ const closestHooksWithSameProperty = [];
798
+ const closestHooksWithoutSameProperty = [];
799
+ const closestHooksWithAllProperty = [];
800
+ const labColor = (0, import_chroma_js.default)(color).lab();
801
+ Object.entries(supportedColors).forEach(([sldsValue, data]) => {
802
+ if (sldsValue && isHexCode(sldsValue)) {
803
+ const hooks = data;
804
+ hooks.forEach((hook) => {
805
+ const labSupportedColor = (0, import_chroma_js.default)(sldsValue).lab();
806
+ const distance = JSON.stringify(labColor) === JSON.stringify(labSupportedColor) ? 0 : import_chroma_js.default.distance(import_chroma_js.default.lab(...labColor), import_chroma_js.default.lab(...labSupportedColor), "lab");
807
+ if (hook.properties.includes(cssProperty)) {
808
+ if (distance <= LAB_THRESHOLD) {
809
+ closestHooksWithSameProperty.push({ name: hook.name, distance });
810
+ }
811
+ } else if (hook.properties.includes("*")) {
812
+ if (distance <= LAB_THRESHOLD) {
813
+ closestHooksWithAllProperty.push({ name: hook.name, distance });
814
+ }
815
+ } else {
816
+ if (distance <= LAB_THRESHOLD) {
817
+ closestHooksWithoutSameProperty.push({ name: hook.name, distance });
818
+ }
819
+ }
820
+ });
821
+ }
822
+ });
823
+ const closesthookGroups = [
824
+ { hooks: closestHooksWithSameProperty, distance: 0 },
825
+ { hooks: closestHooksWithAllProperty, distance: 0 },
826
+ { hooks: closestHooksWithSameProperty, distance: Infinity },
827
+ // For hooks with distance > 0
828
+ { hooks: closestHooksWithAllProperty, distance: Infinity },
829
+ { hooks: closestHooksWithoutSameProperty, distance: Infinity }
830
+ ];
831
+ for (const group of closesthookGroups) {
832
+ const filteredHooks = group.hooks.filter(
833
+ (h) => group.distance === 0 ? h.distance === 0 : h.distance > 0
834
+ );
835
+ if (returnStylingHooks.length < 1 && filteredHooks.length > 0) {
836
+ filteredHooks.sort((a, b) => a.distance - b.distance);
837
+ returnStylingHooks.push(...filteredHooks.slice(0, 5).map((h) => h.name));
838
+ }
839
+ }
840
+ return Array.from(new Set(returnStylingHooks));
841
+ };
842
+ var isValidColor = (val) => import_chroma_js.default.valid(val);
843
+ var extractColorValue = (node) => {
844
+ let colorValue = null;
845
+ switch (node.type) {
846
+ case "Hash":
847
+ colorValue = `#${node.value}`;
848
+ break;
849
+ case "Identifier":
850
+ colorValue = node.name;
851
+ break;
852
+ case "Function":
853
+ if (isCssColorFunction(node.name)) {
854
+ colorValue = (0, import_css_tree.generate)(node);
855
+ }
856
+ break;
857
+ }
858
+ return colorValue && isValidColor(colorValue) ? colorValue : null;
859
+ };
860
+
861
+ // src/utils/hardcoded-shared-utils.ts
862
+ var FONT_WEIGHTS = [
863
+ "normal",
864
+ "bold",
865
+ "bolder",
866
+ "lighter",
867
+ "100",
868
+ "200",
869
+ "300",
870
+ "400",
871
+ "500",
872
+ "600",
873
+ "700",
874
+ "800",
875
+ "900"
876
+ ];
877
+ function isKnownFontWeight(value) {
878
+ const stringValue = value.toString();
879
+ return FONT_WEIGHTS.includes(stringValue.toLowerCase());
880
+ }
881
+ function handleShorthandAutoFix(declarationNode, context, valueText, replacements) {
882
+ const sortedReplacements = replacements.sort((a, b) => a.start - b.start);
883
+ const hasAnyHooks = sortedReplacements.some((r) => r.hasHook);
884
+ const canAutoFix = hasAnyHooks;
885
+ sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook }) => {
886
+ const originalValue = valueText.substring(start, end);
887
+ const valueStartColumn = declarationNode.value.loc.start.column;
888
+ const valueColumn = valueStartColumn + start;
889
+ const { loc: { start: locStart, end: locEnd } } = declarationNode.value;
890
+ const reportNode = {
891
+ ...declarationNode.value,
892
+ loc: {
893
+ ...declarationNode.value.loc,
894
+ start: {
895
+ ...locStart,
896
+ column: valueColumn
897
+ },
898
+ end: {
899
+ ...locEnd,
900
+ column: valueColumn + originalValue.length
901
+ }
902
+ }
903
+ };
904
+ if (hasHook) {
905
+ const fix = canAutoFix ? (fixer) => {
906
+ let newValue = valueText;
907
+ for (let i = sortedReplacements.length - 1; i >= 0; i--) {
908
+ const { start: rStart, end: rEnd, replacement: rReplacement } = sortedReplacements[i];
909
+ newValue = newValue.substring(0, rStart) + rReplacement + newValue.substring(rEnd);
910
+ }
911
+ return fixer.replaceText(declarationNode.value, newValue);
912
+ } : void 0;
913
+ context.context.report({
914
+ node: reportNode,
915
+ messageId: "hardcodedValue",
916
+ data: {
917
+ oldValue: originalValue,
918
+ newValue: displayValue
50
919
  },
51
- parser: parser_1.default,
52
- parserOptions: {
53
- ecmaVersion: 2021,
54
- sourceType: "module"
920
+ fix
921
+ });
922
+ } else {
923
+ context.context.report({
924
+ node: reportNode,
925
+ messageId: "noReplacement",
926
+ data: {
927
+ oldValue: originalValue
928
+ }
929
+ });
930
+ }
931
+ });
932
+ }
933
+ function forEachValue(valueText, extractValue, shouldSkipNode, callback) {
934
+ if (!valueText || typeof valueText !== "string") {
935
+ return;
936
+ }
937
+ try {
938
+ const ast = (0, import_css_tree2.parse)(valueText, { context: "value", positions: true });
939
+ (0, import_css_tree2.walk)(ast, {
940
+ enter(node) {
941
+ if (shouldSkipNode(node)) {
942
+ return this.skip;
55
943
  }
944
+ const value = extractValue(node);
945
+ if (value !== null) {
946
+ const positionInfo = {
947
+ start: node.loc?.start,
948
+ end: node.loc?.end
949
+ };
950
+ callback(value, positionInfo);
951
+ }
952
+ }
953
+ });
954
+ } catch (error) {
955
+ return;
956
+ }
957
+ }
958
+ function shouldSkipColorNode(node) {
959
+ return node.type === "Function" && isCssFunction(node.name);
960
+ }
961
+ function shouldSkipDimensionNode(node) {
962
+ return node.type === "Function";
963
+ }
964
+ function extractDimensionValue(valueNode, cssProperty) {
965
+ if (!valueNode) return null;
966
+ switch (valueNode.type) {
967
+ case "Dimension":
968
+ const numValue = Number(valueNode.value);
969
+ if (numValue === 0) return null;
970
+ const unit = valueNode.unit.toLowerCase();
971
+ if (!ALLOWED_UNITS.includes(unit)) return null;
972
+ return {
973
+ number: numValue,
974
+ unit
975
+ };
976
+ case "Number":
977
+ const numberValue = Number(valueNode.value);
978
+ if (numberValue === 0) return null;
979
+ return {
980
+ number: numberValue,
981
+ unit: null
982
+ };
983
+ case "Percentage":
984
+ const percentValue = Number(valueNode.value);
985
+ if (percentValue === 0) return null;
986
+ return {
987
+ number: percentValue,
988
+ unit: "%"
989
+ };
990
+ case "Value":
991
+ return valueNode.children?.[0] ? extractDimensionValue(valueNode.children[0], cssProperty) : null;
992
+ }
993
+ return null;
994
+ }
995
+ function forEachColorValue(valueText, callback) {
996
+ forEachValue(valueText, extractColorValue, shouldSkipColorNode, callback);
997
+ }
998
+ function forEachDensityValue(valueText, cssProperty, callback) {
999
+ forEachValue(
1000
+ valueText,
1001
+ (node) => extractDimensionValue(node, cssProperty),
1002
+ shouldSkipDimensionNode,
1003
+ callback
1004
+ );
1005
+ }
1006
+ function extractFontValue(node) {
1007
+ if (!node) return null;
1008
+ switch (node.type) {
1009
+ case "Dimension":
1010
+ const numValue = Number(node.value);
1011
+ if (numValue <= 0) return null;
1012
+ const unit = node.unit.toLowerCase();
1013
+ if (!ALLOWED_UNITS.includes(unit)) return null;
1014
+ return {
1015
+ number: numValue,
1016
+ unit
1017
+ };
1018
+ case "Number":
1019
+ const numberValue = Number(node.value);
1020
+ if (numberValue <= 0) {
1021
+ return null;
1022
+ }
1023
+ if (!isKnownFontWeight(numberValue)) {
1024
+ return null;
1025
+ }
1026
+ return {
1027
+ number: numberValue,
1028
+ unit: null
1029
+ };
1030
+ case "Identifier":
1031
+ const namedValue = node.name.toLowerCase();
1032
+ if (!isKnownFontWeight(namedValue)) {
1033
+ return null;
1034
+ }
1035
+ if (namedValue === "normal") {
1036
+ return { number: 400, unit: null };
1037
+ }
1038
+ return { number: namedValue, unit: null };
1039
+ case "Percentage":
1040
+ const percentValue = Number(node.value);
1041
+ if (percentValue === 0) return null;
1042
+ return {
1043
+ number: percentValue,
1044
+ unit: "%"
1045
+ };
1046
+ case "Value":
1047
+ return node.children?.[0] ? extractFontValue(node.children[0]) : null;
1048
+ }
1049
+ return null;
1050
+ }
1051
+ function shouldSkipFontNode(node) {
1052
+ return node.type === "Function";
1053
+ }
1054
+ function forEachFontValue(valueText, callback) {
1055
+ forEachValue(valueText, extractFontValue, shouldSkipFontNode, callback);
1056
+ }
1057
+
1058
+ // src/utils/css-utils.ts
1059
+ function extractSldsVariable(node) {
1060
+ if (!node || node.type !== "Function" || node.name !== "var") {
1061
+ return null;
1062
+ }
1063
+ if (!node.children) {
1064
+ return null;
1065
+ }
1066
+ const childrenArray = Array.from(node.children);
1067
+ if (childrenArray.length === 0) {
1068
+ return null;
1069
+ }
1070
+ const firstChild = childrenArray[0];
1071
+ if (!firstChild || firstChild.type !== "Identifier") {
1072
+ return null;
1073
+ }
1074
+ const variableName = firstChild.name;
1075
+ if (!variableName || !variableName.startsWith("--slds-")) {
1076
+ return null;
1077
+ }
1078
+ const hasFallback = childrenArray.some(
1079
+ (child) => child.type === "Operator" && child.value === ","
1080
+ );
1081
+ return {
1082
+ name: variableName,
1083
+ hasFallback
1084
+ };
1085
+ }
1086
+ function forEachSldsVariable(valueText, callback) {
1087
+ forEachValue(valueText, extractSldsVariable, () => false, callback);
1088
+ }
1089
+ function formatSuggestionHooks(hooks) {
1090
+ if (hooks.length === 1) {
1091
+ return `${hooks[0]}`;
1092
+ }
1093
+ return "\n" + hooks.map((hook, index) => `${index + 1}. ${hook}`).join("\n");
1094
+ }
1095
+
1096
+ // src/rules/v9/lwc-token-to-slds-hook.ts
1097
+ var ruleConfig3 = import_rule_messages5.default["lwc-token-to-slds-hook"];
1098
+ var { type: type4, description: description4, url: url4, messages: messages4 } = ruleConfig3;
1099
+ var lwcToSlds = import_sds_metadata5.default.lwcToSlds;
1100
+ function shouldIgnoreDetection(lwcToken) {
1101
+ return !lwcToken.startsWith("--lwc-") || !(lwcToken in lwcToSlds) || lwcToSlds[lwcToken].continueToUse;
1102
+ }
1103
+ function categorizeReplacement(recommendation) {
1104
+ if (!recommendation || recommendation === "--") {
1105
+ return "empty" /* EMPTY */;
1106
+ }
1107
+ if (Array.isArray(recommendation)) {
1108
+ return "array" /* ARRAY */;
1109
+ }
1110
+ if (typeof recommendation === "string" && recommendation.startsWith("--slds-")) {
1111
+ return "slds_token" /* SLDS_TOKEN */;
1112
+ }
1113
+ return "raw_value" /* RAW_VALUE */;
1114
+ }
1115
+ function getRecommendation(lwcToken) {
1116
+ const oldValue = lwcToken;
1117
+ const recommendation = lwcToSlds[oldValue]?.replacement || "";
1118
+ const replacementCategory = categorizeReplacement(recommendation);
1119
+ const hasRecommendation = oldValue in lwcToSlds && replacementCategory !== "empty" /* EMPTY */;
1120
+ return { hasRecommendation, recommendation, replacementCategory };
1121
+ }
1122
+ function getReportMessage(cssVar, replacementCategory, recommendation) {
1123
+ if (!recommendation) {
1124
+ return {
1125
+ messageId: "errorWithNoRecommendation",
1126
+ data: { oldValue: cssVar }
1127
+ };
1128
+ } else if (replacementCategory === "array" /* ARRAY */) {
1129
+ return {
1130
+ messageId: "errorWithStyleHooks",
1131
+ data: { oldValue: cssVar, newValue: formatSuggestionHooks(recommendation) }
1132
+ };
1133
+ } else if (replacementCategory === "slds_token" /* SLDS_TOKEN */) {
1134
+ return {
1135
+ messageId: "errorWithStyleHooks",
1136
+ data: { oldValue: cssVar, newValue: recommendation }
1137
+ };
1138
+ } else {
1139
+ return {
1140
+ messageId: "errorWithReplacement",
1141
+ data: { oldValue: cssVar, newValue: recommendation }
1142
+ };
1143
+ }
1144
+ }
1145
+ var lwc_token_to_slds_hook_default = {
1146
+ meta: {
1147
+ type: type4,
1148
+ docs: {
1149
+ description: description4,
1150
+ recommended: true,
1151
+ url: url4
1152
+ },
1153
+ fixable: "code",
1154
+ messages: messages4
1155
+ },
1156
+ create(context) {
1157
+ function reportAndFix(node, oldValue, suggestedMatch, messageId, data) {
1158
+ let fixFunction = null;
1159
+ if (suggestedMatch) {
1160
+ fixFunction = (fixer) => {
1161
+ if (node.type === "Declaration") {
1162
+ const sourceCode = context.sourceCode;
1163
+ const fullText = sourceCode.getText();
1164
+ const nodeOffset = node.loc.start.offset;
1165
+ const propertyStart = nodeOffset;
1166
+ const propertyEnd = propertyStart + oldValue.length;
1167
+ const textAtPosition = fullText.substring(propertyStart, propertyEnd);
1168
+ if (textAtPosition === oldValue) {
1169
+ return fixer.replaceTextRange([propertyStart, propertyEnd], suggestedMatch);
1170
+ }
1171
+ } else {
1172
+ const sourceCode = context.sourceCode;
1173
+ const fullText = sourceCode.getText();
1174
+ const varFunctionCall = `var(${oldValue})`;
1175
+ const nodeOffset = node.loc.start.offset;
1176
+ const searchStart = Math.max(0, nodeOffset - 4);
1177
+ const searchEnd = nodeOffset + oldValue.length + 1;
1178
+ const searchArea = fullText.substring(searchStart, searchEnd);
1179
+ const functionCallIndex = searchArea.indexOf(varFunctionCall);
1180
+ if (functionCallIndex !== -1) {
1181
+ const actualStart = searchStart + functionCallIndex;
1182
+ const actualEnd = actualStart + varFunctionCall.length;
1183
+ return fixer.replaceTextRange([actualStart, actualEnd], suggestedMatch);
1184
+ }
1185
+ }
1186
+ return null;
1187
+ };
1188
+ }
1189
+ context.report({
1190
+ node,
1191
+ messageId,
1192
+ data,
1193
+ fix: fixFunction
1194
+ });
1195
+ }
1196
+ return {
1197
+ // CSS custom property declarations: --lwc-* properties
1198
+ "Declaration[property=/^--lwc-/]"(node) {
1199
+ const property = node.property;
1200
+ if (shouldIgnoreDetection(property)) {
1201
+ return;
1202
+ }
1203
+ const { hasRecommendation, recommendation, replacementCategory } = getRecommendation(property);
1204
+ const { messageId, data } = getReportMessage(property, replacementCategory, recommendation);
1205
+ const suggestedMatch = hasRecommendation && replacementCategory === "slds_token" /* SLDS_TOKEN */ ? recommendation : null;
1206
+ reportAndFix(node, property, suggestedMatch, messageId, data);
1207
+ },
1208
+ // LWC tokens inside var() functions: var(--lwc-*)
1209
+ "Function[name='var'] Identifier[name=/^--lwc-/]"(node) {
1210
+ const tokenName = node.name;
1211
+ if (shouldIgnoreDetection(tokenName)) {
1212
+ return;
1213
+ }
1214
+ const { hasRecommendation, recommendation, replacementCategory } = getRecommendation(tokenName);
1215
+ const { messageId, data } = getReportMessage(tokenName, replacementCategory, recommendation);
1216
+ let suggestedMatch = null;
1217
+ if (hasRecommendation) {
1218
+ if (replacementCategory === "slds_token" /* SLDS_TOKEN */) {
1219
+ const originalVarCall = `var(${tokenName})`;
1220
+ suggestedMatch = `var(${recommendation}, ${originalVarCall})`;
1221
+ } else if (replacementCategory === "raw_value" /* RAW_VALUE */) {
1222
+ suggestedMatch = recommendation;
1223
+ }
1224
+ }
1225
+ reportAndFix(node, tokenName, suggestedMatch, messageId, data);
1226
+ }
1227
+ };
1228
+ }
1229
+ };
1230
+
1231
+ // src/rules/v9/enforce-sds-to-slds-hooks.ts
1232
+ var import_sds_metadata6 = __toESM(require("@salesforce-ux/sds-metadata"));
1233
+ var import_rule_messages6 = __toESM(require_rule_messages());
1234
+ var ruleConfig4 = import_rule_messages6.default["enforce-sds-to-slds-hooks"];
1235
+ var { type: type5, description: description5, url: url5, messages: messages5 } = ruleConfig4;
1236
+ var sldsPlusStylingHooks = import_sds_metadata6.default.sldsPlusStylingHooks;
1237
+ var allSldsHooks = [...sldsPlusStylingHooks.global, ...sldsPlusStylingHooks.component];
1238
+ var toSldsToken = (sdsToken) => sdsToken.replace("--sds-", "--slds-");
1239
+ function shouldIgnoreDetection2(sdsToken) {
1240
+ return !sdsToken.startsWith("--sds-") || !allSldsHooks.includes(toSldsToken(sdsToken));
1241
+ }
1242
+ var enforce_sds_to_slds_hooks_default = {
1243
+ meta: {
1244
+ type: type5,
1245
+ docs: {
1246
+ description: description5,
1247
+ recommended: true,
1248
+ url: url5
1249
+ },
1250
+ fixable: "code",
1251
+ messages: messages5
1252
+ },
1253
+ create(context) {
1254
+ function reportAndFix(node, oldValue, suggestedMatch) {
1255
+ context.report({
1256
+ node,
1257
+ messageId: "replaceSdsWithSlds",
1258
+ data: { oldValue, suggestedMatch },
1259
+ fix(fixer) {
1260
+ if (node.type === "Declaration") {
1261
+ const sourceCode = context.sourceCode;
1262
+ const fullText = sourceCode.getText();
1263
+ const nodeOffset = node.loc.start.offset;
1264
+ const propertyStart = nodeOffset;
1265
+ const propertyEnd = propertyStart + oldValue.length;
1266
+ const textAtPosition = fullText.substring(propertyStart, propertyEnd);
1267
+ if (textAtPosition === oldValue) {
1268
+ return fixer.replaceTextRange([propertyStart, propertyEnd], suggestedMatch);
1269
+ }
1270
+ }
1271
+ return fixer.replaceText(node, suggestedMatch);
1272
+ }
1273
+ });
1274
+ }
1275
+ return {
1276
+ // CSS custom property declarations: --sds-* properties
1277
+ "Declaration[property=/^--sds-/]"(node) {
1278
+ const property = node.property;
1279
+ if (shouldIgnoreDetection2(property)) {
1280
+ return;
1281
+ }
1282
+ const suggestedMatch = toSldsToken(property);
1283
+ reportAndFix(node, property, suggestedMatch);
1284
+ },
1285
+ // SDS tokens inside var() functions: var(--sds-*)
1286
+ "Function[name='var'] Identifier[name=/^--sds-/]"(node) {
1287
+ const tokenName = node.name;
1288
+ if (shouldIgnoreDetection2(tokenName)) {
1289
+ return;
1290
+ }
1291
+ const suggestedMatch = toSldsToken(tokenName);
1292
+ reportAndFix(node, tokenName, suggestedMatch);
1293
+ }
1294
+ };
1295
+ }
1296
+ };
1297
+
1298
+ // src/rules/v9/no-sldshook-fallback-for-lwctoken.ts
1299
+ var import_sds_metadata7 = __toESM(require("@salesforce-ux/sds-metadata"));
1300
+ var import_rule_messages7 = __toESM(require_rule_messages());
1301
+ var ruleConfig5 = import_rule_messages7.default["no-sldshook-fallback-for-lwctoken"];
1302
+ var { type: type6, description: description6, url: url6, messages: messages6 } = ruleConfig5;
1303
+ var sldsPlusStylingHooks2 = import_sds_metadata7.default.sldsPlusStylingHooks;
1304
+ var allSldsHooks2 = [...sldsPlusStylingHooks2.global, ...sldsPlusStylingHooks2.component];
1305
+ var allSldsHooksSet = new Set(allSldsHooks2);
1306
+ function hasUnsupportedFallback(lwcToken, sldsToken) {
1307
+ const normalizedSldsToken = sldsToken.replace("--sds-", "--slds-");
1308
+ return lwcToken.startsWith("--lwc-") && normalizedSldsToken.startsWith("--slds-") && allSldsHooksSet.has(normalizedSldsToken);
1309
+ }
1310
+ var no_sldshook_fallback_for_lwctoken_default = {
1311
+ meta: {
1312
+ type: type6,
1313
+ docs: {
1314
+ description: description6,
1315
+ recommended: true,
1316
+ url: url6
1317
+ },
1318
+ messages: messages6
1319
+ },
1320
+ create(context) {
1321
+ return {
1322
+ // Handle LWC tokens inside var() functions: var(--lwc-*, ...)
1323
+ "Function[name='var'] Identifier[name=/^--lwc-/]"(node) {
1324
+ const lwcToken = node.name;
1325
+ const varFunctionNode = context.sourceCode.getAncestors(node).at(-1);
1326
+ if (!varFunctionNode) return;
1327
+ const varFunctionChildren = varFunctionNode.children;
1328
+ if (!varFunctionChildren) return;
1329
+ let foundComma = false;
1330
+ let fallbackRawNode = null;
1331
+ for (const child of varFunctionChildren) {
1332
+ if (child.type === "Operator" && child.value === ",") {
1333
+ foundComma = true;
1334
+ continue;
1335
+ }
1336
+ if (foundComma && child.type === "Raw") {
1337
+ fallbackRawNode = child;
1338
+ break;
1339
+ }
1340
+ }
1341
+ if (!fallbackRawNode) return;
1342
+ const fallbackValue = fallbackRawNode.value.trim();
1343
+ const varMatch = fallbackValue.match(/var\(([^,)]+)/);
1344
+ if (!varMatch) return;
1345
+ const sldsToken = varMatch[1];
1346
+ if (hasUnsupportedFallback(lwcToken, sldsToken)) {
1347
+ context.report({
1348
+ node,
1349
+ messageId: "unsupportedFallback",
1350
+ data: { lwcToken, sldsToken }
1351
+ });
1352
+ }
1353
+ }
1354
+ };
1355
+ }
1356
+ };
1357
+
1358
+ // src/rules/v9/no-unsupported-hooks-slds2.ts
1359
+ var import_sds_metadata8 = __toESM(require("@salesforce-ux/sds-metadata"));
1360
+ var import_rule_messages8 = __toESM(require_rule_messages());
1361
+ var ruleConfig6 = import_rule_messages8.default["no-unsupported-hooks-slds2"];
1362
+ var { type: type7, description: description7, url: url7, messages: messages7 } = ruleConfig6;
1363
+ var deprecatedHooks = new Set(import_sds_metadata8.default.deprecatedStylingHooks);
1364
+ function shouldIgnoreDetection3(sldsHook) {
1365
+ return !deprecatedHooks.has(sldsHook);
1366
+ }
1367
+ var no_unsupported_hooks_slds2_default = {
1368
+ meta: {
1369
+ type: type7,
1370
+ docs: {
1371
+ description: description7,
1372
+ recommended: true,
1373
+ url: url7
1374
+ },
1375
+ messages: messages7
1376
+ },
1377
+ create(context) {
1378
+ function reportDeprecatedHook(node, token) {
1379
+ context.report({
1380
+ node,
1381
+ messageId: "deprecated",
1382
+ data: { token }
1383
+ });
1384
+ }
1385
+ return {
1386
+ // Handle CSS custom property declarations (left-side usage): --slds-* properties
1387
+ // Example: .THIS { --slds-g-link-color: #f73650; }
1388
+ "Declaration[property=/^--s(lds|ds)-/]"(node) {
1389
+ const property = node.property;
1390
+ if (shouldIgnoreDetection3(property)) {
1391
+ return;
1392
+ }
1393
+ reportDeprecatedHook(node, property);
1394
+ },
1395
+ // Handle SLDS/SDS hooks inside var() functions (right-side usage): var(--slds-*)
1396
+ // Example: .THIS .demo { border-top: 1px solid var(--slds-g-color-border-brand-1); }
1397
+ "Function[name='var'] Identifier[name=/^--s(lds|ds)-/]"(node) {
1398
+ const tokenName = node.name;
1399
+ if (shouldIgnoreDetection3(tokenName)) {
1400
+ return;
1401
+ }
1402
+ reportDeprecatedHook(node, tokenName);
1403
+ }
1404
+ };
1405
+ }
1406
+ };
1407
+
1408
+ // src/rules/v9/no-slds-var-without-fallback.ts
1409
+ var import_sds_metadata9 = __toESM(require("@salesforce-ux/sds-metadata"));
1410
+ var import_rule_messages9 = __toESM(require_rule_messages());
1411
+ var ruleConfig7 = import_rule_messages9.default["no-slds-var-without-fallback"];
1412
+ var { type: type8, description: description8, url: url8, messages: messages8 } = ruleConfig7;
1413
+ var sldsVariables = import_sds_metadata9.default.slds1ExcludedVars || {};
1414
+ var no_slds_var_without_fallback_default = {
1415
+ meta: {
1416
+ type: type8,
1417
+ docs: {
1418
+ description: description8,
1419
+ recommended: true,
1420
+ url: url8
1421
+ },
1422
+ fixable: "code",
1423
+ messages: messages8
1424
+ },
1425
+ create(context) {
1426
+ return {
1427
+ "Declaration"(node) {
1428
+ const valueText = context.sourceCode.getText(node.value);
1429
+ if (!valueText) return;
1430
+ const variablesNeedingFallback = [];
1431
+ forEachSldsVariable(valueText, (variableInfo, positionInfo) => {
1432
+ const { name: cssVar, hasFallback } = variableInfo;
1433
+ if (hasFallback) return;
1434
+ const fallbackValue = sldsVariables[cssVar];
1435
+ if (!fallbackValue) return;
1436
+ variablesNeedingFallback.push({
1437
+ cssVar,
1438
+ fallbackValue,
1439
+ start: positionInfo.start?.offset || 0,
1440
+ end: positionInfo.end?.offset || 0
1441
+ });
1442
+ });
1443
+ if (variablesNeedingFallback.length > 0) {
1444
+ let newValue = valueText;
1445
+ const sortedVariables = variablesNeedingFallback.sort((a, b) => b.start - a.start);
1446
+ sortedVariables.forEach(({ cssVar, fallbackValue, start, end }) => {
1447
+ const replacement = `var(${cssVar}, ${fallbackValue})`;
1448
+ newValue = newValue.substring(0, start) + replacement + newValue.substring(end);
1449
+ });
1450
+ variablesNeedingFallback.forEach(({ cssVar, fallbackValue }) => {
1451
+ context.report({
1452
+ node,
1453
+ messageId: "varWithoutFallback",
1454
+ data: { cssVar, recommendation: fallbackValue },
1455
+ fix: (fixer) => fixer.replaceText(node.value, newValue)
1456
+ });
1457
+ });
1458
+ }
1459
+ }
1460
+ };
1461
+ }
1462
+ };
1463
+
1464
+ // src/rules/v9/no-slds-namespace-for-custom-hooks.ts
1465
+ var import_sds_metadata10 = __toESM(require("@salesforce-ux/sds-metadata"));
1466
+ var import_rule_messages10 = __toESM(require_rule_messages());
1467
+ var ruleConfig8 = import_rule_messages10.default["no-slds-namespace-for-custom-hooks"];
1468
+ var { type: type9, description: description9, url: url9, messages: messages9 } = ruleConfig8;
1469
+ var sldsPlusStylingHooks3 = import_sds_metadata10.default.sldsPlusStylingHooks;
1470
+ var allSldsHooks3 = [...sldsPlusStylingHooks3.global, ...sldsPlusStylingHooks3.component];
1471
+ var toSldsToken2 = (sdsToken) => sdsToken.replace("--sds-", "--slds-");
1472
+ function shouldIgnoreDetection4(sdsToken) {
1473
+ if (sdsToken.startsWith("--sds-") || sdsToken.startsWith("--slds-")) {
1474
+ return allSldsHooks3.includes(toSldsToken2(sdsToken));
1475
+ }
1476
+ return true;
1477
+ }
1478
+ var no_slds_namespace_for_custom_hooks_default = {
1479
+ meta: {
1480
+ type: type9,
1481
+ docs: {
1482
+ description: description9,
1483
+ recommended: true,
1484
+ url: url9
1485
+ },
1486
+ messages: messages9
1487
+ },
1488
+ create(context) {
1489
+ function reportViolation(node, token) {
1490
+ const tokenWithoutNamespace = token.replace("--slds-", "").replace("--sds-", "");
1491
+ context.report({
1492
+ node,
1493
+ messageId: "customHookNamespace",
1494
+ data: {
1495
+ token,
1496
+ tokenWithoutNamespace
1497
+ }
1498
+ });
1499
+ }
1500
+ return {
1501
+ // CSS custom property declarations: --slds-* and --sds-* properties
1502
+ "Declaration[property=/^--s(lds|ds)-/]"(node) {
1503
+ const property = node.property;
1504
+ if (shouldIgnoreDetection4(property)) {
1505
+ return;
1506
+ }
1507
+ reportViolation(node, property);
1508
+ },
1509
+ // SLDS/SDS tokens inside var() functions: var(--slds-*) or var(--sds-*)
1510
+ "Function[name='var'] Identifier[name=/^--s(lds|ds)-/]"(node) {
1511
+ const tokenName = node.name;
1512
+ if (shouldIgnoreDetection4(tokenName)) {
1513
+ return;
1514
+ }
1515
+ reportViolation(node, tokenName);
1516
+ }
1517
+ };
1518
+ }
1519
+ };
1520
+
1521
+ // src/rules/v9/enforce-component-hook-naming-convention.ts
1522
+ var import_sds_metadata11 = __toESM(require("@salesforce-ux/sds-metadata"));
1523
+ var import_rule_messages11 = __toESM(require_rule_messages());
1524
+ var ruleConfig9 = import_rule_messages11.default["enforce-component-hook-naming-convention"];
1525
+ var { type: type10, description: description10, url: url10, messages: messages10 } = ruleConfig9;
1526
+ var slds1DeprecatedComponentHooks = import_sds_metadata11.default.slds1DeprecatedComponentHooks;
1527
+ function shouldIgnoreDetection5(hook) {
1528
+ return !hook.startsWith("--slds-c-") || !(hook in slds1DeprecatedComponentHooks);
1529
+ }
1530
+ var enforce_component_hook_naming_convention_default = {
1531
+ meta: {
1532
+ type: type10,
1533
+ docs: {
1534
+ description: description10,
1535
+ recommended: true,
1536
+ url: url10
1537
+ },
1538
+ fixable: "code",
1539
+ messages: messages10
1540
+ },
1541
+ create(context) {
1542
+ return {
1543
+ /*
1544
+ * Handle component hooks in CSS declarations
1545
+ * Limitation: For example:
1546
+ * .testClass{
1547
+ * --slds-c-accordion-section-color-background: var(--slds-c-accordion-section-color-border);
1548
+ * }
1549
+ * var in value is not detected, because eslint treats above statement as custom property assignment
1550
+ * and value treated as raw string, not parsed into function nodes
1551
+ */
1552
+ "Declaration[property=/^--slds-c-/], Function[name='var'] Identifier[name=/^--slds-c-/]"(node) {
1553
+ let hookName;
1554
+ let reportNode = node;
1555
+ if (node.type === "Declaration") {
1556
+ hookName = node.property;
1557
+ } else if (node.type === "Identifier") {
1558
+ hookName = node.name;
1559
+ } else {
1560
+ return;
1561
+ }
1562
+ if (shouldIgnoreDetection5(hookName)) {
1563
+ return;
1564
+ }
1565
+ const suggestedMatch = slds1DeprecatedComponentHooks[hookName];
1566
+ context.report({
1567
+ node: reportNode,
1568
+ messageId: "replace",
1569
+ data: {
1570
+ oldValue: hookName,
1571
+ suggestedMatch
1572
+ },
1573
+ fix(fixer) {
1574
+ if (node.type === "Declaration") {
1575
+ const originalText = context.sourceCode.getText(node);
1576
+ const colonIndex = originalText.indexOf(":");
1577
+ const valuePartWithColon = originalText.substring(colonIndex);
1578
+ return fixer.replaceText(node, `${suggestedMatch}${valuePartWithColon}`);
1579
+ } else if (node.type === "Identifier") {
1580
+ return fixer.replaceText(node, suggestedMatch);
1581
+ }
1582
+ return null;
1583
+ }
1584
+ });
1585
+ }
1586
+ };
1587
+ }
1588
+ };
1589
+
1590
+ // src/rules/v9/reduce-annotations.ts
1591
+ var import_rule_messages12 = __toESM(require_rule_messages());
1592
+ var ruleConfig10 = import_rule_messages12.default["reduce-annotations"];
1593
+ var { type: type11, description: description11, url: url11, messages: messages11 } = ruleConfig10;
1594
+ var SLDS_ANNOTATIONS = [
1595
+ "@sldsValidatorIgnoreNextLine",
1596
+ "@sldsValidatorAllow",
1597
+ "@sldsValidatorIgnore"
1598
+ ];
1599
+ var reduce_annotations_default = {
1600
+ meta: {
1601
+ type: type11,
1602
+ docs: {
1603
+ description: description11,
1604
+ recommended: true,
1605
+ url: url11
1606
+ },
1607
+ messages: messages11
1608
+ },
1609
+ create(context) {
1610
+ return {
1611
+ StyleSheet(node) {
1612
+ const sourceCode = context.sourceCode;
1613
+ let comments = sourceCode?.comments || [];
1614
+ comments.forEach((comment) => {
1615
+ const commentContent = comment.value.trim();
1616
+ const matchingAnnotation = SLDS_ANNOTATIONS.find(
1617
+ (annotation) => commentContent.startsWith(annotation)
1618
+ );
1619
+ if (matchingAnnotation) {
1620
+ context.report({
1621
+ node: comment,
1622
+ messageId: "removeAnnotation"
1623
+ });
1624
+ }
1625
+ });
1626
+ }
1627
+ };
1628
+ }
1629
+ };
1630
+
1631
+ // src/rules/v9/no-slds-private-var.ts
1632
+ var import_rule_messages13 = __toESM(require_rule_messages());
1633
+ var ruleConfig11 = import_rule_messages13.default["no-slds-private-var"];
1634
+ var { type: type12, description: description12, url: url12, messages: messages12 } = ruleConfig11;
1635
+ var no_slds_private_var_default = {
1636
+ meta: {
1637
+ type: type12,
1638
+ docs: {
1639
+ description: description12,
1640
+ recommended: true,
1641
+ url: url12
1642
+ },
1643
+ fixable: "code",
1644
+ messages: messages12
1645
+ },
1646
+ create(context) {
1647
+ return {
1648
+ // Handle CSS custom properties (declarations starting with --)
1649
+ "Declaration"(node) {
1650
+ if (node.property && typeof node.property === "string" && node.property.startsWith("--_slds-")) {
1651
+ context.report({
1652
+ node,
1653
+ messageId: "privateVar",
1654
+ data: { prop: node.property },
1655
+ fix(fixer) {
1656
+ const newProperty = node.property.replace("--_slds-", "--slds-");
1657
+ const sourceCode = context.sourceCode.getText(node);
1658
+ const fixedCode = sourceCode.replace(node.property, newProperty);
1659
+ return fixer.replaceText(node, fixedCode);
1660
+ }
1661
+ });
1662
+ }
1663
+ }
1664
+ };
1665
+ }
1666
+ };
1667
+
1668
+ // src/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.ts
1669
+ var import_sds_metadata12 = __toESM(require("@salesforce-ux/sds-metadata"));
1670
+ var import_rule_messages14 = __toESM(require_rule_messages());
1671
+
1672
+ // src/utils/property-matcher.ts
1673
+ var DIRECTION_VALUES = "(?:top|right|bottom|left|inline|block|inline-start|inline-end|start|end|block-start|block-end)";
1674
+ var CORNER_VALUES = "(?:top-left|top-right|bottom-right|bottom-left|start-start|start-end|end-start|end-end)";
1675
+ var INSET_VALUES = "(?:inline|block|inline-start|inline-end|block-start|block-end)";
1676
+ var BORDER_COLOR_REGEX = new RegExp(`^border(?:-${DIRECTION_VALUES})?-color$`);
1677
+ var BORDER_WIDTH_REGEX = new RegExp(`^border(?:-${DIRECTION_VALUES})?-width$`);
1678
+ var MARGIN_REGEX = new RegExp(`^margin(?:-${DIRECTION_VALUES})?$`);
1679
+ var PADDING_REGEX = new RegExp(`^padding(?:-${DIRECTION_VALUES})?$`);
1680
+ var BORDER_RADIUS_REGEX = new RegExp(`^border(?:-${CORNER_VALUES})?-radius$`);
1681
+ var INSET_REGEX = new RegExp(`^inset(?:-${INSET_VALUES})?$`);
1682
+ function isBorderColorProperty(cssProperty) {
1683
+ return BORDER_COLOR_REGEX.test(cssProperty);
1684
+ }
1685
+ function isBorderWidthProperty(cssProperty) {
1686
+ return BORDER_WIDTH_REGEX.test(cssProperty);
1687
+ }
1688
+ function isMarginProperty(cssProperty) {
1689
+ return MARGIN_REGEX.test(cssProperty);
1690
+ }
1691
+ function isPaddingProperty(cssProperty) {
1692
+ return PADDING_REGEX.test(cssProperty);
1693
+ }
1694
+ function isBorderRadius(cssProperty) {
1695
+ return BORDER_RADIUS_REGEX.test(cssProperty);
1696
+ }
1697
+ function isDimensionProperty(cssProperty) {
1698
+ return ["width", "height", "min-width", "max-width", "min-height", "max-height"].includes(cssProperty);
1699
+ }
1700
+ function isInsetProperty(cssProperty) {
1701
+ return INSET_REGEX.test(cssProperty);
1702
+ }
1703
+ var fontProperties = [
1704
+ "font",
1705
+ "font-size",
1706
+ "font-weight"
1707
+ ];
1708
+ var colorProperties = [
1709
+ "color",
1710
+ "fill",
1711
+ "background",
1712
+ "background-color",
1713
+ "stroke",
1714
+ "border",
1715
+ "border*",
1716
+ "border*-color",
1717
+ "outline",
1718
+ "outline-color"
1719
+ ];
1720
+ var densificationProperties = [
1721
+ "border*",
1722
+ "margin*",
1723
+ "padding*",
1724
+ "width",
1725
+ "height",
1726
+ "min-width",
1727
+ "max-width",
1728
+ "min-height",
1729
+ "max-height",
1730
+ "inset",
1731
+ "top",
1732
+ "right",
1733
+ "left",
1734
+ "bottom",
1735
+ "outline",
1736
+ "outline-width",
1737
+ "line-height"
1738
+ ];
1739
+ function toSelector(properties) {
1740
+ const selectorParts = properties.map((prop) => {
1741
+ if (prop.includes("*")) {
1742
+ const regexPattern = prop.replace(/\*/g, ".*");
1743
+ return `Declaration[property=/^${regexPattern}$/]`;
1744
+ } else {
1745
+ return `Declaration[property='${prop}']`;
1746
+ }
1747
+ });
1748
+ return selectorParts.join(", ");
1749
+ }
1750
+ function resolvePropertyToMatch(cssProperty) {
1751
+ const propertyToMatch = cssProperty.toLowerCase();
1752
+ if (propertyToMatch === "outline" || propertyToMatch === "outline-width" || isBorderWidthProperty(propertyToMatch)) {
1753
+ return "border-width";
1754
+ } else if (isMarginProperty(propertyToMatch)) {
1755
+ return "margin";
1756
+ } else if (isPaddingProperty(propertyToMatch)) {
1757
+ return "padding";
1758
+ } else if (isBorderRadius(propertyToMatch)) {
1759
+ return "border-radius";
1760
+ } else if (isDimensionProperty(propertyToMatch)) {
1761
+ return "width";
1762
+ } else if (isInsetProperty(propertyToMatch)) {
1763
+ return "top";
1764
+ } else if (cssProperty === "background" || cssProperty === "background-color") {
1765
+ return "background-color";
1766
+ } else if (cssProperty === "outline" || cssProperty === "outline-color" || isBorderColorProperty(cssProperty)) {
1767
+ return "border-color";
1768
+ }
1769
+ return propertyToMatch;
1770
+ }
1771
+
1772
+ // src/rules/v9/no-hardcoded-values/handlers/colorHandler.ts
1773
+ var handleColorDeclaration = (node, context) => {
1774
+ const cssProperty = node.property.toLowerCase();
1775
+ const valueText = context.sourceCode.getText(node.value);
1776
+ const replacements = [];
1777
+ forEachColorValue(valueText, (colorValue, positionInfo) => {
1778
+ if (colorValue !== "transparent" && isValidColor(colorValue)) {
1779
+ const replacement = createColorReplacement(colorValue, cssProperty, context, positionInfo, valueText);
1780
+ if (replacement) {
1781
+ replacements.push(replacement);
1782
+ }
1783
+ }
1784
+ });
1785
+ handleShorthandAutoFix(node, context, valueText, replacements);
1786
+ };
1787
+ function createColorReplacement(colorValue, cssProperty, context, positionInfo, originalValueText) {
1788
+ if (!positionInfo?.start) {
1789
+ return null;
1790
+ }
1791
+ const hexValue = convertToHex(colorValue);
1792
+ if (!hexValue) {
1793
+ return null;
1794
+ }
1795
+ const propToMatch = resolvePropertyToMatch(cssProperty);
1796
+ const closestHooks = findClosestColorHook(hexValue, context.valueToStylinghook, propToMatch);
1797
+ const start = positionInfo.start.offset;
1798
+ const end = positionInfo.end.offset;
1799
+ const originalValue = originalValueText ? originalValueText.substring(start, end) : colorValue;
1800
+ if (closestHooks.length === 1) {
1801
+ return {
1802
+ start,
1803
+ end,
1804
+ replacement: `var(${closestHooks[0]}, ${colorValue})`,
1805
+ displayValue: closestHooks[0],
1806
+ hasHook: true
1807
+ };
1808
+ } else if (closestHooks.length > 1) {
1809
+ return {
1810
+ start,
1811
+ end,
1812
+ replacement: originalValue,
1813
+ // Use original value to preserve spacing
1814
+ displayValue: formatSuggestionHooks(closestHooks),
1815
+ hasHook: true
1816
+ };
1817
+ } else {
1818
+ return {
1819
+ start,
1820
+ end,
1821
+ replacement: originalValue,
1822
+ // Use original value to preserve spacing
1823
+ displayValue: originalValue,
1824
+ hasHook: false
1825
+ };
1826
+ }
1827
+ }
1828
+
1829
+ // src/utils/styling-hook-utils.ts
1830
+ function isValueMatch(valueToMatch, sldsValue) {
1831
+ if (!valueToMatch || !sldsValue) {
1832
+ return false;
1833
+ }
1834
+ return valueToMatch.unit == sldsValue.unit && valueToMatch.number === sldsValue.number;
1835
+ }
1836
+ function getStylingHooksForDensityValue(parsedValue, supportedStylinghooks, cssProperty) {
1837
+ if (!parsedValue) return [];
1838
+ const alternateValue = toAlternateUnitValue(parsedValue.number, parsedValue.unit);
1839
+ const matchedHooks = [];
1840
+ for (const [sldsValue, hooks] of Object.entries(supportedStylinghooks)) {
1841
+ const parsedSldsValue = parseUnitValue(sldsValue);
1842
+ if (isValueMatch(parsedValue, parsedSldsValue) || alternateValue && isValueMatch(alternateValue, parsedSldsValue)) {
1843
+ hooks.filter((hook) => hook.properties.includes(cssProperty)).forEach((hook) => matchedHooks.push(hook.name));
1844
+ }
1845
+ }
1846
+ return matchedHooks;
1847
+ }
1848
+
1849
+ // src/rules/v9/no-hardcoded-values/handlers/densityHandler.ts
1850
+ var handleDensityDeclaration = (node, context) => {
1851
+ const cssProperty = node.property.toLowerCase();
1852
+ const valueText = context.sourceCode.getText(node.value);
1853
+ const replacements = [];
1854
+ forEachDensityValue(valueText, cssProperty, (parsedDimension, positionInfo) => {
1855
+ if (parsedDimension) {
1856
+ const replacement = createDimensionReplacement(parsedDimension, cssProperty, context, positionInfo);
1857
+ if (replacement) {
1858
+ replacements.push(replacement);
1859
+ }
1860
+ }
1861
+ });
1862
+ handleShorthandAutoFix(node, context, valueText, replacements);
1863
+ };
1864
+ function createDimensionReplacement(parsedDimension, cssProperty, context, positionInfo) {
1865
+ if (!parsedDimension || !positionInfo?.start) {
1866
+ return null;
1867
+ }
1868
+ const rawValue = parsedDimension.unit ? `${parsedDimension.number}${parsedDimension.unit}` : parsedDimension.number.toString();
1869
+ const propToMatch = resolvePropertyToMatch(cssProperty);
1870
+ const closestHooks = getStylingHooksForDensityValue(parsedDimension, context.valueToStylinghook, propToMatch);
1871
+ const start = positionInfo.start.offset;
1872
+ const end = positionInfo.end.offset;
1873
+ if (closestHooks.length === 1) {
1874
+ return {
1875
+ start,
1876
+ end,
1877
+ replacement: `var(${closestHooks[0]}, ${rawValue})`,
1878
+ displayValue: closestHooks[0],
1879
+ hasHook: true
1880
+ };
1881
+ } else if (closestHooks.length > 1) {
1882
+ return {
1883
+ start,
1884
+ end,
1885
+ replacement: rawValue,
1886
+ displayValue: formatSuggestionHooks(closestHooks),
1887
+ hasHook: true
1888
+ };
1889
+ } else {
1890
+ return {
1891
+ start,
1892
+ end,
1893
+ replacement: rawValue,
1894
+ displayValue: rawValue,
1895
+ hasHook: false
1896
+ };
1897
+ }
1898
+ }
1899
+
1900
+ // src/rules/v9/no-hardcoded-values/handlers/fontHandler.ts
1901
+ var handleFontDeclaration = (node, context) => {
1902
+ const cssProperty = node.property.toLowerCase();
1903
+ const valueText = context.sourceCode.getText(node.value);
1904
+ const replacements = [];
1905
+ forEachFontValue(valueText, (fontValue, positionInfo) => {
1906
+ if (fontValue && isValidFontValue(fontValue, cssProperty)) {
1907
+ const replacement = createFontReplacement(fontValue, cssProperty, context, positionInfo);
1908
+ if (replacement) {
1909
+ replacements.push(replacement);
1910
+ }
1911
+ }
1912
+ });
1913
+ handleShorthandAutoFix(node, context, valueText, replacements);
1914
+ };
1915
+ function isValidFontValue(fontValue, cssProperty) {
1916
+ if (cssProperty === "font-size") {
1917
+ return !!fontValue.unit;
1918
+ } else if (cssProperty === "font-weight") {
1919
+ return !fontValue.unit && isKnownFontWeight(fontValue.number);
1920
+ } else if (cssProperty === "font") {
1921
+ if (!fontValue.unit && isKnownFontWeight(fontValue.number)) {
1922
+ return true;
1923
+ } else if (fontValue.unit) {
1924
+ return true;
1925
+ } else {
1926
+ return false;
1927
+ }
1928
+ }
1929
+ return false;
1930
+ }
1931
+ function createFontReplacement(fontValue, cssProperty, context, positionInfo) {
1932
+ if (!positionInfo?.start) {
1933
+ return null;
1934
+ }
1935
+ const rawValue = fontValue.unit ? `${fontValue.number}${fontValue.unit}` : fontValue.number.toString();
1936
+ const propToMatch = !fontValue.unit && isKnownFontWeight(fontValue.number) ? resolvePropertyToMatch("font-weight") : resolvePropertyToMatch("font-size");
1937
+ const closestHooks = getStylingHooksForDensityValue(fontValue, context.valueToStylinghook, propToMatch);
1938
+ const start = positionInfo.start.offset;
1939
+ const end = positionInfo.end.offset;
1940
+ if (closestHooks.length === 1) {
1941
+ return {
1942
+ start,
1943
+ end,
1944
+ replacement: `var(${closestHooks[0]}, ${rawValue})`,
1945
+ displayValue: closestHooks[0],
1946
+ hasHook: true
1947
+ };
1948
+ } else if (closestHooks.length > 1) {
1949
+ return {
1950
+ start,
1951
+ end,
1952
+ replacement: rawValue,
1953
+ displayValue: formatSuggestionHooks(closestHooks),
1954
+ hasHook: true
1955
+ };
1956
+ } else {
1957
+ return {
1958
+ start,
1959
+ end,
1960
+ replacement: rawValue,
1961
+ displayValue: rawValue,
1962
+ hasHook: false
1963
+ };
1964
+ }
1965
+ }
1966
+
1967
+ // src/utils/boxShadowValueParser.ts
1968
+ var import_css_tree3 = require("@eslint/css-tree");
1969
+ function isColorValue(node) {
1970
+ if (!node) return false;
1971
+ switch (node.type) {
1972
+ case "Hash":
1973
+ return true;
1974
+ // #hex colors
1975
+ case "Identifier":
1976
+ return isValidColor(node.name);
1977
+ case "Function":
1978
+ return isCssColorFunction(node.name.toLowerCase());
1979
+ default:
1980
+ return false;
1981
+ }
1982
+ }
1983
+ function isLengthValue(node) {
1984
+ if (!node) return false;
1985
+ switch (node.type) {
1986
+ case "Dimension":
1987
+ const dimensionStr = `${node.value}${node.unit}`;
1988
+ return parseUnitValue(dimensionStr) !== null;
1989
+ case "Number":
1990
+ return Number(node.value) === 0;
1991
+ default:
1992
+ return false;
1993
+ }
1994
+ }
1995
+ function isInsetKeyword(node) {
1996
+ return node?.type === "Identifier" && node.name.toLowerCase() === "inset";
1997
+ }
1998
+ function extractShadowParts(valueText) {
1999
+ const shadows = [];
2000
+ let currentShadow = {
2001
+ lengthParts: [],
2002
+ colorParts: [],
2003
+ inset: false
2004
+ };
2005
+ try {
2006
+ const ast = (0, import_css_tree3.parse)(valueText, { context: "value" });
2007
+ (0, import_css_tree3.walk)(ast, {
2008
+ enter(node) {
2009
+ if (node.type === "Function") {
2010
+ return this.skip;
2011
+ }
2012
+ if (isInsetKeyword(node)) {
2013
+ currentShadow.inset = true;
2014
+ } else if (isLengthValue(node)) {
2015
+ currentShadow.lengthParts.push((0, import_css_tree3.generate)(node));
2016
+ } else if (isColorValue(node)) {
2017
+ currentShadow.colorParts.push((0, import_css_tree3.generate)(node));
2018
+ }
2019
+ }
2020
+ });
2021
+ if (currentShadow.lengthParts.length > 0 || currentShadow.colorParts.length > 0 || currentShadow.inset) {
2022
+ shadows.push(currentShadow);
2023
+ }
2024
+ } catch (error) {
2025
+ return [];
2026
+ }
2027
+ return shadows;
2028
+ }
2029
+ function parseBoxShadowValue(value) {
2030
+ const shadowStrings = value.split(",").map((s) => s.trim());
2031
+ const allShadows = [];
2032
+ for (const shadowString of shadowStrings) {
2033
+ const shadows = extractShadowParts(shadowString);
2034
+ const parsedShadows = shadows.map((shadow) => {
2035
+ const shadowValue = {};
2036
+ const lengthProps = ["offsetX", "offsetY", "blurRadius", "spreadRadius"];
2037
+ lengthProps.forEach((prop, index) => {
2038
+ if (shadow.lengthParts.length > index) {
2039
+ shadowValue[prop] = shadow.lengthParts[index];
2040
+ }
2041
+ });
2042
+ if (shadow.colorParts.length > 0) {
2043
+ shadowValue.color = shadow.colorParts[0];
2044
+ }
2045
+ if (shadow.inset) {
2046
+ shadowValue.inset = true;
2047
+ }
2048
+ return shadowValue;
2049
+ });
2050
+ allShadows.push(...parsedShadows);
2051
+ }
2052
+ return allShadows;
2053
+ }
2054
+ function normalizeLengthValue(value) {
2055
+ if (!value) return "0px";
2056
+ if (value === "0") return "0px";
2057
+ return value;
2058
+ }
2059
+ function isBoxShadowMatch(parsedCssValue, parsedValueHook) {
2060
+ if (parsedCssValue.length !== parsedValueHook.length) {
2061
+ return false;
2062
+ }
2063
+ for (let i = 0; i < parsedCssValue.length; i++) {
2064
+ const cssShadow = parsedCssValue[i];
2065
+ const hookShadow = parsedValueHook[i];
2066
+ if (cssShadow.color !== hookShadow.color || cssShadow.inset !== hookShadow.inset) {
2067
+ return false;
2068
+ }
2069
+ const lengthProps = ["offsetX", "offsetY", "blurRadius", "spreadRadius"];
2070
+ for (const prop of lengthProps) {
2071
+ if (normalizeLengthValue(cssShadow[prop]) !== normalizeLengthValue(hookShadow[prop])) {
2072
+ return false;
2073
+ }
2074
+ }
2075
+ }
2076
+ return true;
2077
+ }
2078
+
2079
+ // src/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.ts
2080
+ function toBoxShadowValue(cssValue) {
2081
+ const parsedCssValue = parseBoxShadowValue(cssValue).filter((shadow) => Object.keys(shadow).length > 0);
2082
+ if (parsedCssValue.length === 0) {
2083
+ return null;
2084
+ }
2085
+ return parsedCssValue;
2086
+ }
2087
+ function shadowValueToHookEntries(supportedStylinghooks) {
2088
+ return Object.entries(supportedStylinghooks).filter(([key, value]) => {
2089
+ return value.some((hook) => hook.properties.includes("box-shadow"));
2090
+ }).map(([key, value]) => {
2091
+ return [key, value.map((hook) => hook.name)];
2092
+ });
2093
+ }
2094
+ var handleBoxShadowDeclaration = (node, context) => {
2095
+ const cssProperty = node.property.toLowerCase();
2096
+ const valueText = context.sourceCode.getText(node.value);
2097
+ const shadowHooks = shadowValueToHookEntries(context.valueToStylinghook);
2098
+ const parsedCssValue = toBoxShadowValue(valueText);
2099
+ if (!parsedCssValue) {
2100
+ return;
2101
+ }
2102
+ for (const [shadow, closestHooks] of shadowHooks) {
2103
+ const parsedValueHook = toBoxShadowValue(shadow);
2104
+ if (parsedValueHook && isBoxShadowMatch(parsedCssValue, parsedValueHook)) {
2105
+ if (closestHooks.length > 0) {
2106
+ const positionInfo = {
2107
+ start: { offset: 0, line: 1, column: 1 },
2108
+ end: { offset: valueText.length, line: 1, column: valueText.length + 1 }
2109
+ };
2110
+ const replacement = createBoxShadowReplacement(
2111
+ valueText,
2112
+ closestHooks,
2113
+ context,
2114
+ positionInfo
2115
+ );
2116
+ if (replacement) {
2117
+ const replacements = [replacement];
2118
+ handleShorthandAutoFix(node, context, valueText, replacements);
2119
+ }
2120
+ }
2121
+ return;
2122
+ }
2123
+ }
2124
+ };
2125
+ function createBoxShadowReplacement(originalValue, hooks, context, positionInfo) {
2126
+ if (!positionInfo?.start) {
2127
+ return null;
2128
+ }
2129
+ const start = positionInfo.start.offset;
2130
+ const end = positionInfo.end.offset;
2131
+ if (hooks.length === 1) {
2132
+ return {
2133
+ start,
2134
+ end,
2135
+ replacement: `var(${hooks[0]}, ${originalValue})`,
2136
+ displayValue: hooks[0],
2137
+ hasHook: true
2138
+ };
2139
+ } else {
2140
+ return {
2141
+ start,
2142
+ end,
2143
+ replacement: originalValue,
2144
+ displayValue: formatSuggestionHooks(hooks),
2145
+ hasHook: true
2146
+ };
2147
+ }
2148
+ }
2149
+
2150
+ // src/utils/rule-utils.ts
2151
+ function isRuleEnabled(context, ruleName3) {
2152
+ try {
2153
+ const rules2 = context.settings?.sldsRules || {};
2154
+ if (ruleName3 in rules2) {
2155
+ const ruleConfig14 = rules2[ruleName3];
2156
+ if (Array.isArray(ruleConfig14)) {
2157
+ return ruleConfig14[0] === true;
2158
+ } else if (ruleConfig14 !== void 0 && ruleConfig14 !== null) {
2159
+ return true;
2160
+ } else if (ruleConfig14 === false) {
2161
+ return false;
2162
+ }
2163
+ }
2164
+ } catch (error) {
2165
+ return false;
2166
+ }
2167
+ }
2168
+
2169
+ // src/rules/v9/no-hardcoded-values/noHardcodedValueRule.ts
2170
+ function defineNoHardcodedValueRule(config) {
2171
+ const { ruleConfig: ruleConfig14, ruleName: ruleName3 } = config;
2172
+ const { type: type15, description: description15, url: url15, messages: messages15 } = ruleConfig14;
2173
+ return {
2174
+ meta: {
2175
+ type: type15,
2176
+ docs: {
2177
+ description: description15,
2178
+ recommended: true,
2179
+ url: url15
2180
+ },
2181
+ fixable: "code",
2182
+ messages: messages15
2183
+ },
2184
+ create(context) {
2185
+ if (ruleName3 === "no-hardcoded-values-slds1" && isRuleEnabled(context, "@salesforce-ux/slds/no-hardcoded-values-slds2")) {
2186
+ return {};
2187
+ }
2188
+ const handlerContext = {
2189
+ valueToStylinghook: config.valueToStylinghook,
2190
+ context,
2191
+ sourceCode: context.sourceCode
2192
+ };
2193
+ const colorOnlySelector = toSelector(colorProperties);
2194
+ const densityOnlySelector = toSelector(densificationProperties);
2195
+ const fontDensitySelector = toSelector(fontProperties);
2196
+ const overlappingProperties = colorProperties.filter((colorProp) => {
2197
+ return densificationProperties.some((densityProp) => {
2198
+ if (densityProp === colorProp) {
2199
+ return true;
2200
+ }
2201
+ if (densityProp.includes("*")) {
2202
+ const regexPattern = new RegExp("^" + densityProp.replace(/\*/g, ".*") + "$");
2203
+ return regexPattern.test(colorProp);
2204
+ }
2205
+ return false;
2206
+ });
2207
+ });
2208
+ const overlappingSet = new Set(overlappingProperties);
2209
+ const colorOnlyProps = colorProperties.filter((prop) => !overlappingSet.has(prop));
2210
+ const densityOnlyProps = densificationProperties.filter((prop) => !overlappingSet.has(prop));
2211
+ const visitors = {};
2212
+ if (colorOnlyProps.length > 0) {
2213
+ const colorOnlySelector2 = toSelector(colorOnlyProps);
2214
+ visitors[colorOnlySelector2] = (node) => {
2215
+ handleColorDeclaration(node, handlerContext);
2216
+ };
2217
+ }
2218
+ if (densityOnlyProps.length > 0) {
2219
+ const densityOnlySelector2 = toSelector(densityOnlyProps);
2220
+ visitors[densityOnlySelector2] = (node) => {
2221
+ handleDensityDeclaration(node, handlerContext);
2222
+ };
2223
+ }
2224
+ visitors[fontDensitySelector] = (node) => {
2225
+ handleFontDeclaration(node, handlerContext);
2226
+ };
2227
+ visitors['Declaration[property="box-shadow"]'] = (node) => {
2228
+ handleBoxShadowDeclaration(node, handlerContext);
2229
+ };
2230
+ if (overlappingProperties.length > 0) {
2231
+ const overlappingSelector = toSelector(overlappingProperties);
2232
+ visitors[overlappingSelector] = (node) => {
2233
+ handleColorDeclaration(node, handlerContext);
2234
+ handleDensityDeclaration(node, handlerContext);
2235
+ };
2236
+ }
2237
+ return visitors;
2238
+ }
2239
+ };
2240
+ }
2241
+
2242
+ // src/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.ts
2243
+ var ruleName = "no-hardcoded-values-slds1";
2244
+ var ruleConfig12 = import_rule_messages14.default[ruleName];
2245
+ var { type: type13, description: description13, url: url13, messages: messages13 } = ruleConfig12;
2246
+ var valueToStylinghook = import_sds_metadata12.default.valueToStylingHooksSlds;
2247
+ var no_hardcoded_values_slds1_default = defineNoHardcodedValueRule({
2248
+ ruleConfig: ruleConfig12,
2249
+ valueToStylinghook,
2250
+ ruleName
2251
+ });
2252
+
2253
+ // src/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.ts
2254
+ var import_sds_metadata13 = __toESM(require("@salesforce-ux/sds-metadata"));
2255
+ var import_rule_messages15 = __toESM(require_rule_messages());
2256
+ var ruleName2 = "no-hardcoded-values-slds2";
2257
+ var ruleConfig13 = import_rule_messages15.default[ruleName2];
2258
+ var { type: type14, description: description14, url: url14, messages: messages14 } = ruleConfig13;
2259
+ var valueToStylinghook2 = import_sds_metadata13.default.valueToStylingHooksCosmos;
2260
+ var no_hardcoded_values_slds2_default = defineNoHardcodedValueRule({
2261
+ ruleConfig: ruleConfig13,
2262
+ valueToStylinghook: valueToStylinghook2,
2263
+ ruleName: ruleName2
2264
+ });
2265
+
2266
+ // src/index.ts
2267
+ var import_parser2 = __toESM(require("@html-eslint/parser"));
2268
+ var import_css = __toESM(require("@eslint/css"));
2269
+
2270
+ // eslint.rules.json
2271
+ var eslint_rules_default = {
2272
+ css: {
2273
+ "@salesforce-ux/slds/no-slds-class-overrides": "warn",
2274
+ "@salesforce-ux/slds/no-deprecated-slds-classes": "warn",
2275
+ "@salesforce-ux/slds/enforce-sds-to-slds-hooks": "warn",
2276
+ "@salesforce-ux/slds/no-sldshook-fallback-for-lwctoken": "warn",
2277
+ "@salesforce-ux/slds/no-unsupported-hooks-slds2": "warn",
2278
+ "@salesforce-ux/slds/no-slds-var-without-fallback": "warn",
2279
+ "@salesforce-ux/slds/no-slds-namespace-for-custom-hooks": "warn",
2280
+ "@salesforce-ux/slds/enforce-component-hook-naming-convention": "error",
2281
+ "@salesforce-ux/slds/no-slds-private-var": "warn",
2282
+ "@salesforce-ux/slds/no-hardcoded-values-slds2": "warn",
2283
+ "@salesforce-ux/slds/reduce-annotations": "warn"
2284
+ },
2285
+ html: {
2286
+ "@salesforce-ux/slds/enforce-bem-usage": "error",
2287
+ "@salesforce-ux/slds/no-deprecated-classes-slds2": "error",
2288
+ "@salesforce-ux/slds/modal-close-button-issue": "error"
2289
+ }
2290
+ };
2291
+
2292
+ // src/index.ts
2293
+ var rules = {
2294
+ "enforce-bem-usage": import_enforce_bem_usage.default,
2295
+ "no-deprecated-classes-slds2": import_no_deprecated_classes_slds2.default,
2296
+ "modal-close-button-issue": import_modal_close_button_issue.default,
2297
+ "no-slds-class-overrides": no_slds_class_overrides_default,
2298
+ "no-deprecated-slds-classes": no_deprecated_slds_classes_default,
2299
+ "no-deprecated-tokens-slds1": no_deprecated_tokens_slds1_default,
2300
+ "lwc-token-to-slds-hook": lwc_token_to_slds_hook_default,
2301
+ "enforce-sds-to-slds-hooks": enforce_sds_to_slds_hooks_default,
2302
+ "no-sldshook-fallback-for-lwctoken": no_sldshook_fallback_for_lwctoken_default,
2303
+ "no-unsupported-hooks-slds2": no_unsupported_hooks_slds2_default,
2304
+ "no-slds-var-without-fallback": no_slds_var_without_fallback_default,
2305
+ "no-slds-namespace-for-custom-hooks": no_slds_namespace_for_custom_hooks_default,
2306
+ "enforce-component-hook-naming-convention": enforce_component_hook_naming_convention_default,
2307
+ "no-slds-private-var": no_slds_private_var_default,
2308
+ "no-hardcoded-values-slds1": no_hardcoded_values_slds1_default,
2309
+ "no-hardcoded-values-slds2": no_hardcoded_values_slds2_default,
2310
+ "reduce-annotations": reduce_annotations_default
2311
+ };
2312
+ var plugin = {
2313
+ meta: {
2314
+ name: "@salesforce-ux/eslint-plugin-slds",
2315
+ version: "1.0.0-alpha.0"
2316
+ },
2317
+ rules,
2318
+ configs: {}
2319
+ };
2320
+ var cssConfigArray = [
2321
+ // CSS config - Standard CSS files
2322
+ {
2323
+ files: ["**/*.{css,scss}"],
2324
+ language: "css/css",
2325
+ ...import_css.default.configs.recommended,
2326
+ languageOptions: {
2327
+ tolerant: true
2328
+ // Allow recoverable parsing errors for SCSS syntax
2329
+ },
2330
+ plugins: {
2331
+ css: import_css.default,
2332
+ "@salesforce-ux/slds": plugin
2333
+ },
2334
+ rules: eslint_rules_default.css,
2335
+ settings: {
2336
+ // Pass rules configuration to context for runtime access
2337
+ sldsRules: { ...eslint_rules_default.css }
2338
+ }
2339
+ }
2340
+ ];
2341
+ var htmlConfigArray = [
2342
+ // HTML/Component config
2343
+ {
2344
+ files: ["**/*.html", "**/*.cmp"],
2345
+ languageOptions: {
2346
+ parser: import_parser2.default,
2347
+ ecmaVersion: 2021,
2348
+ sourceType: "module"
2349
+ },
2350
+ plugins: {
2351
+ "@salesforce-ux/slds": plugin
2352
+ },
2353
+ rules: eslint_rules_default.html
2354
+ }
2355
+ ];
2356
+ Object.assign(plugin.configs, {
2357
+ // Flat config for ESLint v9+
2358
+ "flat/recommended-css": cssConfigArray,
2359
+ "flat/recommended-html": htmlConfigArray,
2360
+ "flat/recommended": [...cssConfigArray, ...htmlConfigArray],
2361
+ // legacy config for ESLint v8-
2362
+ recommended: {
2363
+ plugins: ["@salesforce-ux/slds"],
2364
+ rules: eslint_rules_default.html,
2365
+ parser: import_parser2.default,
2366
+ parserOptions: {
2367
+ ecmaVersion: 2021,
2368
+ sourceType: "module"
56
2369
  }
2370
+ }
57
2371
  });
58
2372
  module.exports = plugin;
2373
+ //# sourceMappingURL=index.js.map