babel-plugin-emotion
Advanced tools
Comparing version 7.3.2 to 8.0.0-0
@@ -5,171 +5,13 @@ 'use strict'; | ||
var _postcssJs = require('postcss-js'); | ||
var _postcssJs2 = _interopRequireDefault(_postcssJs); | ||
var _input = require('postcss/lib/input'); | ||
var _input2 = _interopRequireDefault(_input); | ||
var _parser = require('./parser'); | ||
var _emotionUtils = require('emotion-utils'); | ||
var _index = require('./index'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function prefixAst(args, t, path) { | ||
function isLiteral(value) { | ||
return t.isStringLiteral(value) || t.isNumericLiteral(value) || t.isBooleanLiteral(value); | ||
} | ||
if (Array.isArray(args)) { | ||
return args.map(function (element) { | ||
return prefixAst(element, t, path); | ||
}); | ||
} | ||
if (t.isObjectExpression(args)) { | ||
var properties = []; | ||
args.properties.forEach(function (property) { | ||
// nested objects | ||
if (t.isObjectExpression(property.value)) { | ||
var key = property.computed ? property.key : t.isStringLiteral(property.key) ? t.stringLiteral(property.key.value) : t.identifier(property.key.name); | ||
var prefixedPseudoSelectors = { | ||
'::placeholder': ['::-webkit-input-placeholder', '::-moz-placeholder', ':-ms-input-placeholder'], | ||
':fullscreen': [':-webkit-full-screen', ':-moz-full-screen', ':-ms-fullscreen'] | ||
}; | ||
var prefixedValue = prefixAst(property.value, t, path); | ||
if (!property.computed) { | ||
if (prefixedPseudoSelectors[key.value]) { | ||
(0, _emotionUtils.forEach)(prefixedPseudoSelectors[key.value], function (prefixedKey) { | ||
properties.push(t.objectProperty(t.stringLiteral(prefixedKey), prefixedValue, false)); | ||
}); | ||
} | ||
} | ||
return properties.push(t.objectProperty(key, prefixedValue, property.computed)); | ||
} else if ( | ||
// literal value or array of literal values | ||
isLiteral(property.value) || t.isArrayExpression(property.value) && property.value.elements.every(isLiteral)) { | ||
var _style; | ||
// bail on computed properties | ||
if (property.computed) { | ||
properties.push(property); | ||
return; | ||
} | ||
// handle array values: { display: ['flex', 'block'] } | ||
var propertyValue = t.isArrayExpression(property.value) ? property.value.elements.map(function (element) { | ||
return element.value; | ||
}) : property.value.value; | ||
var style = (_style = {}, _style[property.key.name] = propertyValue, _style); | ||
var parsedStyle = _postcssJs2.default.parse(style); | ||
parsedStyle.source = {}; | ||
parsedStyle.source.input = new _input2.default(parsedStyle.toString(), { | ||
from: (0, _index.getFilename)(path) | ||
}); | ||
var prefixedStyle = (0, _parser.expandCSSFallbacks)((0, _parser.processor)(parsedStyle)); | ||
for (var k in prefixedStyle) { | ||
var _key = t.isStringLiteral(property.key) ? t.stringLiteral(k) : t.identifier(k); | ||
var val = prefixedStyle[k]; | ||
var value = void 0; | ||
if (typeof val === 'number') { | ||
value = t.numericLiteral(val); | ||
} else if (typeof val === 'string') { | ||
value = t.stringLiteral(val); | ||
} else if (Array.isArray(val)) { | ||
value = t.arrayExpression(val.map(function (i) { | ||
return t.stringLiteral(i); | ||
})); | ||
} | ||
properties.push(t.objectProperty(_key, value)); | ||
} | ||
// expressions | ||
} else { | ||
properties.push(property); | ||
} | ||
}); | ||
return t.objectExpression(properties); | ||
} | ||
if (t.isArrayExpression(args)) { | ||
return t.arrayExpression(prefixAst(args.elements, t, path)); | ||
} | ||
return args; | ||
} | ||
var ASTObject = function () { | ||
function ASTObject(props, expressions, composesCount, t) { | ||
function ASTObject(src, expressions, t) { | ||
_classCallCheck(this, ASTObject); | ||
this.props = props; | ||
this.stringSrc = src; | ||
this.expressions = expressions || []; | ||
this.composesCount = composesCount; | ||
this.t = t; | ||
} | ||
ASTObject.prototype.objKeyToAst = function objKeyToAst(key) { | ||
var t = this.t; | ||
var matches = this.getDynamicMatches(key); | ||
if (matches.length) { | ||
return { | ||
computed: true, | ||
composes: key === 'composes', | ||
ast: this.replacePlaceholdersWithExpressions(matches, key) | ||
}; | ||
} | ||
return { | ||
computed: false, | ||
composes: key === 'composes', | ||
ast: t.stringLiteral(key === 'cssFloat' ? 'float' : key) | ||
}; | ||
}; | ||
ASTObject.prototype.objValueToAst = function objValueToAst(value) { | ||
var _this = this; | ||
var composesCount = this.composesCount, | ||
t = this.t; | ||
if (typeof value === 'string') { | ||
var matches = this.getDynamicMatches(value); | ||
if (matches.length) { | ||
return this.replacePlaceholdersWithExpressions(matches, value); | ||
} | ||
return t.stringLiteral(value); | ||
} else if (typeof value === 'number') { | ||
return t.numericLiteral(value); | ||
} else if (Array.isArray(value)) { | ||
// should never hit here | ||
if (value[0] && (value[0].key || value[0].value || value[0].spread)) { | ||
return this.toAST(value); | ||
} | ||
return t.arrayExpression(value.map(function (v) { | ||
return _this.objValueToAst(v); | ||
})); | ||
} | ||
return ASTObject.fromJS(value, composesCount, t).toAST(); | ||
}; | ||
ASTObject.prototype.getDynamicMatches = function getDynamicMatches(str) { | ||
@@ -192,12 +34,11 @@ var re = /xxx(\d+)xxx/gm; | ||
var expressions = this.expressions, | ||
composesCount = this.composesCount, | ||
t = this.t; | ||
if (expressions.length === 0) { | ||
return t.templateLiteral([t.templateElement({ cooked: str, raw: str })], []); | ||
} | ||
var templateElements = []; | ||
var templateExpressions = []; | ||
var cursor = 0; | ||
// not sure how to detect when to add 'px' | ||
var hasSingleInterpolation = false; | ||
(0, _emotionUtils.forEach)(matches, function (_ref, i) { | ||
matches.forEach(function (_ref, i) { | ||
var value = _ref.value, | ||
@@ -214,7 +55,4 @@ p1 = _ref.p1, | ||
} | ||
if (value === str) { | ||
hasSingleInterpolation = true; | ||
} | ||
templateExpressions.push(expressions.length ? expressions[p1 - composesCount] : t.identifier('x' + (p1 - composesCount))); | ||
templateExpressions.push(expressions[p1]); | ||
if (i === matches.length - 1) { | ||
@@ -227,165 +65,9 @@ templateElements.push(t.templateElement({ | ||
}); | ||
if (hasSingleInterpolation) { | ||
return templateExpressions[0]; | ||
} | ||
return t.templateLiteral(templateElements, templateExpressions); | ||
}; | ||
ASTObject.prototype.toAST = function toAST() { | ||
var _this2 = this; | ||
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props; | ||
return this.t.objectExpression(props.map(function (prop) { | ||
if (_this2.t.isObjectProperty(prop)) { | ||
return prop; | ||
} | ||
var property = prop.property, | ||
key = prop.key, | ||
value = prop.value, | ||
spread = prop.spread, | ||
shorthand = prop.shorthand; | ||
if (spread || shorthand) { | ||
return property; | ||
} | ||
var _objKeyToAst = _this2.objKeyToAst(key), | ||
computed = _objKeyToAst.computed, | ||
keyAST = _objKeyToAst.ast; | ||
var valueAST = _this2.objValueToAst(value); | ||
return _this2.t.objectProperty(keyAST, valueAST, computed); | ||
})); | ||
ASTObject.prototype.toTemplateLiteral = function toTemplateLiteral() { | ||
return this.replacePlaceholdersWithExpressions(this.getDynamicMatches(this.stringSrc), this.stringSrc); | ||
}; | ||
ASTObject.prototype.toJS = function toJS() { | ||
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props; | ||
return props.reduce(function (accum, _ref2) { | ||
var property = _ref2.property, | ||
key = _ref2.key, | ||
value = _ref2.value, | ||
isComputedProperty = _ref2.computed, | ||
spread = _ref2.spread; | ||
if (spread) { | ||
return accum; | ||
} | ||
accum[key] = value; | ||
return accum; | ||
}, {}); | ||
}; | ||
ASTObject.fromJS = function fromJS(jsObj, composesCount, t) { | ||
var props = []; | ||
for (var key in jsObj) { | ||
if (jsObj.hasOwnProperty(key)) { | ||
var value = void 0; | ||
if (Object.prototype.toString.call(jsObj[key]) === '[object Object]') { | ||
value = jsObj[key]; | ||
} else { | ||
value = jsObj[key]; | ||
} | ||
props.push({ | ||
key: key, | ||
value: value, | ||
computed: false, | ||
spread: false, | ||
property: null | ||
}); | ||
} | ||
} | ||
return new ASTObject(props, [], composesCount, t); | ||
}; | ||
ASTObject.fromAST = function fromAST(astObj, t, path) { | ||
function isLiteral(value) { | ||
return t.isStringLiteral(value) || t.isNumericLiteral(value) || t.isBooleanLiteral(value); | ||
} | ||
var expressions = []; | ||
function replaceExpressionsWithPlaceholders(node) { | ||
if (t.isArrayExpression(node)) { | ||
return node.elements.map(replaceExpressionsWithPlaceholders); | ||
} else if (isLiteral(node)) { | ||
return node.value; | ||
} else if (t.isTemplateLiteral(node)) { | ||
var strs = node.quasis.map(function (x) { | ||
return x.value.cooked; | ||
}); | ||
var exprs = node.expressions; | ||
return (0, _emotionUtils.reduce)(strs, function (arr, str, i) { | ||
arr.push(str); | ||
if (i !== strs.length - 1) { | ||
expressions.push(exprs[i]); | ||
arr.push('xxx' + (expressions.length - 1) + 'xxx'); | ||
} | ||
return arr; | ||
}, []).join('').trim(); | ||
} | ||
expressions.push(node); | ||
return 'xxx' + (expressions.length - 1) + 'xxx'; | ||
} | ||
function convertAstToObj(astObj) { | ||
var props = []; | ||
(0, _emotionUtils.forEach)(astObj.properties, function (property, i) { | ||
var key = void 0; | ||
if (t.isSpreadProperty(property)) { | ||
props.push({ | ||
key: null, | ||
value: null, | ||
computed: false, | ||
shorthand: false, | ||
spread: true, | ||
property: property | ||
}); | ||
return; | ||
} | ||
if (property.computed) { | ||
key = replaceExpressionsWithPlaceholders(property.key); | ||
} else { | ||
key = t.isIdentifier(property.key) ? property.key.name : property.key.value; | ||
} | ||
// nested objects | ||
if (t.isObjectExpression(property.value)) { | ||
props.push({ | ||
key: key, | ||
value: convertAstToObj(property.value), | ||
computed: property.computed, | ||
spread: false, | ||
shorthand: false, | ||
property: property | ||
}); | ||
} else { | ||
props.push({ | ||
key: key, | ||
value: replaceExpressionsWithPlaceholders(property.value), | ||
computed: property.computed, | ||
spread: false, | ||
shorthand: false, | ||
property: property | ||
}); | ||
} | ||
}); | ||
return props; | ||
} | ||
var objectProperties = convertAstToObj(prefixAst(astObj, t, path)); | ||
return new ASTObject(objectProperties, expressions, 0, // composesCount: we should support this, | ||
t); | ||
}; | ||
return ASTObject; | ||
@@ -392,0 +74,0 @@ }(); |
'use strict'; | ||
exports.__esModule = true; | ||
exports.minify = undefined; | ||
exports.getIdentifierName = getIdentifierName; | ||
@@ -8,4 +9,7 @@ exports.getRuntimeImportPath = getRuntimeImportPath; | ||
exports.addRuntimeImports = addRuntimeImports; | ||
exports.getName = getName; | ||
exports.createRawStringFromTemplateLiteral = createRawStringFromTemplateLiteral; | ||
exports.omit = omit; | ||
var _emotionUtils = require('emotion-utils'); | ||
var _index = require('./index'); | ||
@@ -42,5 +46,5 @@ function getIdentifierName(path, t) { | ||
if (state.emotionImports === undefined) return; | ||
(0, _emotionUtils.forEach)((0, _emotionUtils.keys)(state.emotionImports), function (importPath) { | ||
Object.keys(state.emotionImports).forEach(function (importPath) { | ||
var importSpecifiers = []; | ||
(0, _emotionUtils.forEach)((0, _emotionUtils.keys)(state.emotionImports[importPath]), function (importName) { | ||
Object.keys(state.emotionImports[importPath]).forEach(function (importName) { | ||
var identifier = state.emotionImports[importPath][importName]; | ||
@@ -56,2 +60,63 @@ if (importName === 'default') { | ||
state.emotionImports = undefined; | ||
} | ||
} | ||
function getName(identifierName, prefix) { | ||
var parts = []; | ||
parts.push(prefix); | ||
if (identifierName) { | ||
parts.push(identifierName); | ||
} | ||
return parts.join('-'); | ||
} | ||
function createRawStringFromTemplateLiteral(quasi) { | ||
var strs = quasi.quasis.map(function (x) { | ||
return x.value.cooked; | ||
}); | ||
var hash = (0, _index.hashArray)([].concat(strs)); | ||
var src = strs.reduce(function (arr, str, i) { | ||
arr.push(str); | ||
if (i !== strs.length - 1) { | ||
arr.push('xxx' + i + 'xxx'); | ||
} | ||
return arr; | ||
}, []).join('').trim(); | ||
return { src: src, hash: hash }; | ||
} | ||
function omit(obj, testFn) { | ||
var target = {}; | ||
var i = void 0; | ||
for (i in obj) { | ||
if (!testFn(i, obj)) continue; | ||
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; | ||
target[i] = obj[i]; | ||
} | ||
return target; | ||
} | ||
// babel-plugin-styled-components | ||
// https://github.com/styled-components/babel-plugin-styled-components/blob/8d44acc36f067d60d4e09f9c22ff89695bc332d2/src/minify/index.js | ||
var symbolRegex = /(\s*[;:{},]\s*)/g; | ||
// Counts occurences of substr inside str | ||
var countOccurences = function countOccurences(str, substr) { | ||
return str.split(substr).length - 1; | ||
}; | ||
var minify = exports.minify = function minify(code) { | ||
return code.split(symbolRegex).reduce(function (str, fragment, index) { | ||
// Even-indices are non-symbol fragments | ||
if (index % 2 === 0) { | ||
return str + fragment; | ||
} | ||
// Only manipulate symbols outside of strings | ||
if (countOccurences(str, "'") % 2 === 0 && countOccurences(str, '"') % 2 === 0) { | ||
return str + fragment.trim(); | ||
} | ||
return str + fragment; | ||
}, ''); | ||
}; |
@@ -46,4 +46,4 @@ 'use strict'; | ||
} | ||
if (!classNamesValue) { | ||
if (!classNamesValue || t.isStringLiteral(classNamesValue) && !classNamesValue.value) { | ||
if (classNamesPath) classNamesPath.parentPath.remove(); | ||
cssPath.parentPath.replaceWith(createClassNameAttr(cssTemplateExpression)); | ||
@@ -55,5 +55,5 @@ return; | ||
if (t.isJSXExpressionContainer(classNamesValue)) { | ||
classNamesPath.parentPath.replaceWith(createClassNameAttr(add(add(classNamesValue.expression, t.stringLiteral(' ')), cssTemplateExpression))); | ||
classNamesPath.parentPath.replaceWith(createClassNameAttr(t.callExpression(getMergeIdentifier(), [add(cssTemplateExpression, add(t.stringLiteral(' '), classNamesValue.expression))]))); | ||
} else { | ||
classNamesPath.parentPath.replaceWith(createClassNameAttr(add(add(t.stringLiteral(classNamesValue.value || ''), t.stringLiteral(' ')), cssTemplateExpression))); | ||
classNamesPath.parentPath.replaceWith(createClassNameAttr(add(cssTemplateExpression, t.stringLiteral(' ' + (classNamesValue.value || ''))))); | ||
} | ||
@@ -72,3 +72,3 @@ | ||
if (!state.cssPropIdentifier) { | ||
state.cssPropIdentifier = path.scope.generateUidIdentifier(state.importedNames.css); | ||
state.cssPropIdentifier = path.hub.file.addImport('emotion', 'css'); | ||
} | ||
@@ -80,2 +80,12 @@ return state.cssPropIdentifier; | ||
} | ||
function getMergeIdentifier() { | ||
if (state.opts.autoImportCssProp !== false) { | ||
if (!state.cssPropMergeIdentifier) { | ||
state.cssPropMergeIdentifier = path.hub.file.addImport('emotion', 'merge'); | ||
} | ||
return state.cssPropMergeIdentifier; | ||
} else { | ||
return t.identifier(state.importedNames.merge); | ||
} | ||
} | ||
function createCssTemplateExpression(templateLiteral) { | ||
@@ -82,0 +92,0 @@ return t.taggedTemplateExpression(getCssIdentifer(), templateLiteral); |
146
lib/index.js
@@ -8,7 +8,6 @@ 'use strict'; | ||
exports.getFilename = getFilename; | ||
exports.hashArray = hashArray; | ||
exports.replaceCssWithCallExpression = replaceCssWithCallExpression; | ||
exports.buildStyledCallExpression = buildStyledCallExpression; | ||
exports.buildStyledObjectCallExpression = buildStyledObjectCallExpression; | ||
exports.replaceCssObjectCallExpression = replaceCssObjectCallExpression; | ||
@@ -33,3 +32,3 @@ exports.default = function (babel) { | ||
var importedNames = specifiers.filter(function (v) { | ||
return ['default', 'css', 'keyframes', 'injectGlobal', 'fontFace'].indexOf(v.imported) !== -1; | ||
return ['default', 'css', 'keyframes', 'injectGlobal', 'fontFace', 'merge'].indexOf(v.imported) !== -1; | ||
}).reduce(function (acc, _ref2) { | ||
@@ -74,5 +73,2 @@ var _extends2; | ||
} | ||
if (state.cssPropIdentifier) { | ||
path.node.body.unshift(t.importDeclaration([t.importSpecifier(state.cssPropIdentifier, t.identifier('css'))], t.stringLiteral('emotion'))); | ||
} | ||
} | ||
@@ -92,5 +88,2 @@ }, | ||
} | ||
if (path.node.callee.name === state.importedNames.css && !path.node.arguments[1] && path.node.arguments[0]) { | ||
replaceCssObjectCallExpression(path, t.identifier(state.importedNames.css), t); | ||
} | ||
} catch (e) { | ||
@@ -103,2 +96,6 @@ throw path.buildCodeFrameError(e); | ||
TaggedTemplateExpression: function TaggedTemplateExpression(path, state) { | ||
if (path[visited]) { | ||
return; | ||
} | ||
path[visited] = true; | ||
if ( | ||
@@ -116,13 +113,15 @@ // styled.h1`color:${color};` | ||
} else if (path.node.tag.name === state.importedNames.keyframes) { | ||
replaceCssWithCallExpression(path, path.node.tag, state, t, function (name, hash, src) { | ||
replaceCssWithCallExpression(path, path.node.tag, state, t, function (src, name, hash) { | ||
return '@keyframes ' + name + '-' + hash + ' { ' + src + ' }'; | ||
}, false, function () { | ||
return ''; | ||
}); | ||
} else if (path.node.tag.name === state.importedNames.fontFace) { | ||
replaceCssWithCallExpression(path, path.node.tag, state, t, function (name, hash, src) { | ||
replaceCssWithCallExpression(path, path.node.tag, state, t, function (src, name, hash) { | ||
return '@font-face {' + src + '}'; | ||
}, true); | ||
} else if (path.node.tag.name === state.importedNames.injectGlobal) { | ||
replaceCssWithCallExpression(path, path.node.tag, state, t, function (name, hash, src) { | ||
return src; | ||
}, true); | ||
replaceCssWithCallExpression(path, path.node.tag, state, t, undefined, true, function () { | ||
return ''; | ||
}); | ||
} | ||
@@ -143,6 +142,2 @@ } | ||
var _inline4 = require('./inline'); | ||
var _parser = require('./parser'); | ||
var _babelUtils = require('./babel-utils'); | ||
@@ -162,25 +157,27 @@ | ||
function getFilename(path) { | ||
return path.hub.file.opts.filename === 'unknown' ? '' : path.hub.file.opts.filename; | ||
function hashArray(arr) { | ||
return (0, _emotionUtils.hashString)(arr.join('')); | ||
} | ||
var staticStylis = new _emotionUtils.Stylis({ keyframe: false }); | ||
function replaceCssWithCallExpression(path, identifier, state, t) { | ||
var staticCSSTextCreator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : function (name, hash, src) { | ||
return '.' + name + '-' + hash + ' { ' + src + ' }'; | ||
var staticCSSSrcCreator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : function (src) { | ||
return src; | ||
}; | ||
var removePath = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; | ||
var staticCSSSelectorCreator = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : function (name, hash) { | ||
return '.' + name + '-' + hash; | ||
}; | ||
try { | ||
var _inline = (0, _inline4.inline)(path.node.quasi, (0, _babelUtils.getIdentifierName)(path, t), 'css'), | ||
name = _inline.name, | ||
hash = _inline.hash, | ||
src = _inline.src; | ||
var _createRawStringFromT = (0, _babelUtils.createRawStringFromTemplateLiteral)(path.node.quasi), | ||
hash = _createRawStringFromT.hash, | ||
src = _createRawStringFromT.src; | ||
var name = (0, _babelUtils.getName)((0, _babelUtils.getIdentifierName)(path, t), 'css'); | ||
if (state.extractStatic && !path.node.quasi.expressions.length) { | ||
var cssText = staticCSSTextCreator(name, hash, src); | ||
var _parseCSS = (0, _parser.parseCSS)(cssText, true, getFilename(path)), | ||
staticCSSRules = _parseCSS.staticCSSRules; | ||
state.insertStaticRules(staticCSSRules); | ||
var staticCSSRules = staticStylis(staticCSSSelectorCreator(name, hash), staticCSSSrcCreator(src, name, hash)); | ||
state.insertStaticRules([staticCSSRules]); | ||
if (!removePath) { | ||
@@ -192,15 +189,7 @@ return path.replaceWith(t.stringLiteral(name + '-' + hash)); | ||
var _parseCSS2 = (0, _parser.parseCSS)(src, false, getFilename(path)), | ||
styles = _parseCSS2.styles, | ||
composesCount = _parseCSS2.composesCount; | ||
if (!removePath) { | ||
path.addComment('leading', '#__PURE__'); | ||
} | ||
var composeValues = path.node.quasi.expressions.slice(0, composesCount); | ||
var vars = path.node.quasi.expressions.slice(composesCount); | ||
path.replaceWith(t.callExpression(identifier, [t.arrayExpression(composeValues), t.arrayExpression(vars), t.functionExpression(t.identifier('createEmotionStyledRules'), vars.map(function (x, i) { | ||
return t.identifier('x' + i); | ||
}), t.blockStatement([t.returnStatement(t.arrayExpression([_astObject2.default.fromJS(styles, composesCount, t).toAST()]))]))])); | ||
path.node.quasi = new _astObject2.default((0, _babelUtils.minify)(src), path.node.quasi.expressions, t).toTemplateLiteral(); | ||
path.node.tag = identifier; | ||
} catch (e) { | ||
@@ -257,3 +246,3 @@ if (path) { | ||
var fileHash = (0, _emotionUtils.hashArray)([moduleName, filePath, code]); | ||
var fileHash = hashArray([moduleName, filePath, code]); | ||
file.set(FILE_HASH, fileHash); | ||
@@ -277,2 +266,8 @@ return fileHash; | ||
var interleave = function interleave(strings, interpolations) { | ||
return interpolations.reduce(function (array, interp, i) { | ||
return array.concat(interp, strings[i + 1]); | ||
}, [strings[0]]); | ||
}; | ||
function buildStyledCallExpression(identifier, tag, path, state, t) { | ||
@@ -282,34 +277,28 @@ var identifierName = (0, _babelUtils.getIdentifierName)(path, t); | ||
if (state.extractStatic && !path.node.quasi.expressions.length) { | ||
var _inline2 = (0, _inline4.inline)(path.node.quasi, identifierName, 'styled' // we don't want these styles to be merged in css`` | ||
var _createRawStringFromT2 = (0, _babelUtils.createRawStringFromTemplateLiteral)(path.node.quasi, identifierName, 'styled' // we don't want these styles to be merged in css`` | ||
), | ||
_name = _inline2.name, | ||
hash = _inline2.hash, | ||
_src = _inline2.src; | ||
hash = _createRawStringFromT2.hash, | ||
_src = _createRawStringFromT2.src; | ||
var cssText = '.' + _name + '-' + hash + ' { ' + _src + ' }'; | ||
var staticClassName = 'css-' + hash; | ||
var staticCSSRules = staticStylis('.' + staticClassName, _src); | ||
var _parseCSS3 = (0, _parser.parseCSS)(cssText, true, getFilename(path)), | ||
staticCSSRules = _parseCSS3.staticCSSRules; | ||
state.insertStaticRules(staticCSSRules); | ||
return t.callExpression(identifier, [tag, t.stringLiteral(getComponentId(state, _name)), t.arrayExpression([t.stringLiteral(_name + '-' + hash)])]); | ||
state.insertStaticRules([staticCSSRules]); | ||
return t.callExpression(t.callExpression(identifier, [tag, t.objectExpression([t.objectProperty(t.identifier('id'), t.stringLiteral(getComponentId(state, (0, _babelUtils.getName)((0, _babelUtils.getIdentifierName)(path, t), 'css')))), t.objectProperty(t.identifier('e'), t.stringLiteral(staticClassName))])]), []); | ||
} | ||
var _inline3 = (0, _inline4.inline)(path.node.quasi, identifierName, 'css'), | ||
src = _inline3.src, | ||
name = _inline3.name; | ||
var _createRawStringFromT3 = (0, _babelUtils.createRawStringFromTemplateLiteral)(path.node.quasi), | ||
src = _createRawStringFromT3.src; | ||
path.addComment('leading', '#__PURE__'); | ||
var _parseCSS4 = (0, _parser.parseCSS)(src, false, getFilename(path)), | ||
styles = _parseCSS4.styles, | ||
composesCount = _parseCSS4.composesCount; | ||
var templateLiteral = new _astObject2.default((0, _babelUtils.minify)(src), path.node.quasi.expressions, t).toTemplateLiteral(); | ||
var objs = path.node.quasi.expressions.slice(0, composesCount); | ||
var vars = path.node.quasi.expressions.slice(composesCount); | ||
var args = [tag, t.stringLiteral(getComponentId(state, name)), t.arrayExpression(objs), t.arrayExpression(vars), t.functionExpression(t.identifier('createEmotionStyledRules'), vars.map(function (x, i) { | ||
return t.identifier('x' + i); | ||
}), t.blockStatement([t.returnStatement(_astObject2.default.fromJS(styles, composesCount, t).toAST())]))]; | ||
var values = interleave(templateLiteral.quasis.map(function (node) { | ||
return t.stringLiteral(node.value.cooked); | ||
}), path.node.quasi.expressions).filter(function (node) { | ||
return node.value !== ''; | ||
}); | ||
return t.callExpression(identifier, args); | ||
return t.callExpression(t.callExpression(identifier, [tag, t.objectExpression([t.objectProperty(t.identifier('id'), t.stringLiteral(getComponentId(state, (0, _babelUtils.getName)((0, _babelUtils.getIdentifierName)(path, t), 'css'))))])]), values); | ||
} | ||
@@ -319,27 +308,5 @@ | ||
var tag = t.isCallExpression(path.node.callee) ? path.node.callee.arguments[0] : t.stringLiteral(path.node.callee.property.name); | ||
return t.callExpression(identifier, [tag, t.stringLiteral(getComponentId(state, (0, _inline4.getName)((0, _babelUtils.getIdentifierName)(path, t), 'css'))), t.arrayExpression(buildProcessedStylesFromObjectAST(path.node.arguments, path, t))]); | ||
return t.callExpression(t.callExpression(identifier, [tag, t.objectExpression([t.objectProperty(t.identifier('id'), t.stringLiteral(getComponentId(state, (0, _babelUtils.getName)((0, _babelUtils.getIdentifierName)(path, t), 'css'))))])]), path.node.arguments); | ||
} | ||
function buildProcessedStylesFromObjectAST(objectAST, path, t) { | ||
if (t.isObjectExpression(objectAST)) { | ||
return _astObject2.default.fromAST(objectAST, t, path).toAST(); | ||
} | ||
if (t.isArrayExpression(objectAST)) { | ||
return t.arrayExpression(buildProcessedStylesFromObjectAST(objectAST.elements, path, t)); | ||
} | ||
if (Array.isArray(objectAST)) { | ||
return (0, _emotionUtils.map)(objectAST, function (obj) { | ||
return buildProcessedStylesFromObjectAST(obj, path, t); | ||
}); | ||
} | ||
return objectAST; | ||
} | ||
function replaceCssObjectCallExpression(path, identifier, t) { | ||
var argWithStyles = path.node.arguments[0]; | ||
var styles = buildProcessedStylesFromObjectAST(argWithStyles, path, t); | ||
path.replaceWith(t.callExpression(identifier, [styles])); | ||
} | ||
var visited = Symbol('visited'); | ||
@@ -352,3 +319,4 @@ | ||
injectGlobal: 'injectGlobal', | ||
fontFace: 'fontFace' | ||
fontFace: 'fontFace', | ||
merge: 'merge' | ||
}; |
@@ -13,4 +13,2 @@ 'use strict'; | ||
var _emotionUtils = require('emotion-utils'); | ||
var _babelMacros = require('babel-macros'); | ||
@@ -30,3 +28,3 @@ | ||
if (references.default) { | ||
referencesWithoutDefault = (0, _emotionUtils.omit)(references, function (key) { | ||
referencesWithoutDefault = (0, _babelUtils.omit)(references, function (key) { | ||
return key !== 'default'; | ||
@@ -33,0 +31,0 @@ }); |
@@ -7,4 +7,2 @@ 'use strict'; | ||
var _emotionUtils = require('emotion-utils'); | ||
var _babelMacros = require('babel-macros'); | ||
@@ -20,3 +18,3 @@ | ||
if (!state.inline) state.inline = true; | ||
(0, _emotionUtils.forEach)((0, _emotionUtils.keys)(references), function (referenceKey) { | ||
Object.keys(references).forEach(function (referenceKey) { | ||
if (referenceKey === 'injectGlobal') { | ||
@@ -42,4 +40,2 @@ references.injectGlobal.forEach(function (injectGlobalReference) { | ||
(0, _index.replaceCssWithCallExpression)(path, runtimeNode, state, t); | ||
} else if (!path.node.arguments[1] && path.node.arguments[0]) { | ||
(0, _index.replaceCssObjectCallExpression)(path, runtimeNode, t); | ||
} else { | ||
@@ -46,0 +42,0 @@ cssReference.replaceWith(runtimeNode); |
{ | ||
"name": "babel-plugin-emotion", | ||
"version": "7.3.2", | ||
"version": "8.0.0-0", | ||
"description": "A recommended babel preprocessing plugin for emotion, the The Next Generation of CSS-in-JS.", | ||
@@ -19,3 +19,3 @@ "main": "lib/index.js", | ||
"babel-plugin-syntax-jsx": "^6.18.0", | ||
"emotion-utils": "^7.3.1", | ||
"emotion-utils": "^8.0.0-0", | ||
"postcss": "^6.0.9", | ||
@@ -22,0 +22,0 @@ "postcss-js": "^1.0.0", |
@@ -1,122 +0,1 @@ | ||
import postcssJs from 'postcss-js' | ||
import Input from 'postcss/lib/input' | ||
import { expandCSSFallbacks, processor } from './parser' | ||
import { forEach, reduce } from 'emotion-utils' | ||
import { getFilename } from './index' | ||
function prefixAst(args, t, path) { | ||
function isLiteral(value) { | ||
return ( | ||
t.isStringLiteral(value) || | ||
t.isNumericLiteral(value) || | ||
t.isBooleanLiteral(value) | ||
) | ||
} | ||
if (Array.isArray(args)) { | ||
return args.map(element => prefixAst(element, t, path)) | ||
} | ||
if (t.isObjectExpression(args)) { | ||
let properties = [] | ||
args.properties.forEach(property => { | ||
// nested objects | ||
if (t.isObjectExpression(property.value)) { | ||
const key = property.computed | ||
? property.key | ||
: t.isStringLiteral(property.key) | ||
? t.stringLiteral(property.key.value) | ||
: t.identifier(property.key.name) | ||
const prefixedPseudoSelectors = { | ||
'::placeholder': [ | ||
'::-webkit-input-placeholder', | ||
'::-moz-placeholder', | ||
':-ms-input-placeholder' | ||
], | ||
':fullscreen': [ | ||
':-webkit-full-screen', | ||
':-moz-full-screen', | ||
':-ms-fullscreen' | ||
] | ||
} | ||
const prefixedValue = prefixAst(property.value, t, path) | ||
if (!property.computed) { | ||
if (prefixedPseudoSelectors[key.value]) { | ||
forEach(prefixedPseudoSelectors[key.value], prefixedKey => { | ||
properties.push( | ||
t.objectProperty( | ||
t.stringLiteral(prefixedKey), | ||
prefixedValue, | ||
false | ||
) | ||
) | ||
}) | ||
} | ||
} | ||
return properties.push( | ||
t.objectProperty(key, prefixedValue, property.computed) | ||
) | ||
} else if ( | ||
// literal value or array of literal values | ||
isLiteral(property.value) || | ||
(t.isArrayExpression(property.value) && | ||
property.value.elements.every(isLiteral)) | ||
) { | ||
// bail on computed properties | ||
if (property.computed) { | ||
properties.push(property) | ||
return | ||
} | ||
// handle array values: { display: ['flex', 'block'] } | ||
const propertyValue = t.isArrayExpression(property.value) | ||
? property.value.elements.map(element => element.value) | ||
: property.value.value | ||
const style = { [property.key.name]: propertyValue } | ||
const parsedStyle = postcssJs.parse(style) | ||
parsedStyle.source = {} | ||
parsedStyle.source.input = new Input(parsedStyle.toString(), { | ||
from: getFilename(path) | ||
}) | ||
const prefixedStyle = expandCSSFallbacks(processor(parsedStyle)) | ||
for (let k in prefixedStyle) { | ||
const key = t.isStringLiteral(property.key) | ||
? t.stringLiteral(k) | ||
: t.identifier(k) | ||
const val = prefixedStyle[k] | ||
let value | ||
if (typeof val === 'number') { | ||
value = t.numericLiteral(val) | ||
} else if (typeof val === 'string') { | ||
value = t.stringLiteral(val) | ||
} else if (Array.isArray(val)) { | ||
value = t.arrayExpression(val.map(i => t.stringLiteral(i))) | ||
} | ||
properties.push(t.objectProperty(key, value)) | ||
} | ||
// expressions | ||
} else { | ||
properties.push(property) | ||
} | ||
}) | ||
return t.objectExpression(properties) | ||
} | ||
if (t.isArrayExpression(args)) { | ||
return t.arrayExpression(prefixAst(args.elements, t, path)) | ||
} | ||
return args | ||
} | ||
export default class ASTObject { | ||
@@ -128,51 +7,7 @@ props: Array<any> | ||
constructor(props, expressions, composesCount, t) { | ||
this.props = props | ||
constructor(src, expressions, t) { | ||
this.stringSrc = src | ||
this.expressions = expressions || [] | ||
this.composesCount = composesCount | ||
this.t = t | ||
} | ||
objKeyToAst(key): { computed: boolean, ast: any, composes: boolean } { | ||
const { t } = this | ||
const matches = this.getDynamicMatches(key) | ||
if (matches.length) { | ||
return { | ||
computed: true, | ||
composes: key === 'composes', | ||
ast: this.replacePlaceholdersWithExpressions(matches, key) | ||
} | ||
} | ||
return { | ||
computed: false, | ||
composes: key === 'composes', | ||
ast: t.stringLiteral(key === 'cssFloat' ? 'float' : key) | ||
} | ||
} | ||
objValueToAst(value) { | ||
const { composesCount, t } = this | ||
if (typeof value === 'string') { | ||
const matches = this.getDynamicMatches(value) | ||
if (matches.length) { | ||
return this.replacePlaceholdersWithExpressions(matches, value) | ||
} | ||
return t.stringLiteral(value) | ||
} else if (typeof value === 'number') { | ||
return t.numericLiteral(value) | ||
} else if (Array.isArray(value)) { | ||
// should never hit here | ||
if (value[0] && (value[0].key || value[0].value || value[0].spread)) { | ||
return this.toAST(value) | ||
} | ||
return t.arrayExpression(value.map(v => this.objValueToAst(v))) | ||
} | ||
return ASTObject.fromJS(value, composesCount, t).toAST() | ||
} | ||
getDynamicMatches(str) { | ||
@@ -194,10 +29,13 @@ const re = /xxx(\d+)xxx/gm | ||
replacePlaceholdersWithExpressions(matches: any[], str: string) { | ||
const { expressions, composesCount, t } = this | ||
const { expressions, t } = this | ||
if (expressions.length === 0) { | ||
return t.templateLiteral( | ||
[t.templateElement({ cooked: str, raw: str })], | ||
[] | ||
) | ||
} | ||
const templateElements = [] | ||
const templateExpressions = [] | ||
let cursor = 0 | ||
// not sure how to detect when to add 'px' | ||
let hasSingleInterpolation = false | ||
forEach(matches, ({ value, p1, index }, i) => { | ||
matches.forEach(({ value, p1, index }, i) => { | ||
const preMatch = str.substring(cursor, index) | ||
@@ -212,11 +50,4 @@ cursor = cursor + preMatch.length + value.length | ||
} | ||
if (value === str) { | ||
hasSingleInterpolation = true | ||
} | ||
templateExpressions.push( | ||
expressions.length | ||
? expressions[p1 - composesCount] | ||
: t.identifier(`x${p1 - composesCount}`) | ||
) | ||
templateExpressions.push(expressions[p1]) | ||
if (i === matches.length - 1) { | ||
@@ -234,166 +65,10 @@ templateElements.push( | ||
}) | ||
if (hasSingleInterpolation) { | ||
return templateExpressions[0] | ||
} | ||
return t.templateLiteral(templateElements, templateExpressions) | ||
} | ||
toAST(props = this.props) { | ||
return this.t.objectExpression( | ||
props.map(prop => { | ||
if (this.t.isObjectProperty(prop)) { | ||
return prop | ||
} | ||
const { property, key, value, spread, shorthand } = prop | ||
if (spread || shorthand) { | ||
return property | ||
} | ||
const { computed, ast: keyAST } = this.objKeyToAst(key) | ||
const valueAST = this.objValueToAst(value) | ||
return this.t.objectProperty(keyAST, valueAST, computed) | ||
}) | ||
toTemplateLiteral() { | ||
return this.replacePlaceholdersWithExpressions( | ||
this.getDynamicMatches(this.stringSrc), | ||
this.stringSrc | ||
) | ||
} | ||
toJS(props = this.props) { | ||
return props.reduce( | ||
( | ||
accum, | ||
{ property, key, value, computed: isComputedProperty, spread } | ||
) => { | ||
if (spread) { | ||
return accum | ||
} | ||
accum[key] = value | ||
return accum | ||
}, | ||
{} | ||
) | ||
} | ||
static fromJS(jsObj, composesCount, t) { | ||
const props = [] | ||
for (let key in jsObj) { | ||
if (jsObj.hasOwnProperty(key)) { | ||
let value | ||
if (Object.prototype.toString.call(jsObj[key]) === '[object Object]') { | ||
value = jsObj[key] | ||
} else { | ||
value = jsObj[key] | ||
} | ||
props.push({ | ||
key: key, | ||
value: value, | ||
computed: false, | ||
spread: false, | ||
property: null | ||
}) | ||
} | ||
} | ||
return new ASTObject(props, [], composesCount, t) | ||
} | ||
static fromAST(astObj, t, path) { | ||
function isLiteral(value) { | ||
return ( | ||
t.isStringLiteral(value) || | ||
t.isNumericLiteral(value) || | ||
t.isBooleanLiteral(value) | ||
) | ||
} | ||
let expressions = [] | ||
function replaceExpressionsWithPlaceholders(node) { | ||
if (t.isArrayExpression(node)) { | ||
return node.elements.map(replaceExpressionsWithPlaceholders) | ||
} else if (isLiteral(node)) { | ||
return node.value | ||
} else if (t.isTemplateLiteral(node)) { | ||
const strs = node.quasis.map(x => x.value.cooked) | ||
const exprs = node.expressions | ||
return reduce( | ||
strs, | ||
(arr, str, i) => { | ||
arr.push(str) | ||
if (i !== strs.length - 1) { | ||
expressions.push(exprs[i]) | ||
arr.push(`xxx${expressions.length - 1}xxx`) | ||
} | ||
return arr | ||
}, | ||
[] | ||
) | ||
.join('') | ||
.trim() | ||
} | ||
expressions.push(node) | ||
return `xxx${expressions.length - 1}xxx` | ||
} | ||
function convertAstToObj(astObj) { | ||
const props = [] | ||
forEach(astObj.properties, (property, i) => { | ||
let key | ||
if (t.isSpreadProperty(property)) { | ||
props.push({ | ||
key: null, | ||
value: null, | ||
computed: false, | ||
shorthand: false, | ||
spread: true, | ||
property | ||
}) | ||
return | ||
} | ||
if (property.computed) { | ||
key = replaceExpressionsWithPlaceholders(property.key) | ||
} else { | ||
key = t.isIdentifier(property.key) | ||
? property.key.name | ||
: property.key.value | ||
} | ||
// nested objects | ||
if (t.isObjectExpression(property.value)) { | ||
props.push({ | ||
key, | ||
value: convertAstToObj(property.value), | ||
computed: property.computed, | ||
spread: false, | ||
shorthand: false, | ||
property | ||
}) | ||
} else { | ||
props.push({ | ||
key, | ||
value: replaceExpressionsWithPlaceholders(property.value), | ||
computed: property.computed, | ||
spread: false, | ||
shorthand: false, | ||
property | ||
}) | ||
} | ||
}) | ||
return props | ||
} | ||
const objectProperties = convertAstToObj(prefixAst(astObj, t, path)) | ||
return new ASTObject( | ||
objectProperties, | ||
expressions, | ||
0, // composesCount: we should support this, | ||
t | ||
) | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import { keys, forEach } from 'emotion-utils' | ||
import { hashArray } from './index' | ||
@@ -35,5 +35,5 @@ export function getIdentifierName(path, t) { | ||
if (state.emotionImports === undefined) return | ||
forEach(keys(state.emotionImports), importPath => { | ||
Object.keys(state.emotionImports).forEach(importPath => { | ||
const importSpecifiers = [] | ||
forEach(keys(state.emotionImports[importPath]), importName => { | ||
Object.keys(state.emotionImports[importPath]).forEach(importName => { | ||
const identifier = state.emotionImports[importPath][importName] | ||
@@ -54,1 +54,68 @@ if (importName === 'default') { | ||
} | ||
export function getName(identifierName?: string, prefix: string): string { | ||
const parts = [] | ||
parts.push(prefix) | ||
if (identifierName) { | ||
parts.push(identifierName) | ||
} | ||
return parts.join('-') | ||
} | ||
export function createRawStringFromTemplateLiteral(quasi: { | ||
quasis: Array<{ value: { cooked: string } }> | ||
}): { src: string, dynamicValueCount: number } { | ||
let strs = quasi.quasis.map(x => x.value.cooked) | ||
let hash = hashArray([...strs]) | ||
const src = strs | ||
.reduce((arr, str, i) => { | ||
arr.push(str) | ||
if (i !== strs.length - 1) { | ||
arr.push(`xxx${i}xxx`) | ||
} | ||
return arr | ||
}, []) | ||
.join('') | ||
.trim() | ||
return { src, hash } | ||
} | ||
export function omit( | ||
obj: { [string]: any }, | ||
testFn: (key: string, obj: any) => boolean | ||
) { | ||
let target: { [string]: any } = {} | ||
let i: string | ||
for (i in obj) { | ||
if (!testFn(i, obj)) continue | ||
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue | ||
target[i] = obj[i] | ||
} | ||
return target | ||
} | ||
// babel-plugin-styled-components | ||
// https://github.com/styled-components/babel-plugin-styled-components/blob/8d44acc36f067d60d4e09f9c22ff89695bc332d2/src/minify/index.js | ||
const symbolRegex = /(\s*[;:{},]\s*)/g | ||
// Counts occurences of substr inside str | ||
const countOccurences = (str, substr) => str.split(substr).length - 1 | ||
export const minify = code => | ||
code.split(symbolRegex).reduce((str, fragment, index) => { | ||
// Even-indices are non-symbol fragments | ||
if (index % 2 === 0) { | ||
return str + fragment | ||
} | ||
// Only manipulate symbols outside of strings | ||
if ( | ||
countOccurences(str, "'") % 2 === 0 && | ||
countOccurences(str, '"') % 2 === 0 | ||
) { | ||
return str + fragment.trim() | ||
} | ||
return str + fragment | ||
}, '') |
@@ -50,4 +50,7 @@ export default function(path, state, t) { | ||
} | ||
if (!classNamesValue) { | ||
if ( | ||
!classNamesValue || | ||
(t.isStringLiteral(classNamesValue) && !classNamesValue.value) | ||
) { | ||
if (classNamesPath) classNamesPath.parentPath.remove() | ||
cssPath.parentPath.replaceWith(createClassNameAttr(cssTemplateExpression)) | ||
@@ -61,6 +64,8 @@ return | ||
createClassNameAttr( | ||
add( | ||
add(classNamesValue.expression, t.stringLiteral(' ')), | ||
cssTemplateExpression | ||
) | ||
t.callExpression(getMergeIdentifier(), [ | ||
add( | ||
cssTemplateExpression, | ||
add(t.stringLiteral(' '), classNamesValue.expression) | ||
) | ||
]) | ||
) | ||
@@ -72,7 +77,4 @@ ) | ||
add( | ||
add( | ||
t.stringLiteral(classNamesValue.value || ''), | ||
t.stringLiteral(' ') | ||
), | ||
cssTemplateExpression | ||
cssTemplateExpression, | ||
t.stringLiteral(` ${classNamesValue.value || ''}`) | ||
) | ||
@@ -97,5 +99,3 @@ ) | ||
if (!state.cssPropIdentifier) { | ||
state.cssPropIdentifier = path.scope.generateUidIdentifier( | ||
state.importedNames.css | ||
) | ||
state.cssPropIdentifier = path.hub.file.addImport('emotion', 'css') | ||
} | ||
@@ -107,2 +107,15 @@ return state.cssPropIdentifier | ||
} | ||
function getMergeIdentifier() { | ||
if (state.opts.autoImportCssProp !== false) { | ||
if (!state.cssPropMergeIdentifier) { | ||
state.cssPropMergeIdentifier = path.hub.file.addImport( | ||
'emotion', | ||
'merge' | ||
) | ||
} | ||
return state.cssPropMergeIdentifier | ||
} else { | ||
return t.identifier(state.importedNames.merge) | ||
} | ||
} | ||
function createCssTemplateExpression(templateLiteral) { | ||
@@ -109,0 +122,0 @@ return t.taggedTemplateExpression(getCssIdentifer(), templateLiteral) |
238
src/index.js
@@ -11,15 +11,18 @@ // @flow weak | ||
import { touchSync } from 'touch' | ||
import { inline, getName } from './inline' | ||
import { parseCSS } from './parser' | ||
import { getIdentifierName } from './babel-utils' | ||
import { hashArray, map } from 'emotion-utils' | ||
import { | ||
getIdentifierName, | ||
getName, | ||
createRawStringFromTemplateLiteral, | ||
minify | ||
} from './babel-utils' | ||
import { hashString, Stylis } from 'emotion-utils' | ||
import cssProps from './css-prop' | ||
import ASTObject from './ast-object' | ||
export function getFilename(path) { | ||
return path.hub.file.opts.filename === 'unknown' | ||
? '' | ||
: path.hub.file.opts.filename | ||
export function hashArray(arr) { | ||
return hashString(arr.join('')) | ||
} | ||
const staticStylis = new Stylis({ keyframe: false }) | ||
export function replaceCssWithCallExpression( | ||
@@ -30,16 +33,16 @@ path, | ||
t, | ||
staticCSSTextCreator = (name, hash, src) => `.${name}-${hash} { ${src} }`, | ||
removePath = false | ||
staticCSSSrcCreator = src => src, | ||
removePath = false, | ||
staticCSSSelectorCreator = (name, hash) => `.${name}-${hash}` | ||
) { | ||
try { | ||
const { name, hash, src } = inline( | ||
path.node.quasi, | ||
getIdentifierName(path, t), | ||
'css' | ||
) | ||
const { hash, src } = createRawStringFromTemplateLiteral(path.node.quasi) | ||
const name = getName(getIdentifierName(path, t), 'css') | ||
if (state.extractStatic && !path.node.quasi.expressions.length) { | ||
const cssText = staticCSSTextCreator(name, hash, src) | ||
const { staticCSSRules } = parseCSS(cssText, true, getFilename(path)) | ||
state.insertStaticRules(staticCSSRules) | ||
const staticCSSRules = staticStylis( | ||
staticCSSSelectorCreator(name, hash), | ||
staticCSSSrcCreator(src, name, hash) | ||
) | ||
state.insertStaticRules([staticCSSRules]) | ||
if (!removePath) { | ||
@@ -51,27 +54,11 @@ return path.replaceWith(t.stringLiteral(`${name}-${hash}`)) | ||
const { styles, composesCount } = parseCSS(src, false, getFilename(path)) | ||
if (!removePath) { | ||
path.addComment('leading', '#__PURE__') | ||
} | ||
const composeValues = path.node.quasi.expressions.slice(0, composesCount) | ||
const vars = path.node.quasi.expressions.slice(composesCount) | ||
path.replaceWith( | ||
t.callExpression(identifier, [ | ||
t.arrayExpression(composeValues), | ||
t.arrayExpression(vars), | ||
t.functionExpression( | ||
t.identifier('createEmotionStyledRules'), | ||
vars.map((x, i) => t.identifier(`x${i}`)), | ||
t.blockStatement([ | ||
t.returnStatement( | ||
t.arrayExpression([ | ||
ASTObject.fromJS(styles, composesCount, t).toAST() | ||
]) | ||
) | ||
]) | ||
) | ||
]) | ||
) | ||
path.node.quasi = new ASTObject( | ||
minify(src), | ||
path.node.quasi.expressions, | ||
t | ||
).toTemplateLiteral() | ||
path.node.tag = identifier | ||
} catch (e) { | ||
@@ -147,2 +134,8 @@ if (path) { | ||
const interleave = (strings, interpolations) => | ||
interpolations.reduce( | ||
(array, interp, i) => array.concat(interp, strings[i + 1]), | ||
[strings[0]] | ||
) | ||
export function buildStyledCallExpression(identifier, tag, path, state, t) { | ||
@@ -152,3 +145,3 @@ const identifierName = getIdentifierName(path, t) | ||
if (state.extractStatic && !path.node.quasi.expressions.length) { | ||
const { name, hash, src } = inline( | ||
const { hash, src } = createRawStringFromTemplateLiteral( | ||
path.node.quasi, | ||
@@ -158,37 +151,52 @@ identifierName, | ||
) | ||
const staticClassName = `css-${hash}` | ||
const staticCSSRules = staticStylis(`.${staticClassName}`, src) | ||
const cssText = `.${name}-${hash} { ${src} }` | ||
const { staticCSSRules } = parseCSS(cssText, true, getFilename(path)) | ||
state.insertStaticRules(staticCSSRules) | ||
return t.callExpression(identifier, [ | ||
tag, | ||
t.stringLiteral(getComponentId(state, name)), | ||
t.arrayExpression([t.stringLiteral(`${name}-${hash}`)]) | ||
]) | ||
state.insertStaticRules([staticCSSRules]) | ||
return t.callExpression( | ||
t.callExpression(identifier, [ | ||
tag, | ||
t.objectExpression([ | ||
t.objectProperty( | ||
t.identifier('id'), | ||
t.stringLiteral( | ||
getComponentId(state, getName(getIdentifierName(path, t), 'css')) | ||
) | ||
), | ||
t.objectProperty(t.identifier('e'), t.stringLiteral(staticClassName)) | ||
]) | ||
]), | ||
[] | ||
) | ||
} | ||
const { src, name } = inline(path.node.quasi, identifierName, 'css') | ||
const { src } = createRawStringFromTemplateLiteral(path.node.quasi) | ||
path.addComment('leading', '#__PURE__') | ||
const { styles, composesCount } = parseCSS(src, false, getFilename(path)) | ||
const templateLiteral = new ASTObject( | ||
minify(src), | ||
path.node.quasi.expressions, | ||
t | ||
).toTemplateLiteral() | ||
const objs = path.node.quasi.expressions.slice(0, composesCount) | ||
const vars = path.node.quasi.expressions.slice(composesCount) | ||
const args = [ | ||
tag, | ||
t.stringLiteral(getComponentId(state, name)), | ||
t.arrayExpression(objs), | ||
t.arrayExpression(vars), | ||
t.functionExpression( | ||
t.identifier('createEmotionStyledRules'), | ||
vars.map((x, i) => t.identifier(`x${i}`)), | ||
t.blockStatement([ | ||
t.returnStatement(ASTObject.fromJS(styles, composesCount, t).toAST()) | ||
const values = interleave( | ||
templateLiteral.quasis.map(node => t.stringLiteral(node.value.cooked)), | ||
path.node.quasi.expressions | ||
).filter(node => node.value !== '') | ||
return t.callExpression( | ||
t.callExpression(identifier, [ | ||
tag, | ||
t.objectExpression([ | ||
t.objectProperty( | ||
t.identifier('id'), | ||
t.stringLiteral( | ||
getComponentId(state, getName(getIdentifierName(path, t), 'css')) | ||
) | ||
) | ||
]) | ||
) | ||
] | ||
return t.callExpression(identifier, args) | ||
]), | ||
values | ||
) | ||
} | ||
@@ -200,37 +208,18 @@ | ||
: t.stringLiteral(path.node.callee.property.name) | ||
return t.callExpression(identifier, [ | ||
tag, | ||
t.stringLiteral( | ||
getComponentId(state, getName(getIdentifierName(path, t), 'css')) | ||
), | ||
t.arrayExpression( | ||
buildProcessedStylesFromObjectAST(path.node.arguments, path, t) | ||
) | ||
]) | ||
return t.callExpression( | ||
t.callExpression(identifier, [ | ||
tag, | ||
t.objectExpression([ | ||
t.objectProperty( | ||
t.identifier('id'), | ||
t.stringLiteral( | ||
getComponentId(state, getName(getIdentifierName(path, t), 'css')) | ||
) | ||
) | ||
]) | ||
]), | ||
path.node.arguments | ||
) | ||
} | ||
function buildProcessedStylesFromObjectAST(objectAST, path, t) { | ||
if (t.isObjectExpression(objectAST)) { | ||
return ASTObject.fromAST(objectAST, t, path).toAST() | ||
} | ||
if (t.isArrayExpression(objectAST)) { | ||
return t.arrayExpression( | ||
buildProcessedStylesFromObjectAST(objectAST.elements, path, t) | ||
) | ||
} | ||
if (Array.isArray(objectAST)) { | ||
return map(objectAST, obj => | ||
buildProcessedStylesFromObjectAST(obj, path, t) | ||
) | ||
} | ||
return objectAST | ||
} | ||
export function replaceCssObjectCallExpression(path, identifier, t) { | ||
const argWithStyles = path.node.arguments[0] | ||
const styles = buildProcessedStylesFromObjectAST(argWithStyles, path, t) | ||
path.replaceWith(t.callExpression(identifier, [styles])) | ||
} | ||
const visited = Symbol('visited') | ||
@@ -243,3 +232,4 @@ | ||
injectGlobal: 'injectGlobal', | ||
fontFace: 'fontFace' | ||
fontFace: 'fontFace', | ||
merge: 'merge' | ||
} | ||
@@ -271,3 +261,4 @@ | ||
'injectGlobal', | ||
'fontFace' | ||
'fontFace', | ||
'merge' | ||
].indexOf(v.imported) !== -1 | ||
@@ -323,15 +314,2 @@ ) | ||
} | ||
if (state.cssPropIdentifier) { | ||
path.node.body.unshift( | ||
t.importDeclaration( | ||
[ | ||
t.importSpecifier( | ||
state.cssPropIdentifier, | ||
t.identifier('css') | ||
) | ||
], | ||
t.stringLiteral('emotion') | ||
) | ||
) | ||
} | ||
} | ||
@@ -361,13 +339,2 @@ }, | ||
} | ||
if ( | ||
path.node.callee.name === state.importedNames.css && | ||
!path.node.arguments[1] && | ||
path.node.arguments[0] | ||
) { | ||
replaceCssObjectCallExpression( | ||
path, | ||
t.identifier(state.importedNames.css), | ||
t | ||
) | ||
} | ||
} catch (e) { | ||
@@ -380,2 +347,6 @@ throw path.buildCodeFrameError(e) | ||
TaggedTemplateExpression(path, state) { | ||
if (path[visited]) { | ||
return | ||
} | ||
path[visited] = true | ||
if ( | ||
@@ -421,3 +392,5 @@ // styled.h1`color:${color};` | ||
t, | ||
(name, hash, src) => `@keyframes ${name}-${hash} { ${src} }` | ||
(src, name, hash) => `@keyframes ${name}-${hash} { ${src} }`, | ||
false, | ||
() => '' | ||
) | ||
@@ -430,3 +403,3 @@ } else if (path.node.tag.name === state.importedNames.fontFace) { | ||
t, | ||
(name, hash, src) => `@font-face {${src}}`, | ||
(src, name, hash) => `@font-face {${src}}`, | ||
true | ||
@@ -440,4 +413,5 @@ ) | ||
t, | ||
(name, hash, src) => src, | ||
true | ||
undefined, | ||
true, | ||
() => '' | ||
) | ||
@@ -444,0 +418,0 @@ } |
@@ -5,5 +5,4 @@ import { | ||
} from './index' | ||
import { buildMacroRuntimeNode } from './babel-utils' | ||
import { buildMacroRuntimeNode, omit } from './babel-utils' | ||
import emotionMacro from './macro' | ||
import { omit } from 'emotion-utils' | ||
import { createMacro } from 'babel-macros' | ||
@@ -10,0 +9,0 @@ |
@@ -1,7 +0,3 @@ | ||
import { | ||
replaceCssWithCallExpression, | ||
replaceCssObjectCallExpression | ||
} from './index' | ||
import { replaceCssWithCallExpression } from './index' | ||
import { buildMacroRuntimeNode, addRuntimeImports } from './babel-utils' | ||
import { forEach, keys } from 'emotion-utils' | ||
import { createMacro } from 'babel-macros' | ||
@@ -13,3 +9,3 @@ | ||
if (!state.inline) state.inline = true | ||
forEach(keys(references), referenceKey => { | ||
Object.keys(references).forEach(referenceKey => { | ||
if (referenceKey === 'injectGlobal') { | ||
@@ -63,4 +59,2 @@ references.injectGlobal.forEach(injectGlobalReference => { | ||
replaceCssWithCallExpression(path, runtimeNode, state, t) | ||
} else if (!path.node.arguments[1] && path.node.arguments[0]) { | ||
replaceCssObjectCallExpression(path, runtimeNode, t) | ||
} else { | ||
@@ -67,0 +61,0 @@ cssReference.replaceWith(runtimeNode) |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
51865
13
1369
1
+ Addedemotion-utils@8.0.12(transitive)
- Removedasap@2.0.6(transitive)
- Removedcore-js@1.2.7(transitive)
- Removedemotion-utils@7.3.1(transitive)
- Removedencoding@0.1.13(transitive)
- Removedfbjs@0.8.18(transitive)
- Removediconv-lite@0.6.3(transitive)
- Removedis-stream@1.1.0(transitive)
- Removedisomorphic-fetch@2.2.1(transitive)
- Removedjs-tokens@4.0.0(transitive)
- Removedloose-envify@1.4.0(transitive)
- Removednode-fetch@1.7.3(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedpromise@7.3.1(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsetimmediate@1.0.5(transitive)
- Removedua-parser-js@0.7.38(transitive)
- Removedwhatwg-fetch@3.6.20(transitive)
Updatedemotion-utils@^8.0.0-0