@yinxulai/babel-plugin-less
Version:
一个 `Babel` 插件,用来帮助你对文件中引用的 `less` 进行预处理、转换成 `css` 并自动管理, 支持 `cssModule`, `autoPrefix`
80 lines • 3.09 kB
JavaScript
import path from 'path';
import hash from './hash';
import * as t from '@babel/types';
import { execFileSync } from 'child_process';
import { insertStyleElement, styleTokenMap } from './template';
function isDevelopment() {
return process.env.NODE_ENV === 'development';
}
// 同步调用 PostCss 处理资源
function transformStyle(options) {
const isDev = isDevelopment();
const optionsStr = JSON.stringify(options);
const transform = path.resolve(__dirname, `./transform.${isDev ? 'ts' : 'js'}`);
const result = execFileSync(isDev ? 'ts-node' : 'node', [transform, optionsStr]);
return JSON.parse(result.toString());
}
function getImportDefaultSpecifier(node) {
const defaultImport = node.specifiers.find(s => t.isImportDefaultSpecifier(s));
if (t.isImportDefaultSpecifier(defaultImport)) {
return defaultImport;
}
return null;
}
function generateImportStyleAST(data, node) {
const nodeArray = [];
if (data.css) {
const elementID = hash(data.css);
nodeArray.push(insertStyleElement(elementID, data.css));
}
if (data.tokens) {
// 获取默认导入的信息
// import * from '*'
const defaultImport = getImportDefaultSpecifier(node);
// 用户没有默认导入
// TODO: 支持其他类型的导入
if (!defaultImport) {
return nodeArray;
}
// TODO: 考虑允许用户其他方式导入
const variableName = defaultImport.local.name;
nodeArray.push(styleTokenMap(variableName, data.tokens));
}
return nodeArray;
}
function plugin() {
return {
name: 'less',
// 语法转换
visitor: {
// import styles from './style.css';
ImportDeclaration: {
enter: function (data, state) {
const { source } = data.node;
const pluginOptions = state.opts;
const matcher = /(.less)|(.css)$/i;
const entryfile = state.file.opts.filename;
const importSourceliteralValue = source.value;
const styleFileName = path.resolve(path.dirname(entryfile), importSourceliteralValue);
// 匹配文件后缀
if (!matcher.test(importSourceliteralValue)) {
return;
}
// import '*'
// 关闭 css module
if (!data.node.specifiers.length) {
pluginOptions.cssModule = false;
}
// 转换 css
const result = transformStyle(Object.assign(Object.assign({}, pluginOptions), { fileName: styleFileName }));
// 生成 AST
const newImportAST = generateImportStyleAST(result, data.node);
// 替换当前节点
data.replaceWithMultiple(newImportAST);
}
},
}
};
}
export default plugin;
//# sourceMappingURL=index.js.map