DEV Community

Cover image for postcss-custom-property-prefixer
ice breaker
ice breaker

Posted on

postcss-custom-property-prefixer

Add prefix to your css custom-property

Usage

<npm/yarn/pnpm> i -D postcss-custom-property-prefixer
Enter fullscreen mode Exit fullscreen mode

Then register this plugin into your postcss.config.js:

module.exports = {
  plugins: {
    // ...
    'postcss-custom-property-prefixer': {
      // prefix option must be passed! 
      prefix: 'ice-'
    }
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

Demo

.a {
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1));
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

Will be transformed to:

.a {
  --ice-tab-color: hsl(var(--ice-bc) / var(--ice-tw-text-opacity, 1));
  --ice-tab-bg: hsl(var(--ice-b1) / var(--ice-tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--ice-b3) / var(--ice-tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

Not right? Yes! Default this plugin will transform all css custom property!

If you want to ignore some custom properties like --tw-*, you should pass some ignore* options, See Below!

Use with Tailwindcss

Css nodes are generated by tailwindcss, because it's custom property all start with '--tw-', so you can pass options like below.

    'postcss-custom-property-prefixer': {
      // your custom prefix
      prefix: 'ice-',
      ignoreValueCustomProperty(cp, decl) {
        // ignore value
        return cp.startsWith('--tw-')
      },
      ignoreProp(decl) {
        // ignore prop
        return decl.prop.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Options

ignoreValueCustomProperty

plugin options:

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  /*                              ⬇ --tw-* */
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1));
  /*                            ⬇ --tw-* */
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));
  /*                                      ⬇ --tw-* */
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --ice-tab-color: hsl(var(--ice-bc) / var(--tw-text-opacity, 1));
  --ice-tab-bg: hsl(var(--ice-b1) / var(--tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--ice-b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

See! All css decl's value's custom properties which start with --tw- are ignored!

ignoreDecl

This option will ignore the whole decl!

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      ignoreDecl(decl) {
        return decl.prop === '--tab-color' || decl.value.includes('hsl(var(--b1)')
      },
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  /* prop === --tab-color , this decl will be ignored */
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1)); 
  /* value.includes('hsl(var(--b1)') , this will be ignored */
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1)); 
  /* will be transformed */
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1)); 
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1));
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--ice-b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

ignoreProp

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      ignoreProp(decl) {
        return decl.prop === '--tab-color'
      },
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  /* ⬇ only ignore the prop , not value ⬇ */
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1)); 
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1)); 
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1)); 
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  /* ⬇ target prop */
  --tab-color: hsl(var(--ice-bc) / var(--tw-text-opacity, 1));
  --ice-tab-bg: hsl(var(--ice-b1) / var(--tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--ice-b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

ignoreValue

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      ignoreValue(decl) {
        return decl.value.includes('hsl(var(--b3)')
      },
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1)); 
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));  
  /*                       ⬇ target value , ignored*/
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --ice-tab-color: hsl(var(--ice-bc) / var(--tw-text-opacity, 1));
  --ice-tab-bg: hsl(var(--ice-b1) / var(--tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

prefix

Type: String|PrefixFunction, The prefix will be add to all custom property!

export type PrefixFunction = (decl: Declaration, target: 'prop' | 'value') => string
Enter fullscreen mode Exit fullscreen mode
    'postcss-custom-property-prefixer': {
      prefix: (decl,target)=>{
        if (target === 'prop' && decl.prop.startsWith('--bg-')) {
          return 'aaa-'
        }
        if (target === 'value' && decl.prop.startsWith('--text-')) {
          return 'bbb-'
        }
        return ''
      },
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  --bg-red: hsl(var(--text-red-100));
  --text-red: hsl(var(--text-red-500));
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --aaa-bg-red: hsl(var(--text-red-100));
  --text-red: hsl(var(--bbb-text-red-500));
}
Enter fullscreen mode Exit fullscreen mode

propPrefix

Type: Same as prefix

you can pass different prefix to prop and value:

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      propPrefix: 'xx-',
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode
.a {
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1)); 
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));  
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1)); 
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --xx-tab-color: hsl(var(--ice-bc) / var(--tw-text-opacity, 1));
  --xx-tab-bg: hsl(var(--ice-b1) / var(--tw-bg-opacity, 1));
  --xx-tab-border-color: hsl(var(--ice-b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

transformProp

Boolean: whether transform css decl's prop, default: true

transformValue

Boolean: whether transform css decl's value, default: true

License

MIT License © 2023-PRESENT sonofmagic

Top comments (0)