glasswork 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/bootstrap.js +5 -0
- package/dist/core/bootstrap.js.map +1 -1
- package/dist/core/types.d.ts +11 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/email/compiler/compile-templates.d.ts +68 -0
- package/dist/email/compiler/compile-templates.d.ts.map +1 -0
- package/dist/email/compiler/compile-templates.js +156 -0
- package/dist/email/compiler/compile-templates.js.map +1 -0
- package/dist/email/compiler/compiler.d.ts +30 -0
- package/dist/email/compiler/compiler.d.ts.map +1 -0
- package/dist/email/compiler/compiler.js +510 -0
- package/dist/email/compiler/compiler.js.map +1 -0
- package/dist/email/compiler/index.d.ts +4 -0
- package/dist/email/compiler/index.d.ts.map +1 -0
- package/dist/email/compiler/index.js +3 -0
- package/dist/email/compiler/index.js.map +1 -0
- package/dist/email/compiler/tokenizer.d.ts +7 -0
- package/dist/email/compiler/tokenizer.d.ts.map +1 -0
- package/dist/email/compiler/tokenizer.js +154 -0
- package/dist/email/compiler/tokenizer.js.map +1 -0
- package/dist/email/compiler/type-extractor.d.ts +11 -0
- package/dist/email/compiler/type-extractor.d.ts.map +1 -0
- package/dist/email/compiler/type-extractor.js +296 -0
- package/dist/email/compiler/type-extractor.js.map +1 -0
- package/dist/email/compiler/types.d.ts +108 -0
- package/dist/email/compiler/types.d.ts.map +1 -0
- package/dist/email/compiler/types.js +2 -0
- package/dist/email/compiler/types.js.map +1 -0
- package/dist/email/config.d.ts +89 -0
- package/dist/email/config.d.ts.map +1 -0
- package/dist/email/config.js +55 -0
- package/dist/email/config.js.map +1 -0
- package/dist/email/email-service.d.ts +54 -0
- package/dist/email/email-service.d.ts.map +1 -0
- package/dist/email/email-service.js +94 -0
- package/dist/email/email-service.js.map +1 -0
- package/dist/email/index.d.ts +12 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +23 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/template-registry.d.ts +83 -0
- package/dist/email/template-registry.d.ts.map +1 -0
- package/dist/email/template-registry.js +85 -0
- package/dist/email/template-registry.js.map +1 -0
- package/dist/email/templated-email-service.d.ts +59 -0
- package/dist/email/templated-email-service.d.ts.map +1 -0
- package/dist/email/templated-email-service.js +63 -0
- package/dist/email/templated-email-service.js.map +1 -0
- package/dist/email/transports/index.d.ts +3 -0
- package/dist/email/transports/index.d.ts.map +1 -0
- package/dist/email/transports/index.js +3 -0
- package/dist/email/transports/index.js.map +1 -0
- package/dist/email/transports/mock-transport.d.ts +74 -0
- package/dist/email/transports/mock-transport.d.ts.map +1 -0
- package/dist/email/transports/mock-transport.js +102 -0
- package/dist/email/transports/mock-transport.js.map +1 -0
- package/dist/email/transports/ses-transport.d.ts +65 -0
- package/dist/email/transports/ses-transport.d.ts.map +1 -0
- package/dist/email/transports/ses-transport.js +290 -0
- package/dist/email/transports/ses-transport.js.map +1 -0
- package/dist/email/types.d.ts +128 -0
- package/dist/email/types.d.ts.map +1 -0
- package/dist/email/types.js +2 -0
- package/dist/email/types.js.map +1 -0
- package/dist/email/webhooks/handler-factory.d.ts +41 -0
- package/dist/email/webhooks/handler-factory.d.ts.map +1 -0
- package/dist/email/webhooks/handler-factory.js +136 -0
- package/dist/email/webhooks/handler-factory.js.map +1 -0
- package/dist/email/webhooks/index.d.ts +6 -0
- package/dist/email/webhooks/index.d.ts.map +1 -0
- package/dist/email/webhooks/index.js +9 -0
- package/dist/email/webhooks/index.js.map +1 -0
- package/dist/email/webhooks/notification-parser.d.ts +45 -0
- package/dist/email/webhooks/notification-parser.d.ts.map +1 -0
- package/dist/email/webhooks/notification-parser.js +150 -0
- package/dist/email/webhooks/notification-parser.js.map +1 -0
- package/dist/email/webhooks/signature-verification.d.ts +38 -0
- package/dist/email/webhooks/signature-verification.d.ts.map +1 -0
- package/dist/email/webhooks/signature-verification.js +179 -0
- package/dist/email/webhooks/signature-verification.js.map +1 -0
- package/dist/email/webhooks/subscription-handler.d.ts +37 -0
- package/dist/email/webhooks/subscription-handler.d.ts.map +1 -0
- package/dist/email/webhooks/subscription-handler.js +99 -0
- package/dist/email/webhooks/subscription-handler.js.map +1 -0
- package/dist/email/webhooks/types.d.ts +187 -0
- package/dist/email/webhooks/types.d.ts.map +1 -0
- package/dist/email/webhooks/types.js +5 -0
- package/dist/email/webhooks/types.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/list-query/builder.d.ts +5 -0
- package/dist/list-query/builder.d.ts.map +1 -1
- package/dist/list-query/builder.js +11 -3
- package/dist/list-query/builder.js.map +1 -1
- package/dist/list-query/validator.d.ts +3 -3
- package/dist/list-query/validator.d.ts.map +1 -1
- package/dist/list-query/validator.js.map +1 -1
- package/dist/middleware/rate-limit.d.ts +5 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +31 -0
- package/dist/middleware/rate-limit.js.map +1 -1
- package/dist/utils/get-client-ip.d.ts.map +1 -1
- package/dist/utils/get-client-ip.js +15 -10
- package/dist/utils/get-client-ip.js.map +1 -1
- package/package.json +25 -17
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
import { tokenize } from './tokenizer.js';
|
|
2
|
+
import { extractTypes, generateInterface } from './type-extractor.js';
|
|
3
|
+
/**
|
|
4
|
+
* Two-pass MJML template compiler.
|
|
5
|
+
*
|
|
6
|
+
* Pass 1: MJML → HTML (preserving control flow markers in comments)
|
|
7
|
+
* Pass 2: HTML with markers → TypeScript template literal function
|
|
8
|
+
*
|
|
9
|
+
* This approach allows us to:
|
|
10
|
+
* 1. Use the full power of MJML at build time
|
|
11
|
+
* 2. Generate zero-dependency TypeScript render functions
|
|
12
|
+
* 3. Infer TypeScript types from template usage
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Compiles an MJML template with control flow syntax to a TypeScript render function.
|
|
16
|
+
*
|
|
17
|
+
* @param source - MJML source with control flow markers
|
|
18
|
+
* @param name - Template name (used for interface naming)
|
|
19
|
+
* @param mjmlCompile - MJML compiler function (injected to avoid bundling MJML)
|
|
20
|
+
* @returns Compiled TypeScript source code
|
|
21
|
+
*/
|
|
22
|
+
export function compile(source, name, mjmlCompile) {
|
|
23
|
+
// Pass 1: Compile MJML to HTML (markers are preserved in comments)
|
|
24
|
+
const { html, errors } = mjmlCompile(source);
|
|
25
|
+
if (errors.length > 0) {
|
|
26
|
+
const errorMessages = errors.map((e) => e.message).join('\n');
|
|
27
|
+
throw new Error(`MJML compilation errors:\n${errorMessages}`);
|
|
28
|
+
}
|
|
29
|
+
// Extract subject from <mj-title> in source or <title> in compiled HTML
|
|
30
|
+
const subject = extractSubject(source, html);
|
|
31
|
+
// Tokenize the original source to extract control flow structure and variables
|
|
32
|
+
const tokens = tokenize(source);
|
|
33
|
+
// Extract types from tokens
|
|
34
|
+
const types = extractTypes(tokens);
|
|
35
|
+
// Pass 2: Transform compiled HTML to TypeScript
|
|
36
|
+
const tsSource = generateTypeScriptSource(name, html, tokens, types);
|
|
37
|
+
return {
|
|
38
|
+
source: tsSource,
|
|
39
|
+
contextInterface: generateInterface(`${toPascalCase(name)}Context`, types),
|
|
40
|
+
name,
|
|
41
|
+
subject,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Extracts subject from MJML source (<mj-title>) or compiled HTML (<title>)
|
|
46
|
+
*/
|
|
47
|
+
function extractSubject(source, html) {
|
|
48
|
+
// First try to get from <mj-title> in MJML source
|
|
49
|
+
const mjTitleMatch = source.match(/<mj-title>([^<]+)<\/mj-title>/i);
|
|
50
|
+
if (mjTitleMatch) {
|
|
51
|
+
return mjTitleMatch[1].trim();
|
|
52
|
+
}
|
|
53
|
+
// Fall back to <title> in compiled HTML
|
|
54
|
+
const titleMatch = html.match(/<title>([^<]+)<\/title>/i);
|
|
55
|
+
if (titleMatch) {
|
|
56
|
+
return titleMatch[1].trim();
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generates TypeScript source code for a compiled template.
|
|
62
|
+
*/
|
|
63
|
+
function generateTypeScriptSource(name, html, _tokens, types) {
|
|
64
|
+
const interfaceName = `${toPascalCase(name)}Context`;
|
|
65
|
+
const interfaceCode = generateInterface(interfaceName, types);
|
|
66
|
+
// Transform the HTML with control flow markers into template literal
|
|
67
|
+
const transformedHtml = transformHtmlToTemplateLiteral(html);
|
|
68
|
+
return `// This file is auto-generated by @glasswork/email. Do not edit manually.
|
|
69
|
+
|
|
70
|
+
${interfaceCode}
|
|
71
|
+
|
|
72
|
+
export function render(ctx: ${interfaceName}): { html: string; text: string } {
|
|
73
|
+
const html = \`${escapeTemplateLiteral(transformedHtml)}\`;
|
|
74
|
+
|
|
75
|
+
// Auto-generated plain text version
|
|
76
|
+
const text = htmlToText(html);
|
|
77
|
+
|
|
78
|
+
return { html, text };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Converts HTML to plain text for email clients that don't support HTML.
|
|
83
|
+
*/
|
|
84
|
+
function htmlToText(html: string): string {
|
|
85
|
+
return html
|
|
86
|
+
// Remove style and script tags with content
|
|
87
|
+
.replace(/<style[^>]*>[\\s\\S]*?<\\/style>/gi, '')
|
|
88
|
+
.replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '')
|
|
89
|
+
// Convert line breaks
|
|
90
|
+
.replace(/<br\\s*\\/?>/gi, '\\n')
|
|
91
|
+
// Convert block elements to newlines
|
|
92
|
+
.replace(/<\\/(p|div|tr|h[1-6])>/gi, '\\n')
|
|
93
|
+
// Convert list items
|
|
94
|
+
.replace(/<li[^>]*>/gi, '• ')
|
|
95
|
+
.replace(/<\\/li>/gi, '\\n')
|
|
96
|
+
// Remove remaining HTML tags
|
|
97
|
+
.replace(/<[^>]+>/g, '')
|
|
98
|
+
// Decode common HTML entities
|
|
99
|
+
.replace(/ /gi, ' ')
|
|
100
|
+
.replace(/&/gi, '&')
|
|
101
|
+
.replace(/</gi, '<')
|
|
102
|
+
.replace(/>/gi, '>')
|
|
103
|
+
.replace(/"/gi, '"')
|
|
104
|
+
.replace(/'/gi, "'")
|
|
105
|
+
// Clean up whitespace
|
|
106
|
+
.replace(/\\n\\s*\\n\\s*\\n/g, '\\n\\n')
|
|
107
|
+
.trim();
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Finds all control flow markers in HTML
|
|
113
|
+
*/
|
|
114
|
+
function findMarkers(html) {
|
|
115
|
+
const markers = [];
|
|
116
|
+
// Find @if markers
|
|
117
|
+
const ifPattern = /<!--\s*@if\s+([^-]+?)\s*-->/g;
|
|
118
|
+
let match = ifPattern.exec(html);
|
|
119
|
+
while (match !== null) {
|
|
120
|
+
markers.push({
|
|
121
|
+
type: 'if',
|
|
122
|
+
match: match[0],
|
|
123
|
+
index: match.index,
|
|
124
|
+
condition: match[1].trim(),
|
|
125
|
+
});
|
|
126
|
+
match = ifPattern.exec(html);
|
|
127
|
+
}
|
|
128
|
+
// Find @elseif markers
|
|
129
|
+
const elseifPattern = /<!--\s*@elseif\s+([^-]+?)\s*-->/g;
|
|
130
|
+
match = elseifPattern.exec(html);
|
|
131
|
+
while (match !== null) {
|
|
132
|
+
markers.push({
|
|
133
|
+
type: 'elseif',
|
|
134
|
+
match: match[0],
|
|
135
|
+
index: match.index,
|
|
136
|
+
condition: match[1].trim(),
|
|
137
|
+
});
|
|
138
|
+
match = elseifPattern.exec(html);
|
|
139
|
+
}
|
|
140
|
+
// Find @else markers
|
|
141
|
+
const elsePattern = /<!--\s*@else\s*-->/g;
|
|
142
|
+
match = elsePattern.exec(html);
|
|
143
|
+
while (match !== null) {
|
|
144
|
+
markers.push({
|
|
145
|
+
type: 'else',
|
|
146
|
+
match: match[0],
|
|
147
|
+
index: match.index,
|
|
148
|
+
});
|
|
149
|
+
match = elsePattern.exec(html);
|
|
150
|
+
}
|
|
151
|
+
// Find @each markers
|
|
152
|
+
const eachPattern = /<!--\s*@each\s+(\S+)\s+as\s+(\w+)(?:\s*,\s*(\w+))?\s*-->/g;
|
|
153
|
+
match = eachPattern.exec(html);
|
|
154
|
+
while (match !== null) {
|
|
155
|
+
markers.push({
|
|
156
|
+
type: 'each',
|
|
157
|
+
match: match[0],
|
|
158
|
+
index: match.index,
|
|
159
|
+
arrayPath: match[1],
|
|
160
|
+
itemName: match[2],
|
|
161
|
+
indexName: match[3],
|
|
162
|
+
});
|
|
163
|
+
match = eachPattern.exec(html);
|
|
164
|
+
}
|
|
165
|
+
// Find @end markers
|
|
166
|
+
const endPattern = /<!--\s*@end\s*-->/g;
|
|
167
|
+
match = endPattern.exec(html);
|
|
168
|
+
while (match !== null) {
|
|
169
|
+
markers.push({
|
|
170
|
+
type: 'end',
|
|
171
|
+
match: match[0],
|
|
172
|
+
index: match.index,
|
|
173
|
+
});
|
|
174
|
+
match = endPattern.exec(html);
|
|
175
|
+
}
|
|
176
|
+
// Sort markers by position
|
|
177
|
+
markers.sort((a, b) => a.index - b.index);
|
|
178
|
+
return markers;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Builds a map of loop variables at each marker position
|
|
182
|
+
*/
|
|
183
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Control flow tracking requires nested conditionals
|
|
184
|
+
function buildLoopVarScope(markers) {
|
|
185
|
+
const loopVarsAtPosition = new Map();
|
|
186
|
+
const controlStack = [];
|
|
187
|
+
for (const marker of markers) {
|
|
188
|
+
if (marker.type === 'each') {
|
|
189
|
+
controlStack.push({
|
|
190
|
+
type: 'each',
|
|
191
|
+
loop: { itemName: marker.itemName, indexName: marker.indexName },
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
else if (marker.type === 'if') {
|
|
195
|
+
controlStack.push({ type: 'if' });
|
|
196
|
+
}
|
|
197
|
+
else if (marker.type === 'end' && controlStack.length > 0) {
|
|
198
|
+
controlStack.pop();
|
|
199
|
+
}
|
|
200
|
+
const currentLoopVars = new Set();
|
|
201
|
+
for (const ctx of controlStack) {
|
|
202
|
+
if (ctx.type === 'each' && ctx.loop) {
|
|
203
|
+
if (ctx.loop.itemName)
|
|
204
|
+
currentLoopVars.add(ctx.loop.itemName);
|
|
205
|
+
if (ctx.loop.indexName)
|
|
206
|
+
currentLoopVars.add(ctx.loop.indexName);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
loopVarsAtPosition.set(marker.index, currentLoopVars);
|
|
210
|
+
}
|
|
211
|
+
return loopVarsAtPosition;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Creates replacement for if marker
|
|
215
|
+
*/
|
|
216
|
+
const EXPR_OPEN = '__GW_EXPR_START__';
|
|
217
|
+
const EXPR_CLOSE = '__GW_EXPR_END__';
|
|
218
|
+
function wrapExpression(expression) {
|
|
219
|
+
return `${EXPR_OPEN}${expression}${EXPR_CLOSE}`;
|
|
220
|
+
}
|
|
221
|
+
function createIfReplacement(marker, loopVars) {
|
|
222
|
+
if (!marker.condition) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
original: marker.match,
|
|
227
|
+
replacement: wrapExpression(`\${${transformConditionExpr(marker.condition, loopVars)} ? \``),
|
|
228
|
+
index: marker.index,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Creates replacement for elseif marker
|
|
233
|
+
*/
|
|
234
|
+
function createElseifReplacement(marker, loopVars) {
|
|
235
|
+
if (!marker.condition) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
original: marker.match,
|
|
240
|
+
replacement: wrapExpression(`\` : ${transformConditionExpr(marker.condition, loopVars)} ? \``),
|
|
241
|
+
index: marker.index,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Creates replacement for each marker
|
|
246
|
+
*/
|
|
247
|
+
function createEachReplacement(marker) {
|
|
248
|
+
const mapParams = marker.indexName
|
|
249
|
+
? `(${marker.itemName}, ${marker.indexName})`
|
|
250
|
+
: `(${marker.itemName}, __index)`;
|
|
251
|
+
return {
|
|
252
|
+
original: marker.match,
|
|
253
|
+
replacement: wrapExpression(`\${((__array) => __array.map(${mapParams} => \``),
|
|
254
|
+
index: marker.index,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Creates replacement for end marker
|
|
259
|
+
*/
|
|
260
|
+
function createEndReplacement(marker, block) {
|
|
261
|
+
if (block?.type === 'if') {
|
|
262
|
+
return {
|
|
263
|
+
original: marker.match,
|
|
264
|
+
replacement: "` : ''}",
|
|
265
|
+
index: marker.index,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
if (block?.type === 'each') {
|
|
269
|
+
return {
|
|
270
|
+
original: marker.match,
|
|
271
|
+
replacement: `\`).join(''))(ctx.${block.arrayPath})}`,
|
|
272
|
+
index: marker.index,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Builds replacement array from markers
|
|
279
|
+
*/
|
|
280
|
+
function buildReplacements(markers, loopVarsAtPosition) {
|
|
281
|
+
const replacements = [];
|
|
282
|
+
const blockStack = [];
|
|
283
|
+
for (const marker of markers) {
|
|
284
|
+
const loopVars = loopVarsAtPosition.get(marker.index) || new Set();
|
|
285
|
+
switch (marker.type) {
|
|
286
|
+
case 'if':
|
|
287
|
+
blockStack.push({ type: 'if' });
|
|
288
|
+
{
|
|
289
|
+
const replacement = createIfReplacement(marker, loopVars);
|
|
290
|
+
if (replacement) {
|
|
291
|
+
replacements.push(replacement);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
break;
|
|
295
|
+
case 'elseif': {
|
|
296
|
+
const replacement = createElseifReplacement(marker, loopVars);
|
|
297
|
+
if (replacement) {
|
|
298
|
+
replacements.push(replacement);
|
|
299
|
+
}
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case 'else':
|
|
303
|
+
replacements.push({
|
|
304
|
+
original: marker.match,
|
|
305
|
+
replacement: '` : `',
|
|
306
|
+
index: marker.index,
|
|
307
|
+
});
|
|
308
|
+
break;
|
|
309
|
+
case 'each':
|
|
310
|
+
blockStack.push({
|
|
311
|
+
type: 'each',
|
|
312
|
+
arrayPath: marker.arrayPath,
|
|
313
|
+
});
|
|
314
|
+
replacements.push(createEachReplacement(marker));
|
|
315
|
+
break;
|
|
316
|
+
case 'end': {
|
|
317
|
+
const block = blockStack.pop();
|
|
318
|
+
const replacement = createEndReplacement(marker, block);
|
|
319
|
+
if (replacement) {
|
|
320
|
+
replacements.push(replacement);
|
|
321
|
+
}
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return replacements;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Applies replacements to HTML string
|
|
330
|
+
*/
|
|
331
|
+
function applyReplacements(html, replacements) {
|
|
332
|
+
let result = html;
|
|
333
|
+
// Apply replacements (in reverse order to preserve indices)
|
|
334
|
+
for (let i = replacements.length - 1; i >= 0; i--) {
|
|
335
|
+
const { original, replacement, index } = replacements[i];
|
|
336
|
+
result = result.slice(0, index) + replacement + result.slice(index + original.length);
|
|
337
|
+
}
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Transforms variable interpolations in HTML
|
|
342
|
+
*/
|
|
343
|
+
function transformVariables(html, markers) {
|
|
344
|
+
// Build final loop variable set from all @each markers
|
|
345
|
+
const allLoopVars = new Set();
|
|
346
|
+
for (const marker of markers) {
|
|
347
|
+
if (marker.type === 'each') {
|
|
348
|
+
if (marker.itemName)
|
|
349
|
+
allLoopVars.add(marker.itemName);
|
|
350
|
+
if (marker.indexName)
|
|
351
|
+
allLoopVars.add(marker.indexName);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Transform variable interpolations
|
|
355
|
+
return html.replace(/\{\{([^}]+)\}\}/g, (_match, expression) => {
|
|
356
|
+
return transformVariableExpr(expression.trim(), allLoopVars);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Transforms compiled HTML by replacing control flow markers and variables
|
|
361
|
+
* with JavaScript template literal expressions.
|
|
362
|
+
*/
|
|
363
|
+
function transformHtmlToTemplateLiteral(html) {
|
|
364
|
+
const markers = findMarkers(html);
|
|
365
|
+
const loopVarsAtPosition = buildLoopVarScope(markers);
|
|
366
|
+
const replacements = buildReplacements(markers, loopVarsAtPosition);
|
|
367
|
+
let result = applyReplacements(html, replacements);
|
|
368
|
+
result = transformVariables(result, markers);
|
|
369
|
+
return result;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Transforms a condition expression, handling loop context variables.
|
|
373
|
+
*/
|
|
374
|
+
function transformConditionExpr(condition, loopVars) {
|
|
375
|
+
let result = condition
|
|
376
|
+
.replace(/@index/g, '__index')
|
|
377
|
+
.replace(/@first/g, '(__index === 0)')
|
|
378
|
+
.replace(/@last/g, '(__index === __array.length - 1)')
|
|
379
|
+
.replace(/@length/g, '__array.length');
|
|
380
|
+
// Add ctx. prefix to root-level variables only
|
|
381
|
+
// Match variable paths like "items", "items.length", "user.isAdmin"
|
|
382
|
+
result = result.replace(/\b([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)\b/g, (match, varPath) => {
|
|
383
|
+
const rootVar = varPath.split('.')[0];
|
|
384
|
+
// Don't prefix JS keywords
|
|
385
|
+
if (['true', 'false', 'null', 'undefined', 'length'].includes(rootVar)) {
|
|
386
|
+
return match;
|
|
387
|
+
}
|
|
388
|
+
// Don't prefix internal loop variables
|
|
389
|
+
if (['__index', '__array'].includes(rootVar)) {
|
|
390
|
+
return match;
|
|
391
|
+
}
|
|
392
|
+
// Don't prefix loop item variables
|
|
393
|
+
if (loopVars.has(rootVar)) {
|
|
394
|
+
return match;
|
|
395
|
+
}
|
|
396
|
+
return `ctx.${match}`;
|
|
397
|
+
});
|
|
398
|
+
return result;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Transforms a variable expression to a template literal expression.
|
|
402
|
+
*/
|
|
403
|
+
function prefixContextVariables(expression, loopVars) {
|
|
404
|
+
const reserved = new Set([
|
|
405
|
+
'true',
|
|
406
|
+
'false',
|
|
407
|
+
'null',
|
|
408
|
+
'undefined',
|
|
409
|
+
'length',
|
|
410
|
+
'Math',
|
|
411
|
+
'Number',
|
|
412
|
+
'String',
|
|
413
|
+
'Boolean',
|
|
414
|
+
]);
|
|
415
|
+
return expression.replace(/\b([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)\b/g, (match, varPath) => {
|
|
416
|
+
const rootVar = varPath.split('.')[0];
|
|
417
|
+
if (reserved.has(rootVar)) {
|
|
418
|
+
return match;
|
|
419
|
+
}
|
|
420
|
+
if (['__index', '__array'].includes(rootVar)) {
|
|
421
|
+
return match;
|
|
422
|
+
}
|
|
423
|
+
if (loopVars.has(rootVar)) {
|
|
424
|
+
return match;
|
|
425
|
+
}
|
|
426
|
+
return `ctx.${match}`;
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
function transformVariableExpr(expression, loopVars) {
|
|
430
|
+
// Check for default value: name ?? 'default'
|
|
431
|
+
const defaultMatch = expression.match(/^(.+?)\s*\?\?\s*['"]([^'"]*)['"]\s*$/);
|
|
432
|
+
if (defaultMatch) {
|
|
433
|
+
const path = defaultMatch[1].trim();
|
|
434
|
+
const defaultValue = defaultMatch[2];
|
|
435
|
+
const rootVar = path.split('.')[0];
|
|
436
|
+
// Check if root is a loop variable
|
|
437
|
+
if (loopVars.has(rootVar)) {
|
|
438
|
+
return wrapExpression(`\${${path} ?? '${defaultValue}'}`);
|
|
439
|
+
}
|
|
440
|
+
return wrapExpression(`\${ctx.${path} ?? '${defaultValue}'}`);
|
|
441
|
+
}
|
|
442
|
+
// Handle loop context variables (@index, @first, @last, @length)
|
|
443
|
+
if (expression.startsWith('@')) {
|
|
444
|
+
const loopVar = expression.slice(1);
|
|
445
|
+
switch (loopVar) {
|
|
446
|
+
case 'index':
|
|
447
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Intentional - building template literal string
|
|
448
|
+
return wrapExpression('${__index}');
|
|
449
|
+
case 'first':
|
|
450
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Intentional - building template literal string
|
|
451
|
+
return wrapExpression('${__index === 0}');
|
|
452
|
+
case 'last':
|
|
453
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Intentional - building template literal string
|
|
454
|
+
return wrapExpression('${__index === __array.length - 1}');
|
|
455
|
+
case 'length':
|
|
456
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Intentional - building template literal string
|
|
457
|
+
return wrapExpression('${__array.length}');
|
|
458
|
+
default:
|
|
459
|
+
return wrapExpression(`\${${loopVar}}`);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
// Handle expressions with operators or loop context
|
|
463
|
+
if (expression.includes('@') || expression.includes('+') || expression.includes('-')) {
|
|
464
|
+
const transformed = prefixContextVariables(expression
|
|
465
|
+
.replace(/@index/g, '__index')
|
|
466
|
+
.replace(/@first/g, '(__index === 0)')
|
|
467
|
+
.replace(/@last/g, '(__index === __array.length - 1)')
|
|
468
|
+
.replace(/@length/g, '__array.length'), loopVars);
|
|
469
|
+
return wrapExpression(`\${${transformed}}`);
|
|
470
|
+
}
|
|
471
|
+
// Check if root variable is a loop item variable
|
|
472
|
+
const rootVar = expression.split('.')[0];
|
|
473
|
+
if (loopVars.has(rootVar)) {
|
|
474
|
+
return wrapExpression(`\${${expression}}`);
|
|
475
|
+
}
|
|
476
|
+
// Regular context variable
|
|
477
|
+
return wrapExpression(`\${ctx.${expression}}`);
|
|
478
|
+
}
|
|
479
|
+
function toPascalCase(str) {
|
|
480
|
+
return str
|
|
481
|
+
.split(/[-_\s.]+/)
|
|
482
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
483
|
+
.join('');
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Escapes template literal control characters while preserving generated expressions.
|
|
487
|
+
*
|
|
488
|
+
* We temporarily replace protected expressions (wrapped with EXPR_OPEN/EXPR_CLOSE)
|
|
489
|
+
* with placeholders, escape the remaining content, and then restore the expressions.
|
|
490
|
+
*/
|
|
491
|
+
function escapeTemplateLiteral(str) {
|
|
492
|
+
const placeholders = new Map();
|
|
493
|
+
let index = 0;
|
|
494
|
+
const protectedStr = str.replace(new RegExp(`${EXPR_OPEN}([\\s\\S]*?)${EXPR_CLOSE}`, 'g'), (_match, expr) => {
|
|
495
|
+
const key = `__GW_EXPR_PLACEHOLDER_${index}__`;
|
|
496
|
+
placeholders.set(index, expr);
|
|
497
|
+
index++;
|
|
498
|
+
return key;
|
|
499
|
+
});
|
|
500
|
+
const escaped = protectedStr.replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
|
|
501
|
+
let restored = escaped;
|
|
502
|
+
for (const [placeholderIndex, expr] of placeholders.entries()) {
|
|
503
|
+
restored = restored.replace(`__GW_EXPR_PLACEHOLDER_${placeholderIndex}__`, expr);
|
|
504
|
+
}
|
|
505
|
+
return restored;
|
|
506
|
+
}
|
|
507
|
+
// Re-export types and utilities
|
|
508
|
+
export { tokenize } from './tokenizer.js';
|
|
509
|
+
export { extractTypes, generateInterface } from './type-extractor.js';
|
|
510
|
+
//# sourceMappingURL=compiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../src/email/compiler/compiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { type CompiledTemplateInfo, type CompileOptions, type CompileResult, compileTemplates, } from './compile-templates.js';
|
|
2
|
+
export { compile, extractTypes, generateInterface, tokenize } from './compiler.js';
|
|
3
|
+
export type { CompiledTemplate, CompilerOptions, EachToken, ElseIfToken, ElseToken, EndToken, IfToken, InferredType, ParseResult, TextToken, Token, TokenType, VariableToken, } from './types.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/email/compiler/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnF,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,KAAK,EACL,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/email/compiler/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Token } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tokenizes a template string into a stream of tokens.
|
|
4
|
+
* Handles both control flow markers (<!-- @if -->) and variable interpolation ({{var}}).
|
|
5
|
+
*/
|
|
6
|
+
export declare function tokenize(input: string): Token[];
|
|
7
|
+
//# sourceMappingURL=tokenizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../../../src/email/compiler/tokenizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAOV,KAAK,EAEN,MAAM,YAAY,CAAC;AAYpB;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,CA2D/C"}
|