postcss / postcss-mixins

PostCSS plugin for mixins
MIT License
466 stars 47 forks source link

add mixinsText option #96

Closed hipstersmoothie closed 5 years ago

hipstersmoothie commented 5 years ago

I need the ability to run this plugin synchronously. This PR add an option to pass all your mixins as the actually CSS text. This enable you to load whatever you want synchronously so postcss can stay sync

closes #95

ai commented 5 years ago

What is your use case? Maybe we can find better API for it.

hipstersmoothie commented 5 years ago

@ai

  1. as a vscode language service plugin (they can't be async to my knowledge) https://github.com/mrmckeb/typescript-plugin-css-modules
  2. as a typescript compiler plugin (writing this internally at my company) where again all my postcss plugins must load synchronously
hipstersmoothie commented 5 years ago

I tried just adding a sync option but it required a lot of code changes that I feel wouldn't be accepted from an outside contributor. All the file loading is so Promise based I would've had to move a lot of code. This seemed like the easiest alternative

ai commented 5 years ago

Why mixins option is not a solution here? You can pass a custom sync function.

hipstersmoothie commented 5 years ago

I already have all my mixins in css files and I was under the impression that the mixins option you had to use the postcss API to creating the mixins manually.

Is there a way to just pass a string to mixins?

ai commented 5 years ago

You can create function, which will take string, parse it and create mixins object with functions.

I think it will be the best option, since it doesn't add new options, which we will need to support in the future.

hipstersmoothie commented 5 years ago

which will take string, parse it and create mixins object with functions

I am not sure how to convert the string to the mixins object....

const mixinsPlugin = require('postcss-mixins');
const fs = require('fs');
const postcss = require('postcss');

const mixins = [
  fs.readFileSync(require.resolve('@cgds/styles/elevation.css'), 'utf8'),
  fs.readFileSync(require.resolve('@cgds/styles/typography.css'), 'utf8')
];

function defineMixin(mixins, rule) {
  const name = rule.params.split(/\s/, 1)[0];
  const other = rule.params.slice(name.length).trim();
  let args = [];

  if (other.length) {
    args = postcss.list.comma(other).map(function(str) {
      const arg = str.split(':', 1)[0];
      const defaults = str.slice(arg.length + 1);
      return [arg.slice(1).trim(), defaults.trim()];
    });
  }

  mixins[name] = { mixin: rule, args, content: false };
  rule.remove();
}

function makeMixinDefinition(file) {
  const mixins = {};

  postcss.parse(file).walkAtRules('define-mixin', atrule => {
    defineMixin(mixins, atrule);
  });

  return mixins;
}

module.exports = () => {
  return {
    plugins: [
      mixinsPlugin({
        mixins: mixins
          .map(makeMixinDefinition)
          .reduce((all, item) => ({ ...all, ...item }), {})
      })
    ]
  };
};

This doesn't seem to work.