@twstyled/babel-preset
Version:
Babel plugin for twstyled -- the full-featured Tailwind CSS + CSS in JS Compiler
151 lines (150 loc) • 7.11 kB
JavaScript
;
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$;