Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion: Convert PostCSS to use @rules instead of custom selectors #48

Open
zspecza opened this issue May 29, 2015 · 2 comments
Open

Comments

@zspecza
Copy link
Contributor

zspecza commented May 29, 2015

This will have some benefits. The most notable benefit is that Stylus leaves custom @rules as-is when it compiles down to CSS (so, @component { } in file.styl will be @component { } in file.css. That means that the Stylus CSStyle plugin can simply hook into Stylus, listen for it's end event, grab the processed css, pass it to PostCSS which will run it through CSStyle and finally pass it back to Stylus, and hey presto, a working Stylus plugin! :)

module.exports = function(opts) {
  opts = opts || {};
  var settings = _.defaults({
    // csstyle prefix settings
  }, opts);

  return function(style){
    style = this || style;
    var filename = style.options.filename;

    style.on('end', function(err, css){
      // ... handle error

      // configure the options to be passed to csstyle
      process_opts = {
        from: filename,
        to: path.join(
          path.dirname(filename),
          path.basename(filename, path.extname(filename))
        ) + '.css'
      }

      // if there is a stylus sourcemap, ensure postcss also generates one
      if (style.sourcemap) {
        process_opts.map = { annotation: false }
      }

      // run csstyle
      var res = postcss(opts).use(nested).use(csstyle(settings).process(css, process_opts);

      // if sourcemaps are generated, combine the two
      if (res.map && style.sourcemap) {
        var combined_map = map.transfer({
          fromSourceMap: res.map.toString(),
          toSourceMap: style.sourcemap
        });

        // then set the combined result as the new sourcemap
        style.sourcemap = JSON.parse(combined_map);
      }

      // return the css output
      return res.css;
    });

  }

}

The second benefit is that postcss-nested supports custom @rules bubbling:

By default, plugin will unwrap only @media, @support and @document
at-rules. You can add your custom at-rules to this list by bubble option:

postcss([ require('postcss-nested')({ bubble: ['phone'] }) ]

Which will help clean up a lot of the PostCSS code in CSStyle.

If only Sass and Less also allowed custom @rules and left them as-is - then no one would have to write 3 different versions of their plugin ^_^

Also, I did read something (trying to find it, will update this when I do) about PostCSS plugins eventually being able to detect the use of plugins previously in the chain, so you could refactor CSStyle to be a plugin pack consisting of:

  • postcss-simple-nested - the function of this is obvious.
  • postcss-csstyle-transformer - this handles transforming at-rules to selectors.

Then, if nested is not found, you could simply flag csstyle to use it - if it is found, csstyle will just use the already-existing version in the pipeline - this makes installation/setup a tad easier, and has a little bit of performance benefit.

What do you think @geddski?

@zspecza
Copy link
Contributor Author

zspecza commented May 29, 2015

Side note:

If it's possible to pipe output from Sass / Less to PostCSS and then back again the same way Stylus can, then it might be possible to re-use the PostCSS CSStyle internals for each and every CSS preprocessor, as long as the PostCSS version handles both the selector syntax (component(name)) and the AtRule syntax (@component(name)).

Here's what's possible to output using Stylus, Sass and Less (the css output is commented out):

Stylus:

@component(name)
  color: blue
/*
  @component (name) {
    color: blue;
  }
*/

Sass:

$com: 'component()';

#{$com} {
  color: blue;
}

/*
  component() {
    color: blue;
  }
*/

Less:

@com: component();

@{com} {
  color: blue;
}

/*
component() {
  color: blue;
}
*/

So, as long as we have a way to build the necessary syntax in each processor, CSStyle can just keep all the transformation logic in one place - making it easier to update and maintain. 💥

@geddski
Copy link
Owner

geddski commented Jul 29, 2016

I'd like to explore this option, thanks for the suggestion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants