generated from okikio/deno-github-proxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
process.ts
144 lines (136 loc) · 4.69 KB
/
process.ts
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
133
134
135
136
137
138
139
140
141
142
143
144
import { Typescript } from "./deps.ts"
/**
* Determines whether escape sequences in a token of a specific kind should be preserved.
* Useful for maintaining the integrity of literals where escape characters are meaningful.
*
* @example
* // Simple: In string literals like `"Hello\nWorld"`, the `\n` should be preserved.
* shouldPreserveEscapes(ts.SyntaxKind.StringLiteral);
*
* @example
* // Complex: In JSX text, escape sequences are part of the content and should not be altered.
* shouldPreserveEscapes(ts.SyntaxKind.JsxText);
*
* @param kind - The kind of the token being analyzed.
* @returns True if escape sequences should be preserved; otherwise, false.
*/
export function shouldPreserveEscapes(kind: Typescript.SyntaxKind, ts = Typescript): boolean {
return [
ts.SyntaxKind.StringLiteral,
ts.SyntaxKind.JsxText,
ts.SyntaxKind.JsxTextAllWhiteSpaces,
ts.SyntaxKind.RegularExpressionLiteral,
ts.SyntaxKind.NoSubstitutionTemplateLiteral,
ts.SyntaxKind.TemplateHead,
ts.SyntaxKind.TemplateMiddle,
ts.SyntaxKind.TemplateTail,
// Additional kinds can be added as needed.
].includes(kind);
}
/**
* Processes the text of a token, applying or preserving escape sequences based on the token kind.
* This function handles different contexts like strings, regexes, and templates.
*
* @example
* // Simple: Convert escape sequences in a regular code line.
* processToken('console.log("Line1\\nLine2");', ts.SyntaxKind.StringLiteral);
*
* @example
* // Advanced: Leave a regex pattern unchanged.
* processToken('/\\d+/', ts.SyntaxKind.RegularExpressionLiteral);
*
* @param text - The text of the token.
* @param kind - The kind of the token.
* @returns The processed text.
*/
export function processToken(text: string, kind: Typescript.SyntaxKind, ts = Typescript): string {
if (shouldPreserveEscapes(kind, ts)) {
// Special handling for regex literals to preserve their pattern.
if (kind === ts.SyntaxKind.RegularExpressionLiteral) {
return processRegex(text);
}
return text;
}
// Unescape common escape sequences for other kinds of tokens.
return unescapeSequences(text);
}
/**
* Replaces escape sequences in a given text with their corresponding characters.
* This function is commonly used for non-literal parts of the code.
*
* @example
* // Simple: Replace basic escape sequences.
* unescapeSequences("Line1\\nLine2");
*
* @example
* // Complex: Handle Unicode escapes.
* unescapeSequences("\\u0041\\u0042\\u0043");
*
* @param text - The text to be processed.
* @returns The text with escape sequences replaced.
*/
export function unescapeSequences(text: string): string {
const result = text
.replace(/\\f/g, '\f')
.replace(/\\n/g, '\n')
.replace(/\\r/g, '\r')
.replace(/\\t/g, '\t')
.replace(/\\v/g, '\v')
.replace(/\\0/g, '\0')
.replace(/\\x([0-9A-Fa-f]{2})/g, (_, h) => String.fromCharCode(parseInt(h, 16)))
.replace(/\\u([0-9A-Fa-f]{4})/g, (_, h) => String.fromCharCode(parseInt(h, 16)))
.replace(/\\u{([0-9A-Fa-f]{1,6})}/g, (_, h) => String.fromCodePoint(parseInt(h, 16)));
console.log({ text, result, test: /\n/g.test(text) })
return result
}
/**
* Processes regex literals, ensuring that escape sequences are handled correctly.
* This function is designed to preserve the pattern of the regex.
*
* @example
* // Simple: Keep a basic regex pattern unchanged.
* processRegex('/\\d+/');
*
* @example
* // Advanced: Complex regex patterns remain intact.
* processRegex('/^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$/');
*
* @param regex - The regex literal text.
* @returns The processed regex.
*/
export function processRegex(regex: string): string {
// Add any specific processing for regex literals if necessary.
// For now, it returns the regex as-is.
return regex;
}
/**
* Processes TypeScript source code to handle escape sequences.
* It scans the code, processes each token, and reconstructs the code with escape sequences handled.
*
* @example
* // Simple: Process a single line of code.
* processCode('let example = "Line1\\nLine2";');
*
* @example
* // Complex: Process a block of code with various contexts.
* processCode(`function greet() { console.log("Hello\\nWorld"); } /\\d+/.test("123");`);
*
* @param code - The TypeScript source code.
* @returns The processed code.
*/
export function processCode(code: string, ts = Typescript): string {
let output = '';
const scanner = ts.createScanner(
ts.ScriptTarget.Latest,
false,
ts.LanguageVariant.Standard,
code
);
let token = scanner.scan();
while (token !== ts.SyntaxKind.EndOfFileToken) {
const text = scanner.getTokenText();
output += processToken(text, token);
token = scanner.scan();
}
return output;
}