transform-to-unocss
Version:
🚀 Effortlessly transform CSS, inline styles, and preprocessors (Sass/Less/Stylus) to UnoCSS with smart conflict resolution and debug support
1,214 lines (1,199 loc) • 61.3 kB
JavaScript
"use strict";
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
const node_fs = __toESM(require("node:fs"));
const node_path = __toESM(require("node:path"));
const node_process = __toESM(require("node:process"));
const __unocss_core = __toESM(require("@unocss/core"));
const __unocss_preset_uno = __toESM(require("@unocss/preset-uno"));
const node_fs_promises = __toESM(require("node:fs/promises"));
const transform_to_unocss_core = __toESM(require("transform-to-unocss-core"));
const node_html_parser = __toESM(require("node-html-parser"));
const __babel_core = __toESM(require("@babel/core"));
const __vue_babel_plugin_jsx = __toESM(require("@vue/babel-plugin-jsx"));
//#region src/utils.ts
const TRANSFER_FLAG = ".__unocss_transfer__";
function transformUnocssBack(code) {
const result = [];
return new Promise((resolve) => {
(0, __unocss_core.createGenerator)({}, { presets: [(0, __unocss_preset_uno.default)()] }).generate(code || "").then((res) => {
const css = res.getLayers();
code.forEach((item) => {
try {
const reg = new RegExp(`${item.replace(/([!()[\]*])/g, "\\\\$1")}{(.*)}`);
const match = css.match(reg);
if (!match) return;
const matcher = match[1];
matcher.split(";").filter(Boolean).forEach((item$1) => {
const [key, v] = item$1.split(":");
result.push(key.trim());
});
} catch (error) {}
});
resolve(result);
});
});
}
function diffTemplateStyle(before, after) {
const s1 = before.match(/<style scoped>.*<\/style>/s);
const s2 = after.match(/<style scoped>.*<\/style>/s);
if (!s1 || !s2) return false;
return s1[0] === s2[0];
}
function isEmptyStyle(code) {
return /<style scoped>\s*<\/style>/.test(code);
}
function getStyleScoped(code) {
const match = code.match(/<style scoped>(.*)<\/style>/s);
if (!match) return "";
return match[1];
}
function getCssType(filename) {
const ext = filename.split(".").pop();
const result = ext === "styl" ? "stylus" : ext;
return result;
}
/**
* 动态导入 Vue Compiler SFC,避免打包时的问题
* @returns Vue Compiler SFC 中的方法
*/
async function getVueCompilerSfc() {
const { parse: parse$1 } = await import("@vue/compiler-sfc");
return { parse: parse$1 };
}
/**
* 检查是否在 Node.js 环境中运行
* @returns {boolean} 如果在 Node.js 环境中返回 true,在浏览器环境中返回 false
*/
function isNodeEnvironment() {
try {
var _process$versions;
const process$4 = require("node:process");
return typeof window === "undefined" && typeof process$4 !== "undefined" && Boolean((_process$versions = process$4.versions) === null || _process$versions === void 0 ? void 0 : _process$versions.node);
} catch {
return false;
}
}
//#endregion
//#region src/prettierCode.ts
const emptyStyle = /<style[\s\w'=]*>(\s+)/;
async function prettierCode(code) {
const { parse: parse$1 } = await getVueCompilerSfc();
const { descriptor: { styles } } = parse$1(code);
if (!styles.length) return code.replace(emptyStyle, (all, v) => all.replace(v, "")).replace(/\n+/g, "\n");
const { content } = styles[0];
return code.replace(content, removeEmptyStyle(content.replace(/\n+/g, "\n")));
}
function removeEmptyStyle(code) {
return code.replace(/([\w.#:[\]="'\-\s,>~]+)\{\s*\}/g, "");
}
//#endregion
//#region src/lessCompiler.ts
async function lessCompiler(css, filepath, globalCss, debug, resolveAlias) {
if (typeof window !== "undefined") throw new Error("lessCompiler is not supported in this browser");
if (debug) console.log(`[transform-to-tailwindcss] Compiling LESS file: ${filepath || "unknown file"}`);
let result = globalCss ? `${globalCss}\n${css}` : css;
try {
const less = await import("less");
const { LessPluginModuleResolver } = await import("less-plugin-module-resolver");
const aliasObj = {};
try {
if (resolveAlias) {
if (Array.isArray(resolveAlias)) {
for (const a of resolveAlias) if (a && a.find && a.replacement) aliasObj[a.find] = node_path.default.isAbsolute(a.replacement) ? a.replacement : node_path.default.resolve(node_process.default.cwd(), a.replacement);
} else if (typeof resolveAlias === "object") for (const k of Object.keys(resolveAlias)) {
const val = resolveAlias[k];
aliasObj[k] = node_path.default.isAbsolute(val) ? val : node_path.default.resolve(node_process.default.cwd(), val);
}
}
} catch (e) {
if (debug) console.warn("[transform-to-unocss] less resolveAlias normalize failed", e);
}
result = (await less.default.render(result, {
filename: filepath,
plugins: [new LessPluginModuleResolver({ alias: aliasObj })]
})).css;
return result;
} catch (error) {
if (error.code === "MODULE_NOT_FOUND" || error.message.includes("Cannot resolve module")) {
const missingModule = error.message.includes("less-plugin-module-resolver") ? "less-plugin-module-resolver" : "less";
throw new Error(`${missingModule} not found. Please install it in your project:\nnpm install ${missingModule}\nor\nyarn add ${missingModule}\nor\npnpm add ${missingModule}`);
}
console.error(`Error:\n transform-to-unocss(lessCompiler) ${error.toString()}`);
}
}
//#endregion
//#region src/sassCompiler.ts
/**
* Sass 编译器 - 处理 SCSS/Sass 文件编译
*
* 解决了以下问题:
* 1. Sass 新版本的 mixed-decls 弃用警告
* 2. legacy-js-api 弃用警告(优先使用新 API)
* 3. @import 规则弃用警告(Dart Sass 3.0.0 将移除)
* 4. 嵌套规则后声明的兼容性问题
* 5. 支持用户项目中的 Sass 版本
* 6. 自动检测并使用最合适的 Sass API
* 7. 多层次的警告抑制机制(console.warn 拦截 + 自定义 logger + silenceDeprecations)
*
* @param css 要编译的 CSS 内容
* @param filepath 文件路径,用于解析 @import 等
* @param globalCss 全局 CSS 内容(字符串)或包含 CSS 的对象(如 {css: string})
* @param debug 是否开启调试模式
* @returns 编译后的 CSS 字符串
*/
async function sassCompiler(css, filepath, globalCss, debug, resolveAlias) {
if (typeof window !== "undefined") throw new Error("sassCompiler is not supported in this browser");
if (typeof css !== "string") {
if (debug) console.warn(`[transform-to-unocss] sassCompiler received non-string CSS input: ${typeof css}`);
return String(css || "");
}
if (filepath) {
const isValidSassFile = filepath.endsWith(".scss") || filepath.endsWith(".sass") || filepath.includes(".vue") || filepath.includes(".svelte") || filepath.includes(".astro") || filepath.includes(".tsx") || filepath.includes(".jsx");
if (!isValidSassFile && debug) console.warn(`[transform-to-unocss] sassCompiler called for unexpected file type: ${filepath}`);
}
if (debug) console.log(`[transform-to-unocss] Compiling SCSS file: ${filepath || "unknown file"}`);
const baseDir = node_path.default.dirname(filepath);
let result = "";
if (globalCss) {
if (typeof globalCss === "string") result += globalCss;
else if (typeof globalCss === "object" && globalCss !== null) {
const globalCssObj = globalCss;
if ("css" in globalCssObj && typeof globalCssObj.css === "string") result += globalCssObj.css;
else if (debug) console.warn(`[transform-to-unocss] Unexpected globalCss object format:`, globalCss);
} else if (debug) console.warn(`[transform-to-unocss] globalCss is not a string or valid object: ${typeof globalCss}`, globalCss);
}
if (result) result += "\n";
result += css;
if (node_process.default.env.DEBUG_SASS) {
console.log("[transform-to-unocss] [sassCompiler] globalCss type:", typeof globalCss);
console.log("[transform-to-unocss] [sassCompiler] result before replace length:", result.length);
console.log("[transform-to-unocss] [sassCompiler] result before replace snippet:", result.slice(0, 200));
}
try {
const sass = await import("sass");
const originalWarn = console.warn;
const filteredWarn = (message, ...args) => {
const messageStr = String(message);
const deprecationPatterns = [
"Deprecation Warning",
"mixed-decls",
"legacy-js-api",
"import",
"Sass @import rules are deprecated",
"will be removed in Dart Sass",
"More info and automated migrator"
];
const shouldIgnore = deprecationPatterns.some((pattern) => messageStr.includes(pattern));
if (!shouldIgnore) originalWarn(message, ...args);
};
try {
const sassInfo = sass.info || "";
const isModernSass = sassInfo.includes("dart-sass") || sassInfo.includes("1.");
const compileOptions = {
syntax: "scss",
loadPaths: [baseDir, node_path.default.resolve(node_process.default.cwd(), "src")]
};
if (isModernSass) {
compileOptions.quietDeps = true;
compileOptions.verbose = false;
try {
compileOptions.silenceDeprecations = [
"mixed-decls",
"import",
"legacy-js-api"
];
} catch (e) {}
compileOptions.logger = { warn: (message, options) => {
const deprecationPatterns = [
"mixed-decls",
"legacy-js-api",
"import",
"Deprecation Warning",
"behavior for declarations that appear after nested",
"will be changing to match the behavior specified by CSS",
"The legacy JS API is deprecated",
"Sass @import rules are deprecated",
"will be removed in Dart Sass 3.0.0",
"More info and automated migrator"
];
const shouldIgnore = deprecationPatterns.some((pattern) => message.includes(pattern));
if (shouldIgnore) return;
if (debug) console.warn(`[transform-to-unocss] Sass warning: ${message}`);
} };
}
const fs$1 = await import("node:fs");
const replaceAliasImports = (source) => {
const importRegex = /@(import|use|forward)\s+(['"])(~?@\/[\w\-./]+)\2/g;
const getAliasSuffix = (impPath, find) => impPath.slice(find.length).replace(/^\/+/, "");
const tryResolveViaAlias = (impPath) => {
try {
if (resolveAlias) {
if (Array.isArray(resolveAlias)) {
for (const a of resolveAlias) if (typeof a.find === "string" && impPath.startsWith(a.find)) return {
suffix: getAliasSuffix(impPath, a.find),
aliasRoot: a.replacement
};
} else if (typeof resolveAlias === "object") {
for (const key of Object.keys(resolveAlias)) if (impPath.startsWith(key)) return {
suffix: getAliasSuffix(impPath, key),
aliasRoot: resolveAlias[key]
};
}
}
} catch (e) {
if (debug) console.warn("[transform-to-unocss] tryResolveViaAlias failed", e);
}
return null;
};
const resolveAliasLocal = (impPath) => {
const rel = impPath.replace(/^~?@\//, "");
try {
if (resolveAlias) {
if (Array.isArray(resolveAlias)) for (const a of resolveAlias) {
if (typeof a.find === "string" && impPath.startsWith(a.find)) return node_path.default.resolve(a.replacement, getAliasSuffix(impPath, a.find));
if (a.find instanceof RegExp) {
const m = impPath.match(a.find);
if (m) return impPath.replace(a.find, a.replacement);
}
}
else if (typeof resolveAlias === "object") {
for (const key of Object.keys(resolveAlias)) if (impPath.startsWith(key)) return node_path.default.resolve(resolveAlias[key], getAliasSuffix(impPath, key));
}
}
} catch (e) {
if (debug) console.warn("[transform-to-unocss] resolveAlias failed", e);
}
const candidateSrc = node_path.default.resolve(node_process.default.cwd(), "src", rel);
const candidateRoot = node_path.default.resolve(node_process.default.cwd(), rel);
const exts = [
"",
".scss",
".sass",
".css"
];
const underscoreVariants = (p) => {
const dir = node_path.default.dirname(p);
const base = node_path.default.basename(p);
return node_path.default.join(dir, `_${base}`);
};
const tryPaths = (base) => {
for (const e of exts) {
const p1 = base + e;
if (fs$1.existsSync(p1)) return p1;
const p2 = underscoreVariants(base) + e;
if (fs$1.existsSync(p2)) return p2;
}
return null;
};
let found = tryPaths(candidateSrc);
if (found) return found;
found = tryPaths(candidateRoot);
if (found) return found;
return candidateSrc;
};
return source.replace(importRegex, (match, kw, quote, impPath) => {
try {
const aliasResult = tryResolveViaAlias(impPath);
if (aliasResult) {
const { suffix, aliasRoot } = aliasResult;
if (!compileOptions.loadPaths.includes(aliasRoot)) compileOptions.loadPaths.push(aliasRoot);
if (debug) console.log(`[transform-to-unocss] Rewriting ${kw} ${impPath} -> ${suffix} (added ${aliasRoot} to loadPaths)`);
return `@${kw} ${quote}${suffix}${quote}`;
}
const resolved = resolveAliasLocal(impPath);
if (resolved && resolved !== impPath) {
let finalPath = resolved;
try {
if (!node_path.default.isAbsolute(finalPath)) finalPath = node_path.default.resolve(node_process.default.cwd(), finalPath);
} catch (e) {}
finalPath = finalPath.replace(/\\/g, "/");
if (debug) console.log(`[transform-to-unocss] Rewriting ${kw} ${impPath} -> ${finalPath}`);
return `@${kw} ${quote}${finalPath}${quote}`;
}
} catch (e) {
if (debug) console.warn("[transform-to-unocss] alias resolution error", e);
}
return match;
});
};
const sourceToCompile = replaceAliasImports(result);
if (node_process.default.env.DEBUG_SASS) console.log("[transform-to-unocss] [sassCompiler] sourceToCompile:", sourceToCompile);
let compiledResult;
console.warn = filteredWarn;
if (sass.compile && typeof sass.compile === "function") {
const os = await import("node:os");
const tempDirPath = fs$1.mkdtempSync(node_path.default.join(os.tmpdir(), "transform-to-unocss-"));
const tempFilePath = node_path.default.join(tempDirPath, "input.scss");
try {
fs$1.writeFileSync(tempFilePath, sourceToCompile);
compiledResult = sass.compile(tempFilePath, compileOptions);
} finally {
try {
fs$1.unlinkSync(tempFilePath);
} catch (e) {}
try {
fs$1.rmdirSync(tempDirPath);
} catch (e) {}
}
} else compiledResult = sass.compileString(sourceToCompile, compileOptions);
result = compiledResult.css;
return result;
} finally {
console.warn = originalWarn;
}
} catch (error) {
if (error.code === "MODULE_NOT_FOUND" || error.message.includes("Cannot resolve module")) throw new Error("Sass compiler not found. Please install sass in your project:\nnpm install sass\nor\nyarn add sass\nor\npnpm add sass");
console.error(`Error:\n transform-to-unocss(sassCompiler) ${error.toString()}`);
return css;
}
}
//#endregion
//#region src/stylusCompiler.ts
async function stylusCompiler(css, filepath, globalCss, debug, resolveAlias) {
if (typeof window !== "undefined") throw new Error("Stylus is not supported in this browser");
if (debug) console.log(`[transform-to-tailwindcss] Compiling Stylus file: ${filepath || "unknown file"}`);
let result = globalCss ? `${globalCss}\n${css}` : css;
if (resolveAlias) try {
const importRegex = /@import\s+['"](~?@\/[\w\-./]+)['"]/g;
result = result.replace(importRegex, (m, imp) => {
const rel = imp.replace(/^~?@\//, "");
if (Array.isArray(resolveAlias)) {
for (const a of resolveAlias) if (typeof a.find === "string" && imp.startsWith(a.find)) {
const resolved = node_path.default.isAbsolute(a.replacement) ? node_path.default.join(a.replacement, imp.slice(a.find.length)) : node_path.default.join(node_process.default.cwd(), a.replacement, imp.slice(a.find.length));
return `@import '${resolved.replace(/\\/g, "/")}'`;
}
} else if (typeof resolveAlias === "object") {
for (const k of Object.keys(resolveAlias)) if (imp.startsWith(k)) {
const val = resolveAlias[k];
const resolved = node_path.default.isAbsolute(val) ? node_path.default.join(val, imp.slice(k.length)) : node_path.default.join(node_process.default.cwd(), val, imp.slice(k.length));
return `@import '${resolved.replace(/\\/g, "/")}'`;
}
}
return `@import '${node_path.default.resolve(node_process.default.cwd(), "src", rel).replace(/\\/g, "/")}'`;
});
} catch (e) {
if (debug) console.warn("[transform-to-unocss] stylus alias replace failed", e);
}
try {
const stylus = await import("stylus");
const includePaths = [];
try {
if (resolveAlias) {
if (Array.isArray(resolveAlias)) {
for (const a of resolveAlias) if (a && a.replacement) includePaths.push(node_path.default.isAbsolute(a.replacement) ? a.replacement : node_path.default.resolve(node_process.default.cwd(), a.replacement));
} else if (typeof resolveAlias === "object") for (const k of Object.keys(resolveAlias)) {
const v = resolveAlias[k];
includePaths.push(node_path.default.isAbsolute(v) ? v : node_path.default.resolve(node_process.default.cwd(), v));
}
}
} catch (e) {
if (debug) console.warn("[transform-to-unocss] stylus resolveAlias normalize failed", e);
}
result = stylus.default.render(result, {
filename: filepath,
paths: includePaths.length ? includePaths : void 0
});
return result;
} catch (error) {
if (error.code === "MODULE_NOT_FOUND" || error.message.includes("Cannot resolve module")) throw new Error("Stylus compiler not found. Please install stylus in your project:\nnpm install stylus\nor\nyarn add stylus\nor\npnpm add stylus");
console.error(`Error:\n transform-to-unocss(stylusCompiler) ${error.toString()}`);
}
}
//#endregion
//#region src/compilerCss.ts
function compilerCss(css, lang, filepath = isNodeEnvironment() ? node_process.default.cwd() : "", globalCss, debug, resolveAlias) {
if (typeof css !== "string") {
if (debug) console.warn(`[transform-to-unocss] compilerCss received non-string CSS input: ${typeof css}, filepath: ${filepath}`);
return String(css || "");
}
if (![
"stylus",
"less",
"scss",
"css"
].includes(lang)) {
if (debug) console.warn(`[transform-to-unocss] compilerCss received unknown language: ${lang}, filepath: ${filepath}`);
return css;
}
const normalizedGlobalCss = getGlobalCssByLang(globalCss, lang);
switch (lang) {
case "stylus": return stylusCompiler(css, filepath, normalizedGlobalCss, debug, resolveAlias);
case "less": return lessCompiler(css, filepath, normalizedGlobalCss, debug, resolveAlias);
case "scss": return sassCompiler(css, filepath, normalizedGlobalCss, debug, resolveAlias);
default: return css;
}
}
function getGlobalCssByLang(globalCss, lang) {
if (globalCss == null || typeof globalCss === "string") return globalCss;
if (typeof globalCss !== "object") return globalCss;
if ("css" in globalCss) return typeof globalCss.css === "string" ? globalCss.css : void 0;
const langConfig = globalCss[lang] ?? (lang === "scss" ? globalCss.sass : void 0);
if (typeof langConfig === "string") return langConfig;
if (langConfig && typeof langConfig === "object" && typeof langConfig.additionalData === "string") return langConfig.additionalData;
return void 0;
}
//#endregion
//#region src/node-html-parser.ts
function nodeHtmlParser(code, selector, stack) {
const results = [];
if (!stack || !stack.length) return results;
const root = (0, node_html_parser.parse)(code);
let elements = [];
try {
elements = root.querySelectorAll(selector);
} catch (error) {}
while (elements.length === 0 && selector.includes(":")) {
const index = selector.lastIndexOf(":");
selector = selector.slice(0, index);
try {
elements = root.querySelectorAll(selector);
} catch (error) {}
}
if (elements.length) elements.forEach((element) => {
const targetNode = getMatchNode(element.range, stack);
if (targetNode) results.push(targetNode);
});
return results;
}
function getMatchNode(range, elements) {
for (const element of elements) {
const { start, end } = element.loc;
if (range[0] === start.offset && range[1] === end.offset) return element;
else if (element.children && element.children.length) {
const match = getMatchNode(range, element.children);
if (match) return match;
}
}
}
//#endregion
//#region src/tail.ts
function tail(css) {
if (/not\(/.test(css)) return `[&:${css}]:`;
if (css.startsWith("nth")) {
if (css === "nth-child(odd)") return "odd";
if (css === "nth-child(even)") return "even";
if (css.startsWith("nth-child(")) {
const match = css.match(/nth-child\((.*)\)/);
if (match && match[1]) return `nth-[${match[1]}]`;
return "";
}
if (css.startsWith("nth-last-child(")) {
const match = css.match(/nth-last-child\((.*)\)/);
if (match && match[1]) return `nth-last-[${match[1]}]`;
return "";
}
if (!css.includes("(")) return css;
return css.split("(")[0];
}
if (css.startsWith("aria-") || css.startsWith("data-")) return css.split("=")[0];
if (css.startsWith("dir=")) return css.split("=")[1];
if (css === "file-selector-button") return "file";
if (css.endsWith("-child")) return css.split("-")[0];
if (css.startsWith("has(")) {
const match = css.match(/has\((.*)\)/);
if (match && match[1]) return `has-[${match[1]}]`;
return "";
}
if (css.startsWith("where(")) {
const match = css.match(/where\((.*)\)/);
if (match && match[1]) return `in-[${match[1]}]`;
return "";
}
if ([
"first-child",
"last-child",
"only-child"
].includes(css)) return css.split("-")[0];
const [first, ...rest] = css.split(":");
if (rest.length) return `[&:${(0, transform_to_unocss_core.joinWithUnderLine)(first)}]:${rest.join(":")}`;
return `[&:${(0, transform_to_unocss_core.joinWithUnderLine)(first)}]`;
}
//#endregion
//#region src/wrapperVueTemplate.ts
function wrapperVueTemplate(template, css) {
let _template = /<template>/.test(template) ? template.replace(/\n+/g, "\n") : `<template>
${template}
</template>`;
_template = /<style scoped>/.test(_template) ? _template.replace("</style>", `\n${css}<\/style>`) : `${_template}\n<style scoped>
${css}
</style>`;
return `${_template}`;
}
//#endregion
//#region src/transformCss.ts
const tailReg = /:?:(.+)/;
const emptyClass = /[@,\w>.#\-+:[\]="'\s()]+\{\}\n/g;
let isRem;
async function transformCss(style, code, media = "", isJsx = true, filepath, _isRem, debug = false, globalCss, resolveAlias, styleIndex) {
var _parse$descriptor$tem;
isRem = _isRem;
const allChanges = [];
const { parse: parse$1 } = await getVueCompilerSfc();
let newCode = await importCss(code, style, filepath, isJsx, debug, globalCss, resolveAlias, styleIndex);
if (debug) console.log("[DEBUG] transformCss started:", JSON.stringify({
filepath,
media,
isJsx,
styleLength: style.length,
codeLength: code.length
}, null, 2));
const stack = (_parse$descriptor$tem = parse$1(newCode).descriptor.template) === null || _parse$descriptor$tem === void 0 ? void 0 : _parse$descriptor$tem.ast;
const updateOffsetMap = {};
const deferRun = [];
style.replace(/([.#\w](?:[^{}]|\n)*)\{([#\\\s\w\-.:;,%@/()+'"!]*)\}/g, (all, name, value = "") => {
name = (0, transform_to_unocss_core.trim)(name.replace(/\s+/g, " "));
if (name.includes(":deep(") || name.includes(">>>") || name.includes("/deep/") || name.includes("::v-deep") || name.includes(":global(") || name.includes("@")) return;
const originClassName = name;
const before = (0, transform_to_unocss_core.trim)(value.replace(/\n\s*/g, ""));
if (debug) console.log("[DEBUG] Processing CSS rule:", JSON.stringify({
originClassName,
before,
all
}, null, 2));
const [transfer, noTransfer] = (0, transform_to_unocss_core.transformStyleToUnocss)(before, isRem);
if (debug) console.log("[DEBUG] CSS transform result:", JSON.stringify({
originClassName,
before,
transfer,
noTransfer: (noTransfer === null || noTransfer === void 0 ? void 0 : noTransfer.length) || 0
}, null, 2));
const tailMatcher = name.match(tailReg);
const prefix = tailMatcher ? (name.endsWith(tailMatcher[0]) ? "" : "group-") + tail(tailMatcher[1]) : "";
if (prefix === "group-deep") return;
if (prefix.includes(" ")) return;
const after = prefix && transfer ? `${prefix}="${transfer.replace(/="\[([^\]]*)\]"/g, (_, v) => `-[${v}]`)}"` : transfer ?? before;
if (before === after) {
if (debug) console.log("[DEBUG] CSS rule skipped - no transformation:", JSON.stringify({
originClassName,
before
}, null, 2));
return;
}
if (prefix) name = name.replace(tailMatcher[0], "");
const result = nodeHtmlParser(newCode, originClassName, stack === null || stack === void 0 ? void 0 : stack.children);
if (!result.length) {
if (debug) console.log("[DEBUG] No HTML elements found for CSS rule:", JSON.stringify({
originClassName,
name
}, null, 2));
return;
}
if (debug) console.log("[DEBUG] Found HTML elements for CSS rule:", JSON.stringify({
originClassName,
elementsCount: result.length,
elements: result.map((r) => ({
tag: r.tag,
start: r.loc.start.offset
}))
}, null, 2));
const styleBlock = getStyleBlock(newCode, parse$1, styleIndex, all);
if (!styleBlock) return;
const _class = styleBlock.content;
let newClass = _class.replace(all, (_) => _.replace(value, noTransfer.join(";")));
newClass = newClass.replace(emptyClass, "");
newCode = replaceStyleBlockContent(newCode, styleBlock, newClass);
for (const r of result) {
const parent = r.parent;
if (prefix.startsWith("group-") && parent) {
const hasClass = parent.props.find((i) => i.name === "class");
if (hasClass) {
if (hasClass.value.content.includes("group")) return;
const index = hasClass.value.loc.start.offset;
const newIndex = hasClass.value.loc.start.offset + getCalculateOffset(updateOffsetMap, index);
const updateText = "group ";
updateOffsetMap[index] = updateText.length;
hasClass.value.content = `${hasClass.value.content} ${updateText}`;
newCode = `${newCode.slice(0, newIndex + 1)}${updateText}${newCode.slice(newIndex + 1)}`;
} else {
const index = parent.loc.start.offset + parent.tag.length + 1;
const newIndex = index + getCalculateOffset(updateOffsetMap, index);
const updateText = "class=\"group\" ";
parent.props.push({
type: 6,
name: "class",
value: {
type: 2,
content: "group",
loc: {
start: {
column: 0,
line: 0,
offset: newIndex
},
end: {
column: 0,
line: 0,
offset: newIndex + updateText.length
}
}
},
loc: {
start: {
column: 0,
line: 0,
offset: newIndex
},
end: {
column: 0,
line: 0,
offset: newIndex + updateText.length
}
}
});
updateOffsetMap[index] = updateText.length;
newCode = `${newCode.slice(0, newIndex)}${updateText}${newCode.slice(newIndex)}`;
}
}
const { loc: { start, end }, tag, props } = r;
let _class$1 = "";
const attr = props.reduce((result$1, cur) => {
var _cur$value;
let item;
if (cur.name === "class" && (item = (_cur$value = cur.value) === null || _cur$value === void 0 ? void 0 : _cur$value.content)) _class$1 = item;
else if (!cur.value) result$1.push(cur.name);
return result$1;
}, []);
deferRun.push(() => {
const newIndex = getCalculateOffset(updateOffsetMap, start.offset);
const newSource = newCode.slice(start.offset + newIndex, end.offset + newIndex);
allChanges.push({
before,
after,
name: originClassName,
source: newSource,
tag,
attr,
class: _class$1,
prefix,
media,
start,
end
});
});
}
return all;
});
deferRun.forEach((run) => run());
if (debug) console.log("[DEBUG] transformCss finished, resolving conflicts:", JSON.stringify({ allChangesCount: allChanges.length }, null, 2));
return await resolveConflictClass(allChanges, newCode, isJsx, updateOffsetMap, debug);
}
async function importCss(code, style, filepath, isJsx, debug = false, globalCss, resolveAlias, styleIndex) {
const { parse: parse$1 } = await getVueCompilerSfc();
if (debug) console.log("[DEBUG] importCss started:", JSON.stringify({
filepath,
styleLength: style.length,
hasImports: /@import/.test(style)
}, null, 2));
for await (const match of style.matchAll(/@import (url\()?["']*([\w./\-]*)["']*\)?;/g)) {
if (!match) continue;
const previousCode = code;
if (debug) console.log("[DEBUG] Processing CSS import:", JSON.stringify({ importUrl: match[2] }, null, 2));
const url = node_path.default.resolve(filepath, "..", match[2]);
const content = await node_fs_promises.default.readFile(node_path.default.resolve(filepath, "..", url), "utf-8");
const type = getCssType(url);
const css = await compilerCss(content, type, url, globalCss, debug, resolveAlias);
const styleBlock = getStyleBlock(code, parse$1, styleIndex, match[0]);
const templateSource = getTemplateSource(code, parse$1);
if (!styleBlock || !templateSource) continue;
const beforeStyle = styleBlock.content;
const vue = wrapperVueTemplate(templateSource, css);
const transfer = await transformVue(vue, {
isJsx,
isRem,
filepath,
globalCss,
debug,
resolveAlias
});
if (diffTemplateStyle(transfer, vue)) {
code = previousCode;
continue;
}
const nextTemplate = getTemplateSource(transfer, parse$1);
if (nextTemplate) code = replaceTemplateContent(code, parse$1, nextTemplate);
if (isEmptyStyle(transfer)) {
code = replaceStyleBlockContent(code, styleBlock, beforeStyle.replace(match[0], ""));
continue;
}
const restStyle = getStyleScoped(transfer);
await node_fs_promises.default.writeFile(url.replace(`.${type}`, `${TRANSFER_FLAG}.${type}`), restStyle, "utf-8");
continue;
}
return code;
}
function getStyleBlock(code, parse$1, styleIndex, needle) {
const styles = parse$1(code).descriptor.styles;
const target = styleIndex !== void 0 ? styles[styleIndex] : styles.find((item) => needle && item.content.includes(needle));
if (!target) return;
return {
content: target.content,
contentEnd: target.loc.end.offset,
contentStart: target.loc.start.offset
};
}
function replaceStyleBlockContent(code, styleBlock, content) {
return `${code.slice(0, styleBlock.contentStart)}${content}${code.slice(styleBlock.contentEnd)}`;
}
function getTemplateSource(code, parse$1) {
const template = parse$1(code).descriptor.template;
if (!template) return "";
return template.loc.source;
}
function replaceTemplateContent(code, parse$1, content) {
const template = parse$1(code).descriptor.template;
if (!template) return code;
return `${code.slice(0, template.loc.start.offset)}${content}${code.slice(template.loc.end.offset)}`;
}
async function resolveConflictClass(allChange, code, isJsx = true, updateOffset, debug = false) {
if (debug) console.log("[DEBUG] resolveConflictClass started:", JSON.stringify({
allChangesCount: allChange.length,
isJsx
}, null, 2));
const changes = findSameSource(allChange);
let result = code;
if (debug) console.log("[DEBUG] Found conflict groups:", JSON.stringify({
groupsCount: Object.keys(changes).length,
groups: Object.keys(changes).map((key) => ({
key,
changesCount: changes[key].length
}))
}, null, 2));
for await (const key of Object.keys(changes)) {
const value = changes[key];
const { tag, prefix, media, source, start: { offset }, end: { offset: offsetEnd } } = value[0];
let [after, transform] = await getConflictClass(value, debug);
if (!after) {
if (debug) console.log("[DEBUG] No conflict resolution needed for group:", key);
continue;
}
if (debug) console.log("[DEBUG] Conflict resolved for group:", JSON.stringify({
key,
after,
originalSource: source
}, null, 2));
const newResult = transform(result);
result = newResult;
const target = transform(source);
if (media) after = `${media}:${after}`;
if (prefix) if ((0, transform_to_unocss_core.isNot)(prefix)) {
const match = target.match(/<[^>]*(class="[^"]+)[^>]*/);
if (match) after = after.replace(/class="(\[&:not\([\w\s\-.#]+\)\]:[\w\-.]+)"\s*/, (_, v) => {
const updateText = ` ${v}`;
result = result.replace(match[1], `${match[1]}${updateText}`);
return "";
});
} else after = after.replace(/="\[/g, "-\"[");
const returnValue = isJsx || after.replace(/(?:[\w\-]+|\[[^\]]+\])=("{1})(.*?)\1/g, "").includes("[") ? after.replace(/\[([^\]]+)\]/g, (all, v) => all.replace(v, (0, transform_to_unocss_core.joinWithUnderLine)(v))).replace(/-(rgba?([^)]+))/g, "-[$1]").replace(/((?:[\w\-]+|\[[^\]]+\])(?::[\w\-]+|-\[[^\]]*\])*)=(['"]{1})(.*?)\2/g, (_all, prefix$1, _, content) => {
const splitContent = content.split(/(?<!\[[^\]]*)\s+/).filter(Boolean);
return splitContent.map((item) => `${prefix$1}-${item}`).join(` `);
}) : after;
const getUpdateOffset = getCalculateOffset(updateOffset, offset);
const startOffset = offset + getUpdateOffset;
const endOffset = offsetEnd + getUpdateOffset;
const start = result.slice(startOffset, endOffset);
if (isJsx || after.replace(/[\w\-]+=("{1})(.*?)\1/g, "").includes("[")) {
const newReg = new RegExp(`^<${tag}(?:[^\/'">]|"[^"]*"|'[^']*')*[^:]class=["']([^"']+)["']([^\/'">]|"[^"]*"|'[^']*')*\/?>`, "s");
const matcher = target.match(newReg);
if (matcher) {
const insertText$1 = ` ${returnValue}`;
result = result.slice(0, startOffset) + start.replace(`class="${matcher[1]}"`, `class="${matcher[1]}${insertText$1}"`) + result.slice(endOffset);
updateOffset[offset] = insertText$1.length;
continue;
}
const insertText = ` class="${returnValue}"`;
result = result.slice(0, startOffset) + start.replace(`<${tag}`, `<${tag}${insertText}`) + result.slice(endOffset);
updateOffset[offset] = insertText.length;
continue;
}
result = result.slice(0, startOffset) + start.replace(`<${tag}`, `<${tag} ${returnValue}`) + result.slice(endOffset);
}
return result;
}
function calculateWeight(c) {
const data = c.split(" ").filter((i) => i !== "+" && i !== ">");
let num = 0;
data.forEach((item) => {
item.replace(/#\w+/g, () => {
num += 100;
return "";
});
item.replace(/.\w+/, () => {
num += 10;
return "";
});
item.replace(/^\w+/, () => {
num += 10;
return "";
});
item.replace(/\[[\w\s='"-]+\]/g, () => {
num += 10;
return "";
});
item.replace(/:\w+/g, () => {
num += 1;
return "";
});
});
return num;
}
function getMatchingWeight(name, currentClass) {
if (name.includes(",")) {
const selectors = name.split(",").map((s) => s.trim());
const currentClasses = currentClass.split(" ").filter(Boolean);
let bestMatch = "";
let maxMatchCount = 0;
for (const selector of selectors) {
let matchCount = 0;
const selectorClasses = selector.match(/\.[A-Z][\w-]*/gi) || [];
for (const selectorClass of selectorClasses) {
const className = selectorClass.substring(1);
if (currentClasses.includes(className)) matchCount++;
}
if (matchCount > maxMatchCount) {
maxMatchCount = matchCount;
bestMatch = selector;
}
}
return calculateWeight(bestMatch || selectors[0]);
}
return calculateWeight(name);
}
function findSameSource(allChange) {
const result = {};
allChange.forEach((item) => {
const { source, start, end } = item;
const key = `${source}:${start.offset}:${end.offset}`;
if (!result[key]) result[key] = [];
result[key].push(item);
});
return result;
}
const skipTransformFlag = Symbol("skipTransformFlag");
async function getConflictClass(allChange, debug = false) {
if (debug) console.log("[DEBUG] getConflictClass started:", JSON.stringify({
changesCount: allChange.length,
changes: allChange.map((c) => ({
name: c.name,
before: c.before,
after: c.after
}))
}, null, 2));
let map = {};
let transform = (code) => code;
for await (const item of allChange) {
const { before, name, source, attr, after, prefix, media, class: _class } = item;
const pre = prefix ? `${prefix}|` : "";
const beforeArr = before.split(";").filter(Boolean);
const data = beforeArr.map((item$1) => {
const trimmed = item$1.trim();
const idx = trimmed.indexOf(":");
if (idx === -1) return [`${pre}${trimmed}`, void 0];
const key = trimmed.slice(0, idx);
const value = trimmed.slice(idx + 1);
return [`${pre}${key}`, value];
});
const currentWeight = getMatchingWeight(name, _class);
data.forEach((item$1) => {
const [key, value] = item$1;
if (value === void 0) return;
if (!map[key]) map[key] = [currentWeight, value];
else {
const [preWeight] = map[key];
if (preWeight === skipTransformFlag) return;
if (+currentWeight >= +preWeight) map[key] = [+currentWeight, value];
}
});
if (attr) {
const res = await transformUnocssBack(attr.map((i) => {
if (prefix) return `${prefix}="${i}"`;
if (media) return `${media}:${i}`;
return i;
}));
Object.keys(map).forEach((i) => {
const index = res.findIndex((r) => r === i);
if (index !== -1) {
const inline = item.attr[index];
if ((inline === null || inline === void 0 ? void 0 : inline.endsWith("!")) || !(after === null || after === void 0 ? void 0 : after.endsWith("!"))) return delete map[i];
else transform = (code) => code.replace(source, source.replace(` ${inline}`, ""));
}
});
}
}
const joinMap = Object.keys(map).map((key) => {
const value = map[key][1];
return `${key}:${value}`;
}).join(";");
const { transformedResult, newStyle } = (0, transform_to_unocss_core.transformStyleToUnocssPre)(joinMap);
if (transformedResult) {
map = newStyle.split(";").reduce((acc, item) => {
const match = item.trim().match(/(^(?:[^:[]|\[[^\]]*\])+):\s*(.*)$/);
if (match) {
const key = match[1].trim();
const value = match[2];
if (value !== void 0) {
var _map$key;
acc[key] = [((_map$key = map[key]) === null || _map$key === void 0 ? void 0 : _map$key[0]) ?? 1, value];
}
}
return acc;
}, {});
map[transformedResult] = [1, skipTransformFlag];
}
return [Object.keys(map).reduce((result, key) => {
const keys = key.split("|");
const styleKey = keys[keys.length - 1];
let prefix = keys.length > 1 ? keys[0] : "";
let transferCss = map[key][1] === skipTransformFlag ? key : (0, transform_to_unocss_core.transformStyleToUnocss)(`${styleKey}:${map[key][1]}`, isRem)[0];
if (debug) console.log("[DEBUG] Processing map key:", JSON.stringify({
key,
styleKey,
prefix,
transferCss,
mapValue: map[key]
}, null, 2));
const match = transferCss.match(/(\S*)="\[([^\]]*)\]"/);
if (match) {
var _match$input;
transferCss = `${(_match$input = match.input) === null || _match$input === void 0 ? void 0 : _match$input.replace(match[0], match[0].replace(/="\[([^\]]*)\]"/, (_, v) => `-[${v}]`).replace(/="([^"]*)"/, "-$1"))}`;
}
transferCss = transferCss.replace(/"/g, "'");
const _transferCss = prefix ? (0, transform_to_unocss_core.isNot)(prefix) ? `class="${prefix}${transferCss.replace(/="\[([^\]]*)\]"/g, (_, v) => `-[${v}]`).replace(/="([^"]*)"/, "-$1")}"` : `${prefix}="${transferCss.replace(/="\[([^\]]*)\]"/g, (_, v) => `-[${v}]`).replace(/="([^"]*)"/, "-$1")}"` : transferCss;
if (!prefix) {
const reg = /^(\S*)="[^"]*"$/;
if (reg.test(transferCss)) prefix = transferCss.match(reg)[1];
}
if (prefix) {
const prefixReg1 = new RegExp(`(?<!\\S)${(0, __unocss_core.escapeRegExp)(prefix)}(?!\\S)`);
if (prefixReg1.test(result)) return result.replace(prefixReg1, (all) => all.replace(prefix, _transferCss));
const prefixReg2 = new RegExp(`(?<!\\S)${(0, __unocss_core.escapeRegExp)(prefix)}=`);
if (prefixReg2.test(result)) {
if ((0, transform_to_unocss_core.isNot)(prefix)) {
const newPrefix = prefix.replace(/[[\]()]/g, (all) => `\\${all}`);
const reg$1 = new RegExp(`${(0, __unocss_core.escapeRegExp)(newPrefix)}([\\w\\:\\-;\\[\\]\\/\\+%]+)`);
return result.replace(reg$1, (all) => `${all}:${transferCss}`);
}
const reg = new RegExp(`${(0, __unocss_core.escapeRegExp)(prefix)}=(["]{1})(.*?)\\1`);
return result.replace(reg, (all, _, v) => {
const unique = [...new Set(v.split(" ").concat(_transferCss.slice(prefix.length + 2, -1).split(" ")))].join(" ");
if (v) return all.replace(v, unique);
return `${prefix}="${unique.trim()}"`;
});
}
}
return `${result}${_transferCss} `;
}, "").trim(), transform];
}
function getCalculateOffset(offsetMap, offset) {
return Object.keys(offsetMap).reduce((result, key) => {
if (+key <= offset) result += offsetMap[key];
return result;
}, 0);
}
//#endregion
//#region src/transformInlineStyle.ts
const styleReg = /<([\w\-]+)[^/>]*[^:]style="([^"]+)"[^>]*>/g;
const removeStyleReg = / style=("{1})(.*?)\1/;
const templateReg = /^<template>(.*)<\/template>$/ms;
const commentReg = /<!--.*-->/gs;
function transformInlineStyle(code, isJsx, isRem$1, debug = false) {
const match = code.match(templateReg);
if (!match) return code;
let templateMatch = match[1];
const commentMap = {};
let count = 0;
const commentPrefix = "__commentMap__";
templateMatch = templateMatch.replace(commentReg, (comment) => {
count++;
commentMap[count] = comment;
return `${commentPrefix}${count}`;
});
templateMatch.replace(styleReg, (target, tag, inlineStyle) => {
const [after, noMap] = isJsx ? (0, transform_to_unocss_core.toUnocssClass)(inlineStyle, isRem$1) : (0, transform_to_unocss_core.transformStyleToUnocss)(inlineStyle, isRem$1, debug);
if (debug) console.log("[DEBUG] transformInlineStyle processing:", JSON.stringify({
tag,
inlineStyle,
after,
noMapLength: (noMap === null || noMap === void 0 ? void 0 : noMap.length) || 0
}, null, 2));
if (isJsx) {
const newReg = new RegExp(`<${tag}.*\\sclass=(["']{1})(.*?)\\1`, "s");
const matcher = target.match(newReg);
if (matcher) return templateMatch = templateMatch.replace(target, target.replace(removeStyleReg, "").replace(`class="${matcher[2]}"`, noMap.length ? `class="${matcher[2]} ${after}" style="${noMap.map((item) => item && item.trim()).join(";")}"` : `class="${matcher[2]} ${after}"`));
return templateMatch = templateMatch.replace(target, target.replace(removeStyleReg, "").replace(`<${tag}`, noMap.length ? `<${tag} class="${after}" style="${noMap.map((item) => item && item.trim()).join(";")}` : `<${tag} class="${after}"`));
}
return templateMatch = templateMatch.replace(target, target.replace(removeStyleReg, "").replace(`<${tag}`, noMap.length ? `<${tag} ${after} style="${noMap.map((item) => item && item.trim()).join(";")}"` : `<${tag} ${after}`));
});
Object.keys(commentMap).forEach((key) => {
const commentKey = `${commentPrefix}${key}`;
const value = commentMap[key];
templateMatch = templateMatch.replace(commentKey, value);
});
return code.replace(templateReg, `<template>${templateMatch}</template>`);
}
//#endregion
//#region src/transformMedia.ts
const mediaReg = /@media([\s\w]*)\(([\w-]+)(?::\s*([\w-]+))?\)\s*\{([\s\w.{}\-:;!]*)\}/g;
const mediaSingleReg = /@media([\s\w]*)\(([\w-]+)(?::\s*([\w-]+))?\)\s*\{([\s\w.{}\-:;!]*)\}/;
const emptyMediaReg = /@media([\s\w]*)\(([\w-]+)(?::\s*([\w-]+))?\)\s*\{\s*\}/g;
const valMap = {
"640px": "sm",
"768px": "md",
"1024px": "lg",
"1280px": "xl",
"1536px": "2xl"
};
/**
* Transforms CSS @media queries to UnoCSS responsive utilities
* @param code - The code containing @media queries
* @param isJsx - Whether the code is JSX/TSX format
* @param isRem - Whether to convert px values to rem
* @param filepath - The file path for resolving CSS imports within media queries
* @param debug - Whether to enable debug logging
* @param globalCss - Global CSS configuration for preprocessors
* @returns A tuple of [transformed code, restore function]
*/
async function transformMedia(code, isJsx, isRem$1, filepath, debug = false, globalCss) {
const transferBackMap = [];
let result = code;
const matcher = code.match(mediaReg);
if (!matcher) {
if (debug) console.log("[DEBUG] transformMedia: No @media queries found");
return returnValue(result);
}
if (debug) console.log("[DEBUG] transformMedia started:", JSON.stringify({
filepath,
isJsx,
isRem: isRem$1,
mediaQueriesCount: matcher.length
}, null, 2));
for await (const item of matcher) {
const [all, pre, key, val, inner] = item.match(mediaSingleReg);
const tempFlag = `/* __transformMedia${Math.random()}__ */`;
const value = valMap[val];
const mediaValue = getMediaValue(pre, key, value, val);
if (debug) console.log("[DEBUG] transformMedia processing query:", JSON.stringify({
all: `${all.substring(0, 100)}...`,
key,
val,
mappedValue: value,
hasPrefix: !!pre.trim()
}, null, 2));
if (!mediaValue) {
result = result.replace(all, tempFlag);
transferBackMap.push((r) => r.replace(tempFlag, all));
continue;
}
const transfer = (await transformCss(inner, result, mediaValue, isJsx, filepath, isRem$1, debug, globalCss)).replace(emptyMediaReg, "");
result = transfer.replace(all, tempFlag);
transferBackMap.push((r) => r.replace(tempFlag, all));
}
return returnValue(result);
function returnValue(result$1) {
return [result$1, (r) => transferBackMap.reduce((result$2, fn) => fn(result$2), r)];
}
}
function getMediaValue(pre, key, value, rawValue) {
if (key === "prefers-reduced-motion") return `${(0, transform_to_unocss_core.getLastName)(key)}-${rawValue === "no-preference" ? "safe" : rawValue || "reduce"}`;
if (!value) return;
const normalizedPre = pre.trim();
const isNegated = normalizedPre.startsWith("not");
if (key === "max-width") return isNegated ? value : `max-${value}`;
if (key === "min-width") return isNegated ? `max-${value}` : value;
return value;
}
//#endregion
//#region src/transformVue.ts
async function transformVue(code, options) {
const { isJsx, filepath, isRem: isRem$1, globalCss, debug, resolveAlias } = options || {};
if (typeof code !== "string") {
if (debug) console.warn(`[transform-to-unocss] transformVue received non-string code: ${typeof code}, filepath: ${filepath}`);
return String(code || "");
}
if (filepath && !filepath.endsWith(".vue") && !code.includes("<template>") && !code.includes("<script>") && !code.includes("<style>")) {
if (debug) console.warn(`[transform-to-unocss] transformVue called for non-Vue file: ${filepath}`);
return code;
}
const { parse: parse$1 } = await getVueCompilerSfc();
if (debug) console.log("[DEBUG] transformVue started:", JSON.stringify({
filepath,
isJsx,
isRem: isRem$1,
codeLength: code.length
}, null, 2));
const { descriptor: { template, styles }, errors } = parse$1(code);
if (errors.length || !template) {
if (debug && errors.length) console.log("[DEBUG] transformVue parse errors:", errors);
return code;
}
code = transformInlineStyle(code, isJsx, isRem$1, debug);
if (debug) console.log("[DEBUG] After inline style transformation");
const [transferMediaCode, transformBack] = await transformMedia(code, isJsx, isRem$1, filepath, debug, globalCss);
code = transferMediaCode;
if (styles.length) {
if (debug) console.log("[DEBUG] Processing styles:", JSON.stringify({ stylesCount: styles.length }, null, 2));
const stylesCount = styles.length;
for (let index = stylesCount - 1; index >= 0; index--) {
const currentStyles = parse$1(code).descriptor.styles;
const currentStyle = currentStyles[index];
if (!currentStyle) break;
const { attrs: { scoped }, content: style, lang = "css", loc: { start, end } } = currentStyle;
const css = await compilerCss(style, lang, filepath, globalCss, debug, resolveAlias);
if (!css) continue;
if (debug) console.log("[DEBUG] CSS compiled successfully:", JSON.stringify({
styleIndex: index,
originalStyleLength: style.length,
compiledCssLength: css.length,
scoped: !!scoped
}, null, 2));
code = `${code.slice(0, start.offset)}\n${css}\n${code.slice(end.offset)}`;
if (lang !== "css") {
const styleTagStart = code.lastIndexOf("<style", start.offset);
const styleTagEnd = code.indexOf(">", styleTagStart);
if (styleTagStart !== -1 && styleTagEnd !== -1) {
const styleTag = code.slice(styleTagStart, styleTagEnd + 1);
const nextStyleTag = styleTag.replace(/\s+lang=(['"]).*?\1/, "");
if (nextStyleTag !== styleTag) code = `${code.slice(0, styleTagStart)}${nextStyleTag}${code.slice(styleTagEnd + 1)}`;
}
}
if (scoped) code = await transformCss(css, code, "", isJsx, filepath, isRem$1, debug, globalCss, resolveAlias, index);
}
}
code = transformBack(code);
if (debug) console.log("[DEBUG] transformVue completed:", JSON.stringify({ finalCodeLength: code.length }, null, 2));
return prettierCode(code);
}
//#endregion
//#region src/transformAstro.ts
const STYLE_PLACEHOLDER$1 = "<!-- __TRANSFORM_TO_UNOCSS_STYLE__ -->";
async function transformAstro(code, options) {
const { filepath, isRem: isRem$1, globalCss, debug = false, resolveAlias } = options || {};
const frontmatterMatch = code.match(/^(---[\s\S]*?---\s*)/);
const frontmatter = (frontmatterMatch === null || frontmatterMatch === void 0 ? void 0 : frontmatterMatch[1]) ?? "";
const rest = code.slice(frontmatter.length);
const styleMatch = rest.match(/<style\b([^>]*)>([\s\S]*?)<\/style>/);
const template = styleMatch ? rest.replace(styleMatch[0], STYLE_PLACEHOLDER$1) : rest;
const styleA