-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpostProcess.ts
More file actions
132 lines (119 loc) · 3.23 KB
/
Copy pathpostProcess.ts
File metadata and controls
132 lines (119 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import type {Options} from 'prettier';
import tsBlankSpace, {blankSourceFile} from 'ts-blank-space';
import ts from 'typescript';
export interface PostProcessOptions {
prettier?: boolean;
transpileToJS?: boolean;
}
export async function postProcessFile(
filePath: string,
content: string,
options: PostProcessOptions = {},
): Promise<{filePath: string; content: string}> {
let processedContent = content;
let processedPath = filePath;
if (options.transpileToJS && canTranspile(filePath)) {
try {
processedPath = transpileExtension(filePath);
processedContent = stripTypes(filePath, processedContent);
} catch (error) {
throw new Error(
`Failed to transpile ${filePath}: ${
error instanceof Error ? error.message : String(error)
}`,
);
}
}
if (options.prettier) {
try {
const prettier = await import('prettier');
const parser = inferParser(processedPath);
const prettierConfig: Options = {
parser,
singleQuote: true,
trailingComma: 'all' as const,
bracketSpacing: false,
};
if (parser === 'svelte') {
const sveltePlugin = await import('prettier-plugin-svelte');
prettierConfig.plugins = [sveltePlugin.default ?? sveltePlugin];
}
processedContent = await prettier.format(
processedContent,
prettierConfig,
);
} catch (error) {
console.warn(`Failed to format ${processedPath}:`, error);
}
}
return {
filePath: processedPath,
content: processedContent,
};
}
export async function postProcessProject(
projectPath: string,
files: Map<string, string>,
options: PostProcessOptions = {},
): Promise<Map<string, string>> {
const processedFiles = new Map<string, string>();
for (const [filePath, content] of files.entries()) {
const {filePath: newPath, content: newContent} = await postProcessFile(
filePath,
content,
options,
);
processedFiles.set(newPath, newContent);
}
return processedFiles;
}
function canTranspile(filePath: string): boolean {
return /\.(tsx?|jsx?)$/.test(filePath);
}
function transpileExtension(filePath: string): string {
return filePath.replace(/\.tsx?$/, (match) => {
return match === '.tsx' ? '.jsx' : '.js';
});
}
function stripTypes(filePath: string, content: string): string {
if (filePath.endsWith('.tsx') || filePath.endsWith('.jsx')) {
return blankSourceFile(
ts.createSourceFile(
filePath,
content,
ts.ScriptTarget.ESNext,
false,
ts.ScriptKind.TSX,
),
);
}
return tsBlankSpace(content);
}
function inferParser(filePath: string): string {
if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
return 'typescript';
}
if (filePath.endsWith('.js') || filePath.endsWith('.jsx')) {
return 'babel';
}
if (
filePath.endsWith('.json') ||
filePath.endsWith('.prettierrc') ||
filePath.endsWith('.eslintrc')
) {
return 'json';
}
if (filePath.endsWith('.css')) {
return 'css';
}
if (filePath.endsWith('.html')) {
return 'html';
}
if (filePath.endsWith('.svelte')) {
return 'svelte';
}
if (filePath.endsWith('.md')) {
return 'markdown';
}
return 'babel';
}