@salesforce-ux/eslint-plugin-slds 1.0.4 → 1.0.6-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 (67) hide show
  1. package/README.md +62 -0
  2. package/build/index.js +280 -141
  3. package/build/index.js.map +4 -4
  4. package/build/rules/enforce-bem-usage.js +5 -5
  5. package/build/rules/enforce-bem-usage.js.map +3 -3
  6. package/build/rules/no-deprecated-classes-slds2.js +2 -2
  7. package/build/rules/no-deprecated-classes-slds2.js.map +2 -2
  8. package/build/rules/v9/enforce-bem-usage.js +2 -2
  9. package/build/rules/v9/enforce-bem-usage.js.map +2 -2
  10. package/build/rules/v9/enforce-component-hook-naming-convention.js +2 -2
  11. package/build/rules/v9/enforce-component-hook-naming-convention.js.map +2 -2
  12. package/build/rules/v9/enforce-sds-to-slds-hooks.js +2 -2
  13. package/build/rules/v9/enforce-sds-to-slds-hooks.js.map +2 -2
  14. package/build/rules/v9/lwc-token-to-slds-hook.js +2 -2
  15. package/build/rules/v9/lwc-token-to-slds-hook.js.map +2 -2
  16. package/build/rules/v9/no-deprecated-slds-classes.js +2 -2
  17. package/build/rules/v9/no-deprecated-slds-classes.js.map +2 -2
  18. package/build/rules/v9/no-deprecated-tokens-slds1.js +2 -2
  19. package/build/rules/v9/no-deprecated-tokens-slds1.js.map +2 -2
  20. package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js +86 -30
  21. package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js.map +3 -3
  22. package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js +116 -104
  23. package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js.map +3 -3
  24. package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js +83 -30
  25. package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js.map +3 -3
  26. package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js +78 -74
  27. package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js.map +3 -3
  28. package/build/rules/v9/no-hardcoded-values/handlers/index.js +175 -99
  29. package/build/rules/v9/no-hardcoded-values/handlers/index.js.map +3 -3
  30. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js +223 -103
  31. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js.map +3 -3
  32. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js +223 -103
  33. package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js.map +3 -3
  34. package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js +221 -101
  35. package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js.map +3 -3
  36. package/build/rules/v9/no-hardcoded-values/ruleOptionsSchema.js +63 -0
  37. package/build/rules/v9/no-hardcoded-values/ruleOptionsSchema.js.map +7 -0
  38. package/build/rules/v9/no-slds-class-overrides.js +2 -2
  39. package/build/rules/v9/no-slds-class-overrides.js.map +2 -2
  40. package/build/rules/v9/no-slds-namespace-for-custom-hooks.js +2 -2
  41. package/build/rules/v9/no-slds-namespace-for-custom-hooks.js.map +2 -2
  42. package/build/rules/v9/no-slds-var-without-fallback.js +2 -2
  43. package/build/rules/v9/no-slds-var-without-fallback.js.map +2 -2
  44. package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js +2 -2
  45. package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js.map +2 -2
  46. package/build/rules/v9/no-unsupported-hooks-slds2.js +2 -2
  47. package/build/rules/v9/no-unsupported-hooks-slds2.js.map +2 -2
  48. package/build/src/rules/v9/no-hardcoded-values/ruleOptionsSchema.d.ts +40 -0
  49. package/build/src/types/index.d.ts +31 -0
  50. package/build/src/utils/color-lib-utils.d.ts +16 -9
  51. package/build/src/utils/custom-mapping-utils.d.ts +9 -0
  52. package/build/src/utils/hardcoded-shared-utils.d.ts +1 -0
  53. package/build/src/utils/property-matcher.d.ts +3 -1
  54. package/build/types/index.js.map +1 -1
  55. package/build/utils/boxShadowValueParser.js.map +2 -2
  56. package/build/utils/color-lib-utils.js +26 -50
  57. package/build/utils/color-lib-utils.js.map +2 -2
  58. package/build/utils/css-utils.js.map +2 -2
  59. package/build/utils/custom-mapping-utils.js +62 -0
  60. package/build/utils/custom-mapping-utils.js.map +7 -0
  61. package/build/utils/hardcoded-shared-utils.js +29 -16
  62. package/build/utils/hardcoded-shared-utils.js.map +2 -2
  63. package/build/utils/property-matcher.js +20 -6
  64. package/build/utils/property-matcher.js.map +2 -2
  65. package/build/utils/styling-hook-utils.js.map +1 -1
  66. package/eslint.config.mjs +1 -5
  67. package/package.json +2 -2
@@ -192,7 +192,7 @@ __export(no_hardcoded_values_slds1_exports, {
192
192
  default: () => no_hardcoded_values_slds1_default
193
193
  });
194
194
  module.exports = __toCommonJS(no_hardcoded_values_slds1_exports);
195
- var import_sds_metadata = __toESM(require("@salesforce-ux/sds-metadata"));
195
+ var import_next = __toESM(require("@salesforce-ux/sds-metadata/next"));
196
196
  var import_rule_messages = __toESM(require_rule_messages());
197
197
 
198
198
  // src/utils/color-lib-utils.ts
@@ -229,11 +229,7 @@ function isCssColorFunction(value) {
229
229
  }
230
230
 
231
231
  // src/utils/color-lib-utils.ts
232
- var LAB_THRESHOLD = 25;
233
- var isHexCode = (color) => {
234
- const hexPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/;
235
- return hexPattern.test(color);
236
- };
232
+ var DELTAE_THRESHOLD = 10;
237
233
  var convertToHex = (color) => {
238
234
  try {
239
235
  return (0, import_chroma_js.default)(color).hex();
@@ -241,52 +237,40 @@ var convertToHex = (color) => {
241
237
  return null;
242
238
  }
243
239
  };
240
+ var isHookPropertyMatch = (hook, cssProperty) => {
241
+ return hook.properties.includes(cssProperty) || hook.properties.includes("*");
242
+ };
243
+ function getOrderByCssProp(cssProperty) {
244
+ if (cssProperty === "color" || cssProperty === "fill") {
245
+ return ["surface", "theme", "feedback", "reference"];
246
+ } else if (cssProperty.match(/background/)) {
247
+ return ["surface", "surface-inverse", "theme", "feedback", "reference"];
248
+ } else if (cssProperty.match(/border/) || cssProperty.match(/outline/) || cssProperty.match(/stroke/)) {
249
+ return ["borders", "borders-inverse", "feedback", "theme", "reference"];
250
+ }
251
+ return ["surface", "surface-inverse", "borders", "borders-inverse", "theme", "feedback", "reference"];
252
+ }
244
253
  var findClosestColorHook = (color, supportedColors, cssProperty) => {
245
- const returnStylingHooks = [];
246
- const closestHooksWithSameProperty = [];
247
- const closestHooksWithoutSameProperty = [];
248
- const closestHooksWithAllProperty = [];
249
- const labColor = (0, import_chroma_js.default)(color).lab();
254
+ const closestHooks = [];
250
255
  Object.entries(supportedColors).forEach(([sldsValue, data]) => {
251
- if (sldsValue && isHexCode(sldsValue)) {
256
+ if (sldsValue && isValidColor(sldsValue)) {
252
257
  const hooks = data;
253
258
  hooks.forEach((hook) => {
254
- const labSupportedColor = (0, import_chroma_js.default)(sldsValue).lab();
255
- 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");
256
- if (hook.properties.includes(cssProperty)) {
257
- if (distance <= LAB_THRESHOLD) {
258
- closestHooksWithSameProperty.push({ name: hook.name, distance });
259
- }
260
- } else if (hook.properties.includes("*")) {
261
- if (distance <= LAB_THRESHOLD) {
262
- closestHooksWithAllProperty.push({ name: hook.name, distance });
263
- }
264
- } else {
265
- if (distance <= LAB_THRESHOLD) {
266
- closestHooksWithoutSameProperty.push({ name: hook.name, distance });
267
- }
259
+ const distance = sldsValue.toLowerCase() === color.toLowerCase() ? 0 : import_chroma_js.default.deltaE(sldsValue, color);
260
+ if (isHookPropertyMatch(hook, cssProperty) && distance <= DELTAE_THRESHOLD) {
261
+ closestHooks.push({ distance, group: hook.group, name: hook.name });
268
262
  }
269
263
  });
270
264
  }
271
265
  });
272
- const closesthookGroups = [
273
- { hooks: closestHooksWithSameProperty, distance: 0 },
274
- { hooks: closestHooksWithAllProperty, distance: 0 },
275
- { hooks: closestHooksWithSameProperty, distance: Infinity },
276
- // For hooks with distance > 0
277
- { hooks: closestHooksWithAllProperty, distance: Infinity },
278
- { hooks: closestHooksWithoutSameProperty, distance: Infinity }
279
- ];
280
- for (const group of closesthookGroups) {
281
- const filteredHooks = group.hooks.filter(
282
- (h) => group.distance === 0 ? h.distance === 0 : h.distance > 0
283
- );
284
- if (returnStylingHooks.length < 1 && filteredHooks.length > 0) {
285
- filteredHooks.sort((a, b) => a.distance - b.distance);
286
- returnStylingHooks.push(...filteredHooks.slice(0, 5).map((h) => h.name));
266
+ const hooksByGroupMap = closestHooks.sort((a, b) => a.distance - b.distance).reduce((acc, hook) => {
267
+ if (!acc[hook.group]) {
268
+ acc[hook.group] = [];
287
269
  }
288
- }
289
- return Array.from(new Set(returnStylingHooks));
270
+ acc[hook.group].push(hook.name);
271
+ return acc;
272
+ }, {});
273
+ return getOrderByCssProp(cssProperty).map((group) => hooksByGroupMap[group] || []).flat().slice(0, 5);
290
274
  };
291
275
  var isValidColor = (val) => import_chroma_js.default.valid(val);
292
276
  var extractColorValue = (node) => {
@@ -385,9 +369,9 @@ function toSelector(properties) {
385
369
  });
386
370
  return selectorParts.join(", ");
387
371
  }
388
- function resolvePropertyToMatch(cssProperty) {
372
+ function resolveDensityPropertyToMatch(cssProperty) {
389
373
  const propertyToMatch = cssProperty.toLowerCase();
390
- if (propertyToMatch === "outline" || propertyToMatch === "outline-width" || isBorderWidthProperty(propertyToMatch)) {
374
+ if (isOutlineWidthProperty(propertyToMatch) || isBorderWidthProperty(propertyToMatch)) {
391
375
  return "border-width";
392
376
  } else if (isMarginProperty(propertyToMatch)) {
393
377
  return "margin";
@@ -399,13 +383,23 @@ function resolvePropertyToMatch(cssProperty) {
399
383
  return "width";
400
384
  } else if (isInsetProperty(propertyToMatch)) {
401
385
  return "top";
402
- } else if (cssProperty === "background" || cssProperty === "background-color") {
386
+ }
387
+ return propertyToMatch;
388
+ }
389
+ function resolveColorPropertyToMatch(cssProperty) {
390
+ const propertyToMatch = cssProperty.toLowerCase();
391
+ if (propertyToMatch === "outline" || propertyToMatch === "outline-color") {
392
+ return "border-color";
393
+ } else if (propertyToMatch === "background" || propertyToMatch === "background-color") {
403
394
  return "background-color";
404
- } else if (cssProperty === "outline" || cssProperty === "outline-color" || isBorderColorProperty(cssProperty)) {
395
+ } else if (isBorderColorProperty(propertyToMatch)) {
405
396
  return "border-color";
406
397
  }
407
398
  return propertyToMatch;
408
399
  }
400
+ function isOutlineWidthProperty(propertyToMatch) {
401
+ return propertyToMatch === "outline" || propertyToMatch === "outline-width";
402
+ }
409
403
 
410
404
  // src/utils/hardcoded-shared-utils.ts
411
405
  var import_css_tree2 = require("@eslint/css-tree");
@@ -465,13 +459,33 @@ function isKnownFontWeight(value) {
465
459
  return FONT_WEIGHTS.includes(stringValue.toLowerCase());
466
460
  }
467
461
  function handleShorthandAutoFix(declarationNode, context, valueText, replacements) {
468
- const sortedReplacements = replacements.sort((a, b) => a.start - b.start);
469
- const hasAnyHooks = sortedReplacements.some((r) => r.hasHook);
470
- const canAutoFix = hasAnyHooks;
471
- sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook }) => {
462
+ if (!replacements || replacements.length === 0) {
463
+ return;
464
+ }
465
+ const sortedReplacements = replacements.sort((a, b) => b.start - a.start);
466
+ const reportNumericValue = context.options?.reportNumericValue || "always";
467
+ const fixCallback = (start, originalValue, replacement) => {
468
+ let newValue = valueText;
469
+ newValue = newValue.substring(0, start) + replacement + newValue.substring(start + originalValue.length);
470
+ if (newValue !== valueText) {
471
+ return (fixer) => {
472
+ return fixer.replaceText(declarationNode.value, newValue);
473
+ };
474
+ }
475
+ };
476
+ sortedReplacements.forEach(({ start, end, replacement, displayValue, hasHook, isNumeric }) => {
472
477
  const originalValue = valueText.substring(start, end);
473
- const valueStartColumn = declarationNode.value.loc.start.column;
474
- const valueColumn = valueStartColumn + start;
478
+ if (isNumeric) {
479
+ if (reportNumericValue === "never") {
480
+ return;
481
+ }
482
+ if (reportNumericValue === "hasReplacement" && !hasHook) {
483
+ return;
484
+ }
485
+ }
486
+ const valueColumnStart = declarationNode.value.loc.start.column + start;
487
+ const valueColumnEnd = valueColumnStart + originalValue.length;
488
+ const canAutoFix = originalValue !== replacement;
475
489
  const { loc: { start: locStart, end: locEnd } } = declarationNode.value;
476
490
  const reportNode = {
477
491
  ...declarationNode.value,
@@ -479,23 +493,16 @@ function handleShorthandAutoFix(declarationNode, context, valueText, replacement
479
493
  ...declarationNode.value.loc,
480
494
  start: {
481
495
  ...locStart,
482
- column: valueColumn
496
+ column: valueColumnStart
483
497
  },
484
498
  end: {
485
499
  ...locEnd,
486
- column: valueColumn + originalValue.length
500
+ column: valueColumnEnd
487
501
  }
488
502
  }
489
503
  };
490
504
  if (hasHook) {
491
- const fix = canAutoFix ? (fixer) => {
492
- let newValue = valueText;
493
- for (let i = sortedReplacements.length - 1; i >= 0; i--) {
494
- const { start: rStart, end: rEnd, replacement: rReplacement } = sortedReplacements[i];
495
- newValue = newValue.substring(0, rStart) + rReplacement + newValue.substring(rEnd);
496
- }
497
- return fixer.replaceText(declarationNode.value, newValue);
498
- } : void 0;
505
+ const fix = canAutoFix ? fixCallback(start, originalValue, replacement) : void 0;
499
506
  context.context.report({
500
507
  node: reportNode,
501
508
  messageId: "hardcodedValue",
@@ -649,6 +656,41 @@ function formatSuggestionHooks(hooks) {
649
656
  return "\n" + hooks.map((hook, index) => `${index + 1}. ${hook}`).join("\n");
650
657
  }
651
658
 
659
+ // src/utils/custom-mapping-utils.ts
660
+ function matchesPropertyPattern(cssProperty, pattern) {
661
+ const normalizedProperty = cssProperty.toLowerCase();
662
+ const normalizedPattern = pattern.toLowerCase();
663
+ if (normalizedProperty === normalizedPattern) {
664
+ return true;
665
+ }
666
+ if (normalizedPattern.endsWith("*")) {
667
+ const prefix = normalizedPattern.slice(0, -1);
668
+ return normalizedProperty.startsWith(prefix);
669
+ }
670
+ return false;
671
+ }
672
+ function getCustomMapping(cssProperty, value, customMapping) {
673
+ if (!customMapping) {
674
+ return null;
675
+ }
676
+ const normalizedValue = value.toLowerCase().trim();
677
+ for (const [hookName, config] of Object.entries(customMapping)) {
678
+ const propertyMatches = config.properties.some(
679
+ (pattern) => matchesPropertyPattern(cssProperty, pattern)
680
+ );
681
+ if (!propertyMatches) {
682
+ continue;
683
+ }
684
+ const valueMatches = config.values.some(
685
+ (configValue) => configValue.toLowerCase().trim() === normalizedValue
686
+ );
687
+ if (valueMatches) {
688
+ return hookName;
689
+ }
690
+ }
691
+ return null;
692
+ }
693
+
652
694
  // src/rules/v9/no-hardcoded-values/handlers/colorHandler.ts
653
695
  var handleColorDeclaration = (node, context) => {
654
696
  const cssProperty = node.property.toLowerCase();
@@ -672,24 +714,32 @@ function createColorReplacement(colorValue, cssProperty, context, positionInfo,
672
714
  if (!hexValue) {
673
715
  return null;
674
716
  }
675
- const propToMatch = resolvePropertyToMatch(cssProperty);
676
- const closestHooks = findClosestColorHook(hexValue, context.valueToStylinghook, propToMatch);
677
717
  const start = positionInfo.start.offset;
678
718
  const end = positionInfo.end.offset;
679
719
  const originalValue = originalValueText ? originalValueText.substring(start, end) : colorValue;
680
- if (closestHooks.length === 1) {
681
- return {
682
- start,
683
- end,
684
- replacement: `var(${closestHooks[0]}, ${colorValue})`,
685
- displayValue: closestHooks[0],
686
- hasHook: true
687
- };
688
- } else if (closestHooks.length > 1) {
720
+ const customHook = getCustomMapping(cssProperty, colorValue, context.options?.customMapping);
721
+ let closestHooks = [];
722
+ if (customHook) {
723
+ closestHooks = [customHook];
724
+ } else {
725
+ const propToMatch = resolveColorPropertyToMatch(cssProperty);
726
+ closestHooks = findClosestColorHook(hexValue, context.valueToStylinghook, propToMatch);
727
+ }
728
+ let replacement = originalValue;
729
+ let paletteHook = null;
730
+ if (context.options?.preferPaletteHook && closestHooks.length > 1) {
731
+ paletteHook = closestHooks.filter((hook) => hook.includes("-palette-"))[0];
732
+ }
733
+ if (paletteHook) {
734
+ replacement = `var(${paletteHook}, ${colorValue})`;
735
+ } else if (closestHooks.length === 1) {
736
+ replacement = `var(${closestHooks[0]}, ${colorValue})`;
737
+ }
738
+ if (closestHooks.length > 0) {
689
739
  return {
690
740
  start,
691
741
  end,
692
- replacement: originalValue,
742
+ replacement,
693
743
  // Use original value to preserve spacing
694
744
  displayValue: formatSuggestionHooks(closestHooks),
695
745
  hasHook: true
@@ -698,7 +748,7 @@ function createColorReplacement(colorValue, cssProperty, context, positionInfo,
698
748
  return {
699
749
  start,
700
750
  end,
701
- replacement: originalValue,
751
+ replacement,
702
752
  // Use original value to preserve spacing
703
753
  displayValue: originalValue,
704
754
  hasHook: false
@@ -746,8 +796,14 @@ function createDimensionReplacement(parsedDimension, cssProperty, context, posit
746
796
  return null;
747
797
  }
748
798
  const rawValue = parsedDimension.unit ? `${parsedDimension.number}${parsedDimension.unit}` : parsedDimension.number.toString();
749
- const propToMatch = resolvePropertyToMatch(cssProperty);
750
- const closestHooks = getStylingHooksForDensityValue(parsedDimension, context.valueToStylinghook, propToMatch);
799
+ const customHook = getCustomMapping(cssProperty, rawValue, context.options?.customMapping);
800
+ let closestHooks = [];
801
+ if (customHook) {
802
+ closestHooks = [customHook];
803
+ } else {
804
+ const propToMatch = resolveDensityPropertyToMatch(cssProperty);
805
+ closestHooks = getStylingHooksForDensityValue(parsedDimension, context.valueToStylinghook, propToMatch);
806
+ }
751
807
  const start = positionInfo.start.offset;
752
808
  const end = positionInfo.end.offset;
753
809
  if (closestHooks.length === 1) {
@@ -756,7 +812,8 @@ function createDimensionReplacement(parsedDimension, cssProperty, context, posit
756
812
  end,
757
813
  replacement: `var(${closestHooks[0]}, ${rawValue})`,
758
814
  displayValue: closestHooks[0],
759
- hasHook: true
815
+ hasHook: true,
816
+ isNumeric: true
760
817
  };
761
818
  } else if (closestHooks.length > 1) {
762
819
  return {
@@ -764,7 +821,8 @@ function createDimensionReplacement(parsedDimension, cssProperty, context, posit
764
821
  end,
765
822
  replacement: rawValue,
766
823
  displayValue: formatSuggestionHooks(closestHooks),
767
- hasHook: true
824
+ hasHook: true,
825
+ isNumeric: true
768
826
  };
769
827
  } else {
770
828
  return {
@@ -772,7 +830,8 @@ function createDimensionReplacement(parsedDimension, cssProperty, context, posit
772
830
  end,
773
831
  replacement: rawValue,
774
832
  displayValue: rawValue,
775
- hasHook: false
833
+ hasHook: false,
834
+ isNumeric: true
776
835
  };
777
836
  }
778
837
  }
@@ -813,8 +872,14 @@ function createFontReplacement(fontValue, cssProperty, context, positionInfo) {
813
872
  return null;
814
873
  }
815
874
  const rawValue = fontValue.unit ? `${fontValue.number}${fontValue.unit}` : fontValue.number.toString();
816
- const propToMatch = !fontValue.unit && isKnownFontWeight(fontValue.number) ? resolvePropertyToMatch("font-weight") : resolvePropertyToMatch("font-size");
817
- const closestHooks = getStylingHooksForDensityValue(fontValue, context.valueToStylinghook, propToMatch);
875
+ const propToMatch = !fontValue.unit && isKnownFontWeight(fontValue.number) ? "font-weight" : "font-size";
876
+ const customHook = getCustomMapping(propToMatch, rawValue, context.options?.customMapping);
877
+ let closestHooks = [];
878
+ if (customHook) {
879
+ closestHooks = [customHook];
880
+ } else {
881
+ closestHooks = getStylingHooksForDensityValue(fontValue, context.valueToStylinghook, propToMatch);
882
+ }
818
883
  const start = positionInfo.start.offset;
819
884
  const end = positionInfo.end.offset;
820
885
  if (closestHooks.length === 1) {
@@ -823,7 +888,8 @@ function createFontReplacement(fontValue, cssProperty, context, positionInfo) {
823
888
  end,
824
889
  replacement: `var(${closestHooks[0]}, ${rawValue})`,
825
890
  displayValue: closestHooks[0],
826
- hasHook: true
891
+ hasHook: true,
892
+ isNumeric: true
827
893
  };
828
894
  } else if (closestHooks.length > 1) {
829
895
  return {
@@ -831,7 +897,8 @@ function createFontReplacement(fontValue, cssProperty, context, positionInfo) {
831
897
  end,
832
898
  replacement: rawValue,
833
899
  displayValue: formatSuggestionHooks(closestHooks),
834
- hasHook: true
900
+ hasHook: true,
901
+ isNumeric: true
835
902
  };
836
903
  } else {
837
904
  return {
@@ -839,7 +906,8 @@ function createFontReplacement(fontValue, cssProperty, context, positionInfo) {
839
906
  end,
840
907
  replacement: rawValue,
841
908
  displayValue: rawValue,
842
- hasHook: false
909
+ hasHook: false,
910
+ isNumeric: true
843
911
  };
844
912
  }
845
913
  }
@@ -971,9 +1039,30 @@ function shadowValueToHookEntries(supportedStylinghooks) {
971
1039
  return [key, value.map((hook) => hook.name)];
972
1040
  });
973
1041
  }
1042
+ function reportBoxShadowViolation(node, context, valueText, hooks) {
1043
+ const positionInfo = {
1044
+ start: { offset: 0, line: 1, column: 1 },
1045
+ end: { offset: valueText.length, line: 1, column: valueText.length + 1 }
1046
+ };
1047
+ const replacement = createBoxShadowReplacement(
1048
+ valueText,
1049
+ hooks,
1050
+ context,
1051
+ positionInfo
1052
+ );
1053
+ if (replacement) {
1054
+ const replacements = [replacement];
1055
+ handleShorthandAutoFix(node, context, valueText, replacements);
1056
+ }
1057
+ }
974
1058
  var handleBoxShadowDeclaration = (node, context) => {
975
1059
  const cssProperty = node.property.toLowerCase();
976
1060
  const valueText = context.sourceCode.getText(node.value);
1061
+ const customHook = getCustomMapping(cssProperty, valueText, context.options?.customMapping);
1062
+ if (customHook) {
1063
+ reportBoxShadowViolation(node, context, valueText, [customHook]);
1064
+ return;
1065
+ }
977
1066
  const shadowHooks = shadowValueToHookEntries(context.valueToStylinghook);
978
1067
  const parsedCssValue = toBoxShadowValue(valueText);
979
1068
  if (!parsedCssValue) {
@@ -983,20 +1072,7 @@ var handleBoxShadowDeclaration = (node, context) => {
983
1072
  const parsedValueHook = toBoxShadowValue(shadow);
984
1073
  if (parsedValueHook && isBoxShadowMatch(parsedCssValue, parsedValueHook)) {
985
1074
  if (closestHooks.length > 0) {
986
- const positionInfo = {
987
- start: { offset: 0, line: 1, column: 1 },
988
- end: { offset: valueText.length, line: 1, column: valueText.length + 1 }
989
- };
990
- const replacement = createBoxShadowReplacement(
991
- valueText,
992
- closestHooks,
993
- context,
994
- positionInfo
995
- );
996
- if (replacement) {
997
- const replacements = [replacement];
998
- handleShorthandAutoFix(node, context, valueText, replacements);
999
- }
1075
+ reportBoxShadowViolation(node, context, valueText, closestHooks);
1000
1076
  }
1001
1077
  return;
1002
1078
  }
@@ -1046,6 +1122,42 @@ function isRuleEnabled(context, ruleName2) {
1046
1122
  }
1047
1123
  }
1048
1124
 
1125
+ // src/rules/v9/no-hardcoded-values/ruleOptionsSchema.ts
1126
+ var ruleOptionsSchema = [
1127
+ {
1128
+ type: "object",
1129
+ properties: {
1130
+ reportNumericValue: {
1131
+ type: "string",
1132
+ enum: ["never", "always", "hasReplacement"],
1133
+ default: "always"
1134
+ },
1135
+ customMapping: {
1136
+ type: "object",
1137
+ additionalProperties: {
1138
+ type: "object",
1139
+ properties: {
1140
+ properties: {
1141
+ type: "array",
1142
+ items: { type: "string" }
1143
+ },
1144
+ values: {
1145
+ type: "array",
1146
+ items: { type: "string" }
1147
+ }
1148
+ },
1149
+ required: ["properties", "values"]
1150
+ }
1151
+ },
1152
+ preferPaletteHook: {
1153
+ type: "boolean",
1154
+ default: false
1155
+ }
1156
+ },
1157
+ additionalProperties: false
1158
+ }
1159
+ ];
1160
+
1049
1161
  // src/rules/v9/no-hardcoded-values/noHardcodedValueRule.ts
1050
1162
  function defineNoHardcodedValueRule(config) {
1051
1163
  const { ruleConfig: ruleConfig2, ruleName: ruleName2 } = config;
@@ -1059,16 +1171,24 @@ function defineNoHardcodedValueRule(config) {
1059
1171
  url: url2
1060
1172
  },
1061
1173
  fixable: "code",
1062
- messages: messages2
1174
+ messages: messages2,
1175
+ schema: ruleOptionsSchema
1063
1176
  },
1064
1177
  create(context) {
1065
1178
  if (ruleName2 === "no-hardcoded-values-slds1" && isRuleEnabled(context, "@salesforce-ux/slds/no-hardcoded-values-slds2")) {
1066
1179
  return {};
1067
1180
  }
1181
+ const options = context.options[0] || {};
1182
+ const ruleOptions = {
1183
+ reportNumericValue: options.reportNumericValue || "always",
1184
+ customMapping: options.customMapping || {},
1185
+ preferPaletteHook: options.preferPaletteHook || false
1186
+ };
1068
1187
  const handlerContext = {
1069
1188
  valueToStylinghook: config.valueToStylinghook,
1070
1189
  context,
1071
- sourceCode: context.sourceCode
1190
+ sourceCode: context.sourceCode,
1191
+ options: ruleOptions
1072
1192
  };
1073
1193
  const colorOnlySelector = toSelector(colorProperties);
1074
1194
  const densityOnlySelector = toSelector(densificationProperties);
@@ -1123,7 +1243,7 @@ function defineNoHardcodedValueRule(config) {
1123
1243
  var ruleName = "no-hardcoded-values-slds1";
1124
1244
  var ruleConfig = import_rule_messages.default[ruleName];
1125
1245
  var { type, description, url, messages } = ruleConfig;
1126
- var valueToStylinghook = import_sds_metadata.default.valueToStylingHooksSlds;
1246
+ var valueToStylinghook = import_next.default.valueToStylingHooksSlds;
1127
1247
  var no_hardcoded_values_slds1_default = defineNoHardcodedValueRule({
1128
1248
  ruleConfig,
1129
1249
  valueToStylinghook,