Package Exports
- red-perfume
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (red-perfume) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Red Perfume
Feedback
Leave feedback as an issue or a response on Twitter.
Star and Watch this repo for updates.
Or follow me on Twitter if that's easier.
Experimental CSS Atomizer (WIP)
This is a library for a build tool that helps to drastically reduce the total amount of CSS that is shipped for your project. Facebook adopted this atomized CSS approach and it reduced their homepage CSS by 80%. Twitter also atomizes their CSS.
With red-perfume
you write your CSS however you like (semantic class names, BEM, utility classes, whatever). Then reference them in your HTML normally.
Example:
.cow,
.cat {
font-size: 12px;
padding: 8px;
}
.dog {
font-size: 12px;
background: #F00;
padding: 8px;
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<p class="cool cow moo">
Hi there!
</p>
<!--
<span class="dog">comments are skipped</span>
-->
<h1 class="cool cat nice wow">
Meow
</h1>
<h2 class="dog">
Woof
</h2>
</body>
</html>
Then red-perfume
atomizes the styling into atomic classes, and replaces the references to them:
.rp__font-size__--COLON12px {
font-size: 12px;
}
.rp__padding__--COLON8px {
padding: 8px;
}
.rp__background__--COLON__--OCTOTHORPF00 {
background: #F00;
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<p class="cool moo rp__font-size__--COLON12px rp__padding__--COLON8px">
Hi there!
</p>
<!--
<span class="dog">comments are skipped</span>
-->
<h1 class="cool nice wow rp__font-size__--COLON12px rp__padding__--COLON8px">
Meow
</h1>
<h2 class="rp__font-size__--COLON12px rp__background__--COLON__--OCTOTHORPF00 rp__padding__--COLON8px">
Woof
</h2>
</body>
</html>
This output isn't as pretty to read, but it's a build step, not your source code, so it doesn't really matter. Note: Uglification of classnames is on the TODO list.
This above example already works as a proof of concept with the current code. However, the library needs a lot more work to be usable in most projects. Look at the issues page to see what work is left to be done and how you can help!
API (subject to change before v1.0.0)
API Example
const redPerfume = require('red-perfume');
redPerfume.atomize({
verbose: true,
customLogger: function (message, err) {
console.log(message, err);
},
tasks: [
{
uglify: false,
styles: {
in: [
'./styles/file.css',
'./styles/style.css'
],
// The two above files will be atomized and combined into this output
out: './dist/styles/styles.css'
},
// The output markup will be a copy of the input but modified to have the class names replaced to match the new atomized styles from styles.out
markup: [
{
in: './index.html',
out: './dist/index.html'
},
{
in: './contact.html',
out: './dist/contact.html'
}
],
scripts: {
out: './dist/atomic-styles.json'
}
},
{
uglify: true,
styles: {
data: '.example { padding: 10px; margin: 10px; }',
result: function (result, err) {
// .rp__a { padding: 10px } .rp__b { margin: 10px }
console.log(result);
}
},
markup: [
{
data: '<!DOCTYPE html><html><body><div class="example"></div></body></html>',
result: function (result, err) {
// '<!DOCTYPE html><html><body><div class="rp__a rp__b"></div></body></html>'
console.log(result);
}
}
],
scripts: {
result: function (result, err) {
// { '.example': [ '.rp__a', '.rp__b' ] }
console.log(result);
}
}
}
]
});
API Implementation Status: ALPHA
The documented API is fully implemented and tested. Though there are many edge cases that have not been covered yet (see: issues), and some more advanced parts of the features yet to be implemented (also: issues).
API Documentation
Key | Type | Allowed | Default | Description |
---|---|---|---|---|
verbose |
Boolean | true , false |
true |
If true, consoles out helpful warnings and errors using customLogger or console.error . |
customLogger |
Function | Any function | console.error |
You can pass in your own custom function to log errors/warnings to. When called the function will receive a message string for the first argument and sometimes an error object for the second argument. This can be useful in scenarios like adding in custom wrappers or colors in a command line/terminal. This function may be called multiple times before all tasks complete. Only called if verbose is true. |
tasks |
Array | Array of objects | undefined |
An array of task objects. Each represents the settings for an atomization task to be performed. |
Tasks API:
Key | Type | Default | Description |
---|---|---|---|
uglify |
Boolean | false |
If false the atomized classes, and all references to them, are long (.rp__padding__--COLOR12px ). If true they are short (.rp__b5p ). |
styles |
Object | undefined |
CSS settings. API below |
markup |
Array | undefined |
HTML settings. An array of objects with their API defined below |
scripts |
Object | undefined |
JS settings. API below |
Styles Task API:
Key | Type | Default | Description |
---|---|---|---|
in |
Array | undefined |
An array of strings to valid paths for CSS files. All files will remain untouched. A new atomized string is produced for out /result . |
out |
String | undefined |
A string file path output. If file exists it will be overwritten with the atomized styles from in and/or data |
data |
String | undefined |
A string of CSS to be atomized. Atomized styles are passed to out and result . |
result |
Function | undefined |
A function, if supplied, will be called with the combined atomized results from data and the files form in as the first argument, and an error for the second argument. You can create a promise in this function to be returned if you like. |
Markup Task API:
Key | Type | Default | Description |
---|---|---|---|
in |
String | undefined |
Path to an HTML file. |
out |
String | undefined |
Path where the modified version of the in file will be stored. If file already exists, it will be overwritten. |
data |
String | undefined |
A string of markup to be processed. This is ignored there is a valid HTML file passed to in |
result |
Function | undefined |
A function, if supplied, will be called with the processed string version of the markup from in or data as the first argument, and an error for the second argument. You can create a promise in this function to be returned if you like. |
Scripts Task API:
Key | Type | Default | Description |
---|---|---|---|
out |
String | undefined |
Path where a JSON object will be stored. The object contains keys (selectors) and values (array of strings of atomized class names). If file already exists, it will be overwritten. |
result |
Function | undefined |
A function, if supplied, will be called with the JSON object as first argument, and an error for the second argument. You can create a promise in this function to be returned if you like. |
Running locally to see the proof of concept or contribute
- Install Node.js & npm
- Download or fork or clone the repo
npm install
node manual-testing.js
Why is it called "Red Perfume"
This library takes in any CSS and breaks it down to pure Atomic CSS. This is a process called "CSS Atomization", and libraries that do this process are called "CSS Atomizers".
Outside of our industry jargon, "Atomizer" already exists as a word.
Atomizer (NOUN)
- A device for emitting water, perfume, or other liquids as a fine spray.
Though actual atomizers themselves have no consistent size, design, color, or shape. So there is no iconic image that represents them.
And though perfume bottles can also come in many shapes, colors, sizes and designs, they are still recognizable as perfume bottles.