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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +62 -0
  2. package/build/config/rule-messages.d.ts +2 -0
  3. package/build/config/rule-messages.js +197 -0
  4. package/build/config/rule-messages.js.map +7 -0
  5. package/build/index.js +40 -2332
  6. package/build/index.js.map +4 -4
  7. package/build/rules/enforce-bem-usage.js +18 -234
  8. package/build/rules/enforce-bem-usage.js.map +4 -4
  9. package/build/rules/modal-close-button-issue.js +11 -183
  10. package/build/rules/modal-close-button-issue.js.map +4 -4
  11. package/build/rules/no-deprecated-classes-slds2.js +6 -178
  12. package/build/rules/no-deprecated-classes-slds2.js.map +4 -4
  13. package/build/rules/v9/enforce-bem-usage.js +3 -163
  14. package/build/rules/v9/enforce-bem-usage.js.map +4 -4
  15. package/build/rules/v9/enforce-component-hook-naming-convention.js +3 -163
  16. package/build/rules/v9/enforce-component-hook-naming-convention.js.map +4 -4
  17. package/build/rules/v9/enforce-sds-to-slds-hooks.js +3 -163
  18. package/build/rules/v9/enforce-sds-to-slds-hooks.js.map +4 -4
  19. package/build/rules/v9/lwc-token-to-slds-hook.js +6 -264
  20. package/build/rules/v9/lwc-token-to-slds-hook.js.map +4 -4
  21. package/build/rules/v9/no-deprecated-slds-classes.js +3 -163
  22. package/build/rules/v9/no-deprecated-slds-classes.js.map +4 -4
  23. package/build/rules/v9/no-deprecated-tokens-slds1.js +30 -169
  24. package/build/rules/v9/no-deprecated-tokens-slds1.js.map +4 -4
  25. package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js +29 -253
  26. package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js.map +4 -4
  27. package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js +31 -289
  28. package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js.map +4 -4
  29. package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js +23 -286
  30. package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js.map +4 -4
  31. package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js +24 -316
  32. package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js.map +4 -4
  33. package/build/rules/v9/no-hardcoded-values/handlers/index.js +8 -799
  34. package/build/rules/v9/no-hardcoded-values/handlers/index.js.map +4 -4
  35. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js +5 -1090
  36. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js.map +4 -4
  37. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js +5 -1090
  38. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js.map +4 -4
  39. package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js +31 -882
  40. package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js.map +4 -4
  41. package/build/rules/v9/no-hardcoded-values/ruleOptionsSchema.d.ts +40 -0
  42. package/build/rules/v9/no-hardcoded-values/ruleOptionsSchema.js +63 -0
  43. package/build/rules/v9/no-hardcoded-values/ruleOptionsSchema.js.map +7 -0
  44. package/build/rules/v9/no-slds-class-overrides.js +3 -163
  45. package/build/rules/v9/no-slds-class-overrides.js.map +4 -4
  46. package/build/rules/v9/no-slds-namespace-for-custom-hooks.js +5 -254
  47. package/build/rules/v9/no-slds-namespace-for-custom-hooks.js.map +4 -4
  48. package/build/rules/v9/no-slds-private-var.js +1 -161
  49. package/build/rules/v9/no-slds-private-var.js.map +4 -4
  50. package/build/rules/v9/no-slds-var-without-fallback.js +5 -257
  51. package/build/rules/v9/no-slds-var-without-fallback.js.map +4 -4
  52. package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js +3 -163
  53. package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js.map +4 -4
  54. package/build/rules/v9/no-unsupported-hooks-slds2.js +3 -163
  55. package/build/rules/v9/no-unsupported-hooks-slds2.js.map +4 -4
  56. package/build/rules/v9/reduce-annotations.js +1 -161
  57. package/build/rules/v9/reduce-annotations.js.map +4 -4
  58. package/build/types/index.d.ts +57 -0
  59. package/build/types/index.js.map +1 -1
  60. package/build/{src/utils → utils}/boxShadowValueParser.d.ts +1 -1
  61. package/build/utils/boxShadowValueParser.js +63 -93
  62. package/build/utils/boxShadowValueParser.js.map +4 -4
  63. package/build/utils/color-lib-utils.d.ts +25 -0
  64. package/build/utils/color-lib-utils.js +28 -79
  65. package/build/utils/color-lib-utils.js.map +3 -3
  66. package/build/{src/utils → utils}/css-utils.d.ts +7 -0
  67. package/build/utils/css-utils.js +10 -71
  68. package/build/utils/css-utils.js.map +4 -4
  69. package/build/utils/custom-mapping-utils.d.ts +9 -0
  70. package/build/utils/custom-mapping-utils.js +62 -0
  71. package/build/utils/custom-mapping-utils.js.map +7 -0
  72. package/build/{src/utils → utils}/hardcoded-shared-utils.d.ts +1 -0
  73. package/build/utils/hardcoded-shared-utils.js +46 -98
  74. package/build/utils/hardcoded-shared-utils.js.map +4 -4
  75. package/build/{src/utils → utils}/property-matcher.d.ts +3 -1
  76. package/build/utils/property-matcher.js +22 -8
  77. package/build/utils/property-matcher.js.map +2 -2
  78. package/build/utils/styling-hook-utils.js +16 -39
  79. package/build/utils/styling-hook-utils.js.map +3 -3
  80. package/build/{src/utils → utils}/value-utils.d.ts +2 -2
  81. package/build/utils/value-utils.js +8 -8
  82. package/build/utils/value-utils.js.map +2 -2
  83. package/package.json +6 -11
  84. package/build/src/types/index.d.ts +0 -26
  85. package/build/src/utils/color-lib-utils.d.ts +0 -18
  86. package/src/config/rule-messages.yml +0 -143
  87. /package/build/{src/index.d.ts → index.d.ts} +0 -0
  88. /package/build/{src/rules → rules}/enforce-bem-usage.d.ts +0 -0
  89. /package/build/{src/rules → rules}/modal-close-button-issue.d.ts +0 -0
  90. /package/build/{src/rules → rules}/no-deprecated-classes-slds2.d.ts +0 -0
  91. /package/build/{src/rules → rules}/v9/enforce-bem-usage.d.ts +0 -0
  92. /package/build/{src/rules → rules}/v9/enforce-component-hook-naming-convention.d.ts +0 -0
  93. /package/build/{src/rules → rules}/v9/enforce-sds-to-slds-hooks.d.ts +0 -0
  94. /package/build/{src/rules → rules}/v9/lwc-token-to-slds-hook.d.ts +0 -0
  95. /package/build/{src/rules → rules}/v9/no-deprecated-slds-classes.d.ts +0 -0
  96. /package/build/{src/rules → rules}/v9/no-deprecated-tokens-slds1.d.ts +0 -0
  97. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/boxShadowHandler.d.ts +0 -0
  98. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/colorHandler.d.ts +0 -0
  99. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/densityHandler.d.ts +0 -0
  100. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/fontHandler.d.ts +0 -0
  101. /package/build/{src/rules → rules}/v9/no-hardcoded-values/handlers/index.d.ts +0 -0
  102. /package/build/{src/rules → rules}/v9/no-hardcoded-values/no-hardcoded-values-slds1.d.ts +0 -0
  103. /package/build/{src/rules → rules}/v9/no-hardcoded-values/no-hardcoded-values-slds2.d.ts +0 -0
  104. /package/build/{src/rules → rules}/v9/no-hardcoded-values/noHardcodedValueRule.d.ts +0 -0
  105. /package/build/{src/rules → rules}/v9/no-slds-class-overrides.d.ts +0 -0
  106. /package/build/{src/rules → rules}/v9/no-slds-namespace-for-custom-hooks.d.ts +0 -0
  107. /package/build/{src/rules → rules}/v9/no-slds-private-var.d.ts +0 -0
  108. /package/build/{src/rules → rules}/v9/no-slds-var-without-fallback.d.ts +0 -0
  109. /package/build/{src/rules → rules}/v9/no-sldshook-fallback-for-lwctoken.d.ts +0 -0
  110. /package/build/{src/rules → rules}/v9/no-unsupported-hooks-slds2.d.ts +0 -0
  111. /package/build/{src/rules → rules}/v9/reduce-annotations.d.ts +0 -0
  112. /package/build/{src/utils → utils}/css-functions.d.ts +0 -0
  113. /package/build/{src/utils → utils}/node.d.ts +0 -0
  114. /package/build/{src/utils → utils}/rule-utils.d.ts +0 -0
  115. /package/build/{src/utils → utils}/styling-hook-utils.d.ts +0 -0
@@ -1,8 +1,6 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
5
  var __export = (target, all) => {
8
6
  for (var name in all)
@@ -16,14 +14,6 @@ var __copyProps = (to, from, except, desc) => {
16
14
  }
17
15
  return to;
18
16
  };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
18
 
29
19
  // src/rules/v9/no-hardcoded-values/noHardcodedValueRule.ts
@@ -32,859 +22,10 @@ __export(noHardcodedValueRule_exports, {
32
22
  defineNoHardcodedValueRule: () => defineNoHardcodedValueRule
33
23
  });
34
24
  module.exports = __toCommonJS(noHardcodedValueRule_exports);
35
-
36
- // src/utils/color-lib-utils.ts
37
- var import_chroma_js = __toESM(require("chroma-js"));
38
- var import_css_tree = require("@eslint/css-tree");
39
-
40
- // src/utils/css-functions.ts
41
- var CSS_FUNCTIONS = [
42
- "attr",
43
- "calc",
44
- "color-mix",
45
- "conic-gradient",
46
- "counter",
47
- "cubic-bezier",
48
- "linear-gradient",
49
- "max",
50
- "min",
51
- "radial-gradient",
52
- "repeating-conic-gradient",
53
- "repeating-linear-gradient",
54
- "repeating-radial-gradient",
55
- "var"
56
- ];
57
- var CSS_MATH_FUNCTIONS = ["calc", "min", "max"];
58
- var RGB_COLOR_FUNCTIONS = ["rgb", "rgba", "hsl", "hsla"];
59
- var cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join("|")})`);
60
- var cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join("|")})$`);
61
- var cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join("|")})$`);
62
- function isCssFunction(value) {
63
- return cssFunctionsExactRegex.test(value);
64
- }
65
- function isCssColorFunction(value) {
66
- return RGB_COLOR_FUNCTIONS.includes(value);
67
- }
68
-
69
- // src/utils/color-lib-utils.ts
70
- var LAB_THRESHOLD = 25;
71
- var isHexCode = (color) => {
72
- const hexPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/;
73
- return hexPattern.test(color);
74
- };
75
- var convertToHex = (color) => {
76
- try {
77
- return (0, import_chroma_js.default)(color).hex();
78
- } catch (e) {
79
- return null;
80
- }
81
- };
82
- var findClosestColorHook = (color, supportedColors, cssProperty) => {
83
- const returnStylingHooks = [];
84
- const closestHooksWithSameProperty = [];
85
- const closestHooksWithoutSameProperty = [];
86
- const closestHooksWithAllProperty = [];
87
- const labColor = (0, import_chroma_js.default)(color).lab();
88
- Object.entries(supportedColors).forEach(([sldsValue, data]) => {
89
- if (sldsValue && isHexCode(sldsValue)) {
90
- const hooks = data;
91
- hooks.forEach((hook) => {
92
- const labSupportedColor = (0, import_chroma_js.default)(sldsValue).lab();
93
- 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");
94
- if (hook.properties.includes(cssProperty)) {
95
- if (distance <= LAB_THRESHOLD) {
96
- closestHooksWithSameProperty.push({ name: hook.name, distance });
97
- }
98
- } else if (hook.properties.includes("*")) {
99
- if (distance <= LAB_THRESHOLD) {
100
- closestHooksWithAllProperty.push({ name: hook.name, distance });
101
- }
102
- } else {
103
- if (distance <= LAB_THRESHOLD) {
104
- closestHooksWithoutSameProperty.push({ name: hook.name, distance });
105
- }
106
- }
107
- });
108
- }
109
- });
110
- const closesthookGroups = [
111
- { hooks: closestHooksWithSameProperty, distance: 0 },
112
- { hooks: closestHooksWithAllProperty, distance: 0 },
113
- { hooks: closestHooksWithSameProperty, distance: Infinity },
114
- // For hooks with distance > 0
115
- { hooks: closestHooksWithAllProperty, distance: Infinity },
116
- { hooks: closestHooksWithoutSameProperty, distance: Infinity }
117
- ];
118
- for (const group of closesthookGroups) {
119
- const filteredHooks = group.hooks.filter(
120
- (h) => group.distance === 0 ? h.distance === 0 : h.distance > 0
121
- );
122
- if (returnStylingHooks.length < 1 && filteredHooks.length > 0) {
123
- filteredHooks.sort((a, b) => a.distance - b.distance);
124
- returnStylingHooks.push(...filteredHooks.slice(0, 5).map((h) => h.name));
125
- }
126
- }
127
- return Array.from(new Set(returnStylingHooks));
128
- };
129
- var isValidColor = (val) => import_chroma_js.default.valid(val);
130
- var extractColorValue = (node) => {
131
- let colorValue = null;
132
- switch (node.type) {
133
- case "Hash":
134
- colorValue = `#${node.value}`;
135
- break;
136
- case "Identifier":
137
- colorValue = node.name;
138
- break;
139
- case "Function":
140
- if (isCssColorFunction(node.name)) {
141
- colorValue = (0, import_css_tree.generate)(node);
142
- }
143
- break;
144
- }
145
- return colorValue && isValidColor(colorValue) ? colorValue : null;
146
- };
147
-
148
- // src/utils/property-matcher.ts
149
- var DIRECTION_VALUES = "(?:top|right|bottom|left|inline|block|inline-start|inline-end|start|end|block-start|block-end)";
150
- var CORNER_VALUES = "(?:top-left|top-right|bottom-right|bottom-left|start-start|start-end|end-start|end-end)";
151
- var INSET_VALUES = "(?:inline|block|inline-start|inline-end|block-start|block-end)";
152
- var BORDER_COLOR_REGEX = new RegExp(`^border(?:-${DIRECTION_VALUES})?-color$`);
153
- var BORDER_WIDTH_REGEX = new RegExp(`^border(?:-${DIRECTION_VALUES})?-width$`);
154
- var MARGIN_REGEX = new RegExp(`^margin(?:-${DIRECTION_VALUES})?$`);
155
- var PADDING_REGEX = new RegExp(`^padding(?:-${DIRECTION_VALUES})?$`);
156
- var BORDER_RADIUS_REGEX = new RegExp(`^border(?:-${CORNER_VALUES})?-radius$`);
157
- var INSET_REGEX = new RegExp(`^inset(?:-${INSET_VALUES})?$`);
158
- function isBorderColorProperty(cssProperty) {
159
- return BORDER_COLOR_REGEX.test(cssProperty);
160
- }
161
- function isBorderWidthProperty(cssProperty) {
162
- return BORDER_WIDTH_REGEX.test(cssProperty);
163
- }
164
- function isMarginProperty(cssProperty) {
165
- return MARGIN_REGEX.test(cssProperty);
166
- }
167
- function isPaddingProperty(cssProperty) {
168
- return PADDING_REGEX.test(cssProperty);
169
- }
170
- function isBorderRadius(cssProperty) {
171
- return BORDER_RADIUS_REGEX.test(cssProperty);
172
- }
173
- function isDimensionProperty(cssProperty) {
174
- return ["width", "height", "min-width", "max-width", "min-height", "max-height"].includes(cssProperty);
175
- }
176
- function isInsetProperty(cssProperty) {
177
- return INSET_REGEX.test(cssProperty);
178
- }
179
- var fontProperties = [
180
- "font",
181
- "font-size",
182
- "font-weight"
183
- ];
184
- var colorProperties = [
185
- "color",
186
- "fill",
187
- "background",
188
- "background-color",
189
- "stroke",
190
- "border",
191
- "border*",
192
- "border*-color",
193
- "outline",
194
- "outline-color"
195
- ];
196
- var densificationProperties = [
197
- "border*",
198
- "margin*",
199
- "padding*",
200
- "width",
201
- "height",
202
- "min-width",
203
- "max-width",
204
- "min-height",
205
- "max-height",
206
- "inset",
207
- "top",
208
- "right",
209
- "left",
210
- "bottom",
211
- "outline",
212
- "outline-width",
213
- "line-height"
214
- ];
215
- function toSelector(properties) {
216
- const selectorParts = properties.map((prop) => {
217
- if (prop.includes("*")) {
218
- const regexPattern = prop.replace(/\*/g, ".*");
219
- return `Declaration[property=/^${regexPattern}$/]`;
220
- } else {
221
- return `Declaration[property='${prop}']`;
222
- }
223
- });
224
- return selectorParts.join(", ");
225
- }
226
- function resolvePropertyToMatch(cssProperty) {
227
- const propertyToMatch = cssProperty.toLowerCase();
228
- if (propertyToMatch === "outline" || propertyToMatch === "outline-width" || isBorderWidthProperty(propertyToMatch)) {
229
- return "border-width";
230
- } else if (isMarginProperty(propertyToMatch)) {
231
- return "margin";
232
- } else if (isPaddingProperty(propertyToMatch)) {
233
- return "padding";
234
- } else if (isBorderRadius(propertyToMatch)) {
235
- return "border-radius";
236
- } else if (isDimensionProperty(propertyToMatch)) {
237
- return "width";
238
- } else if (isInsetProperty(propertyToMatch)) {
239
- return "top";
240
- } else if (cssProperty === "background" || cssProperty === "background-color") {
241
- return "background-color";
242
- } else if (cssProperty === "outline" || cssProperty === "outline-color" || isBorderColorProperty(cssProperty)) {
243
- return "border-color";
244
- }
245
- return propertyToMatch;
246
- }
247
-
248
- // src/utils/hardcoded-shared-utils.ts
249
- var import_css_tree2 = require("@eslint/css-tree");
250
-
251
- // src/utils/value-utils.ts
252
- var ALLOWED_UNITS = ["px", "em", "rem", "%", "ch"];
253
- function parseUnitValue(value) {
254
- if (!value) return null;
255
- const unitsPattern = ALLOWED_UNITS.join("|");
256
- const regex = new RegExp(`^(-?\\d*\\.?\\d+)(${unitsPattern})?$`);
257
- const match = value.match(regex);
258
- if (!match) return null;
259
- const number = parseFloat(match[1]);
260
- const unit = match[2] ? match[2] : null;
261
- if (isNaN(number)) return null;
262
- return { number, unit };
263
- }
264
- function toAlternateUnitValue(numberVal, unitType) {
265
- if (unitType === "px") {
266
- let floatValue = parseFloat(`${numberVal / 16}`);
267
- if (!isNaN(floatValue)) {
268
- return {
269
- unit: "rem",
270
- number: parseFloat(floatValue.toFixed(4))
271
- };
272
- }
273
- } else if (unitType === "rem") {
274
- const intValue = parseInt(`${numberVal * 16}`);
275
- if (!isNaN(intValue)) {
276
- return {
277
- unit: "px",
278
- number: intValue
279
- };
280
- }
281
- }
282
- return null;
283
- }
284
-
285
- // src/utils/hardcoded-shared-utils.ts
286
- var FONT_WEIGHTS = [
287
- "normal",
288
- "bold",
289
- "bolder",
290
- "lighter",
291
- "100",
292
- "200",
293
- "300",
294
- "400",
295
- "500",
296
- "600",
297
- "700",
298
- "800",
299
- "900"
300
- ];
301
- function isKnownFontWeight(value) {
302
- const stringValue = value.toString();
303
- return FONT_WEIGHTS.includes(stringValue.toLowerCase());
304
- }
305
- function handleShorthandAutoFix(declarationNode, context, valueText, replacements) {
306
- const sortedReplacements = replacements.sort((a, b) => a.start - b.start);
307
- const hasAnyHooks = sortedReplacements.some((r) => r.hasHook);
308
- const canAutoFix = hasAnyHooks;
309
- sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook }) => {
310
- const originalValue = valueText.substring(start, end);
311
- const valueStartColumn = declarationNode.value.loc.start.column;
312
- const valueColumn = valueStartColumn + start;
313
- const { loc: { start: locStart, end: locEnd } } = declarationNode.value;
314
- const reportNode = {
315
- ...declarationNode.value,
316
- loc: {
317
- ...declarationNode.value.loc,
318
- start: {
319
- ...locStart,
320
- column: valueColumn
321
- },
322
- end: {
323
- ...locEnd,
324
- column: valueColumn + originalValue.length
325
- }
326
- }
327
- };
328
- if (hasHook) {
329
- const fix = canAutoFix ? (fixer) => {
330
- let newValue = valueText;
331
- for (let i = sortedReplacements.length - 1; i >= 0; i--) {
332
- const { start: rStart, end: rEnd, replacement: rReplacement } = sortedReplacements[i];
333
- newValue = newValue.substring(0, rStart) + rReplacement + newValue.substring(rEnd);
334
- }
335
- return fixer.replaceText(declarationNode.value, newValue);
336
- } : void 0;
337
- context.context.report({
338
- node: reportNode,
339
- messageId: "hardcodedValue",
340
- data: {
341
- oldValue: originalValue,
342
- newValue: displayValue
343
- },
344
- fix
345
- });
346
- } else {
347
- context.context.report({
348
- node: reportNode,
349
- messageId: "noReplacement",
350
- data: {
351
- oldValue: originalValue
352
- }
353
- });
354
- }
355
- });
356
- }
357
- function forEachValue(valueText, extractValue, shouldSkipNode, callback) {
358
- if (!valueText || typeof valueText !== "string") {
359
- return;
360
- }
361
- try {
362
- const ast = (0, import_css_tree2.parse)(valueText, { context: "value", positions: true });
363
- (0, import_css_tree2.walk)(ast, {
364
- enter(node) {
365
- if (shouldSkipNode(node)) {
366
- return this.skip;
367
- }
368
- const value = extractValue(node);
369
- if (value !== null) {
370
- const positionInfo = {
371
- start: node.loc?.start,
372
- end: node.loc?.end
373
- };
374
- callback(value, positionInfo);
375
- }
376
- }
377
- });
378
- } catch (error) {
379
- return;
380
- }
381
- }
382
- function shouldSkipColorNode(node) {
383
- return node.type === "Function" && isCssFunction(node.name);
384
- }
385
- function shouldSkipDimensionNode(node) {
386
- return node.type === "Function";
387
- }
388
- function extractDimensionValue(valueNode, cssProperty) {
389
- if (!valueNode) return null;
390
- switch (valueNode.type) {
391
- case "Dimension":
392
- const numValue = Number(valueNode.value);
393
- if (numValue === 0) return null;
394
- const unit = valueNode.unit.toLowerCase();
395
- if (!ALLOWED_UNITS.includes(unit)) return null;
396
- return {
397
- number: numValue,
398
- unit
399
- };
400
- case "Number":
401
- const numberValue = Number(valueNode.value);
402
- if (numberValue === 0) return null;
403
- return {
404
- number: numberValue,
405
- unit: null
406
- };
407
- case "Percentage":
408
- const percentValue = Number(valueNode.value);
409
- if (percentValue === 0) return null;
410
- return {
411
- number: percentValue,
412
- unit: "%"
413
- };
414
- case "Value":
415
- return valueNode.children?.[0] ? extractDimensionValue(valueNode.children[0], cssProperty) : null;
416
- }
417
- return null;
418
- }
419
- function forEachColorValue(valueText, callback) {
420
- forEachValue(valueText, extractColorValue, shouldSkipColorNode, callback);
421
- }
422
- function forEachDensityValue(valueText, cssProperty, callback) {
423
- forEachValue(
424
- valueText,
425
- (node) => extractDimensionValue(node, cssProperty),
426
- shouldSkipDimensionNode,
427
- callback
428
- );
429
- }
430
- function extractFontValue(node) {
431
- if (!node) return null;
432
- switch (node.type) {
433
- case "Dimension":
434
- const numValue = Number(node.value);
435
- if (numValue <= 0) return null;
436
- const unit = node.unit.toLowerCase();
437
- if (!ALLOWED_UNITS.includes(unit)) return null;
438
- return {
439
- number: numValue,
440
- unit
441
- };
442
- case "Number":
443
- const numberValue = Number(node.value);
444
- if (numberValue <= 0) {
445
- return null;
446
- }
447
- if (!isKnownFontWeight(numberValue)) {
448
- return null;
449
- }
450
- return {
451
- number: numberValue,
452
- unit: null
453
- };
454
- case "Identifier":
455
- const namedValue = node.name.toLowerCase();
456
- if (!isKnownFontWeight(namedValue)) {
457
- return null;
458
- }
459
- if (namedValue === "normal") {
460
- return { number: 400, unit: null };
461
- }
462
- return { number: namedValue, unit: null };
463
- case "Percentage":
464
- const percentValue = Number(node.value);
465
- if (percentValue === 0) return null;
466
- return {
467
- number: percentValue,
468
- unit: "%"
469
- };
470
- case "Value":
471
- return node.children?.[0] ? extractFontValue(node.children[0]) : null;
472
- }
473
- return null;
474
- }
475
- function shouldSkipFontNode(node) {
476
- return node.type === "Function";
477
- }
478
- function forEachFontValue(valueText, callback) {
479
- forEachValue(valueText, extractFontValue, shouldSkipFontNode, callback);
480
- }
481
-
482
- // src/utils/css-utils.ts
483
- function formatSuggestionHooks(hooks) {
484
- if (hooks.length === 1) {
485
- return `${hooks[0]}`;
486
- }
487
- return "\n" + hooks.map((hook, index) => `${index + 1}. ${hook}`).join("\n");
488
- }
489
-
490
- // src/rules/v9/no-hardcoded-values/handlers/colorHandler.ts
491
- var handleColorDeclaration = (node, context) => {
492
- const cssProperty = node.property.toLowerCase();
493
- const valueText = context.sourceCode.getText(node.value);
494
- const replacements = [];
495
- forEachColorValue(valueText, (colorValue, positionInfo) => {
496
- if (colorValue !== "transparent" && isValidColor(colorValue)) {
497
- const replacement = createColorReplacement(colorValue, cssProperty, context, positionInfo, valueText);
498
- if (replacement) {
499
- replacements.push(replacement);
500
- }
501
- }
502
- });
503
- handleShorthandAutoFix(node, context, valueText, replacements);
504
- };
505
- function createColorReplacement(colorValue, cssProperty, context, positionInfo, originalValueText) {
506
- if (!positionInfo?.start) {
507
- return null;
508
- }
509
- const hexValue = convertToHex(colorValue);
510
- if (!hexValue) {
511
- return null;
512
- }
513
- const propToMatch = resolvePropertyToMatch(cssProperty);
514
- const closestHooks = findClosestColorHook(hexValue, context.valueToStylinghook, propToMatch);
515
- const start = positionInfo.start.offset;
516
- const end = positionInfo.end.offset;
517
- const originalValue = originalValueText ? originalValueText.substring(start, end) : colorValue;
518
- if (closestHooks.length === 1) {
519
- return {
520
- start,
521
- end,
522
- replacement: `var(${closestHooks[0]}, ${colorValue})`,
523
- displayValue: closestHooks[0],
524
- hasHook: true
525
- };
526
- } else if (closestHooks.length > 1) {
527
- return {
528
- start,
529
- end,
530
- replacement: originalValue,
531
- // Use original value to preserve spacing
532
- displayValue: formatSuggestionHooks(closestHooks),
533
- hasHook: true
534
- };
535
- } else {
536
- return {
537
- start,
538
- end,
539
- replacement: originalValue,
540
- // Use original value to preserve spacing
541
- displayValue: originalValue,
542
- hasHook: false
543
- };
544
- }
545
- }
546
-
547
- // src/utils/styling-hook-utils.ts
548
- function isValueMatch(valueToMatch, sldsValue) {
549
- if (!valueToMatch || !sldsValue) {
550
- return false;
551
- }
552
- return valueToMatch.unit == sldsValue.unit && valueToMatch.number === sldsValue.number;
553
- }
554
- function getStylingHooksForDensityValue(parsedValue, supportedStylinghooks, cssProperty) {
555
- if (!parsedValue) return [];
556
- const alternateValue = toAlternateUnitValue(parsedValue.number, parsedValue.unit);
557
- const matchedHooks = [];
558
- for (const [sldsValue, hooks] of Object.entries(supportedStylinghooks)) {
559
- const parsedSldsValue = parseUnitValue(sldsValue);
560
- if (isValueMatch(parsedValue, parsedSldsValue) || alternateValue && isValueMatch(alternateValue, parsedSldsValue)) {
561
- hooks.filter((hook) => hook.properties.includes(cssProperty)).forEach((hook) => matchedHooks.push(hook.name));
562
- }
563
- }
564
- return matchedHooks;
565
- }
566
-
567
- // src/rules/v9/no-hardcoded-values/handlers/densityHandler.ts
568
- var handleDensityDeclaration = (node, context) => {
569
- const cssProperty = node.property.toLowerCase();
570
- const valueText = context.sourceCode.getText(node.value);
571
- const replacements = [];
572
- forEachDensityValue(valueText, cssProperty, (parsedDimension, positionInfo) => {
573
- if (parsedDimension) {
574
- const replacement = createDimensionReplacement(parsedDimension, cssProperty, context, positionInfo);
575
- if (replacement) {
576
- replacements.push(replacement);
577
- }
578
- }
579
- });
580
- handleShorthandAutoFix(node, context, valueText, replacements);
581
- };
582
- function createDimensionReplacement(parsedDimension, cssProperty, context, positionInfo) {
583
- if (!parsedDimension || !positionInfo?.start) {
584
- return null;
585
- }
586
- const rawValue = parsedDimension.unit ? `${parsedDimension.number}${parsedDimension.unit}` : parsedDimension.number.toString();
587
- const propToMatch = resolvePropertyToMatch(cssProperty);
588
- const closestHooks = getStylingHooksForDensityValue(parsedDimension, context.valueToStylinghook, propToMatch);
589
- const start = positionInfo.start.offset;
590
- const end = positionInfo.end.offset;
591
- if (closestHooks.length === 1) {
592
- return {
593
- start,
594
- end,
595
- replacement: `var(${closestHooks[0]}, ${rawValue})`,
596
- displayValue: closestHooks[0],
597
- hasHook: true
598
- };
599
- } else if (closestHooks.length > 1) {
600
- return {
601
- start,
602
- end,
603
- replacement: rawValue,
604
- displayValue: formatSuggestionHooks(closestHooks),
605
- hasHook: true
606
- };
607
- } else {
608
- return {
609
- start,
610
- end,
611
- replacement: rawValue,
612
- displayValue: rawValue,
613
- hasHook: false
614
- };
615
- }
616
- }
617
-
618
- // src/rules/v9/no-hardcoded-values/handlers/fontHandler.ts
619
- var handleFontDeclaration = (node, context) => {
620
- const cssProperty = node.property.toLowerCase();
621
- const valueText = context.sourceCode.getText(node.value);
622
- const replacements = [];
623
- forEachFontValue(valueText, (fontValue, positionInfo) => {
624
- if (fontValue && isValidFontValue(fontValue, cssProperty)) {
625
- const replacement = createFontReplacement(fontValue, cssProperty, context, positionInfo);
626
- if (replacement) {
627
- replacements.push(replacement);
628
- }
629
- }
630
- });
631
- handleShorthandAutoFix(node, context, valueText, replacements);
632
- };
633
- function isValidFontValue(fontValue, cssProperty) {
634
- if (cssProperty === "font-size") {
635
- return !!fontValue.unit;
636
- } else if (cssProperty === "font-weight") {
637
- return !fontValue.unit && isKnownFontWeight(fontValue.number);
638
- } else if (cssProperty === "font") {
639
- if (!fontValue.unit && isKnownFontWeight(fontValue.number)) {
640
- return true;
641
- } else if (fontValue.unit) {
642
- return true;
643
- } else {
644
- return false;
645
- }
646
- }
647
- return false;
648
- }
649
- function createFontReplacement(fontValue, cssProperty, context, positionInfo) {
650
- if (!positionInfo?.start) {
651
- return null;
652
- }
653
- const rawValue = fontValue.unit ? `${fontValue.number}${fontValue.unit}` : fontValue.number.toString();
654
- const propToMatch = !fontValue.unit && isKnownFontWeight(fontValue.number) ? resolvePropertyToMatch("font-weight") : resolvePropertyToMatch("font-size");
655
- const closestHooks = getStylingHooksForDensityValue(fontValue, context.valueToStylinghook, propToMatch);
656
- const start = positionInfo.start.offset;
657
- const end = positionInfo.end.offset;
658
- if (closestHooks.length === 1) {
659
- return {
660
- start,
661
- end,
662
- replacement: `var(${closestHooks[0]}, ${rawValue})`,
663
- displayValue: closestHooks[0],
664
- hasHook: true
665
- };
666
- } else if (closestHooks.length > 1) {
667
- return {
668
- start,
669
- end,
670
- replacement: rawValue,
671
- displayValue: formatSuggestionHooks(closestHooks),
672
- hasHook: true
673
- };
674
- } else {
675
- return {
676
- start,
677
- end,
678
- replacement: rawValue,
679
- displayValue: rawValue,
680
- hasHook: false
681
- };
682
- }
683
- }
684
-
685
- // src/utils/boxShadowValueParser.ts
686
- var import_css_tree3 = require("@eslint/css-tree");
687
- function isColorValue(node) {
688
- if (!node) return false;
689
- switch (node.type) {
690
- case "Hash":
691
- return true;
692
- // #hex colors
693
- case "Identifier":
694
- return isValidColor(node.name);
695
- case "Function":
696
- return isCssColorFunction(node.name.toLowerCase());
697
- default:
698
- return false;
699
- }
700
- }
701
- function isLengthValue(node) {
702
- if (!node) return false;
703
- switch (node.type) {
704
- case "Dimension":
705
- const dimensionStr = `${node.value}${node.unit}`;
706
- return parseUnitValue(dimensionStr) !== null;
707
- case "Number":
708
- return Number(node.value) === 0;
709
- default:
710
- return false;
711
- }
712
- }
713
- function isInsetKeyword(node) {
714
- return node?.type === "Identifier" && node.name.toLowerCase() === "inset";
715
- }
716
- function extractShadowParts(valueText) {
717
- const shadows = [];
718
- let currentShadow = {
719
- lengthParts: [],
720
- colorParts: [],
721
- inset: false
722
- };
723
- try {
724
- const ast = (0, import_css_tree3.parse)(valueText, { context: "value" });
725
- (0, import_css_tree3.walk)(ast, {
726
- enter(node) {
727
- if (node.type === "Function") {
728
- return this.skip;
729
- }
730
- if (isInsetKeyword(node)) {
731
- currentShadow.inset = true;
732
- } else if (isLengthValue(node)) {
733
- currentShadow.lengthParts.push((0, import_css_tree3.generate)(node));
734
- } else if (isColorValue(node)) {
735
- currentShadow.colorParts.push((0, import_css_tree3.generate)(node));
736
- }
737
- }
738
- });
739
- if (currentShadow.lengthParts.length > 0 || currentShadow.colorParts.length > 0 || currentShadow.inset) {
740
- shadows.push(currentShadow);
741
- }
742
- } catch (error) {
743
- return [];
744
- }
745
- return shadows;
746
- }
747
- function parseBoxShadowValue(value) {
748
- const shadowStrings = value.split(",").map((s) => s.trim());
749
- const allShadows = [];
750
- for (const shadowString of shadowStrings) {
751
- const shadows = extractShadowParts(shadowString);
752
- const parsedShadows = shadows.map((shadow) => {
753
- const shadowValue = {};
754
- const lengthProps = ["offsetX", "offsetY", "blurRadius", "spreadRadius"];
755
- lengthProps.forEach((prop, index) => {
756
- if (shadow.lengthParts.length > index) {
757
- shadowValue[prop] = shadow.lengthParts[index];
758
- }
759
- });
760
- if (shadow.colorParts.length > 0) {
761
- shadowValue.color = shadow.colorParts[0];
762
- }
763
- if (shadow.inset) {
764
- shadowValue.inset = true;
765
- }
766
- return shadowValue;
767
- });
768
- allShadows.push(...parsedShadows);
769
- }
770
- return allShadows;
771
- }
772
- function normalizeLengthValue(value) {
773
- if (!value) return "0px";
774
- if (value === "0") return "0px";
775
- return value;
776
- }
777
- function isBoxShadowMatch(parsedCssValue, parsedValueHook) {
778
- if (parsedCssValue.length !== parsedValueHook.length) {
779
- return false;
780
- }
781
- for (let i = 0; i < parsedCssValue.length; i++) {
782
- const cssShadow = parsedCssValue[i];
783
- const hookShadow = parsedValueHook[i];
784
- if (cssShadow.color !== hookShadow.color || cssShadow.inset !== hookShadow.inset) {
785
- return false;
786
- }
787
- const lengthProps = ["offsetX", "offsetY", "blurRadius", "spreadRadius"];
788
- for (const prop of lengthProps) {
789
- if (normalizeLengthValue(cssShadow[prop]) !== normalizeLengthValue(hookShadow[prop])) {
790
- return false;
791
- }
792
- }
793
- }
794
- return true;
795
- }
796
-
797
- // src/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.ts
798
- function toBoxShadowValue(cssValue) {
799
- const parsedCssValue = parseBoxShadowValue(cssValue).filter((shadow) => Object.keys(shadow).length > 0);
800
- if (parsedCssValue.length === 0) {
801
- return null;
802
- }
803
- return parsedCssValue;
804
- }
805
- function shadowValueToHookEntries(supportedStylinghooks) {
806
- return Object.entries(supportedStylinghooks).filter(([key, value]) => {
807
- return value.some((hook) => hook.properties.includes("box-shadow"));
808
- }).map(([key, value]) => {
809
- return [key, value.map((hook) => hook.name)];
810
- });
811
- }
812
- var handleBoxShadowDeclaration = (node, context) => {
813
- const cssProperty = node.property.toLowerCase();
814
- const valueText = context.sourceCode.getText(node.value);
815
- const shadowHooks = shadowValueToHookEntries(context.valueToStylinghook);
816
- const parsedCssValue = toBoxShadowValue(valueText);
817
- if (!parsedCssValue) {
818
- return;
819
- }
820
- for (const [shadow, closestHooks] of shadowHooks) {
821
- const parsedValueHook = toBoxShadowValue(shadow);
822
- if (parsedValueHook && isBoxShadowMatch(parsedCssValue, parsedValueHook)) {
823
- if (closestHooks.length > 0) {
824
- const positionInfo = {
825
- start: { offset: 0, line: 1, column: 1 },
826
- end: { offset: valueText.length, line: 1, column: valueText.length + 1 }
827
- };
828
- const replacement = createBoxShadowReplacement(
829
- valueText,
830
- closestHooks,
831
- context,
832
- positionInfo
833
- );
834
- if (replacement) {
835
- const replacements = [replacement];
836
- handleShorthandAutoFix(node, context, valueText, replacements);
837
- }
838
- }
839
- return;
840
- }
841
- }
842
- };
843
- function createBoxShadowReplacement(originalValue, hooks, context, positionInfo) {
844
- if (!positionInfo?.start) {
845
- return null;
846
- }
847
- const start = positionInfo.start.offset;
848
- const end = positionInfo.end.offset;
849
- if (hooks.length === 1) {
850
- return {
851
- start,
852
- end,
853
- replacement: `var(${hooks[0]}, ${originalValue})`,
854
- displayValue: hooks[0],
855
- hasHook: true
856
- };
857
- } else {
858
- return {
859
- start,
860
- end,
861
- replacement: originalValue,
862
- displayValue: formatSuggestionHooks(hooks),
863
- hasHook: true
864
- };
865
- }
866
- }
867
-
868
- // src/utils/rule-utils.ts
869
- function isRuleEnabled(context, ruleName) {
870
- try {
871
- const rules = context.settings?.sldsRules || {};
872
- if (ruleName in rules) {
873
- const ruleConfig = rules[ruleName];
874
- if (Array.isArray(ruleConfig)) {
875
- return ruleConfig[0] === true;
876
- } else if (ruleConfig !== void 0 && ruleConfig !== null) {
877
- return true;
878
- } else if (ruleConfig === false) {
879
- return false;
880
- }
881
- }
882
- } catch (error) {
883
- return false;
884
- }
885
- }
886
-
887
- // src/rules/v9/no-hardcoded-values/noHardcodedValueRule.ts
25
+ var import_handlers = require("./handlers/index");
26
+ var import_property_matcher = require("../../../utils/property-matcher");
27
+ var import_rule_utils = require("../../../utils/rule-utils");
28
+ var import_ruleOptionsSchema = require("./ruleOptionsSchema");
888
29
  function defineNoHardcodedValueRule(config) {
889
30
  const { ruleConfig, ruleName } = config;
890
31
  const { type, description, url, messages } = ruleConfig;
@@ -897,22 +38,30 @@ function defineNoHardcodedValueRule(config) {
897
38
  url
898
39
  },
899
40
  fixable: "code",
900
- messages
41
+ messages,
42
+ schema: import_ruleOptionsSchema.ruleOptionsSchema
901
43
  },
902
44
  create(context) {
903
- if (ruleName === "no-hardcoded-values-slds1" && isRuleEnabled(context, "@salesforce-ux/slds/no-hardcoded-values-slds2")) {
45
+ if (ruleName === "no-hardcoded-values-slds1" && (0, import_rule_utils.isRuleEnabled)(context, "@salesforce-ux/slds/no-hardcoded-values-slds2")) {
904
46
  return {};
905
47
  }
48
+ const options = context.options[0] || {};
49
+ const ruleOptions = {
50
+ reportNumericValue: options.reportNumericValue || "always",
51
+ customMapping: options.customMapping || {},
52
+ preferPaletteHook: options.preferPaletteHook || false
53
+ };
906
54
  const handlerContext = {
907
55
  valueToStylinghook: config.valueToStylinghook,
908
56
  context,
909
- sourceCode: context.sourceCode
57
+ sourceCode: context.sourceCode,
58
+ options: ruleOptions
910
59
  };
911
- const colorOnlySelector = toSelector(colorProperties);
912
- const densityOnlySelector = toSelector(densificationProperties);
913
- const fontDensitySelector = toSelector(fontProperties);
914
- const overlappingProperties = colorProperties.filter((colorProp) => {
915
- return densificationProperties.some((densityProp) => {
60
+ const colorOnlySelector = (0, import_property_matcher.toSelector)(import_property_matcher.colorProperties);
61
+ const densityOnlySelector = (0, import_property_matcher.toSelector)(import_property_matcher.densificationProperties);
62
+ const fontDensitySelector = (0, import_property_matcher.toSelector)(import_property_matcher.fontProperties);
63
+ const overlappingProperties = import_property_matcher.colorProperties.filter((colorProp) => {
64
+ return import_property_matcher.densificationProperties.some((densityProp) => {
916
65
  if (densityProp === colorProp) {
917
66
  return true;
918
67
  }
@@ -924,32 +73,32 @@ function defineNoHardcodedValueRule(config) {
924
73
  });
925
74
  });
926
75
  const overlappingSet = new Set(overlappingProperties);
927
- const colorOnlyProps = colorProperties.filter((prop) => !overlappingSet.has(prop));
928
- const densityOnlyProps = densificationProperties.filter((prop) => !overlappingSet.has(prop));
76
+ const colorOnlyProps = import_property_matcher.colorProperties.filter((prop) => !overlappingSet.has(prop));
77
+ const densityOnlyProps = import_property_matcher.densificationProperties.filter((prop) => !overlappingSet.has(prop));
929
78
  const visitors = {};
930
79
  if (colorOnlyProps.length > 0) {
931
- const colorOnlySelector2 = toSelector(colorOnlyProps);
80
+ const colorOnlySelector2 = (0, import_property_matcher.toSelector)(colorOnlyProps);
932
81
  visitors[colorOnlySelector2] = (node) => {
933
- handleColorDeclaration(node, handlerContext);
82
+ (0, import_handlers.handleColorDeclaration)(node, handlerContext);
934
83
  };
935
84
  }
936
85
  if (densityOnlyProps.length > 0) {
937
- const densityOnlySelector2 = toSelector(densityOnlyProps);
86
+ const densityOnlySelector2 = (0, import_property_matcher.toSelector)(densityOnlyProps);
938
87
  visitors[densityOnlySelector2] = (node) => {
939
- handleDensityDeclaration(node, handlerContext);
88
+ (0, import_handlers.handleDensityDeclaration)(node, handlerContext);
940
89
  };
941
90
  }
942
91
  visitors[fontDensitySelector] = (node) => {
943
- handleFontDeclaration(node, handlerContext);
92
+ (0, import_handlers.handleFontDeclaration)(node, handlerContext);
944
93
  };
945
94
  visitors['Declaration[property="box-shadow"]'] = (node) => {
946
- handleBoxShadowDeclaration(node, handlerContext);
95
+ (0, import_handlers.handleBoxShadowDeclaration)(node, handlerContext);
947
96
  };
948
97
  if (overlappingProperties.length > 0) {
949
- const overlappingSelector = toSelector(overlappingProperties);
98
+ const overlappingSelector = (0, import_property_matcher.toSelector)(overlappingProperties);
950
99
  visitors[overlappingSelector] = (node) => {
951
- handleColorDeclaration(node, handlerContext);
952
- handleDensityDeclaration(node, handlerContext);
100
+ (0, import_handlers.handleColorDeclaration)(node, handlerContext);
101
+ (0, import_handlers.handleDensityDeclaration)(node, handlerContext);
953
102
  };
954
103
  }
955
104
  return visitors;