添加获取颜色值

This commit is contained in:
icssoa 2025-07-26 17:39:45 +08:00
parent 79fd3b9093
commit 09d4697629
5 changed files with 346 additions and 13 deletions

View File

@ -92,13 +92,69 @@
function readFile(path, json) {
try {
const content = fs.readFileSync(path, "utf8");
return json
? JSON.parse(content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, ""))
: content;
return json ? JSON.parse(removeJsonComments(content)) : content;
}
catch (err) { }
return "";
}
// 安全地移除JSON中的注释
function removeJsonComments(content) {
let result = "";
let inString = false;
let stringChar = "";
let escaped = false;
let i = 0;
while (i < content.length) {
const char = content[i];
const nextChar = content[i + 1];
// 处理字符串状态
if (!inString && (char === '"' || char === "'")) {
inString = true;
stringChar = char;
result += char;
}
else if (inString && char === stringChar && !escaped) {
inString = false;
stringChar = "";
result += char;
}
else if (inString) {
// 在字符串内,直接添加字符
result += char;
escaped = char === "\\" && !escaped;
}
else {
// 不在字符串内,检查注释
if (char === "/" && nextChar === "/") {
// 单行注释,跳过到行尾
while (i < content.length && content[i] !== "\n") {
i++;
}
if (i < content.length) {
result += content[i]; // 保留换行符
}
}
else if (char === "/" && nextChar === "*") {
// 多行注释,跳过到 */
i += 2;
while (i < content.length - 1) {
if (content[i] === "*" && content[i + 1] === "/") {
i += 2;
break;
}
i++;
}
continue;
}
else {
result += char;
escaped = false;
}
}
i++;
}
return result;
}
// 写入文件
function writeFile(path, data) {
try {
@ -138,6 +194,26 @@
function error(message) {
console.log("\x1B[31m%s\x1B[0m", message);
}
/**
* 比较两个版本号
* @param version1 版本号1 (: "1.2.3")
* @param version2 版本号2 (: "1.2.4")
* @returns 1: version1 > version2, 0: 相等, -1: version1 < version2
*/
function compareVersion(version1, version2) {
const v1Parts = version1.split(".").map(Number);
const v2Parts = version2.split(".").map(Number);
const maxLength = Math.max(v1Parts.length, v2Parts.length);
for (let i = 0; i < maxLength; i++) {
const v1Part = v1Parts[i] || 0;
const v2Part = v2Parts[i] || 0;
if (v1Part > v2Part)
return 1;
if (v1Part < v2Part)
return -1;
}
return 0;
}
/**
* 将模板字符串扁平化处理转换为 Service 类型定义
@ -2176,6 +2252,70 @@ if (typeof window !== 'undefined') {
return [postcssPlugin(), transformPlugin()];
}
// 获取 tailwind.config.ts 中的颜色
function getTailwindColor() {
const config = readFile(rootDir("tailwind.config.ts"));
if (!config) {
return null;
}
try {
// 从配置文件中动态提取主色和表面色
const colorResult = {};
// 提取 getPrimary 调用中的颜色名称
const primaryMatch = config.match(/getPrimary\(["']([^"']+)["']\)/);
const primaryColorName = primaryMatch?.[1];
// 提取 getSurface 调用中的颜色名称
const surfaceMatch = config.match(/getSurface\(["']([^"']+)["']\)/);
const surfaceColorName = surfaceMatch?.[1];
if (primaryColorName) {
// 提取 PRIMARY_COLOR_PALETTES 中对应的调色板
const primaryPaletteMatch = config.match(new RegExp(`{\\s*name:\\s*["']${primaryColorName}["'],\\s*palette:\\s*({[^}]+})`, "s"));
if (primaryPaletteMatch) {
// 解析调色板对象
const paletteStr = primaryPaletteMatch[1];
const paletteEntries = paletteStr.match(/(\d+):\s*["']([^"']+)["']/g);
if (paletteEntries) {
paletteEntries.forEach((entry) => {
const match = entry.match(/(\d+):\s*["']([^"']+)["']/);
if (match) {
const [, key, value] = match;
colorResult[`primary-${key}`] = value;
}
});
}
}
}
if (surfaceColorName) {
// 提取 SURFACE_PALETTES 中对应的调色板
const surfacePaletteMatch = config.match(new RegExp(`{\\s*name:\\s*["']${surfaceColorName}["'],\\s*palette:\\s*({[^}]+})`, "s"));
if (surfacePaletteMatch) {
// 解析调色板对象
const paletteStr = surfacePaletteMatch[1];
const paletteEntries = paletteStr.match(/(\d+):\s*["']([^"']+)["']/g);
if (paletteEntries) {
paletteEntries.forEach((entry) => {
const match = entry.match(/(\d+):\s*["']([^"']+)["']/);
if (match) {
const [, key, value] = match;
// 0 对应 surface其他对应 surface-*
const colorKey = key === "0" ? "surface" : `surface-${key}`;
colorResult[colorKey] = value;
}
});
}
}
}
return colorResult;
}
catch (error) {
return null;
}
}
// 获取版本号
function getVersion() {
const pkg = readFile(rootDir("package.json"), true);
return pkg?.version || "0.0.0";
}
function codePlugin() {
return [
{
@ -2184,12 +2324,21 @@ if (typeof window !== 'undefined') {
async transform(code, id) {
if (id.includes("/cool/ctx/index.ts")) {
const ctx = await createCtx();
const theme = await readFile(rootDir("theme.json"), true);
// 版本
const version = getVersion();
// 主题配置
const theme = readFile(rootDir("theme.json"), true);
// 主题配置
ctx["theme"] = theme;
if (compareVersion(version, "8.0.2") >= 0) {
// 颜色值
ctx["color"] = getTailwindColor();
}
// 安全字符映射
ctx["SAFE_CHAR_MAP_LOCALE"] = [];
for (const i in SAFE_CHAR_MAP_LOCALE) {
ctx["SAFE_CHAR_MAP_LOCALE"].push([i, SAFE_CHAR_MAP_LOCALE[i]]);
}
ctx["theme"] = theme;
code = code.replace("const ctx = {}", `const ctx = ${JSON.stringify(ctx, null, 4)}`);
}
if (id.includes("/cool/service/index.ts")) {

View File

@ -9,3 +9,10 @@ export declare function parseJson(req: any): Promise<any>;
export declare function formatContent(content: string, options?: prettier.Options): Promise<string>;
export declare function error(message: string): void;
export declare function success(message: string): void;
/**
*
* @param version1 1 (: "1.2.3")
* @param version2 2 (: "1.2.4")
* @returns 1: version1 > version2, 0: 相等, -1: version1 < version2
*/
export declare function compareVersion(version1: string, version2: string): number;

View File

@ -1,6 +1,6 @@
{
"name": "@cool-vue/vite-plugin",
"version": "8.2.4",
"version": "8.2.5",
"description": "cool-admin、cool-uni builder",
"types": "./dist/index.d.ts",
"main": "/dist/index.js",

View File

@ -1,10 +1,96 @@
import type { Plugin } from "vite";
import { SAFE_CHAR_MAP_LOCALE } from "./config";
import { createCtx } from "../ctx";
import { readFile, rootDir } from "../utils";
import { compareVersion, readFile, rootDir } from "../utils";
import { createEps } from "../eps";
import { uniq } from "lodash";
// 获取 tailwind.config.ts 中的颜色
function getTailwindColor() {
const config = readFile(rootDir("tailwind.config.ts"));
if (!config) {
return null;
}
try {
// 从配置文件中动态提取主色和表面色
const colorResult: Record<string, string> = {};
// 提取 getPrimary 调用中的颜色名称
const primaryMatch = config.match(/getPrimary\(["']([^"']+)["']\)/);
const primaryColorName = primaryMatch?.[1];
// 提取 getSurface 调用中的颜色名称
const surfaceMatch = config.match(/getSurface\(["']([^"']+)["']\)/);
const surfaceColorName = surfaceMatch?.[1];
if (primaryColorName) {
// 提取 PRIMARY_COLOR_PALETTES 中对应的调色板
const primaryPaletteMatch = config.match(
new RegExp(
`{\\s*name:\\s*["']${primaryColorName}["'],\\s*palette:\\s*({[^}]+})`,
"s",
),
);
if (primaryPaletteMatch) {
// 解析调色板对象
const paletteStr = primaryPaletteMatch[1];
const paletteEntries = paletteStr.match(/(\d+):\s*["']([^"']+)["']/g);
if (paletteEntries) {
paletteEntries.forEach((entry: string) => {
const match = entry.match(/(\d+):\s*["']([^"']+)["']/);
if (match) {
const [, key, value] = match;
colorResult[`primary-${key}`] = value;
}
});
}
}
}
if (surfaceColorName) {
// 提取 SURFACE_PALETTES 中对应的调色板
const surfacePaletteMatch = config.match(
new RegExp(
`{\\s*name:\\s*["']${surfaceColorName}["'],\\s*palette:\\s*({[^}]+})`,
"s",
),
);
if (surfacePaletteMatch) {
// 解析调色板对象
const paletteStr = surfacePaletteMatch[1];
const paletteEntries = paletteStr.match(/(\d+):\s*["']([^"']+)["']/g);
if (paletteEntries) {
paletteEntries.forEach((entry: string) => {
const match = entry.match(/(\d+):\s*["']([^"']+)["']/);
if (match) {
const [, key, value] = match;
// 0 对应 surface其他对应 surface-*
const colorKey = key === "0" ? "surface" : `surface-${key}`;
colorResult[colorKey] = value;
}
});
}
}
}
return colorResult;
} catch (error) {
return null;
}
}
// 获取版本号
function getVersion() {
const pkg = readFile(rootDir("package.json"), true);
return pkg?.version || "0.0.0";
}
export function codePlugin(): Plugin[] {
return [
{
@ -13,15 +99,27 @@ export function codePlugin(): Plugin[] {
async transform(code, id) {
if (id.includes("/cool/ctx/index.ts")) {
const ctx = await createCtx();
const theme = await readFile(rootDir("theme.json"), true);
// 版本
const version = getVersion();
// 主题配置
const theme = readFile(rootDir("theme.json"), true);
// 主题配置
ctx["theme"] = theme;
if (compareVersion(version, "8.0.2") >= 0) {
// 颜色值
ctx["color"] = getTailwindColor();
}
// 安全字符映射
ctx["SAFE_CHAR_MAP_LOCALE"] = [];
for (const i in SAFE_CHAR_MAP_LOCALE) {
ctx["SAFE_CHAR_MAP_LOCALE"].push([i, SAFE_CHAR_MAP_LOCALE[i]]);
}
ctx["theme"] = theme;
code = code.replace(
"const ctx = {}",
`const ctx = ${JSON.stringify(ctx, null, 4)}`,

View File

@ -40,14 +40,70 @@ export function createDir(path: string, recursive?: boolean) {
export function readFile(path: string, json?: boolean) {
try {
const content = fs.readFileSync(path, "utf8");
return json
? JSON.parse(content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, ""))
: content;
return json ? JSON.parse(removeJsonComments(content)) : content;
} catch (err) {}
return "";
}
// 安全地移除JSON中的注释
function removeJsonComments(content: string): string {
let result = "";
let inString = false;
let stringChar = "";
let escaped = false;
let i = 0;
while (i < content.length) {
const char = content[i];
const nextChar = content[i + 1];
// 处理字符串状态
if (!inString && (char === '"' || char === "'")) {
inString = true;
stringChar = char;
result += char;
} else if (inString && char === stringChar && !escaped) {
inString = false;
stringChar = "";
result += char;
} else if (inString) {
// 在字符串内,直接添加字符
result += char;
escaped = char === "\\" && !escaped;
} else {
// 不在字符串内,检查注释
if (char === "/" && nextChar === "/") {
// 单行注释,跳过到行尾
while (i < content.length && content[i] !== "\n") {
i++;
}
if (i < content.length) {
result += content[i]; // 保留换行符
}
} else if (char === "/" && nextChar === "*") {
// 多行注释,跳过到 */
i += 2;
while (i < content.length - 1) {
if (content[i] === "*" && content[i + 1] === "/") {
i += 2;
break;
}
i++;
}
continue;
} else {
result += char;
escaped = false;
}
}
i++;
}
return result;
}
// 写入文件
export function writeFile(path: string, data: any) {
try {
@ -93,3 +149,26 @@ export function error(message: string) {
export function success(message: string) {
console.log("\x1B[32m%s\x1B[0m", message);
}
/**
*
* @param version1 1 (: "1.2.3")
* @param version2 2 (: "1.2.4")
* @returns 1: version1 > version2, 0: 相等, -1: version1 < version2
*/
export function compareVersion(version1: string, version2: string): number {
const v1Parts = version1.split(".").map(Number);
const v2Parts = version2.split(".").map(Number);
const maxLength = Math.max(v1Parts.length, v2Parts.length);
for (let i = 0; i < maxLength; i++) {
const v1Part = v1Parts[i] || 0;
const v2Part = v2Parts[i] || 0;
if (v1Part > v2Part) return 1;
if (v1Part < v2Part) return -1;
}
return 0;
}