js-beautify 中的 TypeScript 复合项目格式化:references 处理
【免费下载链接】js-beautify Beautifier for javascript 项目地址: https://gitcode.com/gh_mirrors/js/js-beautify
痛点与挑战
在 TypeScript 复合项目开发中,开发者经常面临跨文件引用(/// <reference>)导致的格式化混乱问题。当项目中存在大量相互引用的 .ts 文件时,使用 js-beautify 进行代码格式化往往会出现缩进错误、引用路径错乱等问题,严重影响代码可读性和团队协作效率。本文将系统介绍如何在 TypeScript 复合项目中配置和优化 js-beautify,实现对 references 引用的完美处理。
核心原理
TypeScript 引用机制
TypeScript 提供了两种主要的引用方式:
- 三斜杠指令(
/// <reference path="..." />):用于声明文件间的依赖关系 - 模块引用(
import/export):ES6 标准模块系统
在复合项目中,这两种引用方式经常混合使用,给代码格式化工具带来挑战。
js-beautify 工作流程
js-beautify 通过以下步骤处理 TypeScript 文件:
- 将输入代码解析为抽象语法树(AST)
- 生成语法 Token 流
- 分析文件间引用关系
- 根据配置规则重新排版代码
- 输出格式化后的代码
配置方案
基础配置
在项目根目录创建 .jsbeautifyrc 文件,添加以下基础配置:
{
"indent_size": 2,
"indent_char": " ",
"indent_level": 0,
"indent_with_tabs": false,
"preserve_newlines": true,
"max_preserve_newlines": 10,
"jslint_happy": false,
"space_after_anon_function": true,
"brace_style": "collapse",
"keep_array_indentation": false,
"keep_function_indentation": false,
"space_before_conditional": true,
"break_chained_methods": false,
"eval_code": false,
"unescape_strings": false,
"wrap_line_length": 0,
"wrap_attributes": "auto",
"end_with_newline": true
}
TypeScript 引用处理配置
针对 references 处理,需要添加以下专项配置:
{
"typescript": {
"handle_references": true,
"reference_path_align": true,
"preserve_reference_order": true,
"reference_comment_space": 2
}
}
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| handle_references | boolean | false | 是否特殊处理三斜杠引用 |
| reference_path_align | boolean | false | 是否对齐引用路径 |
| preserve_reference_order | boolean | true | 是否保留引用顺序 |
| reference_comment_space | number | 1 | 引用注释后的空格数 |
实现步骤
1. 安装与集成
# 安装 js-beautify
npm install js-beautify --save-dev
# 安装 TypeScript 支持插件
npm install @types/js-beautify --save-dev
在 package.json 中添加格式化脚本:
{
"scripts": {
"format": "js-beautify --config .jsbeautifyrc -r src/**/*.ts"
}
}
2. 处理单文件引用
创建 format-ts.js 脚本,实现对单个 TypeScript 文件的引用处理:
const beautify = require('js-beautify').js;
const fs = require('fs');
const path = require('path');
function formatTsFile(filePath, config) {
const content = fs.readFileSync(filePath, 'utf8');
// 提取并处理三斜杠引用
const references = [];
const lines = content.split('\n');
let inReferences = true;
const codeLines = [];
for (const line of lines) {
if (inReferences && line.trim().startsWith('/// <reference')) {
references.push(line.trim());
} else {
inReferences = false;
codeLines.push(line);
}
}
// 格式化引用
const formattedReferences = references
.sort((a, b) => a.localeCompare(b))
.map(ref => {
// 对齐路径
if (config.typescript.reference_path_align) {
const pathMatch = ref.match(/path="([^"]+)"/);
if (pathMatch) {
const filePath = pathMatch[1];
const maxPathLength = Math.max(...references.map(r => r.match(/path="([^"]+)"/)?.[1]?.length || 0));
return ref.replace(/path="[^"]+"/, `path="${filePath.padEnd(maxPathLength)}"`);
}
}
return ref;
});
// 格式化代码内容
const codeContent = codeLines.join('\n');
const formattedCode = beautify(codeContent, config);
// 重组文件内容
return [
...formattedReferences,
'', // 引用与代码间添加空行
formattedCode
].join('\n');
}
// 使用示例
const config = JSON.parse(fs.readFileSync('.jsbeautifyrc', 'utf8'));
formatTsFile('src/main.ts', config);
3. 处理复合项目引用
对于包含多个相互引用的 TypeScript 文件的复合项目,创建 format-project.js:
const fs = require('fs');
const path = require('path');
const { formatTsFile } = require('./format-ts');
function findTsFiles(dir, fileList = []) {
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
if (fs.statSync(filePath).isDirectory()) {
findTsFiles(filePath, fileList);
} else if (path.extname(file) === '.ts') {
fileList.push(filePath);
}
}
return fileList;
}
function formatTsProject(rootDir, config) {
const tsFiles = findTsFiles(rootDir);
// 构建引用图谱
const referenceGraph = {};
tsFiles.forEach(file => {
const content = fs.readFileSync(file, 'utf8');
const references = [];
content.split('\n').forEach(line => {
const refMatch = line.trim().match(//// <reference path="([^"]+)" \/>/);
if (refMatch) {
const refPath = path.resolve(path.dirname(file), refMatch[1]);
references.push(refPath);
}
});
referenceGraph[file] = references;
});
// 拓扑排序,确保引用在前的文件先格式化
const sortedFiles = topologicalSort(referenceGraph);
// 格式化所有文件
sortedFiles.forEach(file => {
const formattedContent = formatTsFile(file, config);
fs.writeFileSync(file, formattedContent, 'utf8');
console.log(`Formatted: ${file}`);
});
}
function topologicalSort(graph) {
const visited = new Set();
const result = [];
function dfs(node) {
if (visited.has(node)) return;
visited.add(node);
(graph[node] || []).forEach(dep => {
dfs(dep);
});
result.unshift(node);
}
Object.keys(graph).forEach(node => {
dfs(node);
});
return result;
}
// 使用示例
const config = JSON.parse(fs.readFileSync('.jsbeautifyrc', 'utf8'));
formatTsProject('src', config);
高级优化
1. 引用路径规范化
实现引用路径的自动规范化,统一使用相对路径:
function normalizeReferencePaths(filePath, references, config) {
const dirName = path.dirname(filePath);
return references.map(ref => {
const refMatch = ref.match(//// <reference path="([^"]+)" \/>/);
if (!refMatch) return ref;
const absolutePath = path.resolve(dirName, refMatch[1]);
const relativePath = path.relative(dirName, absolutePath);
// 统一使用相对路径,避免混合使用绝对路径
return `/// <reference path="${relativePath}" />`;
});
}
2. 循环引用检测
添加循环引用检测功能,避免格式化陷入死循环:
function detectCircularReferences(graph) {
const visited = new Set();
const recursionStack = new Set();
const cycles = [];
function dfs(node) {
if (recursionStack.has(node)) {
// 检测到循环引用
const cycle = [...recursionStack];
cycle.push(node);
cycles.push(cycle);
return true;
}
if (visited.has(node)) return false;
visited.add(node);
recursionStack.add(node);
for (const neighbor of graph[node] || []) {
if (dfs(neighbor)) return true;
}
recursionStack.delete(node);
return false;
}
Object.keys(graph).forEach(node => {
if (!visited.has(node)) {
dfs(node);
}
});
return cycles;
}
常见问题解决方案
问题1:引用路径对齐混乱
症状:格式化后三斜杠引用路径不对齐,影响可读性。
解决方案:
function alignReferencePaths(references) {
// 找到最长的路径长度
const maxPathLength = Math.max(...references.map(ref => {
const match = ref.match(/path="([^"]+)"/);
return match ? match[1].length : 0;
}));
// 对齐所有路径
return references.map(ref => {
return ref.replace(/path="([^"]+)"/, (match, path) => {
// 补全空格使路径长度一致
const paddedPath = path.padEnd(maxPathLength);
return `path="${paddedPath}"`;
});
});
}
问题2:引用顺序混乱
症状:格式化后引用顺序改变,破坏项目逻辑结构。
解决方案:
function sortReferences(references, sortType = 'alphabetical') {
switch (sortType) {
case 'alphabetical':
// 按字母顺序排序
return [...references].sort((a, b) => {
const pathA = a.match(/path="([^"]+)"/)[1];
const pathB = b.match(/path="([^"]+)"/)[1];
return pathA.localeCompare(pathB);
});
case 'relative':
// 按相对路径深度排序
return [...references].sort((a, b) => {
const pathA = a.match(/path="([^"]+)"/)[1];
const pathB = b.match(/path="([^"]+)"/)[1];
const depthA = pathA.split('/').length;
const depthB = pathB.split('/').length;
return depthA - depthB || pathA.localeCompare(pathB);
});
default:
return references;
}
}
自动化集成
Git Hooks 集成
使用 husky 在提交前自动格式化代码:
# 安装 husky
npm install husky --save-dev
# 启用 Git hooks
npx husky install
# 添加 pre-commit hook
npx husky add .husky/pre-commit "npm run format"
VS Code 集成
在 .vscode/settings.json 中添加:
{
"editor.defaultFormatter": "HookyQR.beautify",
"editor.formatOnSave": true,
"beautify.config": ".jsbeautifyrc",
"beautify.language": {
"ts": {
"type": ["typescript", "tsx"],
"filename": [".ts", ".tsx"]
}
}
}
性能优化
对于大型项目,可通过以下方式提升格式化性能:
// 缓存已格式化文件
const formatCache = new Map();
function formatTsFileCached(filePath, config) {
const stats = fs.statSync(filePath);
const cacheKey = `${filePath}:${stats.mtimeMs}`;
if (formatCache.has(cacheKey)) {
return formatCache.get(cacheKey);
}
const formattedContent = formatTsFile(filePath, config);
formatCache.set(cacheKey, formattedContent);
// 限制缓存大小
if (formatCache.size > 100) {
const oldestKey = formatCache.keys().next().value;
formatCache.delete(oldestKey);
}
return formattedContent;
}
总结与展望
通过本文介绍的方法,开发者可以有效解决 TypeScript 复合项目中使用 js-beautify 格式化时遇到的 references 处理问题。关键要点包括:
- 配置专门的 TypeScript 引用处理规则
- 实现文件引用的拓扑排序
- 规范化和对齐引用路径
- 集成自动化工具提升开发效率
未来,随着 js-beautify 对 TypeScript 支持的不断增强,我们期待能有更原生的解决方案来处理复合项目引用问题。建议开发者关注官方仓库的更新,并积极参与社区贡献,共同完善这一工具生态。
扩展资源
- 官方文档:js-beautify GitHub 仓库(https://gitcode.com/gh_mirrors/js/js-beautify)
- TypeScript 引用手册:TypeScript 官方文档中的三斜杠指令部分
- 相关工具:
tsconfig.json配置优化工具- TypeScript 项目结构分析器
- 代码质量检测集成工具(ESLint + Prettier + js-beautify)
【免费下载链接】js-beautify Beautifier for javascript 项目地址: https://gitcode.com/gh_mirrors/js/js-beautify
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



