mixone
Version:
MixOne is a Node scaffolding tool implemented based on Vite, used for compiling HTML5, JavasCript, Vue, React and other codes. It supports packaging Web applications with multiple HTML entry points (BS architecture) and desktop installation packages (CS a
155 lines (133 loc) • 4.69 kB
JavaScript
// logger.js
const Logger = function (prefix) {
this.prefix = prefix;
// 定义颜色和样式的 ANSI 转义码
this.colors = {
black: 30, // #000000 (黑色)
red: 31, // #FF0000 (红色)
green: 32, // #00FF00 (绿色)
yellow: 33, // #FFFF00 (黄色)
blue: 34, // #0000FF (蓝色)
magenta: 35, // #FF00FF (品红)
cyan: 36, // #00FFFF (青色)
white: 37, // #FFFFFF (白色)
gray: 90, // #808080 (灰色)
brightRed: 91, // #FF6060 (亮红色)
brightGreen: 92, // #60FF60 (亮绿色)
brightYellow: 93, // #FFFF60 (亮黄色)
brightBlue: 94, // #6060FF (亮蓝色)
brightMagenta: 95,// #FF60FF (亮品红)
brightCyan: 96, // #60FFFF (亮青色)
brightWhite: 97, // #FFFFFF (亮白色)
};
// 样式定义
this.styles = {
reset: 0,
bold: 1,
underline: 4,
inverse: 7,
hidden: 8,
};
// 解析标签并返回相应的 ANSI 转义码
this.parseStyledText = function(input) {
const result = [];
const tagRegex = /<(\/?)([a-zA-Z]+)(?:\s+([a-zA-Z]+))?>/g;
let lastIndex = 0;
const stack = [];
let match;
while ((match = tagRegex.exec(input)) !== null) {
const [fullMatch, slash, tagName, attr] = match;
const index = match.index;
// 推送标签之间未被包裹的纯文本(只有在 tag 栈为空时才算“未包裹”)
if (!slash && lastIndex < index && stack.length === 0) {
const plainText = input.slice(lastIndex, index);
result.push({
color: 'white',
bold: false,
underline: false,
text: plainText
});
}
if (!slash) {
// 处理起始标签
let color = 'white';
let bold = false;
let underline = false;
if (tagName === 'b') {
bold = true;
} else if (tagName === 'ul') {
underline = true;
} else {
color = tagName;
bold = attr === 'bold';
}
stack.push({ tagName, color, bold, underline, start: tagRegex.lastIndex });
} else {
// 处理结束标签
const openTag = stack.pop();
if (openTag && openTag.tagName === tagName) {
const content = input.slice(openTag.start, index);
result.push({
color: openTag.color,
bold: openTag.bold,
underline: openTag.underline,
text: content
});
}
}
lastIndex = tagRegex.lastIndex;
}
// 处理最后剩余的纯文本(如果没有包裹)
if (lastIndex < input.length && stack.length === 0) {
const remaining = input.slice(lastIndex);
result.push({
color: 'white',
bold: false,
underline: false,
text: remaining
});
}
return result;
};
this.parseTag = function (tagName, isClosing = false) {
const color = tagName === 'b' || tagName === 'ul' ? 'white' : tagName;
const style = tagName === 'b' ? 'bold' : tagName === 'ul' ? 'underline' : undefined;
let colorCode = this.colors[color] || this.colors.white;
let styleCode = this.styles.reset;
if (style === 'bold') styleCode = this.styles.bold;
else if (style === 'underline') styleCode = this.styles.underline;
const escapeCode = `\x1b[${styleCode};${colorCode}m`;
const resetCode = `\x1b[${this.styles.reset}m`;
return isClosing ? resetCode : escapeCode;
};
// 输出日志
this.log = function (message) {
const prefixWithStyles = this.parseStyledText(this.prefix);
const msgWithStyles = this.parseStyledText(message);
const WithStyles = [...prefixWithStyles, ...msgWithStyles];
let output = '';
WithStyles.forEach(item => {
// 获取颜色代码
const colorCode = this.colors[item.color] || this.colors.white;
// 初始化样式代码
let styleCode = this.styles.reset;
// 检查粗体和下划线
if (item.bold) styleCode |= this.styles.bold;
if (item.underline) styleCode |= this.styles.underline;
// 添加样式
output += `\x1b[${styleCode};${colorCode}m${item.text}\x1b[${this.styles.reset}m`;
}, this);
console.log(output);
};
};
// 工厂函数
function createLogger(prefix) {
const instance = new Logger(prefix);
return instance.log.bind(instance);
}
module.exports = {
Logger,
createLogger,
colors: Logger.colors,
styles: Logger.styles
};