-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathpreprocess.ts
More file actions
111 lines (92 loc) · 2.79 KB
/
preprocess.ts
File metadata and controls
111 lines (92 loc) · 2.79 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
import {
getBuffer,
parse,
type Range,
replaceContents,
sliceByteRange,
} from '../utils/content-tag.js';
export interface Template {
contentRange: Range;
contents: string;
range: Range;
type: 'class-member' | 'expression';
utf16Range: {
end: number;
start: number;
};
}
export const TEMPLATE_IDENTIFIER = '__p_x';
const PLACEHOLDER = '~';
/**
* 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{${TEMPLATE_IDENTIFIER}\``;
suffix = '`}';
} else {
// Replace with a TaggedTemplateExpression
prefix = `${TEMPLATE_IDENTIFIER}\``;
suffix = '`';
// const nextToken = sliceByteRange(code, template.range.endByte).match(/\S+/);
// if (nextToken && (nextToken[0] === 'as' || nextToken[0] === 'satisfies')) {
// // Replace with parenthesized TaggedTemplateExpression
// prefix = `({${TEMPLATE_IDENTIFIER}:\`` + prefix;
// suffix = suffix + '})';
// }
}
// We need to replace forward slash with _something else_, because
// forward slash breaks the parsed templates.
const contents = template.contents.replaceAll('/', PLACEHOLDER);
const templateLength = template.range.endByte - template.range.startByte;
const spaces =
Math.max(templateLength - getBuffer(contents).length - prefix.length - suffix.length, 0);
return replaceContents(code, {
contents: [prefix, contents, ' '.repeat(spaces), suffix].join(''),
range: template.range,
});
}
/** Pre-processes the template info, parsing the template content to Glimmer AST. */
export function codeToGlimmerAst(code: string, filename: string): Template[] {
const contentTags = parse(code, { filename });
const templates: Template[] = contentTags.map((contentTag) => {
const { contentRange, contents, range, type } = contentTag;
const utf16Range = {
end: sliceByteRange(code, 0, range.endByte).length,
start: sliceByteRange(code, 0, range.startByte).length,
};
return {
contentRange,
contents,
range,
type,
utf16Range,
};
});
return templates;
}
/**
* Pre-processes the template info, parsing the template content to Glimmer AST,
* fixing the offsets and locations of all nodes also calculates the block
* params locations & ranges and adding it to the info
*/
export function preprocess(
code: string,
fileName: string,
): {
code: string;
templates: Template[];
} {
const templates = codeToGlimmerAst(code, fileName);
for (const template of templates) {
code = preprocessTemplateRange(template, code);
}
return { code, templates };
}