forked from ember-tooling/prettier-plugin-ember-template-tag
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpreprocess.ts
More file actions
89 lines (78 loc) · 2.26 KB
/
preprocess.ts
File metadata and controls
89 lines (78 loc) · 2.26 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
export interface Template {
contents: string;
type: string;
range: {
start: number;
end: number;
};
utf16Range: {
start: number;
end: number;
};
}
const BufferMap: Map<string, Buffer> = new Map();
export const PLACEHOLDER = '~';
function getBuffer(s: string): Buffer {
let buf = BufferMap.get(s);
if (!buf) {
buf = Buffer.from(s);
BufferMap.set(s, buf);
}
return buf;
}
/** Slice string using byte range */
export function sliceByteRange(s: string, a: number, b?: number): string {
const buf = getBuffer(s);
return buf.subarray(a, b).toString();
}
/** Converts byte index to js char index (utf16) */
export function byteToCharIndex(s: string, byteOffset: number): number {
const buf = getBuffer(s);
return buf.subarray(0, byteOffset).toString().length;
}
/** Calculate byte length */
export function byteLength(s: string): number {
return getBuffer(s).length;
}
function replaceRange(
s: string,
start: number,
end: number,
substitute: string,
): string {
return sliceByteRange(s, 0, start) + substitute + sliceByteRange(s, end);
}
/**
* Replace the template with a parsable placeholder that takes up the same
* range.
*/
export function preprocessTemplateRange(
template: Template,
code: string,
): string {
let prefix: string;
let suffix: string;
if (template.type === 'class-member') {
// Replace with StaticBlock
prefix = 'static{/*';
suffix = '*/}';
} else {
// Replace with BlockStatement or ObjectExpression
prefix = '{/*';
suffix = '*/}';
const nextToken = code.slice(template.range.end).toString().match(/\S+/);
if (nextToken && (nextToken[0] === 'as' || nextToken[0] === 'satisfies')) {
// Replace with parenthesized ObjectExpression
prefix = '(' + prefix;
suffix = suffix + ')';
}
}
// We need to replace forward slash with _something else_, because
// forward slash breaks the parsed templates.
const content = template.contents.replaceAll('/', PLACEHOLDER);
const tplLength = template.range.end - template.range.start;
const spaces =
tplLength - byteLength(content) - prefix.length - suffix.length;
const total = prefix + content + ' '.repeat(spaces) + suffix;
return replaceRange(code, template.range.start, template.range.end, total);
}