less / less.js

Less. The dynamic stylesheet language.
http://lesscss.org
Apache License 2.0
17k stars 3.41k forks source link

Strip empty rulesets that contain only CSS comments #4276

Open jandre3000 opened 4 weeks ago

jandre3000 commented 4 weeks ago

To reproduce:

Currently, when a ruleset contains nothing but a Less comment, that ruleset is considered empty and is stripped from the compile CSS output. The same is not true for CSS comments. Consider the following example:

Current behavior:

Screenshot 2024-08-14 at 12 41 10 PM

Expected behavior: From a developer's perspective, I'd expect that the two rulesets would be treated equally, regardless of the comment format, and that neither would produce any CSS output.

When combined with nesting, this behaviour can lead to unnecessarily duplicated code, as was the case in the following issue: https://phabricator.wikimedia.org/T372101

e.g. Screenshot 2024-08-14 at 12 48 36 PM

Environment information:

p.s. I think this is related to #2477 but I wasn't sure to what extent.

dosubot[bot] commented 4 weeks ago

Hey @jandre3000! I'm here to help you out with any bugs, questions, or contributions you have in mind. Let's squash those bugs together! 😊

To address the issue of stripping empty rulesets that contain only CSS comments, you can modify the wikimedia-stylelint-config to disallow CSS comments within Less selectors. This will prevent rulesets containing only CSS comments from being included in the compiled CSS output.

Here is how you can extend your Stylelint configuration to achieve this:

{
  "extends": "wikimedia-stylelint-config",
  "rules": {
    "selector-no-comment": true
  },
  "plugins": [
    "./path/to/selector-no-comment-plugin"
  ]
}

You will need to create a custom Stylelint plugin (selector-no-comment-plugin) to enforce this rule. Below is an example implementation of such a plugin:

// selector-no-comment-plugin.js
const stylelint = require('stylelint');

const ruleName = 'selector-no-comment';
const messages = stylelint.utils.ruleMessages(ruleName, {
  rejected: 'Comments are not allowed within selectors'
});

module.exports = stylelint.createPlugin(ruleName, function(primaryOption) {
  return function(root, result) {
    root.walkRules(rule => {
      if (rule.selector && rule.selector.includes('/*')) {
        stylelint.utils.report({
          message: messages.rejected,
          node: rule,
          result,
          ruleName
        });
      }
    });
  };
});

module.exports.ruleName = ruleName;
module.exports.messages = messages;

This plugin checks each rule's selector for comments and reports an error if any are found. Make sure to adjust the path to the plugin in your Stylelint configuration file [1].

Additionally, the Less compiler currently preserves CSS-style comments within rulesets during the compilation process. This is handled by the Comment class, which ensures that comments are included in the final output unless the context is set to compress the output, in which case comments are omitted unless they start with /*! [2][3][1].

To continue talking to Dosu, mention @dosu.