postcss / postcss-load-config

Autoload Config for PostCSS
MIT License
642 stars 72 forks source link

Example of how to return styles as variable/value rather than write to file? #194

Closed gavinmcfarland closed 4 years ago

gavinmcfarland commented 4 years ago

Hi, I'm trying to use postcss-load-config to process PostCSS styles programmatically rather than write to a file. I'm not sure how to resolve the promise though so I can access the value.

Given the following, how can I return result.css as a variable?

var css = `{
    user-select: none;
}`

const ctx = { parser: true, map: 'inline' }

var styles = postcssrc(ctx).then(({ plugins, options }) => {
  postcss(plugins)
    .process(css, options)
    .then((result) => console.log(result.css))
})

console.log(styles)

PostCSS has an option to return the css directly without a promise using postcss(plugins).process(css).css. But I'm not sure how I can return this css from inside postcssrc().

michael-ciniawsky commented 4 years ago

You may be looking for the Sync API

postcss(plugins).process(src, options).result

works synchronous, so

const { plugins, options } = postcssrc.sync(ctx)
const { css } = postcss(plugins).process(src, options)

should work, but


⚠️ Some PostCSS Plugins require to use PostCSS asynchronously, so it's recommended to use the Async API whenever possible

async function styles (src = '', ctx = {}) {
  const { plugins, options } = await postcssrc(ctx)
  const { css } = await postcss(plugins).process(src, options)

  return css
}

styles("/* CSS */", { /* Context */ })
gavinmcfarland commented 4 years ago

Thanks @michael-ciniawsky I should have seen that in the documentation. I was so set on having to use async.

There's a small typo in your async example (missing src from postcss.process, although even with the typo corrected the await postcssrc(ctx) isn't returning anything for me and I'm not sure why. The sync process will do me for now.

gavinmcfarland commented 4 years ago

Running some tests I can see that it sometimes the async method returns styles, and sometimes doesn't. Perhaps something is not running in the correct order?

For example:

var test = `.class {
    user-select: none;
}`

async function styles(src = '', ctx = {}) {
    const { plugins, options } = await postcssrc(ctx)
    const { css } = await postcss(plugins).process(src, options)

    console.log(css)
}

styles(test)

The above doesn't always return styles.

michael-ciniawsky commented 4 years ago

There's a small typo in your async example (missing src from postcss.process, although even with the typo corrected the await postcssrc(ctx) isn't returning anything for me and I'm not sure why.

Thanks, corrected

The above doesn't always return styles.

By that you, I assume, you mean that console.log(css) doesn't print anything to the console, since currently you aren't returning anything from your styles function anymore? Note that in my example above styles also returns a {Promise}

styles(srx, ctx)
  .then((css) => /* Do something with css */)
  .catch(console.error)

// or something in like
async function main () {
   const result = await styles(src, ctx)

   // Rest of the programm...
}

main().catch(console.error)
gavinmcfarland commented 4 years ago

Yes sorry, I meant console.log() doesn't return anything for me (except on rare occasions). I decided not to return anything from the function because you still have to use a .then() method to access the value.