@salesforce-ux/eslint-plugin-slds 0.0.5 → 0.0.7

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.
@@ -0,0 +1,22 @@
1
+ root: true
2
+ env:
3
+ es2021: true
4
+ node: true
5
+ parser: "@html-eslint/parser" # ✅ Ensure we are using the correct parser
6
+ parserOptions:
7
+ ecmaVersion: 2021
8
+ sourceType: module
9
+ ignorePatterns:
10
+ - "node_modules/"
11
+ overrides:
12
+ - files:
13
+ - "*.html"
14
+ - "*.cmp"
15
+ parser: "@html-eslint/parser" # ✅ Enforce HTML parser only for these files
16
+ plugins:
17
+ - "@html-eslint"
18
+ - "@salesforce-ux/slds"
19
+ rules:
20
+ "@salesforce-ux/slds/no-bem-class": "error"
21
+ "@salesforce-ux/slds/no-deprecated-slds-classes": "error"
22
+ "@salesforce-ux/slds/modal-close-button-issue": "error"
package/build/index.js CHANGED
@@ -3592,6 +3592,171 @@ function requireNoDeprecatedSldsClasses () {
3592
3592
  return noDeprecatedSldsClasses;
3593
3593
  }
3594
3594
 
3595
+ var modalCloseButtonIssue;
3596
+ var hasRequiredModalCloseButtonIssue;
3597
+
3598
+ function requireModalCloseButtonIssue () {
3599
+ if (hasRequiredModalCloseButtonIssue) return modalCloseButtonIssue;
3600
+ hasRequiredModalCloseButtonIssue = 1;
3601
+ const { findAttr, isAttributesEmpty } = requireNode();
3602
+
3603
+ // This rule specific to CVS, find more details here https://issues.salesforce.com/issue/a028c00000zh1iqAAA/modal-close-button-is-not-visible-with-the-new-white-background-after-winter-25-release
3604
+ modalCloseButtonIssue = {
3605
+ meta: {
3606
+ type: "problem",
3607
+ docs: {
3608
+ description:
3609
+ "Ensure SLDS modal compliance by enforcing correct button and icon attributes.",
3610
+ category: "Best Practices",
3611
+ recommended: true,
3612
+ },
3613
+ fixable: "code",
3614
+ schema: [],
3615
+ messages: {
3616
+ removeClass:
3617
+ "Remove the class 'slds-button_icon-inverse' from SLDS Modal blueprints.",
3618
+ changeVariant:
3619
+ "Change 'variant' attribute from 'bare-inverse' to 'bare' in <lightning-button-icon> or <lightning-icon>.",
3620
+ removeVariant:
3621
+ "Remove 'variant' attribute completely in <lightning-icon> inside <button>.",
3622
+ ensureButtonClasses:
3623
+ "Ensure 'slds-button' and 'slds-button_icon' are in the class attribute of <button> or <lightning-button-icon>.",
3624
+ ensureSizeAttribute:
3625
+ "Ensure 'size' attribute is set to 'large' in <lightning-icon> or <lightning-button-icon> for correct icon sizing.",
3626
+ },
3627
+ },
3628
+
3629
+ create(context) {
3630
+ function check(node) {
3631
+ if (isAttributesEmpty(node)) {
3632
+ return;
3633
+ }
3634
+
3635
+ const tagName = node.name;
3636
+
3637
+ // ✅ Scenario 1: Remove 'slds-button_icon-inverse' from <button>
3638
+ if (tagName === "button") {
3639
+ const classAttr = findAttr(node, "class");
3640
+ if (classAttr && classAttr.value) {
3641
+ const classList = classAttr.value.value.split(/\s+/);
3642
+ if (classList.includes("slds-button_icon-inverse")) {
3643
+ context.report({
3644
+ node,
3645
+ messageId: "removeClass",
3646
+ fix(fixer) {
3647
+ const newClassList = classList
3648
+ .filter((cls) => cls !== "slds-button_icon-inverse")
3649
+ .join(" ");
3650
+ return fixer.replaceText(
3651
+ classAttr, // Replace the full attribute
3652
+ `class="${newClassList}"` // Updated class list
3653
+ );
3654
+ },
3655
+ });
3656
+ }
3657
+ }
3658
+ }
3659
+
3660
+ // ✅ Scenario 2: Fix <lightning-button-icon>
3661
+ if (tagName === "lightning-button-icon" || tagName === "lightning:buttonIcon") {
3662
+ const variantAttr = findAttr(node, "variant");
3663
+ const sizeAttr = findAttr(node, "size");
3664
+ const classAttr = findAttr(node, "class");
3665
+
3666
+ // Fix variant="bare-inverse" to "bare"
3667
+ if (variantAttr && variantAttr.value && variantAttr.value.value === "bare-inverse") {
3668
+ context.report({
3669
+ node: variantAttr,
3670
+ messageId: "changeVariant",
3671
+ fix(fixer) {
3672
+ return fixer.replaceText(variantAttr.value, `bare`);
3673
+ },
3674
+ });
3675
+ }
3676
+
3677
+ // Ensure size="large" exists
3678
+ if (!sizeAttr) {
3679
+ context.report({
3680
+ node,
3681
+ messageId: "ensureSizeAttribute",
3682
+ fix(fixer) {
3683
+ //return fixer.insertTextAfter(node, ' size="large"');
3684
+ return fixer.insertTextAfterRange([variantAttr.range[1], variantAttr.range[1]], ' size="large"')
3685
+ },
3686
+ });
3687
+ }
3688
+
3689
+ // Ensure 'slds-button' and 'slds-button_icon' are in the class attribute
3690
+ if (classAttr && classAttr.value) {
3691
+ const classList = classAttr.value.value.split(/\s+/);
3692
+ if (!classList.includes("slds-button") || !classList.includes("slds-button_icon")) {
3693
+ context.report({
3694
+ node: classAttr,
3695
+ messageId: "ensureButtonClasses",
3696
+ fix(fixer) {
3697
+ const newClassList = [
3698
+ "slds-button",
3699
+ "slds-button_icon",
3700
+ ...classList.filter(
3701
+ (cls) => cls !== "slds-button_icon-inverse"
3702
+ ),
3703
+ ].join(" ");
3704
+ return fixer.replaceText(classAttr.value, `"${newClassList}"`);
3705
+ },
3706
+ });
3707
+ }
3708
+ }
3709
+ }
3710
+
3711
+ // ✅ Scenario 3: Fix <lightning-icon> inside <button>
3712
+ if ((tagName === "lightning-icon" || tagName === "lightning:icon") && node.parent?.name === "button") {
3713
+ const variantAttr = findAttr(node, "variant");
3714
+ const sizeAttr = findAttr(node, "size");
3715
+
3716
+ // Fix variant="bare-inverse" to "bare"
3717
+ if (variantAttr && variantAttr.value && variantAttr.value.value === "bare-inverse") {
3718
+ context.report({
3719
+ node: variantAttr,
3720
+ messageId: "changeVariant",
3721
+ fix(fixer) {
3722
+ return fixer.replaceText(variantAttr.value, `"bare"`);
3723
+ },
3724
+ });
3725
+ }
3726
+
3727
+ // Remove variant attribute completely
3728
+ if (variantAttr) {
3729
+ context.report({
3730
+ node: variantAttr,
3731
+ messageId: "removeVariant",
3732
+ fix(fixer) {
3733
+ return fixer.remove(variantAttr);
3734
+ },
3735
+ });
3736
+ }
3737
+
3738
+ //Ensure size="large" is set
3739
+ if (!sizeAttr) {
3740
+ context.report({
3741
+ node,
3742
+ messageId: "ensureSizeAttribute",
3743
+ fix(fixer) {
3744
+ //return fixer.insertTextAfter(node, ' size="large"');
3745
+ return fixer.insertTextAfterRange([variantAttr.range[1], variantAttr.range[1]], ' size="large"')
3746
+ },
3747
+ });
3748
+ }
3749
+ }
3750
+ }
3751
+
3752
+ return {
3753
+ Tag: check,
3754
+ };
3755
+ },
3756
+ };
3757
+ return modalCloseButtonIssue;
3758
+ }
3759
+
3595
3760
  var src;
3596
3761
  var hasRequiredSrc;
3597
3762
 
@@ -3601,7 +3766,8 @@ function requireSrc () {
3601
3766
  src = {
3602
3767
  rules: {
3603
3768
  "no-bem-class": requireNoBemClass(),
3604
- "no-deprecated-slds-classes": requireNoDeprecatedSldsClasses()
3769
+ "no-deprecated-slds-classes": requireNoDeprecatedSldsClasses(),
3770
+ "modal-close-button-issue": requireModalCloseButtonIssue()
3605
3771
  },
3606
3772
  configs: {
3607
3773
  recommended: {
@@ -3609,7 +3775,8 @@ function requireSrc () {
3609
3775
  plugins: ["slds"],
3610
3776
  rules: {
3611
3777
  "slds/no-bem-class": "error",
3612
- "slds/no-deprecated-slds-classes": "error"
3778
+ "slds/no-deprecated-slds-classes": "error",
3779
+ "slds/modal-close-button-issue": "error"
3613
3780
  },
3614
3781
  },
3615
3782
  },