UNPKG

@twstyled/babel-preset

Version:

Babel plugin for twstyled -- the full-featured Tailwind CSS + CSS in JS Compiler

151 lines (150 loc) 7.11 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getVisitorsPreprocessorTwVariant$ = exports.getVisitorsPreprocessorTw$ = exports.getVisitorsPreprocessorJsx = void 0; const util_1 = require("./util"); const visitors_preprocess_to_css_1 = __importDefault(require("./visitors-preprocess-to-css")); const visitors_preprocess_to_styled_1 = __importDefault(require("./visitors-preprocess-to-styled")); function getVisitorsPreprocess({ types: t }, options) { return { visitor: { Program: { enter(path, state) { const twqueue = []; const jsxKeysToQueue = Object.keys(options.jsxPreprocessors); // We need this transforms to run before anything else // So we traverse here instead of a in a visitor path.traverse({ ImportDeclaration: (p) => { visitorImportDeclaration({ types: t }, p, state); }, TaggedTemplateExpression: (path) => { const { tag } = path.node; if ( // hasImport(t, path.scope, state.file.opts.filename, 'tw', options) && t.isIdentifier(tag) && tag.name === 'tw') { twqueue.push(path); } }, JSXAttribute: (path) => { const { node } = path; if (t.isJSXAttribute(node) && t.isJSXIdentifier(node.name) && jsxKeysToQueue.indexOf(node.name.name) !== -1 && t.isJSXOpeningElement(path.parent)) { twqueue.push(path); } } }); twqueue.forEach((item) => { if (t.isTaggedTemplateExpression(item.node)) { const cssIdentifier = util_1.assureImport({ types: t }, state, 'css', '@twstyled/core'); item.replaceWith(util_1.wrapExpression({ types: t }, item.node, cssIdentifier.name)); } else { const tag = item.node.name.name; const processJSX = options.jsxPreprocessors[tag]; processJSX(item, state); } }); if (twqueue.length > 0) { path.scope.crawl(); } }, exit(nodePath, state) { /** noop */ } } } }; } exports.default = getVisitorsPreprocess; function visitorImportDeclaration({ types: t }, path, state) { if (!t.isLiteral(path.node.source, { value: '@twstyled/core' })) { return; } state.importDeclaration = path; state.importLocalNames = {}; let twImported; path.node.specifiers.forEach((specifier) => { // do not support default import if (!t.isImportSpecifier(specifier)) { return; } const importedName = specifier.imported.name; state.importLocalNames[importedName] = specifier.local.name; if (importedName === 'tw') { twImported = specifier; } }); if (twImported && !state.importLocalNames.css) { path.node.specifiers.push(t.importSpecifier(t.identifier('css'), t.identifier('css'))); state.importLocalNames.css = 'css'; } } function getVisitorsPreprocessorJsx({ types: t }, options) { return (item, state) => { const tag = item.node.name.name; if (tag !== 'tw' && tag !== 'css') { return; } if (!item.node.value) { return; } const css = util_1.prefixTemplateLiteral({ types: t }, util_1.asTemplateLiteral({ types: t }, item.node.value), tag === 'tw' ? '@tailwind ' : '', tag === 'tw' ? ';' : ''); const requiresComponent = css.expressions.length > 0 && css.expressions.some((value) => t.isArrowFunctionExpression(value) || t.isFunctionExpression(value)); if (requiresComponent) { return visitors_preprocess_to_styled_1.default({ types: t }, item, state, css); } else { return visitors_preprocess_to_css_1.default({ types: t }, item, state, css); } }; } exports.getVisitorsPreprocessorJsx = getVisitorsPreprocessorJsx; function getVisitorsPreprocessorTw$({ types: t }, options) { return (item, state) => { const tag = item.node.name.name.replace(/[-\$]$/, ''); let css; if (!item.node.value) { css = util_1.asTemplateLiteral({ types: t }, t.stringLiteral(`@tailwind ${tag};`)); } else if (t.isJSXExpressionContainer(item.node.value) && t.isUnaryExpression(item.node.value.expression) && item.node.value.expression.operator === '-' && t.isNumericLiteral(item.node.value.expression.argument)) { css = util_1.asTemplateLiteral({ types: t }, t.stringLiteral(`@tailwind -${tag}-${item.node.value.expression.argument.value};`)); } else { css = util_1.prefixTemplateLiteral({ types: t }, util_1.asTemplateLiteral({ types: t }, item.node.value), `@tailwind ${tag}-`, ';'); } return visitors_preprocess_to_css_1.default({ types: t }, item, state, css); }; } exports.getVisitorsPreprocessorTw$ = getVisitorsPreprocessorTw$; function getVisitorsPreprocessorTwVariant$({ types: t }, options) { return (item, state) => { const tag = item.node.name.name.replace(/[-\$]*$/, ''); let css; if (item.node.value && t.isJSXExpressionContainer(item.node.value) && item.node.value.expression && t.isArrayExpression(item.node.value.expression)) { css = util_1.asTemplateLiteralFromArray({ types: t }, tag === 'tw' ? ' ' : ` ${tag}:`, [...item.node.value.expression.elements]); css.quasis[0].value.raw = `@tailwind${css.quasis[0].value.raw}`; css.quasis[0].value.cooked = css.quasis[0].value.raw; css.quasis[css.quasis.length - 1].value.raw = `${css.quasis[css.quasis.length - 1].value.raw};`; css.quasis[css.quasis.length - 1].value.cooked = css.quasis[css.quasis.length - 1].value.raw; } else { throw new Error(`inline Tailwind variant ${tag} must be an array expression`); } return visitors_preprocess_to_css_1.default({ types: t }, item, state, css); }; } exports.getVisitorsPreprocessorTwVariant$ = getVisitorsPreprocessorTwVariant$;