Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

1119 строки
37 KiB

  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
  4. var nodePath = _interopDefault(require('path'));
  5. var sourceMap = require('source-map');
  6. var convert = _interopDefault(require('convert-source-map'));
  7. var findRoot = _interopDefault(require('find-root'));
  8. var memoize = _interopDefault(require('@emotion/memoize'));
  9. var hashString = _interopDefault(require('@emotion/hash'));
  10. var escapeRegexp = _interopDefault(require('escape-string-regexp'));
  11. var serialize = require('@emotion/serialize');
  12. var helperModuleImports = require('@babel/helper-module-imports');
  13. var babelPluginMacros = require('babel-plugin-macros');
  14. // babel-plugin-styled-components
  15. // https://github.com/styled-components/babel-plugin-styled-components/blob/8d44acc36f067d60d4e09f9c22ff89695bc332d2/src/minify/index.js
  16. var multilineCommentRegex = /\/\*[^!](.|[\r\n])*?\*\//g;
  17. var lineCommentStart = /\/\//g;
  18. var symbolRegex = /(\s*[;:{},]\s*)/g; // Counts occurences of substr inside str
  19. var countOccurences = function countOccurences(str, substr) {
  20. return str.split(substr).length - 1;
  21. }; // Joins substrings until predicate returns true
  22. var reduceSubstr = function reduceSubstr(substrs, join, predicate) {
  23. var length = substrs.length;
  24. var res = substrs[0];
  25. if (length === 1) {
  26. return res;
  27. }
  28. for (var i = 1; i < length; i++) {
  29. if (predicate(res)) {
  30. break;
  31. }
  32. res += join + substrs[i];
  33. }
  34. return res;
  35. }; // Joins at comment starts when it's inside a string or parantheses
  36. // effectively removing line comments
  37. var stripLineComment = function stripLineComment(line) {
  38. return reduceSubstr(line.split(lineCommentStart), '//', function (str) {
  39. return !str.endsWith(':') && // NOTE: This is another guard against urls, if they're not inside strings or parantheses.
  40. countOccurences(str, "'") % 2 === 0 && countOccurences(str, '"') % 2 === 0 && countOccurences(str, '(') === countOccurences(str, ')');
  41. });
  42. };
  43. var compressSymbols = function compressSymbols(code) {
  44. return code.split(symbolRegex).reduce(function (str, fragment, index) {
  45. // Even-indices are non-symbol fragments
  46. if (index % 2 === 0) {
  47. return str + fragment;
  48. } // Only manipulate symbols outside of strings
  49. if (countOccurences(str, "'") % 2 === 0 && countOccurences(str, '"') % 2 === 0) {
  50. return str + fragment.trim();
  51. }
  52. return str + fragment;
  53. }, '');
  54. }; // Detects lines that are exclusively line comments
  55. var isLineComment = function isLineComment(line) {
  56. return line.trim().startsWith('//');
  57. };
  58. var linebreakRegex = /[\r\n]\s*/g;
  59. var spacesAndLinebreakRegex = /\s+|\n+/g;
  60. function multilineReplacer(match) {
  61. // When we encounter a standard multi-line CSS comment and it contains a '@'
  62. // character, we keep the comment but optimize it into a single line. Some
  63. // Stylis plugins, such as the stylis-rtl via the cssjanus plugin, use this
  64. // special comment syntax to control behavior (such as: /* @noflip */).
  65. // We can do this with standard CSS comments because they will work with
  66. // compression, as opposed to non-standard single-line comments that will
  67. // break compressed CSS. If the comment doesn't contain '@', then we replace
  68. // it with a line break, which effectively removes it from the output.
  69. var keepComment = match.indexOf('@') > -1;
  70. if (keepComment) {
  71. return match.replace(spacesAndLinebreakRegex, ' ').trim();
  72. }
  73. return '\n';
  74. }
  75. var minify = function minify(code) {
  76. var newCode = code.replace(multilineCommentRegex, multilineReplacer) // If allowed, remove line breaks and extra space from multi-line comments so they appear on one line
  77. .split(linebreakRegex) // Split at newlines
  78. .filter(function (line) {
  79. return line.length > 0 && !isLineComment(line);
  80. }) // Removes lines containing only line comments
  81. .map(stripLineComment) // Remove line comments inside text
  82. .join(' '); // Rejoin all lines
  83. return compressSymbols(newCode);
  84. };
  85. function getExpressionsFromTemplateLiteral(node, t) {
  86. var raw = createRawStringFromTemplateLiteral(node);
  87. var minified = minify(raw);
  88. return replacePlaceholdersWithExpressions(minified, node.expressions || [], t);
  89. }
  90. var interleave = function interleave(strings, interpolations) {
  91. return interpolations.reduce(function (array, interp, i) {
  92. return array.concat([interp], strings[i + 1]);
  93. }, [strings[0]]);
  94. };
  95. function getDynamicMatches(str) {
  96. var re = /xxx(\d+)xxx/gm;
  97. var match;
  98. var matches = [];
  99. while ((match = re.exec(str)) !== null) {
  100. // so that flow doesn't complain
  101. if (match !== null) {
  102. matches.push({
  103. value: match[0],
  104. p1: parseInt(match[1], 10),
  105. index: match.index
  106. });
  107. }
  108. }
  109. return matches;
  110. }
  111. function replacePlaceholdersWithExpressions(str, expressions, t) {
  112. var matches = getDynamicMatches(str);
  113. if (matches.length === 0) {
  114. if (str === '') {
  115. return [];
  116. }
  117. return [t.stringLiteral(str)];
  118. }
  119. var strings = [];
  120. var finalExpressions = [];
  121. var cursor = 0;
  122. matches.forEach(function (_ref, i) {
  123. var value = _ref.value,
  124. p1 = _ref.p1,
  125. index = _ref.index;
  126. var preMatch = str.substring(cursor, index);
  127. cursor = cursor + preMatch.length + value.length;
  128. if (preMatch) {
  129. strings.push(t.stringLiteral(preMatch));
  130. } else if (i === 0) {
  131. strings.push(t.stringLiteral(''));
  132. }
  133. finalExpressions.push(expressions[p1]);
  134. if (i === matches.length - 1) {
  135. strings.push(t.stringLiteral(str.substring(index + value.length)));
  136. }
  137. });
  138. return interleave(strings, finalExpressions).filter(function (node) {
  139. return node.value !== '';
  140. });
  141. }
  142. function createRawStringFromTemplateLiteral(quasi) {
  143. var strs = quasi.quasis.map(function (x) {
  144. return x.value.cooked;
  145. });
  146. var src = strs.reduce(function (arr, str, i) {
  147. arr.push(str);
  148. if (i !== strs.length - 1) {
  149. arr.push("xxx" + i + "xxx");
  150. }
  151. return arr;
  152. }, []).join('').trim();
  153. return src;
  154. }
  155. var invalidClassNameCharacters = /[!"#$%&'()*+,./:;<=>?@[\]^`|}~{]/g;
  156. var sanitizeLabelPart = function sanitizeLabelPart(labelPart) {
  157. return labelPart.trim().replace(invalidClassNameCharacters, '-');
  158. };
  159. function getLabel(identifierName, autoLabel, labelFormat, filename) {
  160. if (!identifierName || !autoLabel) return null;
  161. if (!labelFormat) return sanitizeLabelPart(identifierName);
  162. var parsedPath = nodePath.parse(filename);
  163. var localDirname = nodePath.basename(parsedPath.dir);
  164. var localFilename = parsedPath.name;
  165. if (localFilename === 'index') {
  166. localFilename = localDirname;
  167. }
  168. return labelFormat.replace(/\[local\]/gi, sanitizeLabelPart(identifierName)).replace(/\[filename\]/gi, sanitizeLabelPart(localFilename)).replace(/\[dirname\]/gi, sanitizeLabelPart(localDirname));
  169. }
  170. function getLabelFromPath(path, state, t) {
  171. return getLabel(getIdentifierName(path, t), state.opts.autoLabel === undefined ? process.env.NODE_ENV !== 'production' : state.opts.autoLabel, state.opts.labelFormat, state.file.opts.filename);
  172. }
  173. var pascalCaseRegex = /^[A-Z][A-Za-z]+/;
  174. function getDeclaratorName(path, t) {
  175. // $FlowFixMe
  176. var parent = path.findParent(function (p) {
  177. return p.isVariableDeclarator() || p.isFunctionDeclaration() || p.isFunctionExpression() || p.isArrowFunctionExpression() || p.isObjectProperty();
  178. });
  179. if (!parent) {
  180. return '';
  181. } // we probably have a css call assigned to a variable
  182. // so we'll just return the variable name
  183. if (parent.isVariableDeclarator()) {
  184. if (t.isIdentifier(parent.node.id)) {
  185. return parent.node.id.name;
  186. }
  187. return '';
  188. } // we probably have an inline css prop usage
  189. if (parent.isFunctionDeclaration()) {
  190. var _name = parent.node.id.name;
  191. if (pascalCaseRegex.test(_name)) {
  192. return _name;
  193. }
  194. return '';
  195. } // we could also have an object property
  196. if (parent.isObjectProperty() && !parent.node.computed) {
  197. return parent.node.key.name;
  198. }
  199. var variableDeclarator = path.findParent(function (p) {
  200. return p.isVariableDeclarator();
  201. });
  202. if (!variableDeclarator) {
  203. return '';
  204. }
  205. var name = variableDeclarator.node.id.name;
  206. if (pascalCaseRegex.test(name)) {
  207. return name;
  208. }
  209. return '';
  210. }
  211. function getIdentifierName(path, t) {
  212. var classOrClassPropertyParent;
  213. if (t.isObjectProperty(path.parentPath) && path.parentPath.node.computed === false && (t.isIdentifier(path.parentPath.node.key) || t.isStringLiteral(path.parentPath.node.key))) {
  214. return path.parentPath.node.key.name || path.parentPath.node.key.value;
  215. }
  216. if (path) {
  217. // $FlowFixMe
  218. classOrClassPropertyParent = path.findParent(function (p) {
  219. return t.isClassProperty(p) || t.isClass(p);
  220. });
  221. }
  222. if (classOrClassPropertyParent) {
  223. if (t.isClassProperty(classOrClassPropertyParent) && classOrClassPropertyParent.node.computed === false && t.isIdentifier(classOrClassPropertyParent.node.key)) {
  224. return classOrClassPropertyParent.node.key.name;
  225. }
  226. if (t.isClass(classOrClassPropertyParent) && classOrClassPropertyParent.node.id) {
  227. return t.isIdentifier(classOrClassPropertyParent.node.id) ? classOrClassPropertyParent.node.id.name : '';
  228. }
  229. }
  230. var declaratorName = getDeclaratorName(path, t); // if the name starts with _ it was probably generated by babel so we should ignore it
  231. if (declaratorName.charAt(0) === '_') {
  232. return '';
  233. }
  234. return declaratorName;
  235. }
  236. function getGeneratorOpts(file) {
  237. return file.opts.generatorOpts ? file.opts.generatorOpts : file.opts;
  238. }
  239. function makeSourceMapGenerator(file) {
  240. var generatorOpts = getGeneratorOpts(file);
  241. var filename = generatorOpts.sourceFileName;
  242. var generator = new sourceMap.SourceMapGenerator({
  243. file: filename,
  244. sourceRoot: generatorOpts.sourceRoot
  245. });
  246. generator.setSourceContent(filename, file.code);
  247. return generator;
  248. }
  249. function getSourceMap(offset, state) {
  250. var generator = makeSourceMapGenerator(state.file);
  251. var generatorOpts = getGeneratorOpts(state.file);
  252. if (generatorOpts.sourceFileName && generatorOpts.sourceFileName !== 'unknown') {
  253. generator.addMapping({
  254. generated: {
  255. line: 1,
  256. column: 0
  257. },
  258. source: generatorOpts.sourceFileName,
  259. original: offset
  260. });
  261. return convert.fromObject(generator).toComment({
  262. multiline: true
  263. });
  264. }
  265. return '';
  266. }
  267. var hashArray = function hashArray(arr) {
  268. return hashString(arr.join(''));
  269. };
  270. var unsafeRequire = require;
  271. var getPackageRootPath = memoize(function (filename) {
  272. return findRoot(filename);
  273. });
  274. var separator = new RegExp(escapeRegexp(nodePath.sep), 'g');
  275. var normalizePath = function normalizePath(path) {
  276. return nodePath.normalize(path).replace(separator, '/');
  277. };
  278. function getTargetClassName(state, t) {
  279. if (state.emotionTargetClassNameCount === undefined) {
  280. state.emotionTargetClassNameCount = 0;
  281. }
  282. var hasFilepath = state.file.opts.filename && state.file.opts.filename !== 'unknown';
  283. var filename = hasFilepath ? state.file.opts.filename : ''; // normalize the file path to ignore folder structure
  284. // outside the current node project and arch-specific delimiters
  285. var moduleName = '';
  286. var rootPath = filename;
  287. try {
  288. rootPath = getPackageRootPath(filename);
  289. moduleName = unsafeRequire(rootPath + '/package.json').name;
  290. } catch (err) {}
  291. var finalPath = filename === rootPath ? 'root' : filename.slice(rootPath.length);
  292. var positionInFile = state.emotionTargetClassNameCount++;
  293. var stuffToHash = [moduleName];
  294. if (finalPath) {
  295. stuffToHash.push(normalizePath(finalPath));
  296. } else {
  297. stuffToHash.push(state.file.code);
  298. }
  299. var stableClassName = "e" + hashArray(stuffToHash) + positionInFile;
  300. return stableClassName;
  301. }
  302. // it's meant to simplify the most common cases so i don't want to make it especially complex
  303. // also, this will be unnecessary when prepack is ready
  304. function simplifyObject(node, t) {
  305. var finalString = '';
  306. for (var i = 0; i < node.properties.length; i++) {
  307. var _ref;
  308. var property = node.properties[i];
  309. if (!t.isObjectProperty(property) || property.computed || !t.isIdentifier(property.key) && !t.isStringLiteral(property.key) || !t.isStringLiteral(property.value) && !t.isNumericLiteral(property.value) && !t.isObjectExpression(property.value)) {
  310. return node;
  311. }
  312. var key = property.key.name || property.key.value;
  313. if (key === 'styles') {
  314. return node;
  315. }
  316. if (t.isObjectExpression(property.value)) {
  317. var simplifiedChild = simplifyObject(property.value, t);
  318. if (!t.isStringLiteral(simplifiedChild)) {
  319. return node;
  320. }
  321. finalString += key + "{" + simplifiedChild.value + "}";
  322. continue;
  323. }
  324. var value = property.value.value;
  325. finalString += serialize.serializeStyles([(_ref = {}, _ref[key] = value, _ref)]).styles;
  326. }
  327. return t.stringLiteral(finalString);
  328. }
  329. // this only works correctly in modules, but we don't run on scripts anyway, so it's fine
  330. // the difference is that in modules template objects are being cached per call site
  331. function getTypeScriptMakeTemplateObjectPath(path) {
  332. if (path.node.arguments.length === 0) {
  333. return null;
  334. }
  335. var firstArgPath = path.get('arguments')[0];
  336. if (firstArgPath.isLogicalExpression() && firstArgPath.get('left').isIdentifier() && firstArgPath.get('right').isAssignmentExpression() && firstArgPath.get('right.right').isCallExpression() && firstArgPath.get('right.right.callee').isIdentifier() && firstArgPath.node.right.right.callee.name.includes('makeTemplateObject') && firstArgPath.node.right.right.arguments.length === 2) {
  337. return firstArgPath.get('right.right');
  338. }
  339. return null;
  340. } // this is only used to prevent appending strings/expressions to arguments incorectly
  341. // we could push them to found array expressions, as we do it for TS-transpile output ¯\_(ツ)_/¯
  342. // it seems overly complicated though - mainly because we'd also have to check against existing stuff of a particular type (source maps & labels)
  343. // considering Babel double-transpilation as a valid use case seems rather far-fetched
  344. function isTaggedTemplateTranspiledByBabel(path) {
  345. if (path.node.arguments.length === 0) {
  346. return false;
  347. }
  348. var firstArgPath = path.get('arguments')[0];
  349. if (!firstArgPath.isCallExpression() || !firstArgPath.get('callee').isIdentifier()) {
  350. return false;
  351. }
  352. var calleeName = firstArgPath.node.callee.name;
  353. if (!calleeName.includes('templateObject')) {
  354. return false;
  355. }
  356. var bindingPath = path.scope.getBinding(calleeName).path;
  357. if (!bindingPath.isFunction()) {
  358. return false;
  359. }
  360. var functionBody = bindingPath.get('body.body');
  361. if (!functionBody[0].isVariableDeclaration()) {
  362. return false;
  363. }
  364. var declarationInit = functionBody[0].get('declarations')[0].get('init');
  365. if (!declarationInit.isCallExpression()) {
  366. return false;
  367. }
  368. var declarationInitArguments = declarationInit.get('arguments');
  369. if (declarationInitArguments.length === 0 || declarationInitArguments.length > 2 || declarationInitArguments.some(function (argPath) {
  370. return !argPath.isArrayExpression();
  371. })) {
  372. return false;
  373. }
  374. return true;
  375. }
  376. var appendStringToArguments = function appendStringToArguments(path, string, t) {
  377. if (!string) {
  378. return;
  379. }
  380. var args = path.node.arguments;
  381. if (t.isStringLiteral(args[args.length - 1])) {
  382. args[args.length - 1].value += string;
  383. } else {
  384. var makeTemplateObjectCallPath = getTypeScriptMakeTemplateObjectPath(path);
  385. if (makeTemplateObjectCallPath) {
  386. makeTemplateObjectCallPath.get('arguments').forEach(function (argPath) {
  387. var elements = argPath.get('elements');
  388. var lastElement = elements[elements.length - 1];
  389. lastElement.replaceWith(t.stringLiteral(lastElement.node.value + string));
  390. });
  391. } else if (!isTaggedTemplateTranspiledByBabel(path)) {
  392. args.push(t.stringLiteral(string));
  393. }
  394. }
  395. };
  396. var joinStringLiterals = function joinStringLiterals(expressions, t) {
  397. return expressions.reduce(function (finalExpressions, currentExpression, i) {
  398. if (!t.isStringLiteral(currentExpression)) {
  399. finalExpressions.push(currentExpression);
  400. } else if (t.isStringLiteral(finalExpressions[finalExpressions.length - 1])) {
  401. finalExpressions[finalExpressions.length - 1].value += currentExpression.value;
  402. } else {
  403. finalExpressions.push(currentExpression);
  404. }
  405. return finalExpressions;
  406. }, []);
  407. };
  408. var CSS_OBJECT_STRINGIFIED_ERROR = "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; // with babel@6 fallback
  409. var cloneNode = function cloneNode(t, node) {
  410. return typeof t.cloneNode === 'function' ? t.cloneNode(node) : t.cloneDeep(node);
  411. };
  412. function createSourceMapConditional(t, production, development) {
  413. return t.conditionalExpression(t.binaryExpression('===', t.memberExpression(t.memberExpression(t.identifier('process'), t.identifier('env')), t.identifier('NODE_ENV')), t.stringLiteral('production')), production, development);
  414. }
  415. var transformExpressionWithStyles = function transformExpressionWithStyles(_ref) {
  416. var babel = _ref.babel,
  417. state = _ref.state,
  418. path = _ref.path,
  419. shouldLabel = _ref.shouldLabel,
  420. _ref$sourceMap = _ref.sourceMap,
  421. sourceMap = _ref$sourceMap === void 0 ? '' : _ref$sourceMap;
  422. var t = babel.types;
  423. if (t.isTaggedTemplateExpression(path)) {
  424. var expressions = getExpressionsFromTemplateLiteral(path.node.quasi, t);
  425. if (state.emotionSourceMap && path.node.quasi.loc !== undefined) {
  426. sourceMap = getSourceMap(path.node.quasi.loc.start, state);
  427. }
  428. path.replaceWith(t.callExpression(path.node.tag, expressions));
  429. }
  430. if (t.isCallExpression(path)) {
  431. var canAppendStrings = path.node.arguments.every(function (arg) {
  432. return arg.type !== 'SpreadElement';
  433. });
  434. if (canAppendStrings && shouldLabel) {
  435. var label = getLabelFromPath(path, state, t);
  436. if (label) {
  437. appendStringToArguments(path, ";label:" + label + ";", t);
  438. }
  439. }
  440. path.get('arguments').forEach(function (node) {
  441. if (t.isObjectExpression(node)) {
  442. node.replaceWith(simplifyObject(node.node, t));
  443. }
  444. });
  445. path.node.arguments = joinStringLiterals(path.node.arguments, t);
  446. if (canAppendStrings && state.emotionSourceMap && !sourceMap && path.node.loc !== undefined) {
  447. sourceMap = getSourceMap(path.node.loc.start, state);
  448. }
  449. if (path.node.arguments.length === 1 && t.isStringLiteral(path.node.arguments[0])) {
  450. var cssString = path.node.arguments[0].value;
  451. var res = serialize.serializeStyles([cssString]);
  452. var prodNode = t.objectExpression([t.objectProperty(t.identifier('name'), t.stringLiteral(res.name)), t.objectProperty(t.identifier('styles'), t.stringLiteral(res.styles))]);
  453. var node = prodNode;
  454. if (sourceMap) {
  455. if (!state.emotionStringifiedCssId) {
  456. var uid = state.file.scope.generateUidIdentifier('__EMOTION_STRINGIFIED_CSS_ERROR__');
  457. state.emotionStringifiedCssId = uid;
  458. var cssObjectToString = t.functionDeclaration(uid, [], t.blockStatement([t.returnStatement(t.stringLiteral(CSS_OBJECT_STRINGIFIED_ERROR))]));
  459. cssObjectToString._compact = true;
  460. state.file.path.unshiftContainer('body', [cssObjectToString]);
  461. }
  462. var devNode = t.objectExpression([t.objectProperty(t.identifier('name'), t.stringLiteral(res.name)), t.objectProperty(t.identifier('styles'), t.stringLiteral(res.styles)), t.objectProperty(t.identifier('map'), t.stringLiteral(sourceMap)), t.objectProperty(t.identifier('toString'), cloneNode(t, state.emotionStringifiedCssId))]);
  463. node = createSourceMapConditional(t, prodNode, devNode);
  464. }
  465. return node;
  466. }
  467. if (sourceMap) {
  468. var lastIndex = path.node.arguments.length - 1;
  469. var last = path.node.arguments[lastIndex];
  470. var sourceMapConditional = createSourceMapConditional(t, t.stringLiteral(''), t.stringLiteral(sourceMap));
  471. if (t.isStringLiteral(last)) {
  472. path.node.arguments[lastIndex] = t.binaryExpression('+', last, sourceMapConditional);
  473. } else {
  474. var makeTemplateObjectCallPath = getTypeScriptMakeTemplateObjectPath(path);
  475. if (makeTemplateObjectCallPath) {
  476. var sourceMapId = state.file.scope.generateUidIdentifier('emotionSourceMap');
  477. var sourceMapDeclaration = t.variableDeclaration('var', [t.variableDeclarator(sourceMapId, sourceMapConditional)]);
  478. sourceMapDeclaration._compact = true;
  479. state.file.path.unshiftContainer('body', [sourceMapDeclaration]);
  480. makeTemplateObjectCallPath.get('arguments').forEach(function (argPath) {
  481. var elements = argPath.get('elements');
  482. var lastElement = elements[elements.length - 1];
  483. lastElement.replaceWith(t.binaryExpression('+', lastElement.node, cloneNode(t, sourceMapId)));
  484. });
  485. } else if (!isTaggedTemplateTranspiledByBabel(path)) {
  486. path.node.arguments.push(sourceMapConditional);
  487. }
  488. }
  489. }
  490. }
  491. };
  492. var getKnownProperties = function getKnownProperties(t, node) {
  493. return new Set(node.properties.filter(function (n) {
  494. return t.isObjectProperty(n) && !n.computed;
  495. }).map(function (n) {
  496. return t.isIdentifier(n.key) ? n.key.name : n.key.value;
  497. }));
  498. };
  499. var getStyledOptions = function getStyledOptions(t, path, state) {
  500. var args = path.node.arguments;
  501. var optionsArgument = args.length >= 2 ? args[1] : null;
  502. var properties = [];
  503. var knownProperties = optionsArgument && t.isObjectExpression(optionsArgument) ? getKnownProperties(t, optionsArgument) : new Set();
  504. if (!knownProperties.has('target')) {
  505. properties.push(t.objectProperty(t.identifier('target'), t.stringLiteral(getTargetClassName(state))));
  506. }
  507. var label = getLabelFromPath(path, state, t);
  508. if (label && !knownProperties.has('label')) {
  509. properties.push(t.objectProperty(t.identifier('label'), t.stringLiteral(label)));
  510. }
  511. if (optionsArgument) {
  512. if (!t.isObjectExpression(optionsArgument)) {
  513. return t.callExpression(state.file.addHelper('extends'), [t.objectExpression([]), t.objectExpression(properties), optionsArgument]);
  514. }
  515. properties.unshift.apply(properties, optionsArgument.properties);
  516. }
  517. return t.objectExpression( // $FlowFixMe
  518. properties);
  519. };
  520. var createEmotionMacro = function createEmotionMacro(instancePath) {
  521. return babelPluginMacros.createMacro(function macro(_ref) {
  522. var references = _ref.references,
  523. state = _ref.state,
  524. babel = _ref.babel,
  525. isEmotionCall = _ref.isEmotionCall;
  526. if (!isEmotionCall) {
  527. state.emotionSourceMap = true;
  528. }
  529. var t = babel.types;
  530. Object.keys(references).forEach(function (referenceKey) {
  531. var isPure = true;
  532. var runtimeNode = helperModuleImports.addNamed(state.file.path, referenceKey, instancePath);
  533. switch (referenceKey) {
  534. case 'injectGlobal':
  535. {
  536. isPure = false;
  537. }
  538. // eslint-disable-next-line no-fallthrough
  539. case 'css':
  540. case 'keyframes':
  541. {
  542. references[referenceKey].reverse().forEach(function (reference) {
  543. var path = reference.parentPath;
  544. reference.replaceWith(t.cloneDeep(runtimeNode));
  545. if (isPure) {
  546. path.addComment('leading', '#__PURE__');
  547. }
  548. var node = transformExpressionWithStyles({
  549. babel: babel,
  550. state: state,
  551. path: path,
  552. shouldLabel: true
  553. });
  554. if (node) {
  555. path.node.arguments[0] = node;
  556. }
  557. });
  558. break;
  559. }
  560. default:
  561. {
  562. references[referenceKey].reverse().forEach(function (reference) {
  563. reference.replaceWith(t.cloneDeep(runtimeNode));
  564. });
  565. }
  566. }
  567. });
  568. });
  569. };
  570. var createStyledMacro = function createStyledMacro(_ref) {
  571. var importPath = _ref.importPath,
  572. _ref$originalImportPa = _ref.originalImportPath,
  573. originalImportPath = _ref$originalImportPa === void 0 ? importPath : _ref$originalImportPa,
  574. isWeb = _ref.isWeb;
  575. return babelPluginMacros.createMacro(function (_ref2) {
  576. var references = _ref2.references,
  577. state = _ref2.state,
  578. babel = _ref2.babel,
  579. isEmotionCall = _ref2.isEmotionCall;
  580. if (!isEmotionCall) {
  581. state.emotionSourceMap = true;
  582. }
  583. var t = babel.types;
  584. if (references["default"] && references["default"].length) {
  585. var _styledIdentifier;
  586. var getStyledIdentifier = function getStyledIdentifier() {
  587. if (_styledIdentifier === undefined) {
  588. _styledIdentifier = helperModuleImports.addDefault(state.file.path, importPath, {
  589. nameHint: 'styled'
  590. });
  591. }
  592. return t.cloneDeep(_styledIdentifier);
  593. };
  594. var originalImportPathStyledIdentifier;
  595. var getOriginalImportPathStyledIdentifier = function getOriginalImportPathStyledIdentifier() {
  596. if (originalImportPathStyledIdentifier === undefined) {
  597. originalImportPathStyledIdentifier = helperModuleImports.addDefault(state.file.path, originalImportPath, {
  598. nameHint: 'styled'
  599. });
  600. }
  601. return t.cloneDeep(originalImportPathStyledIdentifier);
  602. };
  603. if (importPath === originalImportPath) {
  604. getOriginalImportPathStyledIdentifier = getStyledIdentifier;
  605. }
  606. references["default"].forEach(function (reference) {
  607. var isCall = false;
  608. if (t.isMemberExpression(reference.parent) && reference.parent.computed === false) {
  609. isCall = true;
  610. if ( // checks if the first character is lowercase
  611. // becasue we don't want to transform the member expression if
  612. // it's in primitives/native
  613. reference.parent.property.name.charCodeAt(0) > 96) {
  614. reference.parentPath.replaceWith(t.callExpression(getStyledIdentifier(), [t.stringLiteral(reference.parent.property.name)]));
  615. } else {
  616. reference.replaceWith(getStyledIdentifier());
  617. }
  618. } else if (reference.parentPath && reference.parentPath.parentPath && t.isCallExpression(reference.parentPath) && reference.parent.callee === reference.node) {
  619. isCall = true;
  620. reference.replaceWith(getStyledIdentifier());
  621. } else {
  622. reference.replaceWith(getOriginalImportPathStyledIdentifier());
  623. }
  624. if (reference.parentPath && reference.parentPath.parentPath) {
  625. var styledCallPath = reference.parentPath.parentPath;
  626. var node = transformExpressionWithStyles({
  627. path: styledCallPath,
  628. state: state,
  629. babel: babel,
  630. shouldLabel: false
  631. });
  632. if (node && isWeb) {
  633. // we know the argument length will be 1 since that's the only time we will have a node since it will be static
  634. styledCallPath.node.arguments[0] = node;
  635. }
  636. }
  637. if (isCall) {
  638. reference.addComment('leading', '#__PURE__');
  639. if (isWeb) {
  640. reference.parentPath.node.arguments[1] = getStyledOptions(t, reference.parentPath, state);
  641. }
  642. }
  643. });
  644. }
  645. Object.keys(references).filter(function (x) {
  646. return x !== 'default';
  647. }).forEach(function (referenceKey) {
  648. var runtimeNode = helperModuleImports.addNamed(state.file.path, referenceKey, importPath);
  649. references[referenceKey].reverse().forEach(function (reference) {
  650. reference.replaceWith(t.cloneDeep(runtimeNode));
  651. });
  652. });
  653. });
  654. };
  655. var transformCssCallExpression = function transformCssCallExpression(_ref) {
  656. var babel = _ref.babel,
  657. state = _ref.state,
  658. path = _ref.path,
  659. sourceMap = _ref.sourceMap;
  660. var node = transformExpressionWithStyles({
  661. babel: babel,
  662. state: state,
  663. path: path,
  664. shouldLabel: true,
  665. sourceMap: sourceMap
  666. });
  667. if (node) {
  668. path.replaceWith(node);
  669. path.hoist();
  670. } else if (path.isCallExpression()) {
  671. path.addComment('leading', '#__PURE__');
  672. }
  673. };
  674. var cssMacro = babelPluginMacros.createMacro(function (_ref2) {
  675. var references = _ref2.references,
  676. state = _ref2.state,
  677. babel = _ref2.babel,
  678. isEmotionCall = _ref2.isEmotionCall;
  679. if (!isEmotionCall) {
  680. state.emotionSourceMap = true;
  681. }
  682. var t = babel.types;
  683. if (references["default"] && references["default"].length) {
  684. references["default"].reverse().forEach(function (reference) {
  685. if (!state.cssIdentifier) {
  686. state.cssIdentifier = helperModuleImports.addDefault(reference, '@emotion/css', {
  687. nameHint: 'css'
  688. });
  689. }
  690. reference.replaceWith(t.cloneDeep(state.cssIdentifier));
  691. transformCssCallExpression({
  692. babel: babel,
  693. state: state,
  694. path: reference.parentPath
  695. });
  696. });
  697. }
  698. Object.keys(references).filter(function (x) {
  699. return x !== 'default';
  700. }).forEach(function (referenceKey) {
  701. var runtimeNode = helperModuleImports.addNamed(state.file.path, referenceKey, '@emotion/css', {
  702. nameHint: referenceKey
  703. });
  704. references[referenceKey].reverse().forEach(function (reference) {
  705. reference.replaceWith(t.cloneDeep(runtimeNode));
  706. });
  707. });
  708. });
  709. var webStyledMacro = createStyledMacro({
  710. importPath: '@emotion/styled-base',
  711. originalImportPath: '@emotion/styled',
  712. isWeb: true
  713. });
  714. var nativeStyledMacro = createStyledMacro({
  715. importPath: '@emotion/native',
  716. originalImportPath: '@emotion/native',
  717. isWeb: false
  718. });
  719. var primitivesStyledMacro = createStyledMacro({
  720. importPath: '@emotion/primitives',
  721. originalImportPath: '@emotion/primitives',
  722. isWeb: false
  723. });
  724. var macros = {
  725. createEmotionMacro: createEmotionMacro,
  726. css: cssMacro,
  727. createStyledMacro: createStyledMacro
  728. };
  729. var emotionCoreMacroThatsNotARealMacro = function emotionCoreMacroThatsNotARealMacro(_ref) {
  730. var references = _ref.references,
  731. state = _ref.state,
  732. babel = _ref.babel;
  733. Object.keys(references).forEach(function (refKey) {
  734. if (refKey === 'css') {
  735. references[refKey].forEach(function (path) {
  736. transformCssCallExpression({
  737. babel: babel,
  738. state: state,
  739. path: path.parentPath
  740. });
  741. });
  742. }
  743. });
  744. };
  745. emotionCoreMacroThatsNotARealMacro.keepImport = true;
  746. function getAbsolutePath(instancePath, rootPath) {
  747. if (instancePath.charAt(0) === '.') {
  748. var absoluteInstancePath = nodePath.resolve(rootPath, instancePath);
  749. return absoluteInstancePath;
  750. }
  751. return false;
  752. }
  753. function getInstancePathToCompare(instancePath, rootPath) {
  754. var absolutePath = getAbsolutePath(instancePath, rootPath);
  755. if (absolutePath === false) {
  756. return instancePath;
  757. }
  758. return absolutePath;
  759. }
  760. function index (babel) {
  761. var t = babel.types;
  762. return {
  763. name: 'emotion',
  764. inherits: require('babel-plugin-syntax-jsx'),
  765. visitor: {
  766. ImportDeclaration: function ImportDeclaration(path, state) {
  767. var hasFilepath = path.hub.file.opts.filename && path.hub.file.opts.filename !== 'unknown';
  768. var dirname = hasFilepath ? nodePath.dirname(path.hub.file.opts.filename) : '';
  769. if (!state.pluginMacros[path.node.source.value] && state.emotionInstancePaths.indexOf(getInstancePathToCompare(path.node.source.value, dirname)) !== -1) {
  770. state.pluginMacros[path.node.source.value] = createEmotionMacro(path.node.source.value);
  771. }
  772. var pluginMacros = state.pluginMacros; // most of this is from https://github.com/kentcdodds/babel-plugin-macros/blob/master/src/index.js
  773. if (pluginMacros[path.node.source.value] === undefined) {
  774. return;
  775. }
  776. if (t.isImportNamespaceSpecifier(path.node.specifiers[0])) {
  777. return;
  778. }
  779. var imports = path.node.specifiers.map(function (s) {
  780. return {
  781. localName: s.local.name,
  782. importedName: s.type === 'ImportDefaultSpecifier' ? 'default' : s.imported.name
  783. };
  784. });
  785. var shouldExit = false;
  786. var hasReferences = false;
  787. var referencePathsByImportName = imports.reduce(function (byName, _ref2) {
  788. var importedName = _ref2.importedName,
  789. localName = _ref2.localName;
  790. var binding = path.scope.getBinding(localName);
  791. if (!binding) {
  792. shouldExit = true;
  793. return byName;
  794. }
  795. byName[importedName] = binding.referencePaths;
  796. hasReferences = hasReferences || Boolean(byName[importedName].length);
  797. return byName;
  798. }, {});
  799. if (!hasReferences || shouldExit) {
  800. return;
  801. }
  802. /**
  803. * Other plugins that run before babel-plugin-macros might use path.replace, where a path is
  804. * put into its own replacement. Apparently babel does not update the scope after such
  805. * an operation. As a remedy, the whole scope is traversed again with an empty "Identifier"
  806. * visitor - this makes the problem go away.
  807. *
  808. * See: https://github.com/kentcdodds/import-all.macro/issues/7
  809. */
  810. state.file.scope.path.traverse({
  811. Identifier: function Identifier() {}
  812. });
  813. pluginMacros[path.node.source.value]({
  814. references: referencePathsByImportName,
  815. state: state,
  816. babel: babel,
  817. isBabelMacrosCall: true,
  818. isEmotionCall: true
  819. });
  820. if (!pluginMacros[path.node.source.value].keepImport) {
  821. path.remove();
  822. }
  823. },
  824. Program: function Program(path, state) {
  825. state.emotionInstancePaths = (state.opts.instances || []).map(function (instancePath) {
  826. return getInstancePathToCompare(instancePath, process.cwd());
  827. });
  828. state.pluginMacros = {
  829. '@emotion/css': cssMacro,
  830. '@emotion/styled': webStyledMacro,
  831. '@emotion/core': emotionCoreMacroThatsNotARealMacro,
  832. '@emotion/primitives': primitivesStyledMacro,
  833. '@emotion/native': nativeStyledMacro,
  834. emotion: createEmotionMacro('emotion')
  835. };
  836. if (state.opts.cssPropOptimization === undefined) {
  837. for (var _iterator = path.node.body, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
  838. var _ref3;
  839. if (_isArray) {
  840. if (_i >= _iterator.length) break;
  841. _ref3 = _iterator[_i++];
  842. } else {
  843. _i = _iterator.next();
  844. if (_i.done) break;
  845. _ref3 = _i.value;
  846. }
  847. var node = _ref3;
  848. if (t.isImportDeclaration(node) && node.source.value === '@emotion/core' && node.specifiers.some(function (x) {
  849. return t.isImportSpecifier(x) && x.imported.name === 'jsx';
  850. })) {
  851. state.transformCssProp = true;
  852. break;
  853. }
  854. }
  855. } else {
  856. state.transformCssProp = state.opts.cssPropOptimization;
  857. }
  858. if (state.opts.sourceMap === false) {
  859. state.emotionSourceMap = false;
  860. } else {
  861. state.emotionSourceMap = true;
  862. }
  863. },
  864. JSXAttribute: function JSXAttribute(path, state) {
  865. if (path.node.name.name !== 'css' || !state.transformCssProp) {
  866. return;
  867. }
  868. if (t.isJSXExpressionContainer(path.node.value) && (t.isObjectExpression(path.node.value.expression) || t.isArrayExpression(path.node.value.expression))) {
  869. var expressionPath = path.get('value.expression');
  870. var sourceMap = state.emotionSourceMap && path.node.loc !== undefined ? getSourceMap(path.node.loc.start, state) : '';
  871. expressionPath.replaceWith(t.callExpression( // the name of this identifier doesn't really matter at all
  872. // it'll never appear in generated code
  873. t.identifier('___shouldNeverAppearCSS'), [path.node.value.expression]));
  874. transformCssCallExpression({
  875. babel: babel,
  876. state: state,
  877. path: expressionPath,
  878. sourceMap: sourceMap
  879. });
  880. if (t.isCallExpression(expressionPath)) {
  881. if (!state.cssIdentifier) {
  882. state.cssIdentifier = helperModuleImports.addDefault(path, '@emotion/css', {
  883. nameHint: 'css'
  884. });
  885. }
  886. expressionPath.get('callee').replaceWith(t.cloneDeep(state.cssIdentifier));
  887. }
  888. }
  889. },
  890. CallExpression: {
  891. exit: function exit(path, state) {
  892. try {
  893. if (path.node.callee && path.node.callee.property && path.node.callee.property.name === 'withComponent') {
  894. switch (path.node.arguments.length) {
  895. case 1:
  896. case 2:
  897. {
  898. path.node.arguments[1] = getStyledOptions(t, path, state);
  899. }
  900. }
  901. }
  902. } catch (e) {
  903. throw path.buildCodeFrameError(e);
  904. }
  905. }
  906. }
  907. }
  908. };
  909. }
  910. exports.default = index;
  911. exports.macros = macros;