@salesforce-ux/eslint-plugin-slds 1.0.0 → 1.0.2-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.
- package/README.md +18 -1
- package/build/index.js +728 -699
- package/build/index.js.map +4 -4
- package/build/rules/enforce-bem-usage.js +3 -3
- package/build/rules/enforce-bem-usage.js.map +3 -3
- package/build/rules/modal-close-button-issue.js +3 -3
- package/build/rules/modal-close-button-issue.js.map +3 -3
- package/build/rules/no-deprecated-classes-slds2.js +3 -3
- package/build/rules/no-deprecated-classes-slds2.js.map +3 -3
- package/build/rules/v9/enforce-bem-usage.js +3 -3
- package/build/rules/v9/enforce-bem-usage.js.map +3 -3
- package/build/rules/v9/enforce-component-hook-naming-convention.js +3 -3
- package/build/rules/v9/enforce-component-hook-naming-convention.js.map +3 -3
- package/build/rules/v9/enforce-sds-to-slds-hooks.js +3 -3
- package/build/rules/v9/enforce-sds-to-slds-hooks.js.map +3 -3
- package/build/rules/v9/lwc-token-to-slds-hook.js +86 -11
- package/build/rules/v9/lwc-token-to-slds-hook.js.map +4 -4
- package/build/rules/v9/no-deprecated-slds-classes.js +3 -3
- package/build/rules/v9/no-deprecated-slds-classes.js.map +3 -3
- package/build/rules/v9/no-deprecated-tokens-slds1.js +3 -3
- package/build/rules/v9/no-deprecated-tokens-slds1.js.map +3 -3
- package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js +49 -54
- package/build/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.js.map +3 -3
- package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js +9 -2
- package/build/rules/v9/no-hardcoded-values/handlers/colorHandler.js.map +3 -3
- package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js +14 -3
- package/build/rules/v9/no-hardcoded-values/handlers/densityHandler.js.map +3 -3
- package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js +14 -3
- package/build/rules/v9/no-hardcoded-values/handlers/fontHandler.js.map +3 -3
- package/build/rules/v9/no-hardcoded-values/handlers/index.js +86 -90
- package/build/rules/v9/no-hardcoded-values/handlers/index.js.map +3 -3
- package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js +90 -94
- package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds1.js.map +3 -3
- package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js +90 -94
- package/build/rules/v9/no-hardcoded-values/no-hardcoded-values-slds2.js.map +3 -3
- package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js +87 -91
- package/build/rules/v9/no-hardcoded-values/noHardcodedValueRule.js.map +3 -3
- package/build/rules/v9/no-slds-class-overrides.js +3 -3
- package/build/rules/v9/no-slds-class-overrides.js.map +3 -3
- package/build/rules/v9/no-slds-namespace-for-custom-hooks.js +3 -3
- package/build/rules/v9/no-slds-namespace-for-custom-hooks.js.map +3 -3
- package/build/rules/v9/no-slds-private-var.js +3 -3
- package/build/rules/v9/no-slds-private-var.js.map +3 -3
- package/build/rules/v9/no-slds-var-without-fallback.js +3 -3
- package/build/rules/v9/no-slds-var-without-fallback.js.map +3 -3
- package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js +3 -3
- package/build/rules/v9/no-sldshook-fallback-for-lwctoken.js.map +3 -3
- package/build/rules/v9/no-unsupported-hooks-slds2.js +3 -3
- package/build/rules/v9/no-unsupported-hooks-slds2.js.map +3 -3
- package/build/rules/v9/reduce-annotations.js +3 -3
- package/build/rules/v9/reduce-annotations.js.map +3 -3
- package/build/src/utils/css-utils.d.ts +6 -0
- package/build/src/utils/value-utils.d.ts +3 -2
- package/build/utils/boxShadowValueParser.js +4 -1
- package/build/utils/boxShadowValueParser.js.map +2 -2
- package/build/utils/css-utils.js +8 -0
- package/build/utils/css-utils.js.map +2 -2
- package/build/utils/hardcoded-shared-utils.js +5 -2
- package/build/utils/hardcoded-shared-utils.js.map +3 -3
- package/build/utils/property-matcher.js +1 -1
- package/build/utils/property-matcher.js.map +2 -2
- package/build/utils/styling-hook-utils.js +4 -1
- package/build/utils/styling-hook-utils.js.map +2 -2
- package/build/utils/value-utils.js +6 -1
- package/build/utils/value-utils.js.map +2 -2
- package/package.json +2 -2
- package/src/config/rule-messages.yml +1 -1
package/build/index.js
CHANGED
|
@@ -45,9 +45,9 @@ var init_node = __esm({
|
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
// yaml-file
|
|
48
|
+
// yaml-file:rule-messages.yml
|
|
49
49
|
var require_rule_messages = __commonJS({
|
|
50
|
-
"yaml-file
|
|
50
|
+
"yaml-file:rule-messages.yml"(exports2, module2) {
|
|
51
51
|
module2.exports = {
|
|
52
52
|
"no-slds-class-overrides": {
|
|
53
53
|
"description": "Create new custom CSS classes instead of overriding SLDS selectors",
|
|
@@ -183,7 +183,7 @@ var require_rule_messages = __commonJS({
|
|
|
183
183
|
},
|
|
184
184
|
"no-hardcoded-values-slds2": {
|
|
185
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-
|
|
186
|
+
"url": "https://developer.salesforce.com/docs/platform/slds-linter/guide/reference-rules.html#no-hardcoded-values-slds2",
|
|
187
187
|
"type": "suggestion",
|
|
188
188
|
"messages": {
|
|
189
189
|
"hardcodedValue": "Consider replacing the {{oldValue}} static value with an SLDS 2 styling hook that has a similar value: {{newValue}}.",
|
|
@@ -708,169 +708,482 @@ var no_deprecated_tokens_slds1_default = {
|
|
|
708
708
|
// src/rules/v9/lwc-token-to-slds-hook.ts
|
|
709
709
|
var import_sds_metadata5 = __toESM(require("@salesforce-ux/sds-metadata"));
|
|
710
710
|
var import_rule_messages5 = __toESM(require_rule_messages());
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
var
|
|
714
|
-
|
|
715
|
-
|
|
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 };
|
|
716
727
|
}
|
|
717
|
-
function
|
|
718
|
-
if (
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
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
|
+
}
|
|
726
745
|
}
|
|
727
|
-
return
|
|
746
|
+
return null;
|
|
728
747
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
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);
|
|
735
777
|
}
|
|
736
|
-
function
|
|
737
|
-
|
|
738
|
-
return {
|
|
739
|
-
messageId: "errorWithNoRecommendation",
|
|
740
|
-
data: { oldValue: cssVar }
|
|
741
|
-
};
|
|
742
|
-
} else if (replacementCategory === "array" /* ARRAY */) {
|
|
743
|
-
return {
|
|
744
|
-
messageId: "errorWithStyleHooks",
|
|
745
|
-
data: { oldValue: cssVar, newValue: recommendation.join(" or ") }
|
|
746
|
-
};
|
|
747
|
-
} else if (replacementCategory === "slds_token" /* SLDS_TOKEN */) {
|
|
748
|
-
return {
|
|
749
|
-
messageId: "errorWithStyleHooks",
|
|
750
|
-
data: { oldValue: cssVar, newValue: recommendation }
|
|
751
|
-
};
|
|
752
|
-
} else {
|
|
753
|
-
return {
|
|
754
|
-
messageId: "errorWithReplacement",
|
|
755
|
-
data: { oldValue: cssVar, newValue: recommendation }
|
|
756
|
-
};
|
|
757
|
-
}
|
|
778
|
+
function isCssColorFunction(value) {
|
|
779
|
+
return RGB_COLOR_FUNCTIONS.includes(value);
|
|
758
780
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
const varFunctionCall = `var(${oldValue})`;
|
|
789
|
-
const nodeOffset = node.loc.start.offset;
|
|
790
|
-
const searchStart = Math.max(0, nodeOffset - 4);
|
|
791
|
-
const searchEnd = nodeOffset + oldValue.length + 1;
|
|
792
|
-
const searchArea = fullText.substring(searchStart, searchEnd);
|
|
793
|
-
const functionCallIndex = searchArea.indexOf(varFunctionCall);
|
|
794
|
-
if (functionCallIndex !== -1) {
|
|
795
|
-
const actualStart = searchStart + functionCallIndex;
|
|
796
|
-
const actualEnd = actualStart + varFunctionCall.length;
|
|
797
|
-
return fixer.replaceTextRange([actualStart, actualEnd], suggestedMatch);
|
|
798
|
-
}
|
|
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 });
|
|
799
810
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
fix: fixFunction
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
return {
|
|
811
|
-
// CSS custom property declarations: --lwc-* properties
|
|
812
|
-
"Declaration[property=/^--lwc-/]"(node) {
|
|
813
|
-
const property = node.property;
|
|
814
|
-
if (shouldIgnoreDetection(property)) {
|
|
815
|
-
return;
|
|
816
|
-
}
|
|
817
|
-
const { hasRecommendation, recommendation, replacementCategory } = getRecommendation(property);
|
|
818
|
-
const { messageId, data } = getReportMessage(property, replacementCategory, recommendation);
|
|
819
|
-
const suggestedMatch = hasRecommendation && replacementCategory === "slds_token" /* SLDS_TOKEN */ ? recommendation : null;
|
|
820
|
-
reportAndFix(node, property, suggestedMatch, messageId, data);
|
|
821
|
-
},
|
|
822
|
-
// LWC tokens inside var() functions: var(--lwc-*)
|
|
823
|
-
"Function[name='var'] Identifier[name=/^--lwc-/]"(node) {
|
|
824
|
-
const tokenName = node.name;
|
|
825
|
-
if (shouldIgnoreDetection(tokenName)) {
|
|
826
|
-
return;
|
|
827
|
-
}
|
|
828
|
-
const { hasRecommendation, recommendation, replacementCategory } = getRecommendation(tokenName);
|
|
829
|
-
const { messageId, data } = getReportMessage(tokenName, replacementCategory, recommendation);
|
|
830
|
-
let suggestedMatch = null;
|
|
831
|
-
if (hasRecommendation) {
|
|
832
|
-
if (replacementCategory === "slds_token" /* SLDS_TOKEN */) {
|
|
833
|
-
const originalVarCall = `var(${tokenName})`;
|
|
834
|
-
suggestedMatch = `var(${recommendation}, ${originalVarCall})`;
|
|
835
|
-
} else if (replacementCategory === "raw_value" /* RAW_VALUE */) {
|
|
836
|
-
suggestedMatch = recommendation;
|
|
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 });
|
|
837
818
|
}
|
|
838
819
|
}
|
|
839
|
-
|
|
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);
|
|
840
855
|
}
|
|
841
|
-
|
|
856
|
+
break;
|
|
842
857
|
}
|
|
858
|
+
return colorValue && isValidColor(colorValue) ? colorValue : null;
|
|
843
859
|
};
|
|
844
860
|
|
|
845
|
-
// src/
|
|
846
|
-
var
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
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
|
|
919
|
+
},
|
|
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;
|
|
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 extractLwcVariableWithFallback(node, sourceCode) {
|
|
1123
|
+
if (!node?.children || node.type !== "Function" || node.name !== "var") {
|
|
1124
|
+
return null;
|
|
1125
|
+
}
|
|
1126
|
+
const children = Array.from(node.children);
|
|
1127
|
+
const firstChild = children[0];
|
|
1128
|
+
if (!firstChild?.name?.startsWith("--lwc-") || firstChild.type !== "Identifier") {
|
|
1129
|
+
return null;
|
|
1130
|
+
}
|
|
1131
|
+
const commaIndex = children.findIndex(
|
|
1132
|
+
(child) => child.type === "Operator" && child.value === ","
|
|
1133
|
+
);
|
|
1134
|
+
let fallbackValue = null;
|
|
1135
|
+
if (commaIndex !== -1 && commaIndex + 1 < children.length) {
|
|
1136
|
+
const fallbackStart = children[commaIndex + 1];
|
|
1137
|
+
const fallbackEnd = children[children.length - 1];
|
|
1138
|
+
if (fallbackStart?.loc && fallbackEnd?.loc) {
|
|
1139
|
+
const fullText = sourceCode.getText();
|
|
1140
|
+
fallbackValue = fullText.substring(fallbackStart.loc.start.offset, fallbackEnd.loc.end.offset).trim();
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
return {
|
|
1144
|
+
lwcToken: firstChild.name,
|
|
1145
|
+
fallbackValue
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
function getReportMessage(cssVar, replacementCategory, recommendation) {
|
|
1149
|
+
if (!recommendation) {
|
|
1150
|
+
return {
|
|
1151
|
+
messageId: "errorWithNoRecommendation",
|
|
1152
|
+
data: { oldValue: cssVar }
|
|
1153
|
+
};
|
|
1154
|
+
} else if (replacementCategory === "array" /* ARRAY */) {
|
|
1155
|
+
return {
|
|
1156
|
+
messageId: "errorWithStyleHooks",
|
|
1157
|
+
data: { oldValue: cssVar, newValue: formatSuggestionHooks(recommendation) }
|
|
1158
|
+
};
|
|
1159
|
+
} else if (replacementCategory === "slds_token" /* SLDS_TOKEN */) {
|
|
1160
|
+
return {
|
|
1161
|
+
messageId: "errorWithStyleHooks",
|
|
1162
|
+
data: { oldValue: cssVar, newValue: recommendation }
|
|
1163
|
+
};
|
|
1164
|
+
} else {
|
|
1165
|
+
return {
|
|
1166
|
+
messageId: "errorWithReplacement",
|
|
1167
|
+
data: { oldValue: cssVar, newValue: recommendation }
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
855
1170
|
}
|
|
856
|
-
var
|
|
1171
|
+
var lwc_token_to_slds_hook_default = {
|
|
857
1172
|
meta: {
|
|
858
|
-
type:
|
|
1173
|
+
type: type4,
|
|
859
1174
|
docs: {
|
|
860
|
-
description:
|
|
1175
|
+
description: description4,
|
|
861
1176
|
recommended: true,
|
|
862
|
-
url:
|
|
1177
|
+
url: url4
|
|
863
1178
|
},
|
|
864
1179
|
fixable: "code",
|
|
865
|
-
messages:
|
|
1180
|
+
messages: messages4
|
|
866
1181
|
},
|
|
867
1182
|
create(context) {
|
|
868
|
-
function reportAndFix(node, oldValue, suggestedMatch) {
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
data: { oldValue, suggestedMatch },
|
|
873
|
-
fix(fixer) {
|
|
1183
|
+
function reportAndFix(node, oldValue, suggestedMatch, messageId, data) {
|
|
1184
|
+
let fixFunction = null;
|
|
1185
|
+
if (suggestedMatch) {
|
|
1186
|
+
fixFunction = (fixer) => {
|
|
874
1187
|
if (node.type === "Declaration") {
|
|
875
1188
|
const sourceCode = context.sourceCode;
|
|
876
1189
|
const fullText = sourceCode.getText();
|
|
@@ -881,493 +1194,256 @@ var enforce_sds_to_slds_hooks_default = {
|
|
|
881
1194
|
if (textAtPosition === oldValue) {
|
|
882
1195
|
return fixer.replaceTextRange([propertyStart, propertyEnd], suggestedMatch);
|
|
883
1196
|
}
|
|
1197
|
+
} else if (node.type === "Function" && node.name === "var") {
|
|
1198
|
+
const sourceCode = context.sourceCode;
|
|
1199
|
+
const fullText = sourceCode.getText();
|
|
1200
|
+
const nodeOffset = node.loc.start.offset;
|
|
1201
|
+
const nodeEnd = node.loc.end.offset;
|
|
1202
|
+
return fixer.replaceTextRange([nodeOffset, nodeEnd], suggestedMatch);
|
|
1203
|
+
} else {
|
|
1204
|
+
const sourceCode = context.sourceCode;
|
|
1205
|
+
const fullText = sourceCode.getText();
|
|
1206
|
+
const varFunctionCall = `var(${oldValue})`;
|
|
1207
|
+
const nodeOffset = node.loc.start.offset;
|
|
1208
|
+
const searchStart = Math.max(0, nodeOffset - 4);
|
|
1209
|
+
const searchEnd = nodeOffset + oldValue.length + 1;
|
|
1210
|
+
const searchArea = fullText.substring(searchStart, searchEnd);
|
|
1211
|
+
const functionCallIndex = searchArea.indexOf(varFunctionCall);
|
|
1212
|
+
if (functionCallIndex !== -1) {
|
|
1213
|
+
const actualStart = searchStart + functionCallIndex;
|
|
1214
|
+
const actualEnd = actualStart + varFunctionCall.length;
|
|
1215
|
+
return fixer.replaceTextRange([actualStart, actualEnd], suggestedMatch);
|
|
1216
|
+
}
|
|
884
1217
|
}
|
|
885
|
-
return
|
|
886
|
-
}
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
|
-
return {
|
|
890
|
-
// CSS custom property declarations: --sds-* properties
|
|
891
|
-
"Declaration[property=/^--sds-/]"(node) {
|
|
892
|
-
const property = node.property;
|
|
893
|
-
if (shouldIgnoreDetection2(property)) {
|
|
894
|
-
return;
|
|
895
|
-
}
|
|
896
|
-
const suggestedMatch = toSldsToken(property);
|
|
897
|
-
reportAndFix(node, property, suggestedMatch);
|
|
898
|
-
},
|
|
899
|
-
// SDS tokens inside var() functions: var(--sds-*)
|
|
900
|
-
"Function[name='var'] Identifier[name=/^--sds-/]"(node) {
|
|
901
|
-
const tokenName = node.name;
|
|
902
|
-
if (shouldIgnoreDetection2(tokenName)) {
|
|
903
|
-
return;
|
|
904
|
-
}
|
|
905
|
-
const suggestedMatch = toSldsToken(tokenName);
|
|
906
|
-
reportAndFix(node, tokenName, suggestedMatch);
|
|
907
|
-
}
|
|
908
|
-
};
|
|
909
|
-
}
|
|
910
|
-
};
|
|
911
|
-
|
|
912
|
-
// src/rules/v9/no-sldshook-fallback-for-lwctoken.ts
|
|
913
|
-
var import_sds_metadata7 = __toESM(require("@salesforce-ux/sds-metadata"));
|
|
914
|
-
var import_rule_messages7 = __toESM(require_rule_messages());
|
|
915
|
-
var ruleConfig5 = import_rule_messages7.default["no-sldshook-fallback-for-lwctoken"];
|
|
916
|
-
var { type: type6, description: description6, url: url6, messages: messages6 } = ruleConfig5;
|
|
917
|
-
var sldsPlusStylingHooks2 = import_sds_metadata7.default.sldsPlusStylingHooks;
|
|
918
|
-
var allSldsHooks2 = [...sldsPlusStylingHooks2.global, ...sldsPlusStylingHooks2.component];
|
|
919
|
-
var allSldsHooksSet = new Set(allSldsHooks2);
|
|
920
|
-
function hasUnsupportedFallback(lwcToken, sldsToken) {
|
|
921
|
-
const normalizedSldsToken = sldsToken.replace("--sds-", "--slds-");
|
|
922
|
-
return lwcToken.startsWith("--lwc-") && normalizedSldsToken.startsWith("--slds-") && allSldsHooksSet.has(normalizedSldsToken);
|
|
923
|
-
}
|
|
924
|
-
var no_sldshook_fallback_for_lwctoken_default = {
|
|
925
|
-
meta: {
|
|
926
|
-
type: type6,
|
|
927
|
-
docs: {
|
|
928
|
-
description: description6,
|
|
929
|
-
recommended: true,
|
|
930
|
-
url: url6
|
|
931
|
-
},
|
|
932
|
-
messages: messages6
|
|
933
|
-
},
|
|
934
|
-
create(context) {
|
|
935
|
-
return {
|
|
936
|
-
// Handle LWC tokens inside var() functions: var(--lwc-*, ...)
|
|
937
|
-
"Function[name='var'] Identifier[name=/^--lwc-/]"(node) {
|
|
938
|
-
const lwcToken = node.name;
|
|
939
|
-
const varFunctionNode = context.sourceCode.getAncestors(node).at(-1);
|
|
940
|
-
if (!varFunctionNode) return;
|
|
941
|
-
const varFunctionChildren = varFunctionNode.children;
|
|
942
|
-
if (!varFunctionChildren) return;
|
|
943
|
-
let foundComma = false;
|
|
944
|
-
let fallbackRawNode = null;
|
|
945
|
-
for (const child of varFunctionChildren) {
|
|
946
|
-
if (child.type === "Operator" && child.value === ",") {
|
|
947
|
-
foundComma = true;
|
|
948
|
-
continue;
|
|
949
|
-
}
|
|
950
|
-
if (foundComma && child.type === "Raw") {
|
|
951
|
-
fallbackRawNode = child;
|
|
952
|
-
break;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
if (!fallbackRawNode) return;
|
|
956
|
-
const fallbackValue = fallbackRawNode.value.trim();
|
|
957
|
-
const varMatch = fallbackValue.match(/var\(([^,)]+)/);
|
|
958
|
-
if (!varMatch) return;
|
|
959
|
-
const sldsToken = varMatch[1];
|
|
960
|
-
if (hasUnsupportedFallback(lwcToken, sldsToken)) {
|
|
961
|
-
context.report({
|
|
962
|
-
node,
|
|
963
|
-
messageId: "unsupportedFallback",
|
|
964
|
-
data: { lwcToken, sldsToken }
|
|
965
|
-
});
|
|
966
|
-
}
|
|
1218
|
+
return null;
|
|
1219
|
+
};
|
|
967
1220
|
}
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
};
|
|
971
|
-
|
|
972
|
-
// src/rules/v9/no-unsupported-hooks-slds2.ts
|
|
973
|
-
var import_sds_metadata8 = __toESM(require("@salesforce-ux/sds-metadata"));
|
|
974
|
-
var import_rule_messages8 = __toESM(require_rule_messages());
|
|
975
|
-
var ruleConfig6 = import_rule_messages8.default["no-unsupported-hooks-slds2"];
|
|
976
|
-
var { type: type7, description: description7, url: url7, messages: messages7 } = ruleConfig6;
|
|
977
|
-
var deprecatedHooks = new Set(import_sds_metadata8.default.deprecatedStylingHooks);
|
|
978
|
-
function shouldIgnoreDetection3(sldsHook) {
|
|
979
|
-
return !deprecatedHooks.has(sldsHook);
|
|
980
|
-
}
|
|
981
|
-
var no_unsupported_hooks_slds2_default = {
|
|
982
|
-
meta: {
|
|
983
|
-
type: type7,
|
|
984
|
-
docs: {
|
|
985
|
-
description: description7,
|
|
986
|
-
recommended: true,
|
|
987
|
-
url: url7
|
|
988
|
-
},
|
|
989
|
-
messages: messages7
|
|
990
|
-
},
|
|
991
|
-
create(context) {
|
|
992
|
-
function reportDeprecatedHook(node, token) {
|
|
993
1221
|
context.report({
|
|
994
1222
|
node,
|
|
995
|
-
messageId
|
|
996
|
-
data
|
|
997
|
-
|
|
998
|
-
}
|
|
999
|
-
return {
|
|
1000
|
-
// Handle CSS custom property declarations (left-side usage): --slds-* properties
|
|
1001
|
-
// Example: .THIS { --slds-g-link-color: #f73650; }
|
|
1002
|
-
"Declaration[property=/^--s(lds|ds)-/]"(node) {
|
|
1003
|
-
const property = node.property;
|
|
1004
|
-
if (shouldIgnoreDetection3(property)) {
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1007
|
-
reportDeprecatedHook(node, property);
|
|
1008
|
-
},
|
|
1009
|
-
// Handle SLDS/SDS hooks inside var() functions (right-side usage): var(--slds-*)
|
|
1010
|
-
// Example: .THIS .demo { border-top: 1px solid var(--slds-g-color-border-brand-1); }
|
|
1011
|
-
"Function[name='var'] Identifier[name=/^--s(lds|ds)-/]"(node) {
|
|
1012
|
-
const tokenName = node.name;
|
|
1013
|
-
if (shouldIgnoreDetection3(tokenName)) {
|
|
1014
|
-
return;
|
|
1015
|
-
}
|
|
1016
|
-
reportDeprecatedHook(node, tokenName);
|
|
1017
|
-
}
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1022
|
-
// src/rules/v9/no-slds-var-without-fallback.ts
|
|
1023
|
-
var import_sds_metadata9 = __toESM(require("@salesforce-ux/sds-metadata"));
|
|
1024
|
-
var import_rule_messages9 = __toESM(require_rule_messages());
|
|
1025
|
-
|
|
1026
|
-
// src/utils/hardcoded-shared-utils.ts
|
|
1027
|
-
var import_css_tree2 = require("@eslint/css-tree");
|
|
1028
|
-
|
|
1029
|
-
// src/utils/color-lib-utils.ts
|
|
1030
|
-
var import_chroma_js = __toESM(require("chroma-js"));
|
|
1031
|
-
var import_css_tree = require("@eslint/css-tree");
|
|
1032
|
-
|
|
1033
|
-
// src/utils/css-functions.ts
|
|
1034
|
-
var CSS_FUNCTIONS = [
|
|
1035
|
-
"attr",
|
|
1036
|
-
"calc",
|
|
1037
|
-
"color-mix",
|
|
1038
|
-
"conic-gradient",
|
|
1039
|
-
"counter",
|
|
1040
|
-
"cubic-bezier",
|
|
1041
|
-
"linear-gradient",
|
|
1042
|
-
"max",
|
|
1043
|
-
"min",
|
|
1044
|
-
"radial-gradient",
|
|
1045
|
-
"repeating-conic-gradient",
|
|
1046
|
-
"repeating-linear-gradient",
|
|
1047
|
-
"repeating-radial-gradient",
|
|
1048
|
-
"var"
|
|
1049
|
-
];
|
|
1050
|
-
var CSS_MATH_FUNCTIONS = ["calc", "min", "max"];
|
|
1051
|
-
var RGB_COLOR_FUNCTIONS = ["rgb", "rgba", "hsl", "hsla"];
|
|
1052
|
-
var cssFunctionsRegex = new RegExp(`(?:${CSS_FUNCTIONS.join("|")})`);
|
|
1053
|
-
var cssFunctionsExactRegex = new RegExp(`^(?:${CSS_FUNCTIONS.join("|")})$`);
|
|
1054
|
-
var cssMathFunctionsRegex = new RegExp(`^(?:${CSS_MATH_FUNCTIONS.join("|")})$`);
|
|
1055
|
-
function isCssFunction(value) {
|
|
1056
|
-
return cssFunctionsExactRegex.test(value);
|
|
1057
|
-
}
|
|
1058
|
-
function isCssColorFunction(value) {
|
|
1059
|
-
return RGB_COLOR_FUNCTIONS.includes(value);
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
// src/utils/color-lib-utils.ts
|
|
1063
|
-
var LAB_THRESHOLD = 25;
|
|
1064
|
-
var isHexCode = (color) => {
|
|
1065
|
-
const hexPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/;
|
|
1066
|
-
return hexPattern.test(color);
|
|
1067
|
-
};
|
|
1068
|
-
var convertToHex = (color) => {
|
|
1069
|
-
try {
|
|
1070
|
-
return (0, import_chroma_js.default)(color).hex();
|
|
1071
|
-
} catch (e) {
|
|
1072
|
-
return null;
|
|
1073
|
-
}
|
|
1074
|
-
};
|
|
1075
|
-
var findClosestColorHook = (color, supportedColors, cssProperty) => {
|
|
1076
|
-
const returnStylingHooks = [];
|
|
1077
|
-
const closestHooksWithSameProperty = [];
|
|
1078
|
-
const closestHooksWithoutSameProperty = [];
|
|
1079
|
-
const closestHooksWithAllProperty = [];
|
|
1080
|
-
const labColor = (0, import_chroma_js.default)(color).lab();
|
|
1081
|
-
Object.entries(supportedColors).forEach(([sldsValue, data]) => {
|
|
1082
|
-
if (sldsValue && isHexCode(sldsValue)) {
|
|
1083
|
-
const hooks = data;
|
|
1084
|
-
hooks.forEach((hook) => {
|
|
1085
|
-
const labSupportedColor = (0, import_chroma_js.default)(sldsValue).lab();
|
|
1086
|
-
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");
|
|
1087
|
-
if (hook.properties.includes(cssProperty)) {
|
|
1088
|
-
if (distance <= LAB_THRESHOLD) {
|
|
1089
|
-
closestHooksWithSameProperty.push({ name: hook.name, distance });
|
|
1090
|
-
}
|
|
1091
|
-
} else if (hook.properties.includes("*")) {
|
|
1092
|
-
if (distance <= LAB_THRESHOLD) {
|
|
1093
|
-
closestHooksWithAllProperty.push({ name: hook.name, distance });
|
|
1094
|
-
}
|
|
1095
|
-
} else {
|
|
1096
|
-
if (distance <= LAB_THRESHOLD) {
|
|
1097
|
-
closestHooksWithoutSameProperty.push({ name: hook.name, distance });
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1223
|
+
messageId,
|
|
1224
|
+
data,
|
|
1225
|
+
fix: fixFunction
|
|
1100
1226
|
});
|
|
1101
1227
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1228
|
+
return {
|
|
1229
|
+
// CSS custom property declarations: --lwc-* properties
|
|
1230
|
+
"Declaration[property=/^--lwc-/]"(node) {
|
|
1231
|
+
const property = node.property;
|
|
1232
|
+
if (shouldIgnoreDetection(property)) {
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
const { hasRecommendation, recommendation, replacementCategory } = getRecommendation(property);
|
|
1236
|
+
const { messageId, data } = getReportMessage(property, replacementCategory, recommendation);
|
|
1237
|
+
const suggestedMatch = hasRecommendation && replacementCategory === "slds_token" /* SLDS_TOKEN */ ? recommendation : null;
|
|
1238
|
+
reportAndFix(node, property, suggestedMatch, messageId, data);
|
|
1239
|
+
},
|
|
1240
|
+
// LWC tokens inside var() functions: var(--lwc-*)
|
|
1241
|
+
"Function[name='var']"(node) {
|
|
1242
|
+
const lwcVarInfo = extractLwcVariableWithFallback(node, context.sourceCode);
|
|
1243
|
+
if (!lwcVarInfo) {
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
const { lwcToken, fallbackValue } = lwcVarInfo;
|
|
1247
|
+
if (shouldIgnoreDetection(lwcToken)) {
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
const { hasRecommendation, recommendation, replacementCategory } = getRecommendation(lwcToken);
|
|
1251
|
+
const { messageId, data } = getReportMessage(lwcToken, replacementCategory, recommendation);
|
|
1252
|
+
let suggestedMatch = null;
|
|
1253
|
+
if (hasRecommendation) {
|
|
1254
|
+
if (replacementCategory === "slds_token" /* SLDS_TOKEN */) {
|
|
1255
|
+
const originalVarCall = fallbackValue ? `var(${lwcToken}, ${fallbackValue})` : `var(${lwcToken})`;
|
|
1256
|
+
suggestedMatch = `var(${recommendation}, ${originalVarCall})`;
|
|
1257
|
+
} else if (replacementCategory === "raw_value" /* RAW_VALUE */) {
|
|
1258
|
+
suggestedMatch = recommendation;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
reportAndFix(node, lwcToken, suggestedMatch, messageId, data);
|
|
1135
1262
|
}
|
|
1136
|
-
|
|
1263
|
+
};
|
|
1137
1264
|
}
|
|
1138
|
-
return colorValue && isValidColor(colorValue) ? colorValue : null;
|
|
1139
1265
|
};
|
|
1140
1266
|
|
|
1141
|
-
// src/
|
|
1142
|
-
var
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
"
|
|
1151
|
-
"500",
|
|
1152
|
-
"600",
|
|
1153
|
-
"700",
|
|
1154
|
-
"800",
|
|
1155
|
-
"900"
|
|
1156
|
-
];
|
|
1157
|
-
function isKnownFontWeight(value) {
|
|
1158
|
-
const stringValue = value.toString();
|
|
1159
|
-
return FONT_WEIGHTS.includes(stringValue.toLowerCase());
|
|
1267
|
+
// src/rules/v9/enforce-sds-to-slds-hooks.ts
|
|
1268
|
+
var import_sds_metadata6 = __toESM(require("@salesforce-ux/sds-metadata"));
|
|
1269
|
+
var import_rule_messages6 = __toESM(require_rule_messages());
|
|
1270
|
+
var ruleConfig4 = import_rule_messages6.default["enforce-sds-to-slds-hooks"];
|
|
1271
|
+
var { type: type5, description: description5, url: url5, messages: messages5 } = ruleConfig4;
|
|
1272
|
+
var sldsPlusStylingHooks = import_sds_metadata6.default.sldsPlusStylingHooks;
|
|
1273
|
+
var allSldsHooks = [...sldsPlusStylingHooks.global, ...sldsPlusStylingHooks.component];
|
|
1274
|
+
var toSldsToken = (sdsToken) => sdsToken.replace("--sds-", "--slds-");
|
|
1275
|
+
function shouldIgnoreDetection2(sdsToken) {
|
|
1276
|
+
return !sdsToken.startsWith("--sds-") || !allSldsHooks.includes(toSldsToken(sdsToken));
|
|
1160
1277
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
},
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
return fixer.replaceText(declarationNode.value, newValue);
|
|
1192
|
-
} : void 0;
|
|
1193
|
-
context.context.report({
|
|
1194
|
-
node: reportNode,
|
|
1195
|
-
messageId: "hardcodedValue",
|
|
1196
|
-
data: {
|
|
1197
|
-
oldValue: originalValue,
|
|
1198
|
-
newValue: displayValue
|
|
1199
|
-
},
|
|
1200
|
-
fix
|
|
1201
|
-
});
|
|
1202
|
-
} else {
|
|
1203
|
-
context.context.report({
|
|
1204
|
-
node: reportNode,
|
|
1205
|
-
messageId: "noReplacement",
|
|
1206
|
-
data: {
|
|
1207
|
-
oldValue: originalValue
|
|
1278
|
+
var enforce_sds_to_slds_hooks_default = {
|
|
1279
|
+
meta: {
|
|
1280
|
+
type: type5,
|
|
1281
|
+
docs: {
|
|
1282
|
+
description: description5,
|
|
1283
|
+
recommended: true,
|
|
1284
|
+
url: url5
|
|
1285
|
+
},
|
|
1286
|
+
fixable: "code",
|
|
1287
|
+
messages: messages5
|
|
1288
|
+
},
|
|
1289
|
+
create(context) {
|
|
1290
|
+
function reportAndFix(node, oldValue, suggestedMatch) {
|
|
1291
|
+
context.report({
|
|
1292
|
+
node,
|
|
1293
|
+
messageId: "replaceSdsWithSlds",
|
|
1294
|
+
data: { oldValue, suggestedMatch },
|
|
1295
|
+
fix(fixer) {
|
|
1296
|
+
if (node.type === "Declaration") {
|
|
1297
|
+
const sourceCode = context.sourceCode;
|
|
1298
|
+
const fullText = sourceCode.getText();
|
|
1299
|
+
const nodeOffset = node.loc.start.offset;
|
|
1300
|
+
const propertyStart = nodeOffset;
|
|
1301
|
+
const propertyEnd = propertyStart + oldValue.length;
|
|
1302
|
+
const textAtPosition = fullText.substring(propertyStart, propertyEnd);
|
|
1303
|
+
if (textAtPosition === oldValue) {
|
|
1304
|
+
return fixer.replaceTextRange([propertyStart, propertyEnd], suggestedMatch);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
return fixer.replaceText(node, suggestedMatch);
|
|
1208
1308
|
}
|
|
1209
1309
|
});
|
|
1210
1310
|
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1311
|
+
return {
|
|
1312
|
+
// CSS custom property declarations: --sds-* properties
|
|
1313
|
+
"Declaration[property=/^--sds-/]"(node) {
|
|
1314
|
+
const property = node.property;
|
|
1315
|
+
if (shouldIgnoreDetection2(property)) {
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
const suggestedMatch = toSldsToken(property);
|
|
1319
|
+
reportAndFix(node, property, suggestedMatch);
|
|
1320
|
+
},
|
|
1321
|
+
// SDS tokens inside var() functions: var(--sds-*)
|
|
1322
|
+
"Function[name='var'] Identifier[name=/^--sds-/]"(node) {
|
|
1323
|
+
const tokenName = node.name;
|
|
1324
|
+
if (shouldIgnoreDetection2(tokenName)) {
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
const suggestedMatch = toSldsToken(tokenName);
|
|
1328
|
+
reportAndFix(node, tokenName, suggestedMatch);
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1216
1331
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1332
|
+
};
|
|
1333
|
+
|
|
1334
|
+
// src/rules/v9/no-sldshook-fallback-for-lwctoken.ts
|
|
1335
|
+
var import_sds_metadata7 = __toESM(require("@salesforce-ux/sds-metadata"));
|
|
1336
|
+
var import_rule_messages7 = __toESM(require_rule_messages());
|
|
1337
|
+
var ruleConfig5 = import_rule_messages7.default["no-sldshook-fallback-for-lwctoken"];
|
|
1338
|
+
var { type: type6, description: description6, url: url6, messages: messages6 } = ruleConfig5;
|
|
1339
|
+
var sldsPlusStylingHooks2 = import_sds_metadata7.default.sldsPlusStylingHooks;
|
|
1340
|
+
var allSldsHooks2 = [...sldsPlusStylingHooks2.global, ...sldsPlusStylingHooks2.component];
|
|
1341
|
+
var allSldsHooksSet = new Set(allSldsHooks2);
|
|
1342
|
+
function hasUnsupportedFallback(lwcToken, sldsToken) {
|
|
1343
|
+
const normalizedSldsToken = sldsToken.replace("--sds-", "--slds-");
|
|
1344
|
+
return lwcToken.startsWith("--lwc-") && normalizedSldsToken.startsWith("--slds-") && allSldsHooksSet.has(normalizedSldsToken);
|
|
1345
|
+
}
|
|
1346
|
+
var no_sldshook_fallback_for_lwctoken_default = {
|
|
1347
|
+
meta: {
|
|
1348
|
+
type: type6,
|
|
1349
|
+
docs: {
|
|
1350
|
+
description: description6,
|
|
1351
|
+
recommended: true,
|
|
1352
|
+
url: url6
|
|
1353
|
+
},
|
|
1354
|
+
messages: messages6
|
|
1355
|
+
},
|
|
1356
|
+
create(context) {
|
|
1357
|
+
return {
|
|
1358
|
+
// Handle LWC tokens inside var() functions: var(--lwc-*, ...)
|
|
1359
|
+
"Function[name='var'] Identifier[name=/^--lwc-/]"(node) {
|
|
1360
|
+
const lwcToken = node.name;
|
|
1361
|
+
const varFunctionNode = context.sourceCode.getAncestors(node).at(-1);
|
|
1362
|
+
if (!varFunctionNode) return;
|
|
1363
|
+
const varFunctionChildren = varFunctionNode.children;
|
|
1364
|
+
if (!varFunctionChildren) return;
|
|
1365
|
+
let foundComma = false;
|
|
1366
|
+
let fallbackRawNode = null;
|
|
1367
|
+
for (const child of varFunctionChildren) {
|
|
1368
|
+
if (child.type === "Operator" && child.value === ",") {
|
|
1369
|
+
foundComma = true;
|
|
1370
|
+
continue;
|
|
1371
|
+
}
|
|
1372
|
+
if (foundComma && child.type === "Raw") {
|
|
1373
|
+
fallbackRawNode = child;
|
|
1374
|
+
break;
|
|
1375
|
+
}
|
|
1223
1376
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1377
|
+
if (!fallbackRawNode) return;
|
|
1378
|
+
const fallbackValue = fallbackRawNode.value.trim();
|
|
1379
|
+
const varMatch = fallbackValue.match(/var\(([^,)]+)/);
|
|
1380
|
+
if (!varMatch) return;
|
|
1381
|
+
const sldsToken = varMatch[1];
|
|
1382
|
+
if (hasUnsupportedFallback(lwcToken, sldsToken)) {
|
|
1383
|
+
context.report({
|
|
1384
|
+
node,
|
|
1385
|
+
messageId: "unsupportedFallback",
|
|
1386
|
+
data: { lwcToken, sldsToken }
|
|
1387
|
+
});
|
|
1231
1388
|
}
|
|
1232
1389
|
}
|
|
1233
|
-
}
|
|
1234
|
-
} catch (error) {
|
|
1235
|
-
return;
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
function shouldSkipColorNode(node) {
|
|
1239
|
-
return node.type === "Function" && isCssFunction(node.name);
|
|
1240
|
-
}
|
|
1241
|
-
function shouldSkipDimensionNode(node) {
|
|
1242
|
-
return node.type === "Function";
|
|
1243
|
-
}
|
|
1244
|
-
function extractDimensionValue(valueNode, cssProperty) {
|
|
1245
|
-
if (!valueNode) return null;
|
|
1246
|
-
switch (valueNode.type) {
|
|
1247
|
-
case "Dimension":
|
|
1248
|
-
const numValue = Number(valueNode.value);
|
|
1249
|
-
if (numValue === 0) return null;
|
|
1250
|
-
const unit = valueNode.unit.toLowerCase();
|
|
1251
|
-
if (unit !== "px" && unit !== "rem" && unit !== "%") return null;
|
|
1252
|
-
return {
|
|
1253
|
-
number: numValue,
|
|
1254
|
-
unit
|
|
1255
|
-
};
|
|
1256
|
-
case "Number":
|
|
1257
|
-
const numberValue = Number(valueNode.value);
|
|
1258
|
-
if (numberValue === 0) return null;
|
|
1259
|
-
return {
|
|
1260
|
-
number: numberValue,
|
|
1261
|
-
unit: null
|
|
1262
|
-
};
|
|
1263
|
-
case "Percentage":
|
|
1264
|
-
const percentValue = Number(valueNode.value);
|
|
1265
|
-
if (percentValue === 0) return null;
|
|
1266
|
-
return {
|
|
1267
|
-
number: percentValue,
|
|
1268
|
-
unit: "%"
|
|
1269
|
-
};
|
|
1270
|
-
case "Value":
|
|
1271
|
-
return valueNode.children?.[0] ? extractDimensionValue(valueNode.children[0], cssProperty) : null;
|
|
1390
|
+
};
|
|
1272
1391
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
callback
|
|
1284
|
-
);
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
// src/rules/v9/no-unsupported-hooks-slds2.ts
|
|
1395
|
+
var import_sds_metadata8 = __toESM(require("@salesforce-ux/sds-metadata"));
|
|
1396
|
+
var import_rule_messages8 = __toESM(require_rule_messages());
|
|
1397
|
+
var ruleConfig6 = import_rule_messages8.default["no-unsupported-hooks-slds2"];
|
|
1398
|
+
var { type: type7, description: description7, url: url7, messages: messages7 } = ruleConfig6;
|
|
1399
|
+
var deprecatedHooks = new Set(import_sds_metadata8.default.deprecatedStylingHooks);
|
|
1400
|
+
function shouldIgnoreDetection3(sldsHook) {
|
|
1401
|
+
return !deprecatedHooks.has(sldsHook);
|
|
1285
1402
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1403
|
+
var no_unsupported_hooks_slds2_default = {
|
|
1404
|
+
meta: {
|
|
1405
|
+
type: type7,
|
|
1406
|
+
docs: {
|
|
1407
|
+
description: description7,
|
|
1408
|
+
recommended: true,
|
|
1409
|
+
url: url7
|
|
1410
|
+
},
|
|
1411
|
+
messages: messages7
|
|
1412
|
+
},
|
|
1413
|
+
create(context) {
|
|
1414
|
+
function reportDeprecatedHook(node, token) {
|
|
1415
|
+
context.report({
|
|
1416
|
+
node,
|
|
1417
|
+
messageId: "deprecated",
|
|
1418
|
+
data: { token }
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
return {
|
|
1422
|
+
// Handle CSS custom property declarations (left-side usage): --slds-* properties
|
|
1423
|
+
// Example: .THIS { --slds-g-link-color: #f73650; }
|
|
1424
|
+
"Declaration[property=/^--s(lds|ds)-/]"(node) {
|
|
1425
|
+
const property = node.property;
|
|
1426
|
+
if (shouldIgnoreDetection3(property)) {
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
reportDeprecatedHook(node, property);
|
|
1430
|
+
},
|
|
1431
|
+
// Handle SLDS/SDS hooks inside var() functions (right-side usage): var(--slds-*)
|
|
1432
|
+
// Example: .THIS .demo { border-top: 1px solid var(--slds-g-color-border-brand-1); }
|
|
1433
|
+
"Function[name='var'] Identifier[name=/^--s(lds|ds)-/]"(node) {
|
|
1434
|
+
const tokenName = node.name;
|
|
1435
|
+
if (shouldIgnoreDetection3(tokenName)) {
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1438
|
+
reportDeprecatedHook(node, tokenName);
|
|
1317
1439
|
}
|
|
1318
|
-
|
|
1319
|
-
case "Percentage":
|
|
1320
|
-
const percentValue = Number(node.value);
|
|
1321
|
-
if (percentValue === 0) return null;
|
|
1322
|
-
return {
|
|
1323
|
-
number: percentValue,
|
|
1324
|
-
unit: "%"
|
|
1325
|
-
};
|
|
1326
|
-
case "Value":
|
|
1327
|
-
return node.children?.[0] ? extractFontValue(node.children[0]) : null;
|
|
1328
|
-
}
|
|
1329
|
-
return null;
|
|
1330
|
-
}
|
|
1331
|
-
function shouldSkipFontNode(node) {
|
|
1332
|
-
return node.type === "Function";
|
|
1333
|
-
}
|
|
1334
|
-
function forEachFontValue(valueText, callback) {
|
|
1335
|
-
forEachValue(valueText, extractFontValue, shouldSkipFontNode, callback);
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
|
-
// src/utils/css-utils.ts
|
|
1339
|
-
function extractSldsVariable(node) {
|
|
1340
|
-
if (!node || node.type !== "Function" || node.name !== "var") {
|
|
1341
|
-
return null;
|
|
1342
|
-
}
|
|
1343
|
-
if (!node.children) {
|
|
1344
|
-
return null;
|
|
1345
|
-
}
|
|
1346
|
-
const childrenArray = Array.from(node.children);
|
|
1347
|
-
if (childrenArray.length === 0) {
|
|
1348
|
-
return null;
|
|
1349
|
-
}
|
|
1350
|
-
const firstChild = childrenArray[0];
|
|
1351
|
-
if (!firstChild || firstChild.type !== "Identifier") {
|
|
1352
|
-
return null;
|
|
1353
|
-
}
|
|
1354
|
-
const variableName = firstChild.name;
|
|
1355
|
-
if (!variableName || !variableName.startsWith("--slds-")) {
|
|
1356
|
-
return null;
|
|
1440
|
+
};
|
|
1357
1441
|
}
|
|
1358
|
-
|
|
1359
|
-
(child) => child.type === "Operator" && child.value === ","
|
|
1360
|
-
);
|
|
1361
|
-
return {
|
|
1362
|
-
name: variableName,
|
|
1363
|
-
hasFallback
|
|
1364
|
-
};
|
|
1365
|
-
}
|
|
1366
|
-
function forEachSldsVariable(valueText, callback) {
|
|
1367
|
-
forEachValue(valueText, extractSldsVariable, () => false, callback);
|
|
1368
|
-
}
|
|
1442
|
+
};
|
|
1369
1443
|
|
|
1370
1444
|
// src/rules/v9/no-slds-var-without-fallback.ts
|
|
1445
|
+
var import_sds_metadata9 = __toESM(require("@salesforce-ux/sds-metadata"));
|
|
1446
|
+
var import_rule_messages9 = __toESM(require_rule_messages());
|
|
1371
1447
|
var ruleConfig7 = import_rule_messages9.default["no-slds-var-without-fallback"];
|
|
1372
1448
|
var { type: type8, description: description8, url: url8, messages: messages8 } = ruleConfig7;
|
|
1373
1449
|
var sldsVariables = import_sds_metadata9.default.slds1ExcludedVars || {};
|
|
@@ -1700,7 +1776,7 @@ function toSelector(properties) {
|
|
|
1700
1776
|
const selectorParts = properties.map((prop) => {
|
|
1701
1777
|
if (prop.includes("*")) {
|
|
1702
1778
|
const regexPattern = prop.replace(/\*/g, ".*");
|
|
1703
|
-
return `Declaration[property
|
|
1779
|
+
return `Declaration[property=/^${regexPattern}$/]`;
|
|
1704
1780
|
} else {
|
|
1705
1781
|
return `Declaration[property='${prop}']`;
|
|
1706
1782
|
}
|
|
@@ -1771,9 +1847,8 @@ function createColorReplacement(colorValue, cssProperty, context, positionInfo,
|
|
|
1771
1847
|
end,
|
|
1772
1848
|
replacement: originalValue,
|
|
1773
1849
|
// Use original value to preserve spacing
|
|
1774
|
-
displayValue: closestHooks
|
|
1850
|
+
displayValue: formatSuggestionHooks(closestHooks),
|
|
1775
1851
|
hasHook: true
|
|
1776
|
-
// ← THE FIX: Multiple hooks still means "has hooks"
|
|
1777
1852
|
};
|
|
1778
1853
|
} else {
|
|
1779
1854
|
return {
|
|
@@ -1787,37 +1862,6 @@ function createColorReplacement(colorValue, cssProperty, context, positionInfo,
|
|
|
1787
1862
|
}
|
|
1788
1863
|
}
|
|
1789
1864
|
|
|
1790
|
-
// src/utils/value-utils.ts
|
|
1791
|
-
function parseUnitValue(value) {
|
|
1792
|
-
if (!value) return null;
|
|
1793
|
-
const match = value.match(/^(-?\d*\.?\d+)(px|rem|%)?$/);
|
|
1794
|
-
if (!match) return null;
|
|
1795
|
-
const number = parseFloat(match[1]);
|
|
1796
|
-
const unit = match[2] ? match[2] : null;
|
|
1797
|
-
if (isNaN(number)) return null;
|
|
1798
|
-
return { number, unit };
|
|
1799
|
-
}
|
|
1800
|
-
function toAlternateUnitValue(numberVal, unitType) {
|
|
1801
|
-
if (unitType === "px") {
|
|
1802
|
-
let floatValue = parseFloat(`${numberVal / 16}`);
|
|
1803
|
-
if (!isNaN(floatValue)) {
|
|
1804
|
-
return {
|
|
1805
|
-
unit: "rem",
|
|
1806
|
-
number: parseFloat(floatValue.toFixed(4))
|
|
1807
|
-
};
|
|
1808
|
-
}
|
|
1809
|
-
} else if (unitType === "rem") {
|
|
1810
|
-
const intValue = parseInt(`${numberVal * 16}`);
|
|
1811
|
-
if (!isNaN(intValue)) {
|
|
1812
|
-
return {
|
|
1813
|
-
unit: "px",
|
|
1814
|
-
number: intValue
|
|
1815
|
-
};
|
|
1816
|
-
}
|
|
1817
|
-
}
|
|
1818
|
-
return null;
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
1865
|
// src/utils/styling-hook-utils.ts
|
|
1822
1866
|
function isValueMatch(valueToMatch, sldsValue) {
|
|
1823
1867
|
if (!valueToMatch || !sldsValue) {
|
|
@@ -1875,7 +1919,7 @@ function createDimensionReplacement(parsedDimension, cssProperty, context, posit
|
|
|
1875
1919
|
start,
|
|
1876
1920
|
end,
|
|
1877
1921
|
replacement: rawValue,
|
|
1878
|
-
displayValue: closestHooks
|
|
1922
|
+
displayValue: formatSuggestionHooks(closestHooks),
|
|
1879
1923
|
hasHook: true
|
|
1880
1924
|
};
|
|
1881
1925
|
} else {
|
|
@@ -1942,7 +1986,7 @@ function createFontReplacement(fontValue, cssProperty, context, positionInfo) {
|
|
|
1942
1986
|
start,
|
|
1943
1987
|
end,
|
|
1944
1988
|
replacement: rawValue,
|
|
1945
|
-
displayValue: closestHooks
|
|
1989
|
+
displayValue: formatSuggestionHooks(closestHooks),
|
|
1946
1990
|
hasHook: true
|
|
1947
1991
|
};
|
|
1948
1992
|
} else {
|
|
@@ -2069,59 +2113,51 @@ function isBoxShadowMatch(parsedCssValue, parsedValueHook) {
|
|
|
2069
2113
|
}
|
|
2070
2114
|
|
|
2071
2115
|
// src/rules/v9/no-hardcoded-values/handlers/boxShadowHandler.ts
|
|
2072
|
-
function
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
const cssProperty = node.property.toLowerCase();
|
|
2077
|
-
const valueText = context.sourceCode.getText(node.value);
|
|
2078
|
-
if (containsCssVariable(valueText)) {
|
|
2079
|
-
return;
|
|
2080
|
-
}
|
|
2081
|
-
const replacements = [];
|
|
2082
|
-
const parsedCssValue = parseAndValidateBoxShadow(valueText);
|
|
2083
|
-
if (parsedCssValue) {
|
|
2084
|
-
const shadowHooks = getBoxShadowHooks(context.valueToStylinghook);
|
|
2085
|
-
const closestHooks = findMatchingBoxShadowHooks(parsedCssValue, shadowHooks);
|
|
2086
|
-
const positionInfo = {
|
|
2087
|
-
start: { offset: 0, line: 1, column: 1 },
|
|
2088
|
-
end: { offset: valueText.length, line: 1, column: valueText.length + 1 }
|
|
2089
|
-
};
|
|
2090
|
-
const replacement = createBoxShadowReplacement(
|
|
2091
|
-
valueText,
|
|
2092
|
-
closestHooks,
|
|
2093
|
-
context,
|
|
2094
|
-
positionInfo
|
|
2095
|
-
);
|
|
2096
|
-
if (replacement) {
|
|
2097
|
-
replacements.push(replacement);
|
|
2098
|
-
}
|
|
2116
|
+
function toBoxShadowValue(cssValue) {
|
|
2117
|
+
const parsedCssValue = parseBoxShadowValue(cssValue).filter((shadow) => Object.keys(shadow).length > 0);
|
|
2118
|
+
if (parsedCssValue.length === 0) {
|
|
2119
|
+
return null;
|
|
2099
2120
|
}
|
|
2100
|
-
|
|
2101
|
-
}
|
|
2102
|
-
function
|
|
2121
|
+
return parsedCssValue;
|
|
2122
|
+
}
|
|
2123
|
+
function shadowValueToHookEntries(supportedStylinghooks) {
|
|
2103
2124
|
return Object.entries(supportedStylinghooks).filter(([key, value]) => {
|
|
2104
2125
|
return value.some((hook) => hook.properties.includes("box-shadow"));
|
|
2105
2126
|
}).map(([key, value]) => {
|
|
2106
2127
|
return [key, value.map((hook) => hook.name)];
|
|
2107
2128
|
});
|
|
2108
2129
|
}
|
|
2109
|
-
|
|
2110
|
-
const
|
|
2111
|
-
|
|
2112
|
-
|
|
2130
|
+
var handleBoxShadowDeclaration = (node, context) => {
|
|
2131
|
+
const cssProperty = node.property.toLowerCase();
|
|
2132
|
+
const valueText = context.sourceCode.getText(node.value);
|
|
2133
|
+
const shadowHooks = shadowValueToHookEntries(context.valueToStylinghook);
|
|
2134
|
+
const parsedCssValue = toBoxShadowValue(valueText);
|
|
2135
|
+
if (!parsedCssValue) {
|
|
2136
|
+
return;
|
|
2113
2137
|
}
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2138
|
+
for (const [shadow, closestHooks] of shadowHooks) {
|
|
2139
|
+
const parsedValueHook = toBoxShadowValue(shadow);
|
|
2140
|
+
if (parsedValueHook && isBoxShadowMatch(parsedCssValue, parsedValueHook)) {
|
|
2141
|
+
if (closestHooks.length > 0) {
|
|
2142
|
+
const positionInfo = {
|
|
2143
|
+
start: { offset: 0, line: 1, column: 1 },
|
|
2144
|
+
end: { offset: valueText.length, line: 1, column: valueText.length + 1 }
|
|
2145
|
+
};
|
|
2146
|
+
const replacement = createBoxShadowReplacement(
|
|
2147
|
+
valueText,
|
|
2148
|
+
closestHooks,
|
|
2149
|
+
context,
|
|
2150
|
+
positionInfo
|
|
2151
|
+
);
|
|
2152
|
+
if (replacement) {
|
|
2153
|
+
const replacements = [replacement];
|
|
2154
|
+
handleShorthandAutoFix(node, context, valueText, replacements);
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
return;
|
|
2121
2158
|
}
|
|
2122
2159
|
}
|
|
2123
|
-
|
|
2124
|
-
}
|
|
2160
|
+
};
|
|
2125
2161
|
function createBoxShadowReplacement(originalValue, hooks, context, positionInfo) {
|
|
2126
2162
|
if (!positionInfo?.start) {
|
|
2127
2163
|
return null;
|
|
@@ -2136,21 +2172,13 @@ function createBoxShadowReplacement(originalValue, hooks, context, positionInfo)
|
|
|
2136
2172
|
displayValue: hooks[0],
|
|
2137
2173
|
hasHook: true
|
|
2138
2174
|
};
|
|
2139
|
-
} else if (hooks.length > 1) {
|
|
2140
|
-
return {
|
|
2141
|
-
start,
|
|
2142
|
-
end,
|
|
2143
|
-
replacement: originalValue,
|
|
2144
|
-
displayValue: hooks.join(", "),
|
|
2145
|
-
hasHook: true
|
|
2146
|
-
};
|
|
2147
2175
|
} else {
|
|
2148
2176
|
return {
|
|
2149
2177
|
start,
|
|
2150
2178
|
end,
|
|
2151
2179
|
replacement: originalValue,
|
|
2152
|
-
displayValue:
|
|
2153
|
-
hasHook:
|
|
2180
|
+
displayValue: formatSuggestionHooks(hooks),
|
|
2181
|
+
hasHook: true
|
|
2154
2182
|
};
|
|
2155
2183
|
}
|
|
2156
2184
|
}
|
|
@@ -2280,6 +2308,7 @@ var eslint_rules_default = {
|
|
|
2280
2308
|
css: {
|
|
2281
2309
|
"@salesforce-ux/slds/no-slds-class-overrides": "warn",
|
|
2282
2310
|
"@salesforce-ux/slds/no-deprecated-slds-classes": "warn",
|
|
2311
|
+
"@salesforce-ux/slds/lwc-token-to-slds-hook": "error",
|
|
2283
2312
|
"@salesforce-ux/slds/enforce-sds-to-slds-hooks": "warn",
|
|
2284
2313
|
"@salesforce-ux/slds/no-sldshook-fallback-for-lwctoken": "warn",
|
|
2285
2314
|
"@salesforce-ux/slds/no-unsupported-hooks-slds2": "warn",
|
|
@@ -2320,7 +2349,7 @@ var rules = {
|
|
|
2320
2349
|
var plugin = {
|
|
2321
2350
|
meta: {
|
|
2322
2351
|
name: "@salesforce-ux/eslint-plugin-slds",
|
|
2323
|
-
version: "1.0.0"
|
|
2352
|
+
version: "1.0.2-alpha.0"
|
|
2324
2353
|
},
|
|
2325
2354
|
rules,
|
|
2326
2355
|
configs: {}
|