201 lines
7.2 KiB
JavaScript
201 lines
7.2 KiB
JavaScript
|
|
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|||
|
|
exports.getSquirrelBeautifyOptions = getSquirrelBeautifyOptions;
|
|||
|
|
exports.beautifyCode = beautifyCode;
|
|||
|
|
exports.isSquirrelCode = isSquirrelCode;
|
|||
|
|
// 由于 js-beautify.js 文件体积较大且复杂,我们将创建专门的存根函数
|
|||
|
|
// 将使用原生的 js-beautify 功能
|
|||
|
|
let _jsBeauifyInstance = null;
|
|||
|
|
/**
|
|||
|
|
* 动态创建 js_beautify 函数
|
|||
|
|
*/
|
|||
|
|
function createJsBeautify() {
|
|||
|
|
if (_jsBeauifyInstance) {
|
|||
|
|
return _jsBeauifyInstance;
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
// 加载原始的 js-beautify.js 文件
|
|||
|
|
const beautifyModule = loadJsBeautify();
|
|||
|
|
_jsBeauifyInstance = beautifyModule;
|
|||
|
|
return _jsBeauifyInstance;
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
console.error('加载 js-beautify 失败,使用后备实现:', error);
|
|||
|
|
// 调用后备实现
|
|||
|
|
return createBasicJsBeautify();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 加载 js-beautify 模块
|
|||
|
|
*/
|
|||
|
|
function loadJsBeautify() {
|
|||
|
|
// 根据环境动态加载
|
|||
|
|
try {
|
|||
|
|
// 尝试 require 原始的 js-beautify.js 文件
|
|||
|
|
// 注意:TypeScript 会从 ./dist 目录运行,所以需要从正确的路径加载
|
|||
|
|
const beautifyPath = __dirname + '/../../js-beautify.js';
|
|||
|
|
const Module = require('module');
|
|||
|
|
const vm = require('vm');
|
|||
|
|
const fs = require('fs');
|
|||
|
|
// 读取文件内容
|
|||
|
|
const code = fs.readFileSync(beautifyPath, 'utf8');
|
|||
|
|
// 设置全局环境
|
|||
|
|
const sandbox = {
|
|||
|
|
window: {},
|
|||
|
|
global: {},
|
|||
|
|
console: console,
|
|||
|
|
String: String,
|
|||
|
|
Array: Array,
|
|||
|
|
Object: Object,
|
|||
|
|
Math: Math
|
|||
|
|
};
|
|||
|
|
// 在沙箱中执行代码
|
|||
|
|
const script = new vm.Script(code);
|
|||
|
|
const context = vm.createContext(sandbox);
|
|||
|
|
script.runInContext(context);
|
|||
|
|
// 获取 js_beautify 函数
|
|||
|
|
return context.window.js_beautify || context.js_beautify || sandbox.window.js_beautify;
|
|||
|
|
}
|
|||
|
|
catch (loadError) {
|
|||
|
|
console.error('无法加载原始 js-beautify, 错误:', loadError);
|
|||
|
|
throw loadError;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 基础的 js-beautify 实现(后备方案)
|
|||
|
|
*/
|
|||
|
|
function createBasicJsBeautify() {
|
|||
|
|
return function (code, options = {}) {
|
|||
|
|
// 默认选项
|
|||
|
|
const defaultOptions = {
|
|||
|
|
indent_size: 4,
|
|||
|
|
indent_char: ' ',
|
|||
|
|
preserve_newlines: true,
|
|||
|
|
brace_style: 'collapse',
|
|||
|
|
space_before_conditional: true,
|
|||
|
|
space_after_anon_function: false,
|
|||
|
|
wrap_line_length: 120,
|
|||
|
|
end_with_newline: false
|
|||
|
|
};
|
|||
|
|
// 合并选项
|
|||
|
|
const opts = { ...defaultOptions, ...options };
|
|||
|
|
// 简化的代码美化实现
|
|||
|
|
let formatted = code;
|
|||
|
|
// 清理缩进
|
|||
|
|
formatted = formatted.replace(/[\r\n]+/g, '\n');
|
|||
|
|
const lines = formatted.split('\n');
|
|||
|
|
const result = [];
|
|||
|
|
let indentLevel = 0;
|
|||
|
|
const indentStr = opts.indent_char.repeat(opts.indent_size);
|
|||
|
|
for (const line of lines) {
|
|||
|
|
const trimmed = line.trim();
|
|||
|
|
// 跳过空行
|
|||
|
|
if (trimmed.length === 0) {
|
|||
|
|
result.push('');
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
// 处理大括号
|
|||
|
|
if (trimmed.startsWith('}') || trimmed.startsWith(')') || trimmed.startsWith(']')) {
|
|||
|
|
indentLevel = Math.max(0, indentLevel - 1);
|
|||
|
|
}
|
|||
|
|
// 添加缩进
|
|||
|
|
const indentedLine = indentStr.repeat(indentLevel) + trimmed;
|
|||
|
|
result.push(indentedLine);
|
|||
|
|
// 增加缩进
|
|||
|
|
if (trimmed.endsWith('{') || trimmed.endsWith('(') || trimmed.endsWith('[')) {
|
|||
|
|
indentLevel++;
|
|||
|
|
}
|
|||
|
|
// 特殊处理 else、catch 等关键字
|
|||
|
|
if (trimmed.startsWith('else') || trimmed.startsWith('catch') || trimmed.startsWith('elif')) {
|
|||
|
|
// 检查前面一行是否以 } 结尾
|
|||
|
|
if (result.length > 1) {
|
|||
|
|
const prevLine = result[result.length - 2];
|
|||
|
|
const prevTrimmed = prevLine.trim();
|
|||
|
|
if (prevTrimmed.endsWith('}')) {
|
|||
|
|
// 移动到前一行的必要部分
|
|||
|
|
result[result.length - 2] = indentStr.repeat(indentLevel - 1) +
|
|||
|
|
prevTrimmed + ' ' + trimmed;
|
|||
|
|
result.pop(); // 移除当前行
|
|||
|
|
indentLevel--; // 修正缩进级别
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
let finalResult = result.join('\n');
|
|||
|
|
// 处理空格 - 在操作符周围添加空格
|
|||
|
|
finalResult = finalResult
|
|||
|
|
.replace(/([a-zA-Z0-9_$])([=!<>+\-*/%])([a-zA-Z0-9_$])/g, '$1 $2 $3')
|
|||
|
|
.replace(/([a-zA-Z0-9_$])(,)([a-zA-Z0-9_$])/g, '$1$2 $3')
|
|||
|
|
.replace(/\s+/g, ' ') // 将多个空格替换为单个空格
|
|||
|
|
.trim();
|
|||
|
|
return finalResult;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
// 初始化 js_beautify
|
|||
|
|
const jsBeautify = {
|
|||
|
|
js_beautify: createJsBeautify()
|
|||
|
|
};
|
|||
|
|
/**
|
|||
|
|
* Squirrel 语言的 js-beautify 选项配置
|
|||
|
|
*/
|
|||
|
|
function getSquirrelBeautifyOptions(options) {
|
|||
|
|
return {
|
|||
|
|
indent_size: options.tabSize,
|
|||
|
|
indent_char: options.insertSpaces ? ' ' : '\t',
|
|||
|
|
preserve_newlines: true,
|
|||
|
|
max_preserve_newlines: 2,
|
|||
|
|
jslint_happy: false,
|
|||
|
|
brace_style: "collapse",
|
|||
|
|
space_before_conditional: true,
|
|||
|
|
space_after_anon_function: false,
|
|||
|
|
unescape_strings: false,
|
|||
|
|
wrap_line_length: 120,
|
|||
|
|
end_with_newline: false
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 使用 js-beautify 格式化代码
|
|||
|
|
*/
|
|||
|
|
function beautifyCode(code, options) {
|
|||
|
|
if (!jsBeautify || !jsBeautify.js_beautify) {
|
|||
|
|
console.warn('js-beautify 不可用,返回原始代码');
|
|||
|
|
return code;
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
const beautifyOptions = getSquirrelBeautifyOptions(options);
|
|||
|
|
// 检查代码长度,处理大块代码
|
|||
|
|
const maxChunkSize = 50000; // 50KB 每块
|
|||
|
|
if (code.length > maxChunkSize) {
|
|||
|
|
// 分割代码并分块处理
|
|||
|
|
const chunks = code.split('\n');
|
|||
|
|
const resultChunks = [];
|
|||
|
|
for (const chunk of chunks) {
|
|||
|
|
const formattedChunk = jsBeautify.js_beautify(chunk, beautifyOptions);
|
|||
|
|
resultChunks.push(formattedChunk);
|
|||
|
|
}
|
|||
|
|
return resultChunks.join('\n');
|
|||
|
|
}
|
|||
|
|
// 直接格式化小代码块
|
|||
|
|
return jsBeautify.js_beautify(code, beautifyOptions);
|
|||
|
|
}
|
|||
|
|
catch (error) {
|
|||
|
|
console.error('js-beautify 格式化失败:', error);
|
|||
|
|
// 如果格式化失败,返回原始代码
|
|||
|
|
return code;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* 检测是否为 Squirrel 代码(用于确定是否应用格式化)
|
|||
|
|
*/
|
|||
|
|
function isSquirrelCode(code) {
|
|||
|
|
// 简单的启发式检测 - Squirrel 特有关键字
|
|||
|
|
const squirrelKeywords = [
|
|||
|
|
'function', 'local', 'if', 'else', 'while', 'for', 'foreach',
|
|||
|
|
'class', 'constructor', 'extends', 'instanceof', 'in',
|
|||
|
|
'try', 'catch', 'throw', 'clone', 'delegate', 'resume', 'yield',
|
|||
|
|
'typeof', 'member', 'rawcall', 'call', 'setdebughook'
|
|||
|
|
];
|
|||
|
|
// 提高检测准确性 - 需要至少匹配到1个关键字
|
|||
|
|
return squirrelKeywords.some(keyword => new RegExp(`\\b${keyword}\\b`).test(code));
|
|||
|
|
}
|
|||
|
|
//# sourceMappingURL=beautifyHelper.js.map
|