vite-plugin-vue-css-modules
Version:
✨ Ultimate solution for using CSS modules without any hassle. Automatic replacement for Vue templates and scripts
81 lines (80 loc) • 3.66 kB
JavaScript
import * as babelParser from "@babel/parser";
import babelTraverse from "@babel/traverse";
import { parseQuotedValue } from "./shared.js";
const quoteRotation = (attributeQuote) => {
return attributeQuote === '"' ? "'" : '"';
};
const generateModuleAccess = (path, module, contentOffset, sfcTransform) => {
if (module) {
const { node } = path;
const { range } = node;
const startOffset = contentOffset + range[0] - 1;
const endOffset = contentOffset + range[1] - 1;
sfcTransform.update(startOffset, endOffset, `${module}[${node.name}]`);
}
};
export const transformJsValue = (source, contentOffset, sfcTransform, attributeQuote, { preservePrefix, localNameGenerator, module }) => {
let ast = babelParser.parse(`(${source})`, {
ranges: true,
plugins: ["typescript"],
});
babelTraverse(ast, {
noScope: true,
Identifier(path) {
let { parentPath, node } = path;
if (parentPath.isExpressionStatement() ||
parentPath.isArrayExpression() ||
parentPath.isConditionalExpression({ consequent: node }) ||
parentPath.isConditionalExpression({ alternate: node })) {
generateModuleAccess(path, module, contentOffset, sfcTransform);
path.skip();
}
else if (parentPath.isObjectProperty({ key: node })) {
if (parentPath.node.computed) {
generateModuleAccess(path, module, contentOffset, sfcTransform);
}
else {
const { range } = node;
const startOffset = contentOffset + range[0] - 1;
const endOffset = contentOffset + range[1] - 1;
if (node.name.startsWith(preservePrefix)) {
sfcTransform.update(startOffset, endOffset, node.name.slice(preservePrefix.length));
}
else {
const transformedClass = localNameGenerator(node.name);
const selectedQuote = quoteRotation(attributeQuote);
const quotedTransformedClass = selectedQuote + transformedClass + selectedQuote;
sfcTransform.update(startOffset, endOffset, parentPath.node.shorthand
? `${quotedTransformedClass}: ${node.name}`
: quotedTransformedClass);
}
}
path.skip();
}
},
StringLiteral({ node, parentPath }) {
if (parentPath.isBinaryExpression() ||
parentPath.isCallExpression() ||
parentPath.isOptionalCallExpression())
return;
const { value } = parseQuotedValue(node.extra.raw);
const startOffset = contentOffset + node.range[0]
- 1
+ 1;
const endOffset = contentOffset + node.range[1] - 1 - 1;
if (value.startsWith(preservePrefix)) {
sfcTransform.update(startOffset, endOffset, value.slice(preservePrefix.length));
}
else {
sfcTransform.update(startOffset, endOffset, localNameGenerator(value));
}
},
TemplateElement(path) {
let { node } = path;
const startOffset = contentOffset + node.range[0] - 1;
const endOffset = contentOffset + node.range[1] - 1;
sfcTransform.update(startOffset, endOffset, localNameGenerator(node.value.raw));
path.skip();
},
});
};