如何 在代码中展示 问题
核心就是这三个问题:
- 如何打印出标记相应位置代码的 code frame(就是上图的打印格式)
- 如何实现语法高亮
- 如何在控制台打印颜色
如何打印 code frame
其实就是一个拼接字符串的过程,下面是拼接字符串的细节(了解即可):
传入了源代码、标记开始和结束的行列号,那么我们就能够计算出显示标记(marker “>”)的行是哪些,以及这些行的哪些列,然后依次对每一行代码做处理,如果本行没有标记则保持原样,如果本行有标记的话,那么就在开始打印一个 marker “>”,并且在下面打印一行 marker "^",最后一个标记行还要打印错误信息。
代码参考 ``
function generateCodeFrame(code, location, options = {}) {
const { start, end } = location;
const {
highlightCode = false,
message = '',
linesAbove = 2,
linesBelow = 2,
} = options;
// 将代码分割成行数组
const lines = code.split('\n');
const startLine = start.line - 1; // 转为 0 索引
const startColumn = start.column - 1;
// 上下文行范围
const startContext = Math.max(0, startLine - linesAbove);
const endContext = Math.min(lines.length, startLine + linesBelow + 1);
// 收集上下文行
const result = [];
for (let i = startContext; i < endContext; i++) {
const lineNumber = i + 1; // 转回 1 索引
const line = lines[i];
// 标记错误行
if (i === startLine) {
const pointer = ' '.repeat(startColumn) + '^'; // 指示器
result.push(`> ${lineNumber} | ${line}`);
result.push(` ${' '.repeat(lineNumber.toString().length)} | ${pointer}`);
if (message) {
result.push(` ${' '.repeat(lineNumber.toString().length)} | ${message}`);
}
} else {
result.push(` ${lineNumber} | ${line}`);
}
}
// 高亮代码(可选)
if (highlightCode) {
return result.join('\n'); // 模拟高亮,可以接入 chalk 库优化
}
return result.join('\n');
}
如何实现语法高亮
核心实现思路
-
代码分割和解析
- 按行分割代码,将其分解为更小的片段(单词、标点符号、字符串等)。
- 使用正则表达式或词法分析器对代码进行分类。
-
为代码添加颜色
- 不同类型的代码片段映射到不同的颜色(如关键字为蓝色,字符串为绿色)。
- 使用 ANSI 转义序列实现颜色渲染(或借助
chalk、kleur等库)。
-
重组和输出
- 将高亮后的片段组合回完整代码。
- 确保保留原始格式(如缩进和空行)。
如何在控制台打印颜色
代码 参考
const chalk = require('chalk');
// 定义高亮规则
const HIGHLIGHT_RULES = [
{ type: 'keyword', regex: /\b(function|return|const|let|var|if|else|for|while|switch|case|break|default)\b/g, color: chalk.blue },
{ type: 'string', regex: /(["'])(?:(?=(\\?))\2.)*?\1/g, color: chalk.green },
{ type: 'number', regex: /\b\d+(\.\d+)?\b/g, color: chalk.yellow },
{ type: 'comment', regex: /(\/\/.*$|\/\*[\s\S]*?\*\/)/gm, color: chalk.gray },
{ type: 'operator', regex: /[=+\-*/<>!&|]/g, color: chalk.red },
];
// 代码高亮函数
function highlightCode(code) {
let highlightedCode = code;
// 应用高亮规则
for (const rule of HIGHLIGHT_RULES) {
highlightedCode = highlightedCode.replace(rule.regex, match => rule.color(match));
}
return highlightedCode;
}
// 测试代码
const rawCode = `
function sum(a, b) {
const result = a + b; // Add two numbers
return result;
}
console.log(sum(1, 2)); // Output: 3
`;
console.log(highlightCode(rawCode));