Comparing version 0.1.6 to 0.2.0
@@ -5,3 +5,3 @@ { | ||
"description": "stylis is a small css compiler", | ||
"version": "0.1.6", | ||
"version": "0.2.0", | ||
"homepage": "https://github.com/thysultan/stylis.js", | ||
@@ -8,0 +8,0 @@ "license": "MIT", |
134
README.md
@@ -107,9 +107,24 @@ # Stylis | ||
```javascript | ||
// browser | ||
// browser, if the element passed is a style element the css will | ||
// be append to it, if it is another element a style element with the | ||
// css will be appended to it, thus this adds css to the already | ||
// present style element | ||
stylis('#user', styles, document.querySelector('style')); | ||
// and this appends a style element to the head | ||
stylis('#user', styles, document.head); | ||
// or explicity request a string, | ||
// in node this returns the css wrapped in <style></style> tags | ||
// in node this returns the css wrapped in <style id=stylis-${namespace}></style> tags | ||
// and in the browser this returns a style element with the css | ||
stylis('#user', styles, true); | ||
// you can also pass a function | ||
stylis('#user', styles (type, props, children) => {}); | ||
// where the arguments passed are | ||
{ | ||
type: {string} 'style'; | ||
props: {Object} {id: 'stylis-${namespace}'}; | ||
output: {string} '...compiled css'; | ||
} | ||
``` | ||
@@ -128,3 +143,3 @@ | ||
# Installation | ||
## Installation | ||
@@ -141,3 +156,3 @@ #### direct download | ||
```html | ||
<script src=https://unpkg.com/stylis@0.1.6/stylis.min.js></script> | ||
<script src=https://unpkg.com/stylis@0.2.0/stylis.min.js></script> | ||
``` | ||
@@ -149,2 +164,111 @@ | ||
npm install stylis --save | ||
``` | ||
``` | ||
## API | ||
```javascript | ||
stylis(namespace: {string}, styles: {string}, element: {(function|boolean|Node)}); | ||
// if element is a function the arguments passed are ('style', stylis-${namespace}, output) | ||
// you can also access the low level compiler | ||
stylis.compiler === (ns, id, chars, isattr) => output; | ||
// that can be used as follows | ||
stylis.compiler('.', 'class1', 'css string...', false); | ||
// or using the isattr set to true | ||
stylis.compiler('data-scope', 'user', 'css string...', true); | ||
// that will compile the namespace to '[data-scope=user]'; | ||
``` | ||
## Intergration | ||
Stylis can be used to build an abstraction ontop of it, for example imagine we want to build an abstract that makes the following React Component possible | ||
```javascript | ||
class Heading extends React.Component { | ||
stylesheet(){ | ||
return ` | ||
&{ | ||
color: blue | ||
} | ||
`; | ||
} | ||
render() { | ||
return ( | ||
React.createElement('h1', 'Hello World') | ||
); | ||
} | ||
} | ||
``` | ||
We could simply extend the Component class as follows | ||
```javascript | ||
React.Component.prototype.stylis = function () { | ||
var ctx = this; | ||
var namespace = this.displayName; | ||
return function () { | ||
this.setAttribute(namespace); | ||
stylis(namespace, ctx.stylesheet(), document.head); | ||
} | ||
} | ||
``` | ||
Then use it in the following way | ||
```javascript | ||
class Heading extends React.Component { | ||
stylesheet(){ | ||
return ` | ||
&{ | ||
color: blue | ||
} | ||
`; | ||
} | ||
render() { | ||
return ( | ||
React.createElement('h1', {ref: this.stylis}, 'Hello World') | ||
); | ||
} | ||
} | ||
``` | ||
When the first instance of the component is mounted the function assigned to the ref will get executed adding a style element with the compiled output of `stylesheet()` | ||
where as only the namespace attribute is added to any subsequent instances. | ||
You can of course do this another way | ||
```javascript | ||
class Heading extends React.Component { | ||
constructor (props) { | ||
super(props); | ||
// or you can even inline this | ||
this.style = stylis(this.displayName, this.stylesheet(), React.createElement); | ||
// this.style will be the return value of | ||
// React.createElement('style', {id: 'stylis-Heading'}, this.stylesheet()) | ||
} | ||
stylesheet(){ | ||
return ` | ||
&{ | ||
color: blue | ||
} | ||
`; | ||
} | ||
render() { | ||
return ( | ||
React.createElement('h1', null, 'Hello World', this.style) | ||
); | ||
} | ||
} | ||
``` | ||
Both will add the resulting style element generated only once, one will | ||
add it to the head another will render it in place with the component. | ||
If you want a picture into what can be done, there is an abstraction i created | ||
for [dio.js](https://github.com/thysultan/dio.js) that does away with the boilerplate entirely [http://jsbin.com/mozefe/1/edit?js,output](http://jsbin.com/mozefe/1/edit?js,output) |
@@ -25,9 +25,14 @@ /*! | ||
var document = window.document; | ||
var rkeyf = /@(keyframes +.*?}$)/g; | ||
var rtrans = /(transform:.*?;)/g; | ||
var rspaces = / +/g; | ||
var ranim = /(,|:) +/g; | ||
// enviroment variables | ||
var document = window.document || null; | ||
var browser = document !== null; | ||
// regular expressions | ||
var rkeyf = /@(keyframes +.*?}$)/g; | ||
var rtrans = /(transform:.*?;)/g; | ||
var rspaces = / +/g; | ||
var ranim = /(,|:) +/g; | ||
/** | ||
@@ -38,31 +43,56 @@ * stylis, css compiler interface | ||
* | ||
* @param {string} selector | ||
* @param {string} styles | ||
* @param {(boolean|Node)} element | ||
* @param {string} selector | ||
* @param {string} styles | ||
* @param {(boolean|Node|function)} element | ||
* @return {string} | ||
*/ | ||
function stylis (selector, styles, element) { | ||
var output = cssparser(selector[0], selector.substr(1), styles, false); | ||
// request for element | ||
if (element) { | ||
// there are duplicate compiler(...) calls because | ||
// we defer compiling styles until we know more about the requested output | ||
// to prevent appending dublicate content to the dom when requested | ||
var namespace = 'stylis-'; | ||
// browser | ||
if (document) { | ||
if (element.nodeType) { | ||
if (browser) { | ||
var nodeType = element.nodeType; | ||
if (nodeType && element.nodeName === 'STYLE') { | ||
var output = compiler(selector[0], selector.substring(1), styles, false); | ||
// passed an element, append to preserve elements content | ||
return (element.appendChild(document.createTextNode(output)), element); | ||
} else { | ||
// new element | ||
var _element = document.createElement('style'); | ||
_element.textContent = output; | ||
var id = namespace+selector; | ||
return _element; | ||
// avoid adding duplicate style elements | ||
if (document.getElementById(id) != null) { | ||
return null; | ||
} | ||
var output = compiler(selector[0], selector.substring(1), styles, false); | ||
if (nodeType) { | ||
// new element | ||
var _element = document.createElement('style'); | ||
_element.textContent = output; | ||
_element.id = id; | ||
return element.appendChild(_element); | ||
} else { | ||
// function | ||
return element('style', {id: id}, output); | ||
} | ||
} | ||
} else { | ||
var output = compiler(selector[0], selector.substring(1), styles, false); | ||
// node | ||
return '<style>'+output+'</style>'; | ||
return '<style id="'+namespace+selector+'">'+output+'</style>'; | ||
} | ||
} else { | ||
// string | ||
return output; | ||
return compiler(selector[0], selector.substring(1), styles, false); | ||
} | ||
@@ -75,3 +105,3 @@ } | ||
* | ||
* @example cssparser('.', 'class1', 'css...', false); | ||
* @example compiler('.', 'class1', 'css...', false); | ||
* | ||
@@ -84,3 +114,3 @@ * @param {string} ns | ||
*/ | ||
function cssparser (ns, id, chars, isattr) { | ||
function compiler (ns, id, chars, isattr) { | ||
var prefix = isattr ? '['+ns+'='+id+']' : ns + id; | ||
@@ -98,6 +128,10 @@ var output = ''; | ||
line += chars[i]; | ||
line = line.trim(); | ||
var first = line.charCodeAt(0); | ||
// only trim when the first character is ` ` | ||
if (first === 32) { | ||
first = (line = line.trim()).charCodeAt(0); | ||
} | ||
// / character, line comment | ||
@@ -117,3 +151,3 @@ if (first === 47) { | ||
// @keyframes | ||
line = line.substr(1, 10) + id + line.substr(11); | ||
line = line.substring(1, 11) + id + line.substring(11); | ||
} else { | ||
@@ -216,3 +250,3 @@ // @root | ||
// & character | ||
_line += affix + selector.substr(1); | ||
_line += affix + selector.substring(1); | ||
} else { | ||
@@ -243,3 +277,4 @@ _line += affix + selector; | ||
return stylis; | ||
return (stylis.compiler = compiler, stylis); | ||
})); |
@@ -1,1 +0,1 @@ | ||
!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(global):"function"==typeof define&&define.amd?define(e(window)):window.stylis=e(window)}(function(e){"use strict";function t(e,t,n){var o=r(e[0],e.substr(1),t,!1);if(n){if(i){if(n.nodeType)return n.appendChild(i.createTextNode(o)),n;var a=i.createElement("style");return a.textContent=o,a}return"<style>"+o+"</style>"}return o}function r(e,t,r,i){for(var s=i?"["+e+"="+t+"]":e+t,l="",d=r.length,c=0,u="";c<d;){var p=r.charCodeAt(c);if(123===p||125===p||59===p){u+=r[c],u=u.trim();var v=u.charCodeAt(0);if(47===v)u=125===p?"}":"";else if(64===v){var b=u.charCodeAt(1)||0;if(107===b||114===b){c++,u=107==b?u.substr(1,10)+t+u.substr(11):"";for(var w=0;c<d;){var h=r[c++],y=h.charCodeAt(0);if(9!==y&&13!==y&&10!==y){if(125===y){if(1===w)break;w=1}else 123===y&&(w=0);u+=h}}u=u.replace(a,"").replace(o,"-webkit-$1$1"),u=107===b?"@-webkit-"+u+"}@"+u+"}":u.replace(n,"@-webkit-$1}@$1}")}}else{var b=u.charCodeAt(1)||0,C=u.charCodeAt(2)||0;if(97===v&&110===b&&105===C){var m=u.replace(f,"$1").split(":");u=m[0]+":"+t+m[1].split(",").join(","+t),u="-webkit-"+u+u}else if(116===v&&114===b&&97===C||97===v&&112===b&&112===C)u="-webkit-"+u+u;else if(123===p){for(var m=u.split(","),g="",k=0,A=m.length;k<A;k++){var $=m[k],x=$.charCodeAt(0),j="";j=0===k?58===x||38===x||123===x?s:s+" ":","+s,g+=123===x?j+$:38===x?j+$.substr(1):j+$}u=g}}l+=u,u=""}else 9!==p&&13!==p&&10!==p&&(u+=r[c]);c++}return l}var i=e.document,n=/@(keyframes +.*?}$)/g,o=/(transform:.*?;)/g,a=/ +/g,f=/(,|:) +/g;return t}); | ||
!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(global):"function"==typeof define&&define.amd?define(e(window)):window.stylis=e(window)}(function(e){"use strict";function r(e,r,a){if(a){var l="stylis-";if(n){var s=a.nodeType;if(s&&"STYLE"===a.nodeName){var o=t(e[0],e.substring(1),r,!1);return a.appendChild(i.createTextNode(o)),a}var f=l+e;if(null!=i.getElementById(f))return null;var o=t(e[0],e.substring(1),r,!1);if(s){var d=i.createElement("style");return d.textContent=o,d.id=f,a.appendChild(d)}return a("style",{id:f},o)}var o=t(e[0],e.substring(1),r,!1);return'<style id="'+l+e+'">'+o+"</style>"}return t(e[0],e.substring(1),r,!1)}function t(e,r,t,i){for(var n=i?"["+e+"="+r+"]":e+r,f="",d=t.length,u=0,c="";u<d;){var p=t.charCodeAt(u);if(123===p||125===p||59===p){c+=t[u];var v=c.charCodeAt(0);if(32===v&&(v=(c=c.trim()).charCodeAt(0)),47===v)c=125===p?"}":"";else if(64===v){var b=c.charCodeAt(1)||0;if(107===b||114===b){u++,c=107==b?c.substring(1,11)+r+c.substring(11):"";for(var g=0;u<d;){var h=t[u++],y=h.charCodeAt(0);if(9!==y&&13!==y&&10!==y){if(125===y){if(1===g)break;g=1}else 123===y&&(g=0);c+=h}}c=c.replace(s,"").replace(l,"-webkit-$1$1"),c=107===b?"@-webkit-"+c+"}@"+c+"}":c.replace(a,"@-webkit-$1}@$1}")}}else{var b=c.charCodeAt(1)||0,m=c.charCodeAt(2)||0;if(97===v&&110===b&&105===m){var w=c.replace(o,"$1").split(":");c=w[0]+":"+r+w[1].split(",").join(","+r),c="-webkit-"+c+c}else if(116===v&&114===b&&97===m||97===v&&112===b&&112===m)c="-webkit-"+c+c;else if(123===p){for(var w=c.split(","),C="",A=0,k=w.length;A<k;A++){var $=w[A],x=$.charCodeAt(0),E="";E=0===A?58===x||38===x||123===x?n:n+" ":","+n,C+=123===x?E+$:38===x?E+$.substring(1):E+$}c=C}}f+=c,c=""}else 9!==p&&13!==p&&10!==p&&(c+=t[u]);u++}return f}var i=e.document||null,n=null!==i,a=/@(keyframes +.*?}$)/g,l=/(transform:.*?;)/g,s=/ +/g,o=/(,|:) +/g;return r.compiler=t,r}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19514
230
270