-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from privatenumber/develop
- Loading branch information
Showing
14 changed files
with
635 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,93 @@ | ||
# Pkg Name <a href="https://npm.im/pkg-name"><img src="https://badgen.net/npm/v/pkg-name"></a> <a href="https://npm.im/pkg-name"><img src="https://badgen.net/npm/dm/pkg-name"></a> <a href="https://packagephobia.now.sh/result?p=pkg-name"><img src="https://packagephobia.now.sh/badge?p=pkg-name"></a> <a href="https://bundlephobia.com/result?p=pkg-name"><img src="https://badgen.net/bundlephobia/minzip/pkg-name"></a> | ||
# postcss-custom-properties-transformer [![Latest version](https://badgen.net/npm/v/postcss-custom-properties-transformer)](https://npm.im/postcss-custom-properties-transformer) [![Monthly downloads](https://badgen.net/npm/dm/postcss-custom-properties-transformer)](https://npm.im/postcss-custom-properties-transformer) [![Install size](https://packagephobia.now.sh/badge?p=postcss-custom-properties-transformer)](https://packagephobia.now.sh/result?p=postcss-custom-properties-transformer) | ||
|
||
Description | ||
PostCSS plugin to transform [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) | ||
|
||
## :raising_hand: Why? | ||
## 🙋♂️ Why? | ||
|
||
Transform CSS custom properties to... | ||
|
||
## :rocket: Install | ||
- **🔥 Scope to package** Namespace them to your library to prevent collision with other custom properties | ||
- **👌 Scope to file** Scope to a file to prevent collision with other files | ||
- **🐥 Minify** Shorten long custom properties via hashing | ||
- **🤬 Obfuscate** Mangle custom-property names to deter reverse-engineering | ||
|
||
## 🚀 Install | ||
```sh | ||
npm i pkg-name | ||
npm i -D postcss postcss-custom-properties-transformer | ||
``` | ||
|
||
## 🚦 Quick Setup | ||
|
||
Add `postcss-custom-properties-transformer` to your PostCSS configuration (eg. `postcss.config.js`) and pass in a `transformer` function. | ||
|
||
> Warning: this plugin doesn't validate custom properties. [Make sure to not use invalid characters (eg. period)](https://stackoverflow.com/a/42311038) | ||
```diff | ||
module.exports = { | ||
plugins: [ | ||
|
||
+ // Insert above plugins that read custom properties | ||
+ require('postcss-custom-properties-transformer')({ | ||
+ transformer({ property }) { | ||
+ // Prefixing all custom properties with 'APP-' | ||
+ return 'APP-' + property; | ||
+ } | ||
+ }), | ||
|
||
require('postcss-preset-env')() | ||
] | ||
}; | ||
``` | ||
|
||
## 👨🏻🏫 Examples | ||
|
||
### Namespace with package meta | ||
If you have a CSS library, you can scope your custom properties to every release so that multiple versions of the library used in the same app doesn't yield any collisions. | ||
|
||
```js | ||
const pkg = require('./package.json') | ||
require('postcss-custom-properties-transformer')({ | ||
transformer({ property }) { | ||
return `${pkg.name}-${pkg.version}-${property}`; | ||
} | ||
}) | ||
``` | ||
|
||
### Hash custom properties | ||
If you want to hash your custom properties to shorten/obfuscate them, pass in a hashing algorithm of your choice. | ||
|
||
This demo uses a 6-character truncated MD5 hash; MD5 and the SHA-family has [statistically good uniform distribution](https://stackoverflow.com/questions/8184941/uniform-distribution-of-truncated-md5) and can be truncated. | ||
|
||
However, note that the shorter the hash, the higher the collision rate. There will be a warning if a collision is detected. | ||
|
||
```js | ||
const crypto = require('crypto'); | ||
const md5 = string => crypto.createHash('md5').update(string).digest('hex'); | ||
|
||
require('postcss-custom-properties-transformer')({ | ||
transformer({ property }) { | ||
return md5(property).slice(0, 6); | ||
} | ||
}) | ||
``` | ||
|
||
### Advanced transformations | ||
If you want to do something more complex—such as discriminate between global and local custom properties (eg. theme variables). | ||
|
||
```js | ||
require('postcss-custom-properties-transformer')({ | ||
transformer({ property }) { | ||
if (property.startsWith('theme-')) { | ||
return property; | ||
} | ||
return hash(property); | ||
} | ||
}) | ||
``` | ||
|
||
## ⚙️ Options | ||
- `transformer(data)` `<Function>` | ||
- `data` `<Object>` | ||
- `property` `<String>` - The custom property name that's being transformed. The `--` prefix is omitted | ||
- `filepath` `<String>` - The path to the file where the custom property is being transformed | ||
- `css` `<String>` - The entire CSS code of the file |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
const postcss = require('postcss'); | ||
const assert = require('assert'); | ||
const processPropertyValue = require('./process-property-value'); | ||
|
||
const {stringify: string} = JSON; | ||
|
||
// From postcss-custom-properties | ||
// https://github.com/postcss/postcss-custom-properties/blob/1e1ef6b/src/lib/transform-properties.js#L37 | ||
const customPropertyPtrn = /^--[A-z][\w-]*$/; | ||
const varFnPtrn = /(^|[^\w-])var\([\W\w]+\)/; | ||
const name = 'postcss-custom-properties-transformer'; | ||
|
||
function markHashUsed(map, propertyName, originalPropertyName) { | ||
if (!map.has(propertyName)) { | ||
map.set(propertyName, originalPropertyName); | ||
return; | ||
} | ||
|
||
const previousPropName = map.get(propertyName); | ||
if (originalPropertyName !== previousPropName) { | ||
console.warn(`[${name}] Collision: property name ${string(propertyName)} was generated from input ${string(originalPropertyName)} but was already generated from input ${string(previousPropName)}`); | ||
} | ||
} | ||
|
||
const createTransformer = transformer => { | ||
const usedPropertyNames = new Map(); | ||
|
||
return (customProperty, data) => { | ||
data.property = customProperty.slice(2); | ||
|
||
const newPropertyName = '--' + transformer(data); | ||
|
||
markHashUsed(usedPropertyNames, newPropertyName, customProperty); | ||
|
||
return newPropertyName; | ||
}; | ||
}; | ||
|
||
const customPropertiesTransformer = postcss.plugin(name, options => { | ||
assert(options && options.transformer, `[${name}] a transformer must be passed in`); | ||
assert(typeof options.transformer === 'function', `[${name}] transformer must be a function`); | ||
|
||
const transformer = createTransformer(options.transformer); | ||
|
||
return root => { | ||
const data = Object.create({ | ||
filepath: root.source.input.file, | ||
css: root.source.input.css, | ||
}); | ||
|
||
root.walkDecls(decl => { | ||
// Custom property declaration | ||
if (customPropertyPtrn.test(decl.prop)) { | ||
decl.prop = transformer(decl.prop, data); | ||
} | ||
|
||
// Custom property usage | ||
if (varFnPtrn.test(decl.value)) { | ||
decl.value = processPropertyValue(decl.value, customProperty => transformer(customProperty, data)); | ||
} | ||
}); | ||
}; | ||
}); | ||
|
||
module.exports = customPropertiesTransformer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const {parse} = require('postcss-values-parser'); | ||
|
||
function transformAstVars(root, transformer) { | ||
if (!root.nodes) { | ||
return; | ||
} | ||
|
||
root.nodes.forEach(node => { | ||
if (node.isVar) { | ||
node.nodes.forEach(node2 => { | ||
if (node2.isVariable) { | ||
node2.value = transformer(node2.value); | ||
} | ||
}); | ||
} else { | ||
transformAstVars(node, transformer); | ||
} | ||
}); | ||
} | ||
|
||
function processPropertyValue(value, cb) { | ||
const parsed = parse(value); | ||
|
||
transformAstVars(parsed, cb); | ||
|
||
return parsed.toString(); | ||
} | ||
|
||
module.exports = processPropertyValue; |
Oops, something went wrong.