This commit is contained in:
icssoa 2025-06-10 22:28:29 +08:00
parent d656cddfd3
commit b4eefaa8e4
4 changed files with 172 additions and 39 deletions

View File

@ -272,11 +272,11 @@
/** /**
* 获取类名 * 获取类名
*/ */
function getClassNames(html) { function getClassNames(code) {
const classRegex = /(?:class|:class|:pt)\s*=\s*(['"`])([\s\S]*?)\1/gi; const classRegex = /(?:class|:class|:pt)\s*=\s*(['"`])([\s\S]*?)\1/gi;
const classNames = new Set(); const classNames = new Set();
let match; let match;
while ((match = classRegex.exec(html)) !== null) { while ((match = classRegex.exec(code)) !== null) {
const isStaticClass = match[0].startsWith("class"); const isStaticClass = match[0].startsWith("class");
const value = match[2].trim(); const value = match[2].trim();
if (isStaticClass) { if (isStaticClass) {
@ -293,11 +293,11 @@
/** /**
* 获取 class 内容 * 获取 class 内容
*/ */
function getClassContent(html) { function getClassContent(code) {
const regex = /(?:class|:class|:pt)\s*=\s*(['"`])([\s\S]*?)\1/g; const regex = /(?:class|:class|:pt)\s*=\s*(['"`])([\s\S]*?)\1/g;
const texts = []; const texts = [];
let match; let match;
while ((match = regex.exec(html)) !== null) { while ((match = regex.exec(code)) !== null) {
texts.push(match[2]); texts.push(match[2]);
} }
return texts; return texts;
@ -307,20 +307,79 @@
*/ */
function getNodes(code) { function getNodes(code) {
const nodes = []; const nodes = [];
const templateRegex = /<template[^>]*>([\s\S]*?)<\/template>/g; // 找到所有顶级template标签的完整内容
let templateMatch; function findTemplateContents(content) {
// 找到所有的 template 标签内容 const results = [];
while ((templateMatch = templateRegex.exec(code)) !== null) { let index = 0;
const templateContent = templateMatch[1]; while (index < content.length) {
const templateStart = content.indexOf("<template", index);
if (templateStart === -1)
break;
// 找到模板标签的结束位置
const tagEnd = content.indexOf(">", templateStart);
if (tagEnd === -1)
break;
// 使用栈来匹配配对的template标签
let stack = 1;
let currentPos = tagEnd + 1;
while (currentPos < content.length && stack > 0) {
const nextTemplateStart = content.indexOf("<template", currentPos);
const nextTemplateEnd = content.indexOf("</template>", currentPos);
if (nextTemplateEnd === -1)
break;
// 如果开始标签更近,说明有嵌套
if (nextTemplateStart !== -1 && nextTemplateStart < nextTemplateEnd) {
// 找到开始标签的完整结束
const nestedTagEnd = content.indexOf(">", nextTemplateStart);
if (nestedTagEnd !== -1) {
stack++;
currentPos = nestedTagEnd + 1;
}
else {
break;
}
}
else {
// 找到结束标签
stack--;
currentPos = nextTemplateEnd + 11; // '</template>'.length
}
}
if (stack === 0) {
// 提取template内容不包括template标签本身
const templateContent = content.substring(tagEnd + 1, currentPos - 11);
results.push(templateContent);
index = currentPos;
}
else {
// 如果没有找到匹配的结束标签,跳过这个开始标签
index = tagEnd + 1;
}
}
return results;
}
// 递归提取所有template内容中的节点
function extractNodesFromContent(content) {
// 先提取当前内容中的所有标签
const regex = /<([^>]+)>/g; const regex = /<([^>]+)>/g;
let match; let match;
// 提取每个 template 中的所有标签 while ((match = regex.exec(content)) !== null) {
while ((match = regex.exec(templateContent)) !== null) { if (!match[1].startsWith("/") && !match[1].startsWith("template")) {
if (!match[1].startsWith("/")) {
nodes.push(match[1]); nodes.push(match[1]);
} }
} }
// 递归处理嵌套的template
const nestedTemplates = findTemplateContents(content);
nestedTemplates.forEach((templateContent) => {
extractNodesFromContent(templateContent);
});
} }
// 获取所有顶级template内容
const templateContents = findTemplateContents(code);
// 处理每个template内容
templateContents.forEach((templateContent) => {
extractNodesFromContent(templateContent);
});
return nodes.map((e) => `<${e}>`); return nodes.map((e) => `<${e}>`);
} }
/** /**
@ -1703,9 +1762,18 @@ if (typeof window !== 'undefined') {
// 处理文本大小相关样式 // 处理文本大小相关样式
if (decl.value.includes("rpx") && if (decl.value.includes("rpx") &&
decl.prop == "color" && decl.prop == "color" &&
decl.parent.selector.includes("text-")) { decl.parent.selector?.includes("text-")) {
decl.prop = "font-size"; decl.prop = "font-size";
} }
// 删除不支持的属性
if (["filter"].includes(decl.prop)) {
decl.remove();
return;
}
// 处理 flex-1
if (decl.prop == "flex") {
decl.value = "1";
}
// 解析声明值 // 解析声明值
const parsed = valueParser(decl.value); const parsed = valueParser(decl.value);
let hasChanges = false; let hasChanges = false;
@ -1735,11 +1803,6 @@ if (typeof window !== 'undefined') {
if (hasChanges) { if (hasChanges) {
decl.value = parsed.toString(); decl.value = parsed.toString();
} }
// 删除不支持的属性
if (["filter"].includes(decl.prop)) {
decl.remove();
return;
}
// 移除 undefined // 移除 undefined
decl.value = decl.value.replaceAll(" undefined", ""); decl.value = decl.value.replaceAll(" undefined", "");
}, },

View File

@ -5,11 +5,11 @@ export declare const getDynamicClassNames: (value: string) => string[];
/** /**
* *
*/ */
export declare function getClassNames(html: string): string[]; export declare function getClassNames(code: string): string[];
/** /**
* class * class
*/ */
export declare function getClassContent(html: string): string[]; export declare function getClassContent(code: string): string[];
/** /**
* *
*/ */

View File

@ -150,11 +150,22 @@ function postcssPlugin(): Plugin {
if ( if (
decl.value.includes("rpx") && decl.value.includes("rpx") &&
decl.prop == "color" && decl.prop == "color" &&
decl.parent.selector.includes("text-") decl.parent.selector?.includes("text-")
) { ) {
decl.prop = "font-size"; decl.prop = "font-size";
} }
// 删除不支持的属性
if (["filter"].includes(decl.prop)) {
decl.remove();
return;
}
// 处理 flex-1
if (decl.prop == "flex") {
decl.value = "1";
}
// 解析声明值 // 解析声明值
const parsed = valueParser(decl.value); const parsed = valueParser(decl.value);
let hasChanges = false; let hasChanges = false;
@ -191,12 +202,6 @@ function postcssPlugin(): Plugin {
decl.value = parsed.toString(); decl.value = parsed.toString();
} }
// 删除不支持的属性
if (["filter"].includes(decl.prop)) {
decl.remove();
return;
}
// 移除 undefined // 移除 undefined
decl.value = decl.value.replaceAll(" undefined", ""); decl.value = decl.value.replaceAll(" undefined", "");
}, },

View File

@ -57,12 +57,12 @@ export const getDynamicClassNames = (value: string): string[] => {
/** /**
* *
*/ */
export function getClassNames(html: string): string[] { export function getClassNames(code: string): string[] {
const classRegex = /(?:class|:class|:pt)\s*=\s*(['"`])([\s\S]*?)\1/gi; const classRegex = /(?:class|:class|:pt)\s*=\s*(['"`])([\s\S]*?)\1/gi;
const classNames = new Set<string>(); const classNames = new Set<string>();
let match; let match;
while ((match = classRegex.exec(html)) !== null) { while ((match = classRegex.exec(code)) !== null) {
const isStaticClass = match[0].startsWith("class"); const isStaticClass = match[0].startsWith("class");
const value = match[2].trim(); const value = match[2].trim();
@ -81,12 +81,12 @@ export function getClassNames(html: string): string[] {
/** /**
* class * class
*/ */
export function getClassContent(html: string) { export function getClassContent(code: string) {
const regex = /(?:class|:class|:pt)\s*=\s*(['"`])([\s\S]*?)\1/g; const regex = /(?:class|:class|:pt)\s*=\s*(['"`])([\s\S]*?)\1/g;
const texts: string[] = []; const texts: string[] = [];
let match; let match;
while ((match = regex.exec(html)) !== null) { while ((match = regex.exec(code)) !== null) {
texts.push(match[2]); texts.push(match[2]);
} }
@ -98,23 +98,88 @@ export function getClassContent(html: string) {
*/ */
export function getNodes(code: string) { export function getNodes(code: string) {
const nodes: string[] = []; const nodes: string[] = [];
const templateRegex = /<template[^>]*>([\s\S]*?)<\/template>/g;
let templateMatch;
// 找到所有的 template 标签内容 // 找到所有顶级template标签的完整内容
while ((templateMatch = templateRegex.exec(code)) !== null) { function findTemplateContents(content: string): string[] {
const templateContent = templateMatch[1]; const results: string[] = [];
let index = 0;
while (index < content.length) {
const templateStart = content.indexOf("<template", index);
if (templateStart === -1) break;
// 找到模板标签的结束位置
const tagEnd = content.indexOf(">", templateStart);
if (tagEnd === -1) break;
// 使用栈来匹配配对的template标签
let stack = 1;
let currentPos = tagEnd + 1;
while (currentPos < content.length && stack > 0) {
const nextTemplateStart = content.indexOf("<template", currentPos);
const nextTemplateEnd = content.indexOf("</template>", currentPos);
if (nextTemplateEnd === -1) break;
// 如果开始标签更近,说明有嵌套
if (nextTemplateStart !== -1 && nextTemplateStart < nextTemplateEnd) {
// 找到开始标签的完整结束
const nestedTagEnd = content.indexOf(">", nextTemplateStart);
if (nestedTagEnd !== -1) {
stack++;
currentPos = nestedTagEnd + 1;
} else {
break;
}
} else {
// 找到结束标签
stack--;
currentPos = nextTemplateEnd + 11; // '</template>'.length
}
}
if (stack === 0) {
// 提取template内容不包括template标签本身
const templateContent = content.substring(tagEnd + 1, currentPos - 11);
results.push(templateContent);
index = currentPos;
} else {
// 如果没有找到匹配的结束标签,跳过这个开始标签
index = tagEnd + 1;
}
}
return results;
}
// 递归提取所有template内容中的节点
function extractNodesFromContent(content: string): void {
// 先提取当前内容中的所有标签
const regex = /<([^>]+)>/g; const regex = /<([^>]+)>/g;
let match; let match;
// 提取每个 template 中的所有标签 while ((match = regex.exec(content)) !== null) {
while ((match = regex.exec(templateContent)) !== null) { if (!match[1].startsWith("/") && !match[1].startsWith("template")) {
if (!match[1].startsWith("/")) {
nodes.push(match[1]); nodes.push(match[1]);
} }
} }
// 递归处理嵌套的template
const nestedTemplates = findTemplateContents(content);
nestedTemplates.forEach((templateContent) => {
extractNodesFromContent(templateContent);
});
} }
// 获取所有顶级template内容
const templateContents = findTemplateContents(code);
// 处理每个template内容
templateContents.forEach((templateContent) => {
extractNodesFromContent(templateContent);
});
return nodes.map((e) => `<${e}>`); return nodes.map((e) => `<${e}>`);
} }