UNPKG

manipulative

Version:

React devtool for modifying Emotion styles in browser

92 lines (75 loc) 3.48 kB
'use strict'; var t = require('@babel/types'); function processReferencePaths(referencePaths, state) { if (referencePaths !== undefined) { referencePaths.forEach(function (path) { var callExpressionNode = path.parentPath.node; if (!t.isCallExpression(callExpressionNode)) { return; } var filename = state.file.opts.filename; var start = callExpressionNode.start; if (filename != null && start != null) { callExpressionNode.arguments = [t.arrayExpression([t.stringLiteral(filename), t.numericLiteral(start)].concat(path.node.loc !== null ? [t.numericLiteral(path.node.loc.start.line), t.stringLiteral(state.file.code.split("\n")[path.node.loc.start.line - 1])] : []))]; } }); } } function babelPlugin() { return { visitor: { Program: function Program(path, state) { var needsImport = false; var USECSSPLACEHOLDER_IDENTIFIER_NAME = "useCssPlaceholder__INJECT"; var fileLines = state.file.code.split("\n"); // We're traversing here early before react-refresh does hook extraction. // https://github.com/facebook/react/blob/e6a0f276307fcb2f1c5bc41d630c5e4c9e95a037/packages/react-refresh/src/ReactFreshBabelPlugin.js#L721 path.traverse({ JSXAttribute: function JSXAttribute(path) { var propName = path.node.name; if (!t.isJSXIdentifier(propName) || propName.name !== "css__") { return; } needsImport = true; // TODO: check container for other props named css and warn propName.name = "css"; var filename = state.file.opts.filename; var start = path.node.start; path.node.value = t.jsxExpressionContainer(t.callExpression(t.identifier(USECSSPLACEHOLDER_IDENTIFIER_NAME), [t.arrayExpression([t.stringLiteral(filename), t.numericLiteral(start)].concat(path.node.loc !== null ? [t.numericLiteral(path.node.loc.start.line), t.stringLiteral(fileLines[path.node.loc.start.line - 1])] : []))])); } }); if (needsImport) { path.unshiftContainer("body", [t.importDeclaration([t.importSpecifier(t.identifier(USECSSPLACEHOLDER_IDENTIFIER_NAME), t.identifier("useCssPlaceholder"))], t.stringLiteral("manipulative"))]); } }, ImportDeclaration: function ImportDeclaration(path, state) { if (path.node.source.value !== "manipulative") { return; } var imports = path.node.specifiers.map(function (s) { return { localName: s.local.name, importedName: s.type === "ImportDefaultSpecifier" ? "default" : s.imported.name }; }); var shouldExit = false; var hasReferences = false; var referencePathsByImportName = imports.reduce(function (byName, _ref) { var importedName = _ref.importedName, localName = _ref.localName; var binding = path.scope.getBinding(localName); if (!binding) { shouldExit = true; return byName; } byName[importedName] = binding.referencePaths; hasReferences = hasReferences || Boolean(byName[importedName].length); return byName; }, {}); if (!hasReferences || shouldExit) { return; } processReferencePaths(referencePathsByImportName["useCssPlaceholder"], state); } } }; } module.exports = babelPlugin;