styled-jsx
Advanced tools
Comparing version 0.1.0 to 0.1.1
@@ -30,2 +30,6 @@ 'use strict'; | ||
var makeStyledJsxTag = function makeStyledJsxTag(transformedCss) { | ||
return t.JSXElement(t.JSXOpeningElement(t.JSXIdentifier(STYLE_COMPONENT), [t.JSXAttribute(t.JSXIdentifier(STYLE_COMPONENT_CSS), t.JSXExpressionContainer(t.stringLiteral(transformedCss)))], true), null, []); | ||
}; | ||
return { | ||
@@ -35,50 +39,52 @@ inherits: _babelPluginSyntaxJsx2.default, | ||
JSXOpeningElement: function JSXOpeningElement(path, state) { | ||
if (state.hasJSXStyle) { | ||
if (state.ignoreClosing == null) { | ||
// we keep a counter of elements inside so that we | ||
// can keep track of when we exit the parent to reset state | ||
// note: if we wished to add an option to turn off | ||
// selectors to reach parent elements, it would suffice to | ||
// set this to `1` and do an early return instead | ||
state.ignoreClosing = 0; | ||
} | ||
if (!state.hasJSXStyle) { | ||
return; | ||
} | ||
var el = path.node; | ||
if (state.ignoreClosing === null) { | ||
// we keep a counter of elements inside so that we | ||
// can keep track of when we exit the parent to reset state | ||
// note: if we wished to add an option to turn off | ||
// selectors to reach parent elements, it would suffice to | ||
// set this to `1` and do an early return instead | ||
state.ignoreClosing = 0; | ||
} | ||
if (el.name && el.name.name !== 'style') { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
var el = path.node; | ||
try { | ||
for (var _iterator = el.attributes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var _attr = _step.value; | ||
if (el.name && el.name.name !== 'style') { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
if (_attr.name === MARKUP_ATTRIBUTE) { | ||
// avoid double attributes | ||
return; | ||
} | ||
try { | ||
for (var _iterator = el.attributes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var _attr = _step.value; | ||
if (_attr.name === MARKUP_ATTRIBUTE) { | ||
// avoid double attributes | ||
return; | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
var attr = t.jSXAttribute(t.JSXIdentifier(MARKUP_ATTRIBUTE), t.JSXExpressionContainer(t.stringLiteral(state.jsxId))); | ||
el.attributes.push(attr); | ||
} | ||
state.ignoreClosing++; | ||
// next visit will be: JSXElement exit() | ||
var attr = t.jSXAttribute(t.JSXIdentifier(MARKUP_ATTRIBUTE), t.JSXExpressionContainer(t.numericLiteral(state.jsxId))); | ||
el.attributes.push(attr); | ||
} | ||
state.ignoreClosing++; | ||
// next visit will be: JSXElement exit() | ||
}, | ||
@@ -88,86 +94,71 @@ | ||
enter: function enter(path, state) { | ||
if (state.hasJSXStyle == null) { | ||
var styles = findStyles(path.node.children); | ||
if (state.hasJSXStyle !== null) { | ||
return; | ||
} | ||
if (styles.length > 0) { | ||
state.jsxId = ''; | ||
state.styles = []; | ||
var styles = findStyles(path.node.children); | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
if (styles.length === 0) { | ||
state.hasJSXStyle = false; | ||
return; | ||
} | ||
try { | ||
for (var _iterator2 = styles[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var style = _step2.value; | ||
state.styles = []; | ||
// compute children excluding whitespace | ||
var children = style.children.filter(function (c) { | ||
return t.isJSXExpressionContainer(c) || | ||
// ignore whitespace around the expression container | ||
t.isJSXText(c) && c.value.trim() !== ''; | ||
}); | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
if (children.length !== 1) { | ||
throw path.buildCodeFrameError('Expected one child under ' + ('JSX Style tag, but got ' + style.children.length + ' ') + '(eg: <style jsx>{`hi`}</style>)'); | ||
} | ||
try { | ||
for (var _iterator2 = styles[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var style = _step2.value; | ||
var child = children[0]; | ||
// compute children excluding whitespace | ||
var children = style.children.filter(function (c) { | ||
return t.isJSXExpressionContainer(c) || | ||
// ignore whitespace around the expression container | ||
t.isJSXText(c) && c.value.trim() !== ''; | ||
}); | ||
if (!t.isJSXExpressionContainer(child)) { | ||
throw path.buildCodeFrameError('Expected a child of ' + 'type JSXExpressionContainer under JSX Style tag ' + ('(eg: <style jsx>{`hi`}</style>), got ' + child.type)); | ||
} | ||
if (children.length !== 1) { | ||
throw path.buildCodeFrameError('Expected one child under ' + ('JSX Style tag, but got ' + style.children.length + ' ') + '(eg: <style jsx>{`hi`}</style>)'); | ||
} | ||
var expression = child.expression; | ||
var child = children[0]; | ||
if (!t.isTemplateLiteral(child.expression) && !t.isStringLiteral(child.expression)) { | ||
throw path.buildCodeFrameError('Expected a template ' + 'literal or String literal as the child of the ' + 'JSX Style tag (eg: <style jsx>{`some css`}</style>),' + (' but got ' + expression.type)); | ||
} | ||
if (!t.isJSXExpressionContainer(child)) { | ||
throw path.buildCodeFrameError('Expected a child of ' + 'type JSXExpressionContainer under JSX Style tag ' + ('(eg: <style jsx>{`hi`}</style>), got ' + child.type)); | ||
} | ||
var styleText = getExpressionText(expression); | ||
var styleId = String((0, _murmurhash2.default)(styleText)); | ||
var expression = child.expression; | ||
state.styles.push([styleId, styleText]); | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
if (!t.isTemplateLiteral(child.expression) && !t.isStringLiteral(child.expression)) { | ||
throw path.buildCodeFrameError('Expected a template ' + 'literal or String literal as the child of the ' + 'JSX Style tag (eg: <style jsx>{`some css`}</style>),' + (' but got ' + expression.type)); | ||
} | ||
state.jsxId += (0, _murmurhash2.default)(state.styles.map(function (s) { | ||
return s[1]; | ||
}).join('')); | ||
state.hasJSXStyle = true; | ||
state.file.hasJSXStyle = true; | ||
// next visit will be: JSXOpeningElement | ||
} else { | ||
state.hasJSXStyle = false; | ||
} | ||
} else if (state.hasJSXStyle) { | ||
var el = path.node.openingElement; | ||
var styleText = getExpressionText(expression); | ||
if (el.name && el.name.name === 'style') { | ||
// we replace styles with the function call | ||
var _state$styles$shift = state.styles.shift(), | ||
_state$styles$shift2 = _slicedToArray(_state$styles$shift, 2), | ||
id = _state$styles$shift2[0], | ||
css = _state$styles$shift2[1]; | ||
var skipTransform = el.attributes.some(function (attr) { | ||
return attr.name.name === GLOBAL_ATTRIBUTE; | ||
}); | ||
path.replaceWith(t.JSXElement(t.JSXOpeningElement(t.JSXIdentifier(STYLE_COMPONENT), [t.JSXAttribute(t.JSXIdentifier(STYLE_COMPONENT_CSS), t.JSXExpressionContainer(t.stringLiteral(skipTransform ? css : (0, _styleTransform2.default)(id, css))))], true), null, [])); | ||
state.styles.push([styleText, expression.loc]); | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
state.jsxId = (0, _stringHash2.default)(state.styles.map(function (s) { | ||
return s[0]; | ||
}).join('')); | ||
state.hasJSXStyle = true; | ||
state.file.hasJSXStyle = true; | ||
// next visit will be: JSXOpeningElement | ||
}, | ||
@@ -177,4 +168,46 @@ exit: function exit(path, state) { | ||
state.hasJSXStyle = null; | ||
state.skipTransform = false; | ||
} | ||
if (!state.hasJSXStyle) { | ||
return; | ||
} | ||
var el = path.node.openingElement; | ||
if (!el.name || el.name.name !== 'style') { | ||
return; | ||
} | ||
// we replace styles with the function call | ||
var _state$styles$shift = state.styles.shift(), | ||
_state$styles$shift2 = _slicedToArray(_state$styles$shift, 2), | ||
css = _state$styles$shift2[0], | ||
loc = _state$styles$shift2[1]; | ||
var isGlobal = el.attributes.some(function (attr) { | ||
return attr.name.name === GLOBAL_ATTRIBUTE; | ||
}); | ||
if (isGlobal) { | ||
path.replaceWith(makeStyledJsxTag(css)); | ||
return; | ||
} | ||
var useSourceMaps = Boolean(state.file.opts.sourceMaps); | ||
var transformedCss = void 0; | ||
if (useSourceMaps) { | ||
var filename = state.file.opts.sourceFileName; | ||
var generator = new _sourceMap.SourceMapGenerator({ | ||
file: filename, | ||
sourceRoot: state.file.opts.sourceRoot | ||
}); | ||
generator.setSourceContent(filename, state.file.code); | ||
transformedCss = [(0, _styleTransform2.default)(state.jsxId, css, generator, loc.start, filename), _convertSourceMap2.default.fromObject(generator).toComment({ multiline: true }), '/*@ sourceURL=' + filename + ' */'].join('\n'); | ||
} else { | ||
transformedCss = (0, _styleTransform2.default)(state.jsxId, css); | ||
} | ||
path.replaceWith(makeStyledJsxTag(transformedCss)); | ||
} | ||
@@ -184,2 +217,4 @@ }, | ||
enter: function enter(path, state) { | ||
state.hasJSXStyle = null; | ||
state.ignoreClosing = null; | ||
state.file.hasJSXStyle = false; | ||
@@ -208,6 +243,12 @@ }, | ||
var _murmurhash = require('../lib/murmurhash2'); | ||
var _stringHash = require('string-hash'); | ||
var _murmurhash2 = _interopRequireDefault(_murmurhash); | ||
var _stringHash2 = _interopRequireDefault(_stringHash); | ||
var _sourceMap = require('source-map'); | ||
var _convertSourceMap = require('convert-source-map'); | ||
var _convertSourceMap2 = _interopRequireDefault(_convertSourceMap); | ||
var _styleTransform = require('../lib/style-transform'); | ||
@@ -214,0 +255,0 @@ |
@@ -1,2 +0,2 @@ | ||
// based on Stylis (MIT) | ||
// based on Stylis (MIT) | ||
// modified by Guillermo Rauch to add support for custom | ||
@@ -6,11 +6,11 @@ // attributes instead of custom selector prefix | ||
* | ||
* __ ___ | ||
* __ ___ | ||
* _____/ /___ __/ (_)____ | ||
* / ___/ __/ / / / / / ___/ | ||
* (__ ) /_/ /_/ / / (__ ) | ||
* /____/\__/\__, /_/_/____/ | ||
* /____/ | ||
* | ||
* (__ ) /_/ /_/ / / (__ ) | ||
* /____/\__/\__, /_/_/____/ | ||
* /____/ | ||
* | ||
* stylis is a small css compiler | ||
* | ||
* | ||
* @licence MIT | ||
@@ -40,3 +40,3 @@ */ | ||
* @example compiler('.class1', 'css...', false); | ||
* | ||
* | ||
* @param {string} id to use for data attributes | ||
@@ -46,3 +46,3 @@ * @param {string} styles | ||
*/ | ||
function stylis (id, styles) { | ||
function stylis (id, styles, generator, start, fileName) { | ||
var suffix = '[data-jsx="' + id +'"]'; | ||
@@ -54,3 +54,14 @@ var output = ''; | ||
var i = 0; | ||
var lineNumber = start ? start.line : 0; | ||
var columnNumber = start ? start.column : 0; | ||
generator && generator.addMapping({ | ||
generated: { | ||
line: 1, | ||
column: 0 | ||
}, | ||
source: fileName, | ||
original: start | ||
}) | ||
// parse + compile | ||
@@ -60,2 +71,7 @@ while (i < len) { | ||
if (code === 10) { | ||
lineNumber++; | ||
columnNumber = 0; | ||
} | ||
// {, }, ; characters | ||
@@ -83,2 +99,3 @@ if (code === 123 || code === 125 || code === 59) { | ||
i++; | ||
columnNumber++; | ||
@@ -97,3 +114,8 @@ if (second == 107) { | ||
var char = styles[i++]; | ||
columnNumber++; | ||
var _code = char.charCodeAt(0); | ||
if (_code === 10) { | ||
lineNumber++; | ||
columnNumber = 0; | ||
} | ||
@@ -108,3 +130,3 @@ // not `\t`, `\r`, `\n` characters | ||
} | ||
// current block tag is close tag | ||
// current block tag is close tag | ||
else { | ||
@@ -114,3 +136,3 @@ close = 1; | ||
} | ||
// { character | ||
// { character | ||
else if (_code === 123) { | ||
@@ -127,3 +149,3 @@ // current block tag is open | ||
line = line.replace(regSpaces, '').replace(regPrefix, '-webkit-$1-moz-$1-ms-$1$1'); | ||
if (second === 107) { | ||
@@ -163,3 +185,3 @@ // vendor prefix keyframes blocks | ||
} | ||
// transforms & transitions: t, r, a | ||
// transforms & transitions: t, r, a | ||
// hyphens: h, y, p | ||
@@ -289,5 +311,17 @@ // user-select: u, s, r, s | ||
generator && generator.addMapping({ | ||
generated: { | ||
line: 1, | ||
column: output.length | ||
}, | ||
source: fileName, | ||
original: { | ||
line: lineNumber, | ||
column: columnNumber | ||
} | ||
}) | ||
output += line; | ||
line = ''; | ||
} | ||
} | ||
// not `\t`, `\r`, `\n` characters | ||
@@ -299,3 +333,4 @@ else if (code !== 9 && code !== 13 && code !== 10) { | ||
// next character | ||
i++; | ||
i++; | ||
columnNumber++; | ||
} | ||
@@ -302,0 +337,0 @@ |
{ | ||
"name": "styled-jsx", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"license": "MIT", | ||
@@ -18,3 +18,6 @@ "repository": "zeit/styled-jsx", | ||
"babel-plugin-syntax-jsx": "^6.18.0", | ||
"object.entries": "^1.0.4" | ||
"convert-source-map": "^1.3.0", | ||
"object.entries": "^1.0.4", | ||
"source-map": "^0.5.6", | ||
"string-hash": "^1.1.1" | ||
}, | ||
@@ -27,2 +30,3 @@ "devDependencies": { | ||
"babel-polyfill": "^6.16.0", | ||
"babel-preset-babili": "^0.0.9", | ||
"babel-preset-es2015": "^6.16.0", | ||
@@ -34,2 +38,3 @@ "babel-preset-react": "^6.16.0", | ||
"gulp-babel": "^6.1.2", | ||
"human-size": "^1.1.0", | ||
"mz": "^2.6.0", | ||
@@ -36,0 +41,0 @@ "react": "^15.4.1", |
@@ -48,3 +48,3 @@ # styled-jsx | ||
- Full CSS support, no tradeoffs in power | ||
- Runtime size of just **500 bytes** | ||
- Runtime size of just **2kb** (gzipped, from 6kb) | ||
- Complete isolation: Selectors, animations, keyframes | ||
@@ -81,3 +81,3 @@ - Built-in CSS-prefixing | ||
### Targetting The Root | ||
### Targeting The Root | ||
@@ -178,3 +178,3 @@ Notice that the parent `<div>` above also gets a `data-jsx` atribute. We do this so that | ||
- **Max Stoiber** ([styled-components](https://github.com/styled-components)) proved the value of retaining the familiarity of CSS syntax and pointed me to the very efficient [stylis](https://github.com/thysultan/stylis.js) compiler (which we forked to very efficiently append attribute selectors to the user's css) | ||
- **Yehuda Katz** ([ember](https://github.com/ember)) convinced me on Twitter to transpile CSS as an alternative to CSS-in-JS. | ||
- **Yehuda Katz** ([ember](https://github.com/emberjs)) convinced me on Twitter to transpile CSS as an alternative to CSS-in-JS. | ||
- **Evan You** ([vuejs](https://github.com/vuejs)) discussed his Vue.js CSS transformation with me. | ||
@@ -181,0 +181,0 @@ - **Henry Zhu** ([babel](https://github.com/babel)) helpfully pointed me to some important areas of the babel plugin API. |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
40873
759
0
6
16
14
+ Addedconvert-source-map@^1.3.0
+ Addedsource-map@^0.5.6
+ Addedstring-hash@^1.1.1
+ Addedconvert-source-map@1.9.0(transitive)
+ Addedsource-map@0.5.7(transitive)
+ Addedstring-hash@1.1.3(transitive)