vite-plugin-vue-css-modules
Version:
✨ Ultimate solution for using CSS modules without any hassle. Automatic replacement for Vue templates and scripts
101 lines (100 loc) • 4.42 kB
JavaScript
import { createRequire } from "module";
const require = createRequire(import.meta.url);
import { transformJsValue } from "./transformJsValue.js";
import { parseQuotedValue } from "./shared.js";
let lex;
const resolveLex = () => {
if (!lex) {
lex = require("pug-lexer");
}
};
const getOffset = (lines, pos, localOffset) => {
let offset = localOffset;
for (let l = 1; l < pos.line; l += 1) {
offset += lines[l - 1].length;
}
offset += lines[pos.line - 1].slice(0, pos.column - 1).length;
return offset;
};
const getRange = (lines, loc, localOffset) => {
return [
getOffset(lines, loc.start, localOffset),
getOffset(lines, loc.end, localOffset),
];
};
export const transformPug = (source, contentOffset, sfcTransform, { preservePrefix, localNameGenerator, module }) => {
resolveLex();
let lines = source.split(/(?<=\r?\n)/g);
let tokens = lex(source);
tokens.forEach(t => {
switch (t.type) {
case "class":
case "id":
{
let value = t.val;
t.loc.start.column += 1;
let range = getRange(lines, t.loc, contentOffset);
if (value.startsWith(preservePrefix)) {
sfcTransform.update(...range, value.slice(preservePrefix.length));
}
else {
sfcTransform.update(...range, localNameGenerator(value));
}
}
break;
case "attribute":
{
if (!t.val)
return;
switch (t.name) {
case "class":
case "id":
{
let range = getRange(lines, t.loc, contentOffset);
let { quote, value } = parseQuotedValue(t.val);
const startOffset = range[1] - quote.length - value.length;
const rgx = /\S+/g;
let matchResult = rgx.exec(value);
while (matchResult) {
const [match] = matchResult;
let name = match.startsWith(preservePrefix)
? match.slice(preservePrefix.length)
: localNameGenerator(match);
sfcTransform.update(startOffset + matchResult.index, startOffset + matchResult.index + match.length, name);
matchResult = rgx.exec(value);
}
}
break;
case ":class":
case ":id":
case "v-bind:class":
case "v-bind:id":
{
let [startOffset, endOffset] = getRange(lines, t.loc, contentOffset);
let { value, quote } = parseQuotedValue(t.val);
transformJsValue(value, endOffset - quote.length - value.length, sfcTransform, quote, {
preservePrefix,
localNameGenerator,
module,
});
}
break;
case `${preservePrefix}class`:
case `${preservePrefix}id`:
case `:${preservePrefix}class`:
case `:${preservePrefix}id`:
{
let loc = t.loc;
loc.end.line = loc.start.line;
loc.end.column = loc.start.column + t.name.length;
let range = getRange(lines, loc, contentOffset);
let name = t.name.replace(new RegExp(`(?<=^:?)${preservePrefix}`), "");
sfcTransform.update(...range, name);
}
break;
}
}
break;
}
});
};