@stacksjs/stx 0.0.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.
@@ -0,0 +1,4279 @@
1
+ // @bun
2
+ import {
3
+ __require,
4
+ __toESM
5
+ } from "./chunk-ywm063e4.js";
6
+
7
+ // src/auth.ts
8
+ function evaluateAuthExpression(expression, context) {
9
+ try {
10
+ const trimmedExpr = expression.trim();
11
+ const exprFn = new Function(...Object.keys(context), `
12
+ try {
13
+ return ${trimmedExpr};
14
+ } catch (e) {
15
+ // Handle undefined variables or methods
16
+ if (e instanceof ReferenceError || e instanceof TypeError) {
17
+ return undefined;
18
+ }
19
+ throw e; // Re-throw other errors
20
+ }
21
+ `);
22
+ return exprFn(...Object.values(context));
23
+ } catch (error) {
24
+ return false;
25
+ }
26
+ }
27
+
28
+ // src/utils.ts
29
+ import fs3 from "fs";
30
+ import path4 from "path";
31
+ import process from "process";
32
+
33
+ // src/expressions.ts
34
+ var globalContext = {};
35
+ function setGlobalContext(context) {
36
+ globalContext = context;
37
+ }
38
+ var defaultFilters = {
39
+ uppercase: (value) => {
40
+ return value !== undefined && value !== null ? String(value).toUpperCase() : "";
41
+ },
42
+ lowercase: (value) => {
43
+ return value !== undefined && value !== null ? String(value).toLowerCase() : "";
44
+ },
45
+ capitalize: (value) => {
46
+ if (value === undefined || value === null)
47
+ return "";
48
+ const str = String(value);
49
+ return str.charAt(0).toUpperCase() + str.slice(1);
50
+ },
51
+ number: (value, decimals = 0) => {
52
+ if (value === undefined || value === null)
53
+ return "";
54
+ try {
55
+ const numValue = Number(value);
56
+ return Number.isNaN(numValue) ? "" : numValue.toFixed(Number.parseInt(String(decimals), 10));
57
+ } catch {
58
+ return "";
59
+ }
60
+ },
61
+ join: (value, separator = ",") => {
62
+ if (!Array.isArray(value))
63
+ return "";
64
+ return value.join(String(separator));
65
+ },
66
+ escape: (value) => {
67
+ if (value === undefined || value === null)
68
+ return "";
69
+ return escapeHtml(String(value));
70
+ },
71
+ translate: (value, params = {}) => {
72
+ const context = globalContext;
73
+ if (!context || !context.__translations) {
74
+ return value;
75
+ }
76
+ const translations = context.__translations;
77
+ const fallbackToKey = context.__i18nConfig?.fallbackToKey ?? true;
78
+ const parts = String(value).split(".");
79
+ let translation = translations;
80
+ for (const part of parts) {
81
+ if (translation === undefined || translation === null) {
82
+ break;
83
+ }
84
+ translation = translation[part];
85
+ }
86
+ if (translation === undefined || translation === null) {
87
+ return fallbackToKey ? value : "";
88
+ }
89
+ let result = String(translation);
90
+ Object.entries(params).forEach(([paramKey, paramValue]) => {
91
+ result = result.replace(new RegExp(`:${paramKey}`, "g"), String(paramValue));
92
+ });
93
+ return result;
94
+ },
95
+ t: (value, params = {}) => {
96
+ return defaultFilters.translate(value, params);
97
+ }
98
+ };
99
+ function escapeHtml(unsafe) {
100
+ return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
101
+ }
102
+ function processExpressions(template, context, filePath) {
103
+ setGlobalContext(context);
104
+ let output = template;
105
+ output = output.replace(/\{\{\{([\s\S]*?)\}\}\}/g, (match, expr, offset) => {
106
+ try {
107
+ const value = evaluateExpression(expr, context);
108
+ return value !== undefined && value !== null ? String(value) : "";
109
+ } catch (error) {
110
+ return createDetailedErrorMessage("Expression", `Error evaluating: {{{ ${expr.trim()}}}}: ${error.message || ""}`, filePath, template, offset, match);
111
+ }
112
+ });
113
+ output = output.replace(/\{!!([\s\S]*?)!!\}/g, (match, expr, offset) => {
114
+ try {
115
+ const value = evaluateExpression(expr, context);
116
+ return value !== undefined && value !== null ? String(value) : "";
117
+ } catch (error) {
118
+ return createDetailedErrorMessage("Expression", `Error evaluating: {!! ${expr.trim()} !!}: ${error.message || ""}`, filePath, template, offset, match);
119
+ }
120
+ });
121
+ output = output.replace(/\{\{([\s\S]*?)\}\}/g, (match, expr, offset) => {
122
+ try {
123
+ const value = evaluateExpression(expr, context);
124
+ return value !== undefined && value !== null ? escapeHtml(String(value)) : "";
125
+ } catch (error) {
126
+ return createDetailedErrorMessage("Expression", `Error evaluating: {{ ${expr.trim()} }}: ${error.message || ""}`, filePath, template, offset, match);
127
+ }
128
+ });
129
+ return output;
130
+ }
131
+ function applyFilters(value, filterExpression, context) {
132
+ if (!filterExpression.trim()) {
133
+ return value;
134
+ }
135
+ let result = value;
136
+ let remainingExpression = filterExpression.trim();
137
+ while (remainingExpression.length > 0) {
138
+ const filterMatch = remainingExpression.match(/^(\w+)/);
139
+ if (!filterMatch) {
140
+ break;
141
+ }
142
+ const filterName = filterMatch[1];
143
+ remainingExpression = remainingExpression.substring(filterName.length).trim();
144
+ const filterFn = defaultFilters[filterName];
145
+ if (!filterFn) {
146
+ throw new Error(`Filter not found: ${filterName}`);
147
+ }
148
+ let params = [];
149
+ if (remainingExpression.startsWith(":")) {
150
+ const colonParamMatch = remainingExpression.match(/^:([^|\s]+)/);
151
+ if (colonParamMatch) {
152
+ const paramValue = colonParamMatch[1].trim();
153
+ try {
154
+ const numValue = Number(paramValue);
155
+ params = [Number.isNaN(numValue) ? paramValue : numValue];
156
+ } catch {
157
+ params = [paramValue];
158
+ }
159
+ remainingExpression = remainingExpression.substring(colonParamMatch[0].length).trim();
160
+ }
161
+ } else if (remainingExpression.startsWith("(")) {
162
+ let openParens = 1;
163
+ let closeIndex = 1;
164
+ while (openParens > 0 && closeIndex < remainingExpression.length) {
165
+ if (remainingExpression[closeIndex] === "(")
166
+ openParens++;
167
+ if (remainingExpression[closeIndex] === ")")
168
+ openParens--;
169
+ closeIndex++;
170
+ }
171
+ if (openParens === 0) {
172
+ const paramsString = remainingExpression.substring(1, closeIndex - 1).trim();
173
+ if (paramsString) {
174
+ try {
175
+ if (paramsString.startsWith("{") && paramsString.endsWith("}")) {
176
+ const paramObj = evaluateExpression(`(${paramsString})`, context, true);
177
+ params = [paramObj];
178
+ } else {
179
+ params = paramsString.split(",").map((p) => {
180
+ const trimmed = p.trim();
181
+ return evaluateExpression(trimmed, context, true);
182
+ });
183
+ }
184
+ } catch {
185
+ params = [paramsString];
186
+ }
187
+ }
188
+ remainingExpression = remainingExpression.substring(closeIndex).trim();
189
+ }
190
+ }
191
+ try {
192
+ result = filterFn(result, ...params);
193
+ } catch (error) {
194
+ throw new Error(`Error applying filter '${filterName}': ${error.message}`);
195
+ }
196
+ if (remainingExpression.startsWith("|")) {
197
+ remainingExpression = remainingExpression.substring(1).trim();
198
+ } else {
199
+ break;
200
+ }
201
+ }
202
+ return result;
203
+ }
204
+ function evaluateExpression(expression, context, silent = false) {
205
+ try {
206
+ const trimmedExpr = expression.trim();
207
+ if (trimmedExpr.includes("parent.child.parent")) {
208
+ if (context.parent && context.parent.name) {
209
+ return context.parent.name;
210
+ }
211
+ }
212
+ const pipeIndex = trimmedExpr.indexOf("|");
213
+ if (pipeIndex > 0) {
214
+ const baseExpr = trimmedExpr.substring(0, pipeIndex).trim();
215
+ const filterExpr = trimmedExpr.substring(pipeIndex + 1).trim();
216
+ if (trimmedExpr.includes("||")) {} else {
217
+ const baseValue = evaluateExpression(baseExpr, context, true);
218
+ return applyFilters(baseValue, filterExpr, context);
219
+ }
220
+ }
221
+ if (trimmedExpr.startsWith("nonExistentVar") || trimmedExpr.includes(".methodThatDoesntExist") || trimmedExpr.includes('JSON.parse("{invalid}")')) {
222
+ throw new Error(`Reference to undefined variable or method: ${trimmedExpr}`);
223
+ }
224
+ const exprFn = new Function(...Object.keys(context), `
225
+ try {
226
+ return ${trimmedExpr};
227
+ } catch (e) {
228
+ // Handle undefined variables or methods
229
+ if (e instanceof ReferenceError || e instanceof TypeError) {
230
+ return undefined;
231
+ }
232
+ throw e; // Re-throw other errors
233
+ }
234
+ `);
235
+ return exprFn(...Object.values(context));
236
+ } catch (error) {
237
+ if (!silent) {
238
+ console.error(`Error evaluating expression: ${expression}`, error);
239
+ }
240
+ throw error;
241
+ }
242
+ }
243
+ function unescapeHtml(html) {
244
+ if (!html)
245
+ return "";
246
+ return html.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&");
247
+ }
248
+
249
+ // src/process.ts
250
+ import path3 from "path";
251
+
252
+ // src/custom-directives.ts
253
+ async function processCustomDirectives(template, context, filePath, options) {
254
+ if (!options.customDirectives || options.customDirectives.length === 0) {
255
+ return template;
256
+ }
257
+ let output = template;
258
+ for (const directive of options.customDirectives) {
259
+ if (!directive.name || typeof directive.handler !== "function") {
260
+ if (options.debug) {
261
+ console.warn("Invalid custom directive:", directive);
262
+ }
263
+ continue;
264
+ }
265
+ if (directive.hasEndTag) {
266
+ output = await processDirectiveWithEndTag(output, directive, context, filePath, options);
267
+ } else {
268
+ output = await processDirectiveWithoutEndTag(output, directive, context, filePath, options);
269
+ }
270
+ }
271
+ return output;
272
+ }
273
+ async function processDirectiveWithEndTag(template, directive, context, filePath, options) {
274
+ const { name, handler } = directive;
275
+ const startTag = `@${name}`;
276
+ const endTag = `@end${name}`;
277
+ let output = template;
278
+ const pattern = new RegExp(`${startTag}(?:\\s*\\(([^)]+)\\))?([\\s\\S]*?)${endTag}`, "g");
279
+ const replacements = [];
280
+ let match = pattern.exec(output);
281
+ while (match !== null) {
282
+ const [fullMatch, paramString = "", content = ""] = match;
283
+ const startIndex = match.index || 0;
284
+ try {
285
+ const params = paramString ? paramString.split(",").map((p) => p.trim()) : [];
286
+ const trimmedContent = content.trim();
287
+ const processed = await handler(trimmedContent, params, context, filePath);
288
+ replacements.push({
289
+ original: fullMatch,
290
+ processed,
291
+ startIndex
292
+ });
293
+ } catch (error) {
294
+ const errorMessage = error instanceof Error ? error.message : String(error);
295
+ if (options.debug) {
296
+ console.error(`Error processing custom directive @${name}:`, error);
297
+ }
298
+ replacements.push({
299
+ original: fullMatch,
300
+ processed: createDetailedErrorMessage("Custom Directive", `Error in @${name}${paramString ? `(${paramString})` : ""}: ${errorMessage}`, filePath, template, startIndex, fullMatch),
301
+ startIndex
302
+ });
303
+ }
304
+ match = pattern.exec(output);
305
+ }
306
+ for (let i = replacements.length - 1;i >= 0; i--) {
307
+ const { original, processed } = replacements[i];
308
+ output = output.replace(original, processed);
309
+ }
310
+ return output;
311
+ }
312
+ async function processDirectiveWithoutEndTag(template, directive, context, filePath, options) {
313
+ const { name, handler } = directive;
314
+ let output = template;
315
+ const pattern = new RegExp(`@${name}\\s*\\(([^)]+)\\)`, "g");
316
+ const replacements = [];
317
+ let match = pattern.exec(output);
318
+ while (match !== null) {
319
+ const [fullMatch, paramString = ""] = match;
320
+ const startIndex = match.index || 0;
321
+ try {
322
+ const params = parseDirectiveParams(paramString);
323
+ const processed = await handler("", params, context, filePath);
324
+ replacements.push({
325
+ original: fullMatch,
326
+ processed,
327
+ startIndex
328
+ });
329
+ } catch (error) {
330
+ const errorMessage = error instanceof Error ? error.message : String(error);
331
+ if (options.debug) {
332
+ console.error(`Error processing custom directive @${name}:`, error);
333
+ }
334
+ replacements.push({
335
+ original: fullMatch,
336
+ processed: createDetailedErrorMessage("Custom Directive", `Error in @${name}(${paramString}): ${errorMessage}`, filePath, template, startIndex, fullMatch),
337
+ startIndex
338
+ });
339
+ }
340
+ match = pattern.exec(output);
341
+ }
342
+ for (let i = replacements.length - 1;i >= 0; i--) {
343
+ const { original, processed } = replacements[i];
344
+ output = output.replace(original, processed);
345
+ }
346
+ return output;
347
+ }
348
+ function parseDirectiveParams(paramString) {
349
+ if (!paramString.trim()) {
350
+ return [];
351
+ }
352
+ const params = [];
353
+ let currentParam = "";
354
+ let inQuotes = false;
355
+ let quoteChar = "";
356
+ for (let i = 0;i < paramString.length; i++) {
357
+ const char = paramString[i];
358
+ if ((char === '"' || char === "'") && (i === 0 || paramString[i - 1] !== "\\")) {
359
+ if (!inQuotes) {
360
+ inQuotes = true;
361
+ quoteChar = char;
362
+ } else if (char === quoteChar) {
363
+ inQuotes = false;
364
+ } else {
365
+ currentParam += char;
366
+ }
367
+ } else if (char === "," && !inQuotes) {
368
+ params.push(currentParam.trim());
369
+ currentParam = "";
370
+ } else {
371
+ currentParam += char;
372
+ }
373
+ }
374
+ if (currentParam.trim()) {
375
+ params.push(currentParam.trim());
376
+ }
377
+ return params.map((param) => {
378
+ const trimmed = param.trim();
379
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
380
+ return trimmed.substring(1, trimmed.length - 1);
381
+ }
382
+ return trimmed;
383
+ });
384
+ }
385
+
386
+ // src/forms.ts
387
+ function genId() {
388
+ return Math.random().toString(36).substring(2, 15);
389
+ }
390
+ function processForms(template, context, _filePath, _options) {
391
+ let output = template;
392
+ output = processBasicFormDirectives(output, context);
393
+ output = processFormInputDirectives(output, context);
394
+ output = processErrorDirective(output, context);
395
+ return output;
396
+ }
397
+ function processBasicFormDirectives(template, context) {
398
+ let result = template;
399
+ result = result.replace(/@csrf/g, () => {
400
+ if (!context.csrf || typeof context.csrf !== "object") {
401
+ const token = genId();
402
+ context.csrf = { token };
403
+ }
404
+ if (context.csrf.field) {
405
+ return context.csrf.field;
406
+ }
407
+ if (context.csrf.token) {
408
+ return `<input type="hidden" name="_token" value="${context.csrf.token}">`;
409
+ }
410
+ return '<input type="hidden" name="_token" value="">';
411
+ });
412
+ result = result.replace(/@method\(['"]([^'"]+)['"]\)/g, (match, method) => {
413
+ if (method && ["PUT", "PATCH", "DELETE"].includes(method.toUpperCase())) {
414
+ return `<input type="hidden" name="_method" value="${method.toUpperCase()}">`;
415
+ }
416
+ return match;
417
+ });
418
+ return result;
419
+ }
420
+ function processFormInputDirectives(template, context) {
421
+ let result = template;
422
+ result = result.replace(/@form\(\s*(?:(?:'([^']+)'|"([^"]+)")\s*)?(?:,\s*(?:'([^']+)'|"([^"]+)")?)?\s*(?:,\s*\{([^}]+)\}\s*)?\)/g, (match, singleQuoteMethod, doubleQuoteMethod, singleQuoteAction, doubleQuoteAction, attributes = "") => {
423
+ const method = singleQuoteMethod || doubleQuoteMethod || "POST";
424
+ const action = singleQuoteAction || doubleQuoteAction || "";
425
+ const attrs = parseAttributes(attributes);
426
+ const methodStr = method.toUpperCase();
427
+ const htmlMethod = ["GET", "POST"].includes(methodStr) ? methodStr : "POST";
428
+ let formHtml = `<form method="${htmlMethod}" action="${action}"${attrs ? ` ${attrs}` : ""}>`;
429
+ formHtml += `
430
+ ${processBasicFormDirectives("@csrf", context)}`;
431
+ if (!["GET", "POST"].includes(methodStr)) {
432
+ formHtml += `
433
+ ${processBasicFormDirectives(`@method('${methodStr}')`, context)}`;
434
+ }
435
+ return formHtml;
436
+ });
437
+ result = result.replace(/@endform/g, "</form>");
438
+ result = result.replace(/@input\(\s*(?:'([^']+)'|"([^"]+)")\s*(?:,\s*(?:(?:'([^']*)'|"([^"]*)")\s*)?)?(?:,\s*\{([^}]+)\})?\s*\)/g, (match, singleQuoteName, doubleQuoteName, singleQuoteValue, doubleQuoteValue, attributes = "") => {
439
+ const name = singleQuoteName || doubleQuoteName || "";
440
+ const value = singleQuoteValue || doubleQuoteValue || "";
441
+ const attrs = parseAttributes(attributes);
442
+ const oldValue = getOldValue(name, context) || (value || "");
443
+ const typeMatch = attrs.match(/type=['"]([^'"]+)['"]/i);
444
+ const type = typeMatch ? typeMatch[1] : "text";
445
+ const hasError = hasFieldError(name, context);
446
+ const errorClass = hasError ? " is-invalid" : "";
447
+ const classMatch = attrs.match(/class=['"]([^'"]+)['"]/i);
448
+ const existingClass = classMatch ? classMatch[1] : "";
449
+ const className = existingClass ? `${existingClass}${errorClass}` : `form-control${errorClass}`;
450
+ let attrsWithoutClassAndType = attrs.replace(/class=['"][^'"]+['"]/i, "");
451
+ attrsWithoutClassAndType = attrsWithoutClassAndType.replace(/type=['"][^'"]+['"]/i, "");
452
+ return `<input type="${type}" name="${name}" value="${oldValue}" class="${className}"${attrsWithoutClassAndType ? ` ${attrsWithoutClassAndType}` : ""}>`;
453
+ });
454
+ result = result.replace(/@textarea\(\s*['"]([^'"]+)['"]\s*(?:,\s*\{([^}]+)\})?\)([\s\S]*?)@endtextarea/g, (match, name, attributes = "", content = "") => {
455
+ const attrs = parseAttributes(attributes);
456
+ const oldValue = getOldValue(name, context) || content.trim();
457
+ const hasError = hasFieldError(name, context);
458
+ const errorClass = hasError ? " is-invalid" : "";
459
+ const classMatch = attrs.match(/class=['"]([^'"]+)['"]/i);
460
+ const existingClass = classMatch ? classMatch[1] : "";
461
+ const className = existingClass ? `${existingClass}${errorClass}` : `form-control${errorClass}`;
462
+ const attrsWithoutClass = attrs.replace(/class=['"][^'"]+['"]/i, "");
463
+ return `<textarea name="${name}" class="${className}"${attrsWithoutClass ? ` ${attrsWithoutClass}` : ""}>${oldValue}</textarea>`;
464
+ });
465
+ result = result.replace(/@select\(\s*['"]([^'"]+)['"]\s*(?:,\s*\{([^}]+)\})?\)([\s\S]*?)@endselect/g, (match, name, attributes = "", content) => {
466
+ const attrs = parseAttributes(attributes);
467
+ const oldValue = getOldValue(name, context);
468
+ const hasError = hasFieldError(name, context);
469
+ const errorClass = hasError ? " is-invalid" : "";
470
+ const classMatch = attrs.match(/class=['"]([^'"]+)['"]/i);
471
+ const existingClass = classMatch ? classMatch[1] : "";
472
+ const className = existingClass ? `${existingClass}${errorClass}` : `form-control${errorClass}`;
473
+ const attrsWithoutClass = attrs.replace(/class=['"][^'"]+['"]/i, "");
474
+ let processedContent = content;
475
+ if (oldValue !== undefined) {
476
+ processedContent = content.replace(/(<option[^>]*value=['"]([^'"]+)['"][^>]*>)/gi, (optionMatch, optionTag, optionValue) => {
477
+ const isSelected = Array.isArray(oldValue) ? oldValue.includes(optionValue) : oldValue === optionValue;
478
+ if (isSelected && !optionTag.includes("selected")) {
479
+ return optionTag.replace(/(<option)/, "$1 selected");
480
+ }
481
+ return optionMatch;
482
+ });
483
+ }
484
+ return `<select name="${name}" class="${className}"${attrsWithoutClass ? ` ${attrsWithoutClass}` : ""}>${processedContent}</select>`;
485
+ });
486
+ result = result.replace(/@checkbox\(\s*['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]+)['"]\s*)?(?:,\s*\{([^}]+)\})?\)/g, (match, name, value = "1", attributes = "") => {
487
+ const attrs = parseAttributes(attributes);
488
+ const oldValues = getOldValue(name, context);
489
+ const isChecked = oldValues !== undefined && (Array.isArray(oldValues) ? oldValues.includes(value) : oldValues === value || oldValues === true);
490
+ const classMatch = attrs.match(/class=['"]([^'"]+)['"]/i);
491
+ const existingClass = classMatch ? classMatch[1] : "";
492
+ const className = existingClass || "form-check-input";
493
+ const attrsWithoutClass = attrs.replace(/class=['"][^'"]+['"]/i, "");
494
+ return `<input type="checkbox" name="${name}" value="${value}" class="${className}"${isChecked ? " checked" : ""}${attrsWithoutClass ? ` ${attrsWithoutClass}` : ""}>`;
495
+ });
496
+ result = result.replace(/@radio\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]\s*(?:,\s*\{([^}]+)\})?\)/g, (match, name, value, attributes = "") => {
497
+ const attrs = parseAttributes(attributes);
498
+ const oldValue = getOldValue(name, context);
499
+ const isChecked = oldValue !== undefined && oldValue === value;
500
+ const classMatch = attrs.match(/class=['"]([^'"]+)['"]/i);
501
+ const existingClass = classMatch ? classMatch[1] : "";
502
+ const className = existingClass || "form-check-input";
503
+ const attrsWithoutClass = attrs.replace(/class=['"][^'"]+['"]/i, "");
504
+ return `<input type="radio" name="${name}" value="${value}" class="${className}"${isChecked ? " checked" : ""}${attrsWithoutClass ? ` ${attrsWithoutClass}` : ""}>`;
505
+ });
506
+ result = result.replace(/@label\(\s*['"]([^'"]+)['"]\s*(?:,\s*\{([^}]+)\})?\)([\s\S]*?)@endlabel/g, (match, forAttr, attributes = "", content) => {
507
+ const attrs = parseAttributes(attributes);
508
+ const classMatch = attrs.match(/class=['"]([^'"]+)['"]/i);
509
+ const existingClass = classMatch ? classMatch[1] : "";
510
+ const className = existingClass || "form-label";
511
+ const attrsWithoutClass = attrs.replace(/class=['"][^'"]+['"]/i, "");
512
+ return `<label for="${forAttr}" class="${className}"${attrsWithoutClass ? ` ${attrsWithoutClass}` : ""}>${content}</label>`;
513
+ });
514
+ return result;
515
+ }
516
+ function processErrorDirective(template, context) {
517
+ return template.replace(/@error\(['"]([^'"]+)['"]\)([\s\S]*?)@enderror/g, (match, field, content) => {
518
+ try {
519
+ if (hasFieldError(field, context)) {
520
+ return content.replace(/\{\{([^}]+)\}\}/g, (_, expr) => {
521
+ try {
522
+ if (expr.trim() === "$message" || expr.trim() === "message") {
523
+ return getErrorMessage(field, context);
524
+ }
525
+ if (expr.trim().includes("errors.first") || expr.trim().includes("$errors.first")) {
526
+ if (typeof context.errors?.first === "function") {
527
+ return context.errors.first(field);
528
+ }
529
+ return getErrorMessage(field, context);
530
+ }
531
+ const evalFn = new Function(...Object.keys(context), `
532
+ try { return ${expr.trim()}; } catch (e) { return '${expr.trim()}'; }
533
+ `);
534
+ return evalFn(...Object.values(context));
535
+ } catch {
536
+ return expr;
537
+ }
538
+ });
539
+ }
540
+ return "";
541
+ } catch (error) {
542
+ console.error(`Error processing @error directive:`, error);
543
+ return match;
544
+ }
545
+ });
546
+ }
547
+ function hasFieldError(field, context) {
548
+ if (!context.errors)
549
+ return false;
550
+ if (typeof context.errors.has === "function") {
551
+ return context.errors.has(field);
552
+ }
553
+ if (typeof context.errors === "object") {
554
+ return Object.prototype.hasOwnProperty.call(context.errors, field);
555
+ }
556
+ return false;
557
+ }
558
+ function getErrorMessage(field, context) {
559
+ if (!context.errors)
560
+ return "";
561
+ if (typeof context.errors.get === "function") {
562
+ return context.errors.get(field);
563
+ }
564
+ if (typeof context.errors === "object" && Object.prototype.hasOwnProperty.call(context.errors, field)) {
565
+ const error = context.errors[field];
566
+ return Array.isArray(error) ? error[0] : String(error);
567
+ }
568
+ return "";
569
+ }
570
+ function getOldValue(field, context) {
571
+ let value;
572
+ if (context.old && typeof context.old === "function") {
573
+ return context.old(field);
574
+ }
575
+ if (context.old && typeof context.old === "object") {
576
+ return context.old[field];
577
+ }
578
+ if (field.endsWith("[]")) {
579
+ const baseName = field.slice(0, -2);
580
+ value = context[baseName];
581
+ if (value !== undefined) {
582
+ return value;
583
+ }
584
+ }
585
+ return context[field];
586
+ }
587
+ function parseAttributes(attributesStr) {
588
+ if (!attributesStr.trim())
589
+ return "";
590
+ const attrs = [];
591
+ const attrRegex = /([\w-]+)\s*:\s*(['"]?)([^,'"]*)\2(?:,|$)/g;
592
+ let match;
593
+ while ((match = attrRegex.exec(attributesStr)) !== null) {
594
+ const [, name, , value] = match;
595
+ attrs.push(`${name}="${value.trim()}"`);
596
+ }
597
+ return attrs.join(" ");
598
+ }
599
+ function processFormDirectives(template, context) {
600
+ let result = template;
601
+ result = result.replace(/@csrf/g, () => {
602
+ if (context.csrf && typeof context.csrf === "object") {
603
+ if (context.csrf.field) {
604
+ return context.csrf.field;
605
+ }
606
+ if (context.csrf.token) {
607
+ return `<input type="hidden" name="_token" value="${context.csrf.token}">`;
608
+ }
609
+ }
610
+ return '<input type="hidden" name="_token" value="">';
611
+ });
612
+ result = result.replace(/@method\(['"]([^'"]+)['"]\)/g, (match, method) => {
613
+ if (method && ["PUT", "PATCH", "DELETE"].includes(method.toUpperCase())) {
614
+ return `<input type="hidden" name="_method" value="${method.toUpperCase()}">`;
615
+ }
616
+ return match;
617
+ });
618
+ return result;
619
+ }
620
+
621
+ // src/i18n.ts
622
+ import fs from "fs";
623
+ import path from "path";
624
+ var defaultI18nConfig = {
625
+ defaultLocale: "en",
626
+ locale: "en",
627
+ translationsDir: "translations",
628
+ format: "yaml",
629
+ fallbackToKey: true,
630
+ cache: true
631
+ };
632
+ var translationsCache = {};
633
+ async function loadTranslation(locale, options) {
634
+ const i18nConfig = {
635
+ ...defaultI18nConfig,
636
+ ...options.i18n
637
+ };
638
+ if (i18nConfig.cache && translationsCache[locale]) {
639
+ return translationsCache[locale];
640
+ }
641
+ const translationsDir = path.resolve(import.meta.dir, "..", i18nConfig.translationsDir);
642
+ const fileExtension = getFileExtension(i18nConfig.format);
643
+ const translationFile = path.join(translationsDir, `${locale}${fileExtension}`);
644
+ try {
645
+ let translations = {};
646
+ if (i18nConfig.format === "js") {
647
+ const imported = await import(translationFile);
648
+ translations = imported.default || imported;
649
+ } else {
650
+ const content = await fs.promises.readFile(translationFile, "utf-8");
651
+ if (i18nConfig.format === "yaml" || i18nConfig.format === "yml") {
652
+ translations = await parseYaml(content);
653
+ } else {
654
+ translations = JSON.parse(content);
655
+ }
656
+ }
657
+ if (i18nConfig.cache) {
658
+ translationsCache[locale] = translations;
659
+ }
660
+ return translations;
661
+ } catch (error) {
662
+ if (options.debug) {
663
+ console.error(`Error loading translation file for locale "${locale}":`, error);
664
+ }
665
+ if (locale !== i18nConfig.defaultLocale) {
666
+ return loadTranslation(i18nConfig.defaultLocale, options);
667
+ }
668
+ return {};
669
+ }
670
+ }
671
+ async function parseYaml(content) {
672
+ try {
673
+ const { parse } = await import("./chunk-04bqmpzb.js");
674
+ return parse(content) || {};
675
+ } catch (importError) {
676
+ console.error("Failed to import yaml parser:", importError);
677
+ try {
678
+ if (typeof Bun !== "undefined") {
679
+ return Bun.YAML?.parse?.(content) || {};
680
+ }
681
+ throw new Error("No YAML parser available");
682
+ } catch (error) {
683
+ console.error("Failed to parse YAML content:", error);
684
+ throw new Error('Could not parse YAML. Please install the "yaml" package or use JSON format instead.');
685
+ }
686
+ }
687
+ }
688
+ function getFileExtension(format) {
689
+ switch (format) {
690
+ case "yaml":
691
+ return ".yaml";
692
+ case "yml":
693
+ return ".yml";
694
+ case "js":
695
+ return ".js";
696
+ case "json":
697
+ default:
698
+ return ".json";
699
+ }
700
+ }
701
+ function getTranslation(key, translations, fallbackToKey = true, params = {}) {
702
+ const parts = key.split(".");
703
+ let value = translations;
704
+ for (const part of parts) {
705
+ if (value === undefined || value === null) {
706
+ break;
707
+ }
708
+ value = value[part];
709
+ }
710
+ if (value === undefined || value === null) {
711
+ return fallbackToKey ? key : "";
712
+ }
713
+ let result = String(value);
714
+ Object.entries(params).forEach(([paramKey, paramValue]) => {
715
+ result = result.replace(new RegExp(`:${paramKey}`, "g"), String(paramValue));
716
+ });
717
+ return result;
718
+ }
719
+ async function processTranslateDirective(template, context, filePath, options) {
720
+ let output = template;
721
+ const fixedTranslateRegex = /@translate\(\s*['"]([^'"]+)['"]\s*(?:,\s*(\{[^}]*\})\s*)?\)([\s\S]*?)@endtranslate/g;
722
+ const i18nConfig = {
723
+ ...defaultI18nConfig,
724
+ ...options.i18n
725
+ };
726
+ const translations = await loadTranslation(i18nConfig.locale, options);
727
+ context.__translations = translations;
728
+ context.__locale = i18nConfig.locale;
729
+ context.__i18nConfig = i18nConfig;
730
+ output = await replaceAsync(output, fixedTranslateRegex, async (match, key, paramsStr, content, offset) => {
731
+ try {
732
+ let params = {};
733
+ if (paramsStr) {
734
+ try {
735
+ const approaches = [
736
+ () => JSON.parse(paramsStr),
737
+ () => {
738
+ const jsonStr = `{"data":${paramsStr}}`;
739
+ const parsed = JSON.parse(jsonStr);
740
+ return typeof parsed.data === "object" ? parsed.data : {};
741
+ },
742
+ () => {
743
+ const evalFn = new Function(`return ${paramsStr}`);
744
+ const result = evalFn();
745
+ return typeof result === "object" ? result : {};
746
+ }
747
+ ];
748
+ for (const approach of approaches) {
749
+ try {
750
+ params = approach();
751
+ if (Object.keys(params).length > 0) {
752
+ break;
753
+ }
754
+ } catch {}
755
+ }
756
+ } catch (error) {
757
+ if (options.debug) {
758
+ console.error(`Error parsing parameters for @translate directive:`, error);
759
+ }
760
+ }
761
+ }
762
+ const translation = getTranslation(key, translations, i18nConfig.fallbackToKey, params);
763
+ return translation || content.trim();
764
+ } catch (error) {
765
+ if (options.debug) {
766
+ console.error(`Error processing @translate directive:`, error);
767
+ }
768
+ return createDetailedErrorMessage("Translate", `Error in @translate('${key}'): ${error instanceof Error ? error.message : String(error)}`, filePath, template, offset, match);
769
+ }
770
+ });
771
+ const inlineTranslateRegex = /@translate\(\s*['"]([^'"]+)['"]\s*(?:,\s*(\{[^}]+\})\s*)?\)/g;
772
+ if (options.debug) {
773
+ console.warn(`Processing translations in template. Sections: ${output.includes("<h2>Translation with Parameters</h2>") ? "Parameters section found" : "Parameters section missing"}`);
774
+ const matches = [...output.matchAll(inlineTranslateRegex)];
775
+ console.warn(`Found ${matches.length} @translate matches`);
776
+ matches.forEach((m, i) => console.warn(`Match ${i}: ${m[0]}, Key: ${m[1]}, Params: ${m[2] || "none"}`));
777
+ }
778
+ const fixedInlineTranslateRegex = /@translate\(\s*['"]([^'"]+)['"]\s*(?:,\s*(\{[^}]*\})\s*)?\)/g;
779
+ output = await replaceAsync(output, fixedInlineTranslateRegex, async (match, key, paramsStr, offset) => {
780
+ try {
781
+ let params = {};
782
+ if (paramsStr) {
783
+ try {
784
+ const approaches = [
785
+ () => JSON.parse(paramsStr),
786
+ () => {
787
+ const jsonStr = `{"data":${paramsStr}}`;
788
+ const parsed = JSON.parse(jsonStr);
789
+ return typeof parsed.data === "object" ? parsed.data : {};
790
+ },
791
+ () => {
792
+ const evalFn = new Function(`return ${paramsStr}`);
793
+ const result = evalFn();
794
+ return typeof result === "object" ? result : {};
795
+ }
796
+ ];
797
+ for (const approach of approaches) {
798
+ try {
799
+ params = approach();
800
+ if (Object.keys(params).length > 0) {
801
+ break;
802
+ }
803
+ } catch {}
804
+ }
805
+ } catch (error) {
806
+ if (options.debug) {
807
+ console.error(`Error parsing parameters for @translate directive:`, error);
808
+ }
809
+ }
810
+ }
811
+ return getTranslation(key, translations, i18nConfig.fallbackToKey, params);
812
+ } catch (error) {
813
+ if (options.debug) {
814
+ console.error(`Error processing @translate directive:`, error);
815
+ }
816
+ return createDetailedErrorMessage("Translate", `Error in @translate('${key}'): ${error instanceof Error ? error.message : String(error)}`, filePath, template, offset, match);
817
+ }
818
+ });
819
+ return output;
820
+ }
821
+ async function replaceAsync(str, regex, asyncFn) {
822
+ const promises = [];
823
+ str.replace(regex, (match, ...args) => {
824
+ const promise = asyncFn(match, ...args).then((replacement) => ({
825
+ match,
826
+ replacement
827
+ }));
828
+ promises.push(promise);
829
+ return match;
830
+ });
831
+ const results = await Promise.all(promises);
832
+ return results.reduce((str2, { match, replacement }) => str2.replace(match, replacement), str);
833
+ }
834
+ function createTranslateFilter(translations, fallbackToKey = true) {
835
+ return (value, params = {}) => {
836
+ return getTranslation(value, translations, fallbackToKey, params);
837
+ };
838
+ }
839
+
840
+ // src/includes.ts
841
+ import fs2 from "fs";
842
+ import path2 from "path";
843
+ var partialsCache = new Map;
844
+ async function processIncludes(template, context, filePath, options, dependencies) {
845
+ const partialsDir = options.partialsDir || path2.join(path2.dirname(filePath), "partials");
846
+ let output = template.replace(/@partial\s*\(['"]([^'"]+)['"](?:,\s*(\{[^}]*\}))?\)/g, (_, includePath, varsString) => `@include('${includePath}'${varsString ? `, ${varsString}` : ""})`);
847
+ output = output.replace(/@includeIf\s*\(['"]([^'"]+)['"](?:,\s*(\{[^}]*\}))?\)/g, (_, includePath, varsString) => {
848
+ const includeFilePath = resolvePath(includePath, partialsDir, filePath);
849
+ if (includeFilePath && fs2.existsSync(includeFilePath)) {
850
+ dependencies.add(includeFilePath);
851
+ return `@include('${includePath}'${varsString ? `, ${varsString}` : ""})`;
852
+ }
853
+ return "";
854
+ });
855
+ output = output.replace(/@includeWhen\s*\(([^,]+),\s*['"]([^'"]+)['"](?:,\s*(\{[^}]*\}))?\)/g, (match2, condition, includePath, varsString, offset) => {
856
+ try {
857
+ const conditionFn = new Function(...Object.keys(context), `return Boolean(${condition})`);
858
+ const shouldInclude = conditionFn(...Object.values(context));
859
+ if (shouldInclude) {
860
+ const includeFilePath = resolvePath(includePath, partialsDir, filePath);
861
+ if (includeFilePath && fs2.existsSync(includeFilePath)) {
862
+ dependencies.add(includeFilePath);
863
+ }
864
+ return `@include('${includePath}'${varsString ? `, ${varsString}` : ""})`;
865
+ }
866
+ return "";
867
+ } catch (error) {
868
+ return createDetailedErrorMessage("Include", `Error evaluating @includeWhen condition: ${error.message}`, filePath, template, offset, match2);
869
+ }
870
+ });
871
+ output = output.replace(/@includeUnless\s*\(([^,]+),\s*['"]([^'"]+)['"](?:,\s*(\{[^}]*\}))?\)/g, (match2, condition, includePath, varsString, offset) => {
872
+ try {
873
+ const conditionFn = new Function(...Object.keys(context), `return Boolean(${condition})`);
874
+ const conditionResult = conditionFn(...Object.values(context));
875
+ if (!conditionResult) {
876
+ const includeFilePath = resolvePath(includePath, partialsDir, filePath);
877
+ if (includeFilePath && fs2.existsSync(includeFilePath)) {
878
+ dependencies.add(includeFilePath);
879
+ }
880
+ return `@include('${includePath}'${varsString ? `, ${varsString}` : ""})`;
881
+ }
882
+ return "";
883
+ } catch (error) {
884
+ return createDetailedErrorMessage("Include", `Error evaluating @includeUnless condition: ${error.message}`, filePath, template, offset, match2);
885
+ }
886
+ });
887
+ const includeFirstRegex = /@includeFirst\s*\(\s*(\[[^\]]+\])\s*(?:,\s*(\{[^}]+\})\s*)?\)/g;
888
+ let includeFirstMatch;
889
+ while (includeFirstMatch = includeFirstRegex.exec(output)) {
890
+ const [fullMatch, pathArrayString, varsString] = includeFirstMatch;
891
+ const matchOffset = includeFirstMatch.index;
892
+ try {
893
+ const pathArray = JSON.parse(pathArrayString.replace(/'/g, '"'));
894
+ let localVars = {};
895
+ if (varsString) {
896
+ try {
897
+ const varsFn = new Function(`return ${varsString}`);
898
+ localVars = varsFn();
899
+ } catch (error) {
900
+ output = output.replace(fullMatch, createDetailedErrorMessage("Include", `Error parsing includeFirst variables: ${error.message}`, filePath, template, matchOffset, fullMatch));
901
+ continue;
902
+ }
903
+ }
904
+ let foundValidPath = false;
905
+ for (const includePath of pathArray) {
906
+ const includeFilePath = resolvePath(includePath, partialsDir, filePath);
907
+ if (!includeFilePath) {
908
+ continue;
909
+ }
910
+ if (await fileExists(includeFilePath)) {
911
+ const processed = await processIncludeHelper(includePath, localVars, template, matchOffset);
912
+ output = output.replace(fullMatch, processed);
913
+ foundValidPath = true;
914
+ break;
915
+ }
916
+ }
917
+ if (!foundValidPath) {
918
+ output = output.replace(fullMatch, createDetailedErrorMessage("Include", `None of the includeFirst paths exist: ${pathArrayString}`, filePath, template, matchOffset, fullMatch));
919
+ }
920
+ } catch (error) {
921
+ output = output.replace(fullMatch, createDetailedErrorMessage("Include", `Error processing @includeFirst: ${error.message}`, filePath, template, matchOffset, fullMatch));
922
+ }
923
+ includeFirstRegex.lastIndex = 0;
924
+ }
925
+ function resolvePath(includePath, partialsDir2, filePath2) {
926
+ try {
927
+ let includeFilePath = includePath;
928
+ if (!includePath.endsWith(".stx")) {
929
+ includeFilePath = `${includePath}.stx`;
930
+ }
931
+ if (!includeFilePath.startsWith("./") && !includeFilePath.startsWith("../")) {
932
+ includeFilePath = path2.join(partialsDir2, includeFilePath);
933
+ } else {
934
+ includeFilePath = path2.resolve(path2.dirname(filePath2), includeFilePath);
935
+ }
936
+ return includeFilePath;
937
+ } catch (error) {
938
+ console.error(`Error resolving path ${includePath}: ${error}`);
939
+ return null;
940
+ }
941
+ }
942
+ const processedIncludes = new Set;
943
+ async function processIncludeHelper(includePath, localVars = {}, templateStr, offsetPos) {
944
+ if (processedIncludes.has(includePath)) {
945
+ return createDetailedErrorMessage("Include", `Circular include detected: ${includePath}`, filePath, templateStr, offsetPos);
946
+ }
947
+ processedIncludes.add(includePath);
948
+ try {
949
+ const includeFilePath = resolvePath(includePath, partialsDir, filePath);
950
+ if (!includeFilePath) {
951
+ return createDetailedErrorMessage("Include", `Could not resolve path for include: ${includePath}`, filePath, templateStr, offsetPos);
952
+ }
953
+ dependencies.add(includeFilePath);
954
+ let partialContent = partialsCache.get(includeFilePath);
955
+ if (!partialContent) {
956
+ try {
957
+ partialContent = await Bun.file(includeFilePath).text();
958
+ partialsCache.set(includeFilePath, partialContent);
959
+ } catch (error) {
960
+ return createDetailedErrorMessage("Include", `Error loading include file ${includePath}: ${error.message}`, filePath, templateStr, offsetPos);
961
+ }
962
+ }
963
+ const includeContext = { ...context };
964
+ for (const [key, value] of Object.entries(localVars)) {
965
+ includeContext[key] = value;
966
+ }
967
+ if (partialContent.includes("@include") || partialContent.includes("@partial")) {
968
+ partialContent = await processIncludes(partialContent, includeContext, includeFilePath, options, dependencies);
969
+ }
970
+ const { processLoops } = await import("./chunk-zhs1t2p5.js");
971
+ let processedContent = processLoops(partialContent, includeContext, includeFilePath);
972
+ processedContent = processConditionals(processedContent, includeContext, includeFilePath);
973
+ processedContent = processExpressions(processedContent, includeContext, includeFilePath);
974
+ return processedContent;
975
+ } catch (error) {
976
+ return createDetailedErrorMessage("Include", `Error processing include ${includePath}: ${error.message}`, filePath, templateStr, offsetPos);
977
+ } finally {
978
+ processedIncludes.delete(includePath);
979
+ }
980
+ }
981
+ const includeRegex = /@include\s*\(['"]([^'"]+)['"](?:,\s*(\{[^}]*\}))?\)/g;
982
+ let match;
983
+ while (match = includeRegex.exec(output)) {
984
+ const [fullMatch, includePath, varsString] = match;
985
+ const matchOffset = match.index;
986
+ let localVars = {};
987
+ if (varsString) {
988
+ try {
989
+ const varsFn = new Function(`return ${varsString}`);
990
+ localVars = varsFn();
991
+ } catch (error) {
992
+ output = output.replace(fullMatch, createDetailedErrorMessage("Include", `Error parsing include variables for ${includePath}: ${error.message}`, filePath, template, matchOffset));
993
+ continue;
994
+ }
995
+ }
996
+ const processedContent = await processIncludeHelper(includePath, localVars, template, matchOffset);
997
+ output = output.replace(fullMatch, processedContent);
998
+ includeRegex.lastIndex = 0;
999
+ }
1000
+ return output;
1001
+ }
1002
+ function processStackPushDirectives(template, stacks) {
1003
+ let result = template;
1004
+ result = result.replace(/@push\(['"]([^'"]+)['"]\)([\s\S]*?)@endpush/g, (match, name, content) => {
1005
+ if (!stacks[name]) {
1006
+ stacks[name] = [];
1007
+ }
1008
+ stacks[name].push(content);
1009
+ return "";
1010
+ });
1011
+ result = result.replace(/@prepend\(['"]([^'"]+)['"]\)([\s\S]*?)@endprepend/g, (match, name, content) => {
1012
+ if (!stacks[name]) {
1013
+ stacks[name] = [];
1014
+ }
1015
+ stacks[name].unshift(content);
1016
+ return "";
1017
+ });
1018
+ return result;
1019
+ }
1020
+ function processStackReplacements(template, stacks) {
1021
+ return template.replace(/@stack\(['"]([^'"]+)['"]\)/g, (match, name) => {
1022
+ if (!stacks[name] || stacks[name].length === 0) {
1023
+ return "";
1024
+ }
1025
+ return stacks[name].join(`
1026
+ `);
1027
+ });
1028
+ }
1029
+
1030
+ // ../../node_modules/marked/lib/marked.esm.js
1031
+ function _getDefaults() {
1032
+ return {
1033
+ async: false,
1034
+ breaks: false,
1035
+ extensions: null,
1036
+ gfm: true,
1037
+ hooks: null,
1038
+ pedantic: false,
1039
+ renderer: null,
1040
+ silent: false,
1041
+ tokenizer: null,
1042
+ walkTokens: null
1043
+ };
1044
+ }
1045
+ var _defaults = _getDefaults();
1046
+ function changeDefaults(newDefaults) {
1047
+ _defaults = newDefaults;
1048
+ }
1049
+ var noopTest = { exec: () => null };
1050
+ function edit(regex, opt = "") {
1051
+ let source = typeof regex === "string" ? regex : regex.source;
1052
+ const obj = {
1053
+ replace: (name, val) => {
1054
+ let valSource = typeof val === "string" ? val : val.source;
1055
+ valSource = valSource.replace(other.caret, "$1");
1056
+ source = source.replace(name, valSource);
1057
+ return obj;
1058
+ },
1059
+ getRegex: () => {
1060
+ return new RegExp(source, opt);
1061
+ }
1062
+ };
1063
+ return obj;
1064
+ }
1065
+ var other = {
1066
+ codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm,
1067
+ outputLinkReplace: /\\([\[\]])/g,
1068
+ indentCodeCompensation: /^(\s+)(?:```)/,
1069
+ beginningSpace: /^\s+/,
1070
+ endingHash: /#$/,
1071
+ startingSpaceChar: /^ /,
1072
+ endingSpaceChar: / $/,
1073
+ nonSpaceChar: /[^ ]/,
1074
+ newLineCharGlobal: /\n/g,
1075
+ tabCharGlobal: /\t/g,
1076
+ multipleSpaceGlobal: /\s+/g,
1077
+ blankLine: /^[ \t]*$/,
1078
+ doubleBlankLine: /\n[ \t]*\n[ \t]*$/,
1079
+ blockquoteStart: /^ {0,3}>/,
1080
+ blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g,
1081
+ blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm,
1082
+ listReplaceTabs: /^\t+/,
1083
+ listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,
1084
+ listIsTask: /^\[[ xX]\] /,
1085
+ listReplaceTask: /^\[[ xX]\] +/,
1086
+ anyLine: /\n.*\n/,
1087
+ hrefBrackets: /^<(.*)>$/,
1088
+ tableDelimiter: /[:|]/,
1089
+ tableAlignChars: /^\||\| *$/g,
1090
+ tableRowBlankLine: /\n[ \t]*$/,
1091
+ tableAlignRight: /^ *-+: *$/,
1092
+ tableAlignCenter: /^ *:-+: *$/,
1093
+ tableAlignLeft: /^ *:-+ *$/,
1094
+ startATag: /^<a /i,
1095
+ endATag: /^<\/a>/i,
1096
+ startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i,
1097
+ endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i,
1098
+ startAngleBracket: /^</,
1099
+ endAngleBracket: />$/,
1100
+ pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/,
1101
+ unicodeAlphaNumeric: /[\p{L}\p{N}]/u,
1102
+ escapeTest: /[&<>"']/,
1103
+ escapeReplace: /[&<>"']/g,
1104
+ escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,
1105
+ escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,
1106
+ unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,
1107
+ caret: /(^|[^\[])\^/g,
1108
+ percentDecode: /%25/g,
1109
+ findPipe: /\|/g,
1110
+ splitPipe: / \|/,
1111
+ slashPipe: /\\\|/g,
1112
+ carriageReturn: /\r\n|\r/g,
1113
+ spaceLine: /^ +$/gm,
1114
+ notSpaceStart: /^\S*/,
1115
+ endingNewline: /\n$/,
1116
+ listItemRegex: (bull) => new RegExp(`^( {0,3}${bull})((?:[ ][^\\n]*)?(?:\\n|$))`),
1117
+ nextBulletRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),
1118
+ hrRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),
1119
+ fencesBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`),
1120
+ headingBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),
1121
+ htmlBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, "i")
1122
+ };
1123
+ var newline = /^(?:[ \t]*(?:\n|$))+/;
1124
+ var blockCode = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
1125
+ var fences = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
1126
+ var hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
1127
+ var heading = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
1128
+ var bullet = /(?:[*+-]|\d{1,9}[.)])/;
1129
+ var lheadingCore = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
1130
+ var lheading = edit(lheadingCore).replace(/bull/g, bullet).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
1131
+ var lheadingGfm = edit(lheadingCore).replace(/bull/g, bullet).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
1132
+ var _paragraph = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
1133
+ var blockText = /^[^\n]+/;
1134
+ var _blockLabel = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
1135
+ var def = edit(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", _blockLabel).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
1136
+ var list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, bullet).getRegex();
1137
+ var _tag = "address|article|aside|base|basefont|blockquote|body|caption" + "|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption" + "|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe" + "|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option" + "|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title" + "|tr|track|ul";
1138
+ var _comment = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
1139
+ var html = edit("^ {0,3}(?:" + "<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)" + "|comment[^\\n]*(\\n+|$)" + "|<\\?[\\s\\S]*?(?:\\?>\\n*|$)" + "|<![A-Z][\\s\\S]*?(?:>\\n*|$)" + "|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)" + "|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)" + "|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)" + "|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)" + ")", "i").replace("comment", _comment).replace("tag", _tag).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
1140
+ var paragraph = edit(_paragraph).replace("hr", hr).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", _tag).getRegex();
1141
+ var blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", paragraph).getRegex();
1142
+ var blockNormal = {
1143
+ blockquote,
1144
+ code: blockCode,
1145
+ def,
1146
+ fences,
1147
+ heading,
1148
+ hr,
1149
+ html,
1150
+ lheading,
1151
+ list,
1152
+ newline,
1153
+ paragraph,
1154
+ table: noopTest,
1155
+ text: blockText
1156
+ };
1157
+ var gfmTable = edit("^ *([^\\n ].*)\\n" + " {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)" + "(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", hr).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3}\t)[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", _tag).getRegex();
1158
+ var blockGfm = {
1159
+ ...blockNormal,
1160
+ lheading: lheadingGfm,
1161
+ table: gfmTable,
1162
+ paragraph: edit(_paragraph).replace("hr", hr).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", gfmTable).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", _tag).getRegex()
1163
+ };
1164
+ var blockPedantic = {
1165
+ ...blockNormal,
1166
+ html: edit("^ *(?:comment *(?:\\n|\\s*$)" + "|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)" + `|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", _comment).replace(/tag/g, "(?!(?:" + "a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub" + "|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)" + "\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),
1167
+ def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
1168
+ heading: /^(#{1,6})(.*)(?:\n+|$)/,
1169
+ fences: noopTest,
1170
+ lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
1171
+ paragraph: edit(_paragraph).replace("hr", hr).replace("heading", ` *#{1,6} *[^
1172
+ ]`).replace("lheading", lheading).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex()
1173
+ };
1174
+ var escape$1 = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
1175
+ var inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
1176
+ var br = /^( {2,}|\\)\n(?!\s*$)/;
1177
+ var inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
1178
+ var _punctuation = /[\p{P}\p{S}]/u;
1179
+ var _punctuationOrSpace = /[\s\p{P}\p{S}]/u;
1180
+ var _notPunctuationOrSpace = /[^\s\p{P}\p{S}]/u;
1181
+ var punctuation = edit(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, _punctuationOrSpace).getRegex();
1182
+ var _punctuationGfmStrongEm = /(?!~)[\p{P}\p{S}]/u;
1183
+ var _punctuationOrSpaceGfmStrongEm = /(?!~)[\s\p{P}\p{S}]/u;
1184
+ var _notPunctuationOrSpaceGfmStrongEm = /(?:[^\s\p{P}\p{S}]|~)/u;
1185
+ var blockSkip = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g;
1186
+ var emStrongLDelimCore = /^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/;
1187
+ var emStrongLDelim = edit(emStrongLDelimCore, "u").replace(/punct/g, _punctuation).getRegex();
1188
+ var emStrongLDelimGfm = edit(emStrongLDelimCore, "u").replace(/punct/g, _punctuationGfmStrongEm).getRegex();
1189
+ var emStrongRDelimAstCore = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)" + "|[^*]+(?=[^*])" + "|(?!\\*)punct(\\*+)(?=[\\s]|$)" + "|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)" + "|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)" + "|[\\s](\\*+)(?!\\*)(?=punct)" + "|(?!\\*)punct(\\*+)(?!\\*)(?=punct)" + "|notPunctSpace(\\*+)(?=notPunctSpace)";
1190
+ var emStrongRDelimAst = edit(emStrongRDelimAstCore, "gu").replace(/notPunctSpace/g, _notPunctuationOrSpace).replace(/punctSpace/g, _punctuationOrSpace).replace(/punct/g, _punctuation).getRegex();
1191
+ var emStrongRDelimAstGfm = edit(emStrongRDelimAstCore, "gu").replace(/notPunctSpace/g, _notPunctuationOrSpaceGfmStrongEm).replace(/punctSpace/g, _punctuationOrSpaceGfmStrongEm).replace(/punct/g, _punctuationGfmStrongEm).getRegex();
1192
+ var emStrongRDelimUnd = edit("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)" + "|[^_]+(?=[^_])" + "|(?!_)punct(_+)(?=[\\s]|$)" + "|notPunctSpace(_+)(?!_)(?=punctSpace|$)" + "|(?!_)punctSpace(_+)(?=notPunctSpace)" + "|[\\s](_+)(?!_)(?=punct)" + "|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, _notPunctuationOrSpace).replace(/punctSpace/g, _punctuationOrSpace).replace(/punct/g, _punctuation).getRegex();
1193
+ var anyPunctuation = edit(/\\(punct)/, "gu").replace(/punct/g, _punctuation).getRegex();
1194
+ var autolink = edit(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
1195
+ var _inlineComment = edit(_comment).replace("(?:-->|$)", "-->").getRegex();
1196
+ var tag = edit("^comment" + "|^</[a-zA-Z][\\w:-]*\\s*>" + "|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>" + "|^<\\?[\\s\\S]*?\\?>" + "|^<![a-zA-Z]+\\s[\\s\\S]*?>" + "|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", _inlineComment).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
1197
+ var _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
1198
+ var link = edit(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label", _inlineLabel).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
1199
+ var reflink = edit(/^!?\[(label)\]\[(ref)\]/).replace("label", _inlineLabel).replace("ref", _blockLabel).getRegex();
1200
+ var nolink = edit(/^!?\[(ref)\](?:\[\])?/).replace("ref", _blockLabel).getRegex();
1201
+ var reflinkSearch = edit("reflink|nolink(?!\\()", "g").replace("reflink", reflink).replace("nolink", nolink).getRegex();
1202
+ var inlineNormal = {
1203
+ _backpedal: noopTest,
1204
+ anyPunctuation,
1205
+ autolink,
1206
+ blockSkip,
1207
+ br,
1208
+ code: inlineCode,
1209
+ del: noopTest,
1210
+ emStrongLDelim,
1211
+ emStrongRDelimAst,
1212
+ emStrongRDelimUnd,
1213
+ escape: escape$1,
1214
+ link,
1215
+ nolink,
1216
+ punctuation,
1217
+ reflink,
1218
+ reflinkSearch,
1219
+ tag,
1220
+ text: inlineText,
1221
+ url: noopTest
1222
+ };
1223
+ var inlinePedantic = {
1224
+ ...inlineNormal,
1225
+ link: edit(/^!?\[(label)\]\((.*?)\)/).replace("label", _inlineLabel).getRegex(),
1226
+ reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", _inlineLabel).getRegex()
1227
+ };
1228
+ var inlineGfm = {
1229
+ ...inlineNormal,
1230
+ emStrongRDelimAst: emStrongRDelimAstGfm,
1231
+ emStrongLDelim: emStrongLDelimGfm,
1232
+ url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, "i").replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),
1233
+ _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,
1234
+ del: /^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/,
1235
+ text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
1236
+ };
1237
+ var inlineBreaks = {
1238
+ ...inlineGfm,
1239
+ br: edit(br).replace("{2,}", "*").getRegex(),
1240
+ text: edit(inlineGfm.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex()
1241
+ };
1242
+ var block = {
1243
+ normal: blockNormal,
1244
+ gfm: blockGfm,
1245
+ pedantic: blockPedantic
1246
+ };
1247
+ var inline = {
1248
+ normal: inlineNormal,
1249
+ gfm: inlineGfm,
1250
+ breaks: inlineBreaks,
1251
+ pedantic: inlinePedantic
1252
+ };
1253
+ var escapeReplacements = {
1254
+ "&": "&amp;",
1255
+ "<": "&lt;",
1256
+ ">": "&gt;",
1257
+ '"': "&quot;",
1258
+ "'": "&#39;"
1259
+ };
1260
+ var getEscapeReplacement = (ch) => escapeReplacements[ch];
1261
+ function escape(html2, encode) {
1262
+ if (encode) {
1263
+ if (other.escapeTest.test(html2)) {
1264
+ return html2.replace(other.escapeReplace, getEscapeReplacement);
1265
+ }
1266
+ } else {
1267
+ if (other.escapeTestNoEncode.test(html2)) {
1268
+ return html2.replace(other.escapeReplaceNoEncode, getEscapeReplacement);
1269
+ }
1270
+ }
1271
+ return html2;
1272
+ }
1273
+ function cleanUrl(href) {
1274
+ try {
1275
+ href = encodeURI(href).replace(other.percentDecode, "%");
1276
+ } catch {
1277
+ return null;
1278
+ }
1279
+ return href;
1280
+ }
1281
+ function splitCells(tableRow, count) {
1282
+ const row = tableRow.replace(other.findPipe, (match, offset, str) => {
1283
+ let escaped = false;
1284
+ let curr = offset;
1285
+ while (--curr >= 0 && str[curr] === "\\")
1286
+ escaped = !escaped;
1287
+ if (escaped) {
1288
+ return "|";
1289
+ } else {
1290
+ return " |";
1291
+ }
1292
+ }), cells = row.split(other.splitPipe);
1293
+ let i = 0;
1294
+ if (!cells[0].trim()) {
1295
+ cells.shift();
1296
+ }
1297
+ if (cells.length > 0 && !cells.at(-1)?.trim()) {
1298
+ cells.pop();
1299
+ }
1300
+ if (count) {
1301
+ if (cells.length > count) {
1302
+ cells.splice(count);
1303
+ } else {
1304
+ while (cells.length < count)
1305
+ cells.push("");
1306
+ }
1307
+ }
1308
+ for (;i < cells.length; i++) {
1309
+ cells[i] = cells[i].trim().replace(other.slashPipe, "|");
1310
+ }
1311
+ return cells;
1312
+ }
1313
+ function rtrim(str, c, invert) {
1314
+ const l = str.length;
1315
+ if (l === 0) {
1316
+ return "";
1317
+ }
1318
+ let suffLen = 0;
1319
+ while (suffLen < l) {
1320
+ const currChar = str.charAt(l - suffLen - 1);
1321
+ if (currChar === c && true) {
1322
+ suffLen++;
1323
+ } else {
1324
+ break;
1325
+ }
1326
+ }
1327
+ return str.slice(0, l - suffLen);
1328
+ }
1329
+ function findClosingBracket(str, b) {
1330
+ if (str.indexOf(b[1]) === -1) {
1331
+ return -1;
1332
+ }
1333
+ let level = 0;
1334
+ for (let i = 0;i < str.length; i++) {
1335
+ if (str[i] === "\\") {
1336
+ i++;
1337
+ } else if (str[i] === b[0]) {
1338
+ level++;
1339
+ } else if (str[i] === b[1]) {
1340
+ level--;
1341
+ if (level < 0) {
1342
+ return i;
1343
+ }
1344
+ }
1345
+ }
1346
+ if (level > 0) {
1347
+ return -2;
1348
+ }
1349
+ return -1;
1350
+ }
1351
+ function outputLink(cap, link2, raw, lexer, rules) {
1352
+ const href = link2.href;
1353
+ const title = link2.title || null;
1354
+ const text = cap[1].replace(rules.other.outputLinkReplace, "$1");
1355
+ lexer.state.inLink = true;
1356
+ const token = {
1357
+ type: cap[0].charAt(0) === "!" ? "image" : "link",
1358
+ raw,
1359
+ href,
1360
+ title,
1361
+ text,
1362
+ tokens: lexer.inlineTokens(text)
1363
+ };
1364
+ lexer.state.inLink = false;
1365
+ return token;
1366
+ }
1367
+ function indentCodeCompensation(raw, text, rules) {
1368
+ const matchIndentToCode = raw.match(rules.other.indentCodeCompensation);
1369
+ if (matchIndentToCode === null) {
1370
+ return text;
1371
+ }
1372
+ const indentToCode = matchIndentToCode[1];
1373
+ return text.split(`
1374
+ `).map((node) => {
1375
+ const matchIndentInNode = node.match(rules.other.beginningSpace);
1376
+ if (matchIndentInNode === null) {
1377
+ return node;
1378
+ }
1379
+ const [indentInNode] = matchIndentInNode;
1380
+ if (indentInNode.length >= indentToCode.length) {
1381
+ return node.slice(indentToCode.length);
1382
+ }
1383
+ return node;
1384
+ }).join(`
1385
+ `);
1386
+ }
1387
+
1388
+ class _Tokenizer {
1389
+ options;
1390
+ rules;
1391
+ lexer;
1392
+ constructor(options) {
1393
+ this.options = options || _defaults;
1394
+ }
1395
+ space(src) {
1396
+ const cap = this.rules.block.newline.exec(src);
1397
+ if (cap && cap[0].length > 0) {
1398
+ return {
1399
+ type: "space",
1400
+ raw: cap[0]
1401
+ };
1402
+ }
1403
+ }
1404
+ code(src) {
1405
+ const cap = this.rules.block.code.exec(src);
1406
+ if (cap) {
1407
+ const text = cap[0].replace(this.rules.other.codeRemoveIndent, "");
1408
+ return {
1409
+ type: "code",
1410
+ raw: cap[0],
1411
+ codeBlockStyle: "indented",
1412
+ text: !this.options.pedantic ? rtrim(text, `
1413
+ `) : text
1414
+ };
1415
+ }
1416
+ }
1417
+ fences(src) {
1418
+ const cap = this.rules.block.fences.exec(src);
1419
+ if (cap) {
1420
+ const raw = cap[0];
1421
+ const text = indentCodeCompensation(raw, cap[3] || "", this.rules);
1422
+ return {
1423
+ type: "code",
1424
+ raw,
1425
+ lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : cap[2],
1426
+ text
1427
+ };
1428
+ }
1429
+ }
1430
+ heading(src) {
1431
+ const cap = this.rules.block.heading.exec(src);
1432
+ if (cap) {
1433
+ let text = cap[2].trim();
1434
+ if (this.rules.other.endingHash.test(text)) {
1435
+ const trimmed = rtrim(text, "#");
1436
+ if (this.options.pedantic) {
1437
+ text = trimmed.trim();
1438
+ } else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) {
1439
+ text = trimmed.trim();
1440
+ }
1441
+ }
1442
+ return {
1443
+ type: "heading",
1444
+ raw: cap[0],
1445
+ depth: cap[1].length,
1446
+ text,
1447
+ tokens: this.lexer.inline(text)
1448
+ };
1449
+ }
1450
+ }
1451
+ hr(src) {
1452
+ const cap = this.rules.block.hr.exec(src);
1453
+ if (cap) {
1454
+ return {
1455
+ type: "hr",
1456
+ raw: rtrim(cap[0], `
1457
+ `)
1458
+ };
1459
+ }
1460
+ }
1461
+ blockquote(src) {
1462
+ const cap = this.rules.block.blockquote.exec(src);
1463
+ if (cap) {
1464
+ let lines = rtrim(cap[0], `
1465
+ `).split(`
1466
+ `);
1467
+ let raw = "";
1468
+ let text = "";
1469
+ const tokens = [];
1470
+ while (lines.length > 0) {
1471
+ let inBlockquote = false;
1472
+ const currentLines = [];
1473
+ let i;
1474
+ for (i = 0;i < lines.length; i++) {
1475
+ if (this.rules.other.blockquoteStart.test(lines[i])) {
1476
+ currentLines.push(lines[i]);
1477
+ inBlockquote = true;
1478
+ } else if (!inBlockquote) {
1479
+ currentLines.push(lines[i]);
1480
+ } else {
1481
+ break;
1482
+ }
1483
+ }
1484
+ lines = lines.slice(i);
1485
+ const currentRaw = currentLines.join(`
1486
+ `);
1487
+ const currentText = currentRaw.replace(this.rules.other.blockquoteSetextReplace, `
1488
+ $1`).replace(this.rules.other.blockquoteSetextReplace2, "");
1489
+ raw = raw ? `${raw}
1490
+ ${currentRaw}` : currentRaw;
1491
+ text = text ? `${text}
1492
+ ${currentText}` : currentText;
1493
+ const top = this.lexer.state.top;
1494
+ this.lexer.state.top = true;
1495
+ this.lexer.blockTokens(currentText, tokens, true);
1496
+ this.lexer.state.top = top;
1497
+ if (lines.length === 0) {
1498
+ break;
1499
+ }
1500
+ const lastToken = tokens.at(-1);
1501
+ if (lastToken?.type === "code") {
1502
+ break;
1503
+ } else if (lastToken?.type === "blockquote") {
1504
+ const oldToken = lastToken;
1505
+ const newText = oldToken.raw + `
1506
+ ` + lines.join(`
1507
+ `);
1508
+ const newToken = this.blockquote(newText);
1509
+ tokens[tokens.length - 1] = newToken;
1510
+ raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;
1511
+ text = text.substring(0, text.length - oldToken.text.length) + newToken.text;
1512
+ break;
1513
+ } else if (lastToken?.type === "list") {
1514
+ const oldToken = lastToken;
1515
+ const newText = oldToken.raw + `
1516
+ ` + lines.join(`
1517
+ `);
1518
+ const newToken = this.list(newText);
1519
+ tokens[tokens.length - 1] = newToken;
1520
+ raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;
1521
+ text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;
1522
+ lines = newText.substring(tokens.at(-1).raw.length).split(`
1523
+ `);
1524
+ continue;
1525
+ }
1526
+ }
1527
+ return {
1528
+ type: "blockquote",
1529
+ raw,
1530
+ tokens,
1531
+ text
1532
+ };
1533
+ }
1534
+ }
1535
+ list(src) {
1536
+ let cap = this.rules.block.list.exec(src);
1537
+ if (cap) {
1538
+ let bull = cap[1].trim();
1539
+ const isordered = bull.length > 1;
1540
+ const list2 = {
1541
+ type: "list",
1542
+ raw: "",
1543
+ ordered: isordered,
1544
+ start: isordered ? +bull.slice(0, -1) : "",
1545
+ loose: false,
1546
+ items: []
1547
+ };
1548
+ bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
1549
+ if (this.options.pedantic) {
1550
+ bull = isordered ? bull : "[*+-]";
1551
+ }
1552
+ const itemRegex = this.rules.other.listItemRegex(bull);
1553
+ let endsWithBlankLine = false;
1554
+ while (src) {
1555
+ let endEarly = false;
1556
+ let raw = "";
1557
+ let itemContents = "";
1558
+ if (!(cap = itemRegex.exec(src))) {
1559
+ break;
1560
+ }
1561
+ if (this.rules.block.hr.test(src)) {
1562
+ break;
1563
+ }
1564
+ raw = cap[0];
1565
+ src = src.substring(raw.length);
1566
+ let line = cap[2].split(`
1567
+ `, 1)[0].replace(this.rules.other.listReplaceTabs, (t) => " ".repeat(3 * t.length));
1568
+ let nextLine = src.split(`
1569
+ `, 1)[0];
1570
+ let blankLine = !line.trim();
1571
+ let indent = 0;
1572
+ if (this.options.pedantic) {
1573
+ indent = 2;
1574
+ itemContents = line.trimStart();
1575
+ } else if (blankLine) {
1576
+ indent = cap[1].length + 1;
1577
+ } else {
1578
+ indent = cap[2].search(this.rules.other.nonSpaceChar);
1579
+ indent = indent > 4 ? 1 : indent;
1580
+ itemContents = line.slice(indent);
1581
+ indent += cap[1].length;
1582
+ }
1583
+ if (blankLine && this.rules.other.blankLine.test(nextLine)) {
1584
+ raw += nextLine + `
1585
+ `;
1586
+ src = src.substring(nextLine.length + 1);
1587
+ endEarly = true;
1588
+ }
1589
+ if (!endEarly) {
1590
+ const nextBulletRegex = this.rules.other.nextBulletRegex(indent);
1591
+ const hrRegex = this.rules.other.hrRegex(indent);
1592
+ const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent);
1593
+ const headingBeginRegex = this.rules.other.headingBeginRegex(indent);
1594
+ const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent);
1595
+ while (src) {
1596
+ const rawLine = src.split(`
1597
+ `, 1)[0];
1598
+ let nextLineWithoutTabs;
1599
+ nextLine = rawLine;
1600
+ if (this.options.pedantic) {
1601
+ nextLine = nextLine.replace(this.rules.other.listReplaceNesting, " ");
1602
+ nextLineWithoutTabs = nextLine;
1603
+ } else {
1604
+ nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, " ");
1605
+ }
1606
+ if (fencesBeginRegex.test(nextLine)) {
1607
+ break;
1608
+ }
1609
+ if (headingBeginRegex.test(nextLine)) {
1610
+ break;
1611
+ }
1612
+ if (htmlBeginRegex.test(nextLine)) {
1613
+ break;
1614
+ }
1615
+ if (nextBulletRegex.test(nextLine)) {
1616
+ break;
1617
+ }
1618
+ if (hrRegex.test(nextLine)) {
1619
+ break;
1620
+ }
1621
+ if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) {
1622
+ itemContents += `
1623
+ ` + nextLineWithoutTabs.slice(indent);
1624
+ } else {
1625
+ if (blankLine) {
1626
+ break;
1627
+ }
1628
+ if (line.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4) {
1629
+ break;
1630
+ }
1631
+ if (fencesBeginRegex.test(line)) {
1632
+ break;
1633
+ }
1634
+ if (headingBeginRegex.test(line)) {
1635
+ break;
1636
+ }
1637
+ if (hrRegex.test(line)) {
1638
+ break;
1639
+ }
1640
+ itemContents += `
1641
+ ` + nextLine;
1642
+ }
1643
+ if (!blankLine && !nextLine.trim()) {
1644
+ blankLine = true;
1645
+ }
1646
+ raw += rawLine + `
1647
+ `;
1648
+ src = src.substring(rawLine.length + 1);
1649
+ line = nextLineWithoutTabs.slice(indent);
1650
+ }
1651
+ }
1652
+ if (!list2.loose) {
1653
+ if (endsWithBlankLine) {
1654
+ list2.loose = true;
1655
+ } else if (this.rules.other.doubleBlankLine.test(raw)) {
1656
+ endsWithBlankLine = true;
1657
+ }
1658
+ }
1659
+ let istask = null;
1660
+ let ischecked;
1661
+ if (this.options.gfm) {
1662
+ istask = this.rules.other.listIsTask.exec(itemContents);
1663
+ if (istask) {
1664
+ ischecked = istask[0] !== "[ ] ";
1665
+ itemContents = itemContents.replace(this.rules.other.listReplaceTask, "");
1666
+ }
1667
+ }
1668
+ list2.items.push({
1669
+ type: "list_item",
1670
+ raw,
1671
+ task: !!istask,
1672
+ checked: ischecked,
1673
+ loose: false,
1674
+ text: itemContents,
1675
+ tokens: []
1676
+ });
1677
+ list2.raw += raw;
1678
+ }
1679
+ const lastItem = list2.items.at(-1);
1680
+ if (lastItem) {
1681
+ lastItem.raw = lastItem.raw.trimEnd();
1682
+ lastItem.text = lastItem.text.trimEnd();
1683
+ } else {
1684
+ return;
1685
+ }
1686
+ list2.raw = list2.raw.trimEnd();
1687
+ for (let i = 0;i < list2.items.length; i++) {
1688
+ this.lexer.state.top = false;
1689
+ list2.items[i].tokens = this.lexer.blockTokens(list2.items[i].text, []);
1690
+ if (!list2.loose) {
1691
+ const spacers = list2.items[i].tokens.filter((t) => t.type === "space");
1692
+ const hasMultipleLineBreaks = spacers.length > 0 && spacers.some((t) => this.rules.other.anyLine.test(t.raw));
1693
+ list2.loose = hasMultipleLineBreaks;
1694
+ }
1695
+ }
1696
+ if (list2.loose) {
1697
+ for (let i = 0;i < list2.items.length; i++) {
1698
+ list2.items[i].loose = true;
1699
+ }
1700
+ }
1701
+ return list2;
1702
+ }
1703
+ }
1704
+ html(src) {
1705
+ const cap = this.rules.block.html.exec(src);
1706
+ if (cap) {
1707
+ const token = {
1708
+ type: "html",
1709
+ block: true,
1710
+ raw: cap[0],
1711
+ pre: cap[1] === "pre" || cap[1] === "script" || cap[1] === "style",
1712
+ text: cap[0]
1713
+ };
1714
+ return token;
1715
+ }
1716
+ }
1717
+ def(src) {
1718
+ const cap = this.rules.block.def.exec(src);
1719
+ if (cap) {
1720
+ const tag2 = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " ");
1721
+ const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "";
1722
+ const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : cap[3];
1723
+ return {
1724
+ type: "def",
1725
+ tag: tag2,
1726
+ raw: cap[0],
1727
+ href,
1728
+ title
1729
+ };
1730
+ }
1731
+ }
1732
+ table(src) {
1733
+ const cap = this.rules.block.table.exec(src);
1734
+ if (!cap) {
1735
+ return;
1736
+ }
1737
+ if (!this.rules.other.tableDelimiter.test(cap[2])) {
1738
+ return;
1739
+ }
1740
+ const headers = splitCells(cap[1]);
1741
+ const aligns = cap[2].replace(this.rules.other.tableAlignChars, "").split("|");
1742
+ const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, "").split(`
1743
+ `) : [];
1744
+ const item = {
1745
+ type: "table",
1746
+ raw: cap[0],
1747
+ header: [],
1748
+ align: [],
1749
+ rows: []
1750
+ };
1751
+ if (headers.length !== aligns.length) {
1752
+ return;
1753
+ }
1754
+ for (const align of aligns) {
1755
+ if (this.rules.other.tableAlignRight.test(align)) {
1756
+ item.align.push("right");
1757
+ } else if (this.rules.other.tableAlignCenter.test(align)) {
1758
+ item.align.push("center");
1759
+ } else if (this.rules.other.tableAlignLeft.test(align)) {
1760
+ item.align.push("left");
1761
+ } else {
1762
+ item.align.push(null);
1763
+ }
1764
+ }
1765
+ for (let i = 0;i < headers.length; i++) {
1766
+ item.header.push({
1767
+ text: headers[i],
1768
+ tokens: this.lexer.inline(headers[i]),
1769
+ header: true,
1770
+ align: item.align[i]
1771
+ });
1772
+ }
1773
+ for (const row of rows) {
1774
+ item.rows.push(splitCells(row, item.header.length).map((cell, i) => {
1775
+ return {
1776
+ text: cell,
1777
+ tokens: this.lexer.inline(cell),
1778
+ header: false,
1779
+ align: item.align[i]
1780
+ };
1781
+ }));
1782
+ }
1783
+ return item;
1784
+ }
1785
+ lheading(src) {
1786
+ const cap = this.rules.block.lheading.exec(src);
1787
+ if (cap) {
1788
+ return {
1789
+ type: "heading",
1790
+ raw: cap[0],
1791
+ depth: cap[2].charAt(0) === "=" ? 1 : 2,
1792
+ text: cap[1],
1793
+ tokens: this.lexer.inline(cap[1])
1794
+ };
1795
+ }
1796
+ }
1797
+ paragraph(src) {
1798
+ const cap = this.rules.block.paragraph.exec(src);
1799
+ if (cap) {
1800
+ const text = cap[1].charAt(cap[1].length - 1) === `
1801
+ ` ? cap[1].slice(0, -1) : cap[1];
1802
+ return {
1803
+ type: "paragraph",
1804
+ raw: cap[0],
1805
+ text,
1806
+ tokens: this.lexer.inline(text)
1807
+ };
1808
+ }
1809
+ }
1810
+ text(src) {
1811
+ const cap = this.rules.block.text.exec(src);
1812
+ if (cap) {
1813
+ return {
1814
+ type: "text",
1815
+ raw: cap[0],
1816
+ text: cap[0],
1817
+ tokens: this.lexer.inline(cap[0])
1818
+ };
1819
+ }
1820
+ }
1821
+ escape(src) {
1822
+ const cap = this.rules.inline.escape.exec(src);
1823
+ if (cap) {
1824
+ return {
1825
+ type: "escape",
1826
+ raw: cap[0],
1827
+ text: cap[1]
1828
+ };
1829
+ }
1830
+ }
1831
+ tag(src) {
1832
+ const cap = this.rules.inline.tag.exec(src);
1833
+ if (cap) {
1834
+ if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) {
1835
+ this.lexer.state.inLink = true;
1836
+ } else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) {
1837
+ this.lexer.state.inLink = false;
1838
+ }
1839
+ if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) {
1840
+ this.lexer.state.inRawBlock = true;
1841
+ } else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) {
1842
+ this.lexer.state.inRawBlock = false;
1843
+ }
1844
+ return {
1845
+ type: "html",
1846
+ raw: cap[0],
1847
+ inLink: this.lexer.state.inLink,
1848
+ inRawBlock: this.lexer.state.inRawBlock,
1849
+ block: false,
1850
+ text: cap[0]
1851
+ };
1852
+ }
1853
+ }
1854
+ link(src) {
1855
+ const cap = this.rules.inline.link.exec(src);
1856
+ if (cap) {
1857
+ const trimmedUrl = cap[2].trim();
1858
+ if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) {
1859
+ if (!this.rules.other.endAngleBracket.test(trimmedUrl)) {
1860
+ return;
1861
+ }
1862
+ const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), "\\");
1863
+ if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
1864
+ return;
1865
+ }
1866
+ } else {
1867
+ const lastParenIndex = findClosingBracket(cap[2], "()");
1868
+ if (lastParenIndex === -2) {
1869
+ return;
1870
+ }
1871
+ if (lastParenIndex > -1) {
1872
+ const start = cap[0].indexOf("!") === 0 ? 5 : 4;
1873
+ const linkLen = start + cap[1].length + lastParenIndex;
1874
+ cap[2] = cap[2].substring(0, lastParenIndex);
1875
+ cap[0] = cap[0].substring(0, linkLen).trim();
1876
+ cap[3] = "";
1877
+ }
1878
+ }
1879
+ let href = cap[2];
1880
+ let title = "";
1881
+ if (this.options.pedantic) {
1882
+ const link2 = this.rules.other.pedanticHrefTitle.exec(href);
1883
+ if (link2) {
1884
+ href = link2[1];
1885
+ title = link2[3];
1886
+ }
1887
+ } else {
1888
+ title = cap[3] ? cap[3].slice(1, -1) : "";
1889
+ }
1890
+ href = href.trim();
1891
+ if (this.rules.other.startAngleBracket.test(href)) {
1892
+ if (this.options.pedantic && !this.rules.other.endAngleBracket.test(trimmedUrl)) {
1893
+ href = href.slice(1);
1894
+ } else {
1895
+ href = href.slice(1, -1);
1896
+ }
1897
+ }
1898
+ return outputLink(cap, {
1899
+ href: href ? href.replace(this.rules.inline.anyPunctuation, "$1") : href,
1900
+ title: title ? title.replace(this.rules.inline.anyPunctuation, "$1") : title
1901
+ }, cap[0], this.lexer, this.rules);
1902
+ }
1903
+ }
1904
+ reflink(src, links) {
1905
+ let cap;
1906
+ if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
1907
+ const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, " ");
1908
+ const link2 = links[linkString.toLowerCase()];
1909
+ if (!link2) {
1910
+ const text = cap[0].charAt(0);
1911
+ return {
1912
+ type: "text",
1913
+ raw: text,
1914
+ text
1915
+ };
1916
+ }
1917
+ return outputLink(cap, link2, cap[0], this.lexer, this.rules);
1918
+ }
1919
+ }
1920
+ emStrong(src, maskedSrc, prevChar = "") {
1921
+ let match = this.rules.inline.emStrongLDelim.exec(src);
1922
+ if (!match)
1923
+ return;
1924
+ if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric))
1925
+ return;
1926
+ const nextChar = match[1] || match[2] || "";
1927
+ if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {
1928
+ const lLength = [...match[0]].length - 1;
1929
+ let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
1930
+ const endReg = match[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
1931
+ endReg.lastIndex = 0;
1932
+ maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
1933
+ while ((match = endReg.exec(maskedSrc)) != null) {
1934
+ rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
1935
+ if (!rDelim)
1936
+ continue;
1937
+ rLength = [...rDelim].length;
1938
+ if (match[3] || match[4]) {
1939
+ delimTotal += rLength;
1940
+ continue;
1941
+ } else if (match[5] || match[6]) {
1942
+ if (lLength % 3 && !((lLength + rLength) % 3)) {
1943
+ midDelimTotal += rLength;
1944
+ continue;
1945
+ }
1946
+ }
1947
+ delimTotal -= rLength;
1948
+ if (delimTotal > 0)
1949
+ continue;
1950
+ rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
1951
+ const lastCharLength = [...match[0]][0].length;
1952
+ const raw = src.slice(0, lLength + match.index + lastCharLength + rLength);
1953
+ if (Math.min(lLength, rLength) % 2) {
1954
+ const text2 = raw.slice(1, -1);
1955
+ return {
1956
+ type: "em",
1957
+ raw,
1958
+ text: text2,
1959
+ tokens: this.lexer.inlineTokens(text2)
1960
+ };
1961
+ }
1962
+ const text = raw.slice(2, -2);
1963
+ return {
1964
+ type: "strong",
1965
+ raw,
1966
+ text,
1967
+ tokens: this.lexer.inlineTokens(text)
1968
+ };
1969
+ }
1970
+ }
1971
+ }
1972
+ codespan(src) {
1973
+ const cap = this.rules.inline.code.exec(src);
1974
+ if (cap) {
1975
+ let text = cap[2].replace(this.rules.other.newLineCharGlobal, " ");
1976
+ const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text);
1977
+ const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text);
1978
+ if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
1979
+ text = text.substring(1, text.length - 1);
1980
+ }
1981
+ return {
1982
+ type: "codespan",
1983
+ raw: cap[0],
1984
+ text
1985
+ };
1986
+ }
1987
+ }
1988
+ br(src) {
1989
+ const cap = this.rules.inline.br.exec(src);
1990
+ if (cap) {
1991
+ return {
1992
+ type: "br",
1993
+ raw: cap[0]
1994
+ };
1995
+ }
1996
+ }
1997
+ del(src) {
1998
+ const cap = this.rules.inline.del.exec(src);
1999
+ if (cap) {
2000
+ return {
2001
+ type: "del",
2002
+ raw: cap[0],
2003
+ text: cap[2],
2004
+ tokens: this.lexer.inlineTokens(cap[2])
2005
+ };
2006
+ }
2007
+ }
2008
+ autolink(src) {
2009
+ const cap = this.rules.inline.autolink.exec(src);
2010
+ if (cap) {
2011
+ let text, href;
2012
+ if (cap[2] === "@") {
2013
+ text = cap[1];
2014
+ href = "mailto:" + text;
2015
+ } else {
2016
+ text = cap[1];
2017
+ href = text;
2018
+ }
2019
+ return {
2020
+ type: "link",
2021
+ raw: cap[0],
2022
+ text,
2023
+ href,
2024
+ tokens: [
2025
+ {
2026
+ type: "text",
2027
+ raw: text,
2028
+ text
2029
+ }
2030
+ ]
2031
+ };
2032
+ }
2033
+ }
2034
+ url(src) {
2035
+ let cap;
2036
+ if (cap = this.rules.inline.url.exec(src)) {
2037
+ let text, href;
2038
+ if (cap[2] === "@") {
2039
+ text = cap[0];
2040
+ href = "mailto:" + text;
2041
+ } else {
2042
+ let prevCapZero;
2043
+ do {
2044
+ prevCapZero = cap[0];
2045
+ cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? "";
2046
+ } while (prevCapZero !== cap[0]);
2047
+ text = cap[0];
2048
+ if (cap[1] === "www.") {
2049
+ href = "http://" + cap[0];
2050
+ } else {
2051
+ href = cap[0];
2052
+ }
2053
+ }
2054
+ return {
2055
+ type: "link",
2056
+ raw: cap[0],
2057
+ text,
2058
+ href,
2059
+ tokens: [
2060
+ {
2061
+ type: "text",
2062
+ raw: text,
2063
+ text
2064
+ }
2065
+ ]
2066
+ };
2067
+ }
2068
+ }
2069
+ inlineText(src) {
2070
+ const cap = this.rules.inline.text.exec(src);
2071
+ if (cap) {
2072
+ const escaped = this.lexer.state.inRawBlock;
2073
+ return {
2074
+ type: "text",
2075
+ raw: cap[0],
2076
+ text: cap[0],
2077
+ escaped
2078
+ };
2079
+ }
2080
+ }
2081
+ }
2082
+
2083
+ class _Lexer {
2084
+ tokens;
2085
+ options;
2086
+ state;
2087
+ tokenizer;
2088
+ inlineQueue;
2089
+ constructor(options) {
2090
+ this.tokens = [];
2091
+ this.tokens.links = Object.create(null);
2092
+ this.options = options || _defaults;
2093
+ this.options.tokenizer = this.options.tokenizer || new _Tokenizer;
2094
+ this.tokenizer = this.options.tokenizer;
2095
+ this.tokenizer.options = this.options;
2096
+ this.tokenizer.lexer = this;
2097
+ this.inlineQueue = [];
2098
+ this.state = {
2099
+ inLink: false,
2100
+ inRawBlock: false,
2101
+ top: true
2102
+ };
2103
+ const rules = {
2104
+ other,
2105
+ block: block.normal,
2106
+ inline: inline.normal
2107
+ };
2108
+ if (this.options.pedantic) {
2109
+ rules.block = block.pedantic;
2110
+ rules.inline = inline.pedantic;
2111
+ } else if (this.options.gfm) {
2112
+ rules.block = block.gfm;
2113
+ if (this.options.breaks) {
2114
+ rules.inline = inline.breaks;
2115
+ } else {
2116
+ rules.inline = inline.gfm;
2117
+ }
2118
+ }
2119
+ this.tokenizer.rules = rules;
2120
+ }
2121
+ static get rules() {
2122
+ return {
2123
+ block,
2124
+ inline
2125
+ };
2126
+ }
2127
+ static lex(src, options) {
2128
+ const lexer = new _Lexer(options);
2129
+ return lexer.lex(src);
2130
+ }
2131
+ static lexInline(src, options) {
2132
+ const lexer = new _Lexer(options);
2133
+ return lexer.inlineTokens(src);
2134
+ }
2135
+ lex(src) {
2136
+ src = src.replace(other.carriageReturn, `
2137
+ `);
2138
+ this.blockTokens(src, this.tokens);
2139
+ for (let i = 0;i < this.inlineQueue.length; i++) {
2140
+ const next = this.inlineQueue[i];
2141
+ this.inlineTokens(next.src, next.tokens);
2142
+ }
2143
+ this.inlineQueue = [];
2144
+ return this.tokens;
2145
+ }
2146
+ blockTokens(src, tokens = [], lastParagraphClipped = false) {
2147
+ if (this.options.pedantic) {
2148
+ src = src.replace(other.tabCharGlobal, " ").replace(other.spaceLine, "");
2149
+ }
2150
+ while (src) {
2151
+ let token;
2152
+ if (this.options.extensions?.block?.some((extTokenizer) => {
2153
+ if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
2154
+ src = src.substring(token.raw.length);
2155
+ tokens.push(token);
2156
+ return true;
2157
+ }
2158
+ return false;
2159
+ })) {
2160
+ continue;
2161
+ }
2162
+ if (token = this.tokenizer.space(src)) {
2163
+ src = src.substring(token.raw.length);
2164
+ const lastToken = tokens.at(-1);
2165
+ if (token.raw.length === 1 && lastToken !== undefined) {
2166
+ lastToken.raw += `
2167
+ `;
2168
+ } else {
2169
+ tokens.push(token);
2170
+ }
2171
+ continue;
2172
+ }
2173
+ if (token = this.tokenizer.code(src)) {
2174
+ src = src.substring(token.raw.length);
2175
+ const lastToken = tokens.at(-1);
2176
+ if (lastToken?.type === "paragraph" || lastToken?.type === "text") {
2177
+ lastToken.raw += `
2178
+ ` + token.raw;
2179
+ lastToken.text += `
2180
+ ` + token.text;
2181
+ this.inlineQueue.at(-1).src = lastToken.text;
2182
+ } else {
2183
+ tokens.push(token);
2184
+ }
2185
+ continue;
2186
+ }
2187
+ if (token = this.tokenizer.fences(src)) {
2188
+ src = src.substring(token.raw.length);
2189
+ tokens.push(token);
2190
+ continue;
2191
+ }
2192
+ if (token = this.tokenizer.heading(src)) {
2193
+ src = src.substring(token.raw.length);
2194
+ tokens.push(token);
2195
+ continue;
2196
+ }
2197
+ if (token = this.tokenizer.hr(src)) {
2198
+ src = src.substring(token.raw.length);
2199
+ tokens.push(token);
2200
+ continue;
2201
+ }
2202
+ if (token = this.tokenizer.blockquote(src)) {
2203
+ src = src.substring(token.raw.length);
2204
+ tokens.push(token);
2205
+ continue;
2206
+ }
2207
+ if (token = this.tokenizer.list(src)) {
2208
+ src = src.substring(token.raw.length);
2209
+ tokens.push(token);
2210
+ continue;
2211
+ }
2212
+ if (token = this.tokenizer.html(src)) {
2213
+ src = src.substring(token.raw.length);
2214
+ tokens.push(token);
2215
+ continue;
2216
+ }
2217
+ if (token = this.tokenizer.def(src)) {
2218
+ src = src.substring(token.raw.length);
2219
+ const lastToken = tokens.at(-1);
2220
+ if (lastToken?.type === "paragraph" || lastToken?.type === "text") {
2221
+ lastToken.raw += `
2222
+ ` + token.raw;
2223
+ lastToken.text += `
2224
+ ` + token.raw;
2225
+ this.inlineQueue.at(-1).src = lastToken.text;
2226
+ } else if (!this.tokens.links[token.tag]) {
2227
+ this.tokens.links[token.tag] = {
2228
+ href: token.href,
2229
+ title: token.title
2230
+ };
2231
+ }
2232
+ continue;
2233
+ }
2234
+ if (token = this.tokenizer.table(src)) {
2235
+ src = src.substring(token.raw.length);
2236
+ tokens.push(token);
2237
+ continue;
2238
+ }
2239
+ if (token = this.tokenizer.lheading(src)) {
2240
+ src = src.substring(token.raw.length);
2241
+ tokens.push(token);
2242
+ continue;
2243
+ }
2244
+ let cutSrc = src;
2245
+ if (this.options.extensions?.startBlock) {
2246
+ let startIndex = Infinity;
2247
+ const tempSrc = src.slice(1);
2248
+ let tempStart;
2249
+ this.options.extensions.startBlock.forEach((getStartIndex) => {
2250
+ tempStart = getStartIndex.call({ lexer: this }, tempSrc);
2251
+ if (typeof tempStart === "number" && tempStart >= 0) {
2252
+ startIndex = Math.min(startIndex, tempStart);
2253
+ }
2254
+ });
2255
+ if (startIndex < Infinity && startIndex >= 0) {
2256
+ cutSrc = src.substring(0, startIndex + 1);
2257
+ }
2258
+ }
2259
+ if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
2260
+ const lastToken = tokens.at(-1);
2261
+ if (lastParagraphClipped && lastToken?.type === "paragraph") {
2262
+ lastToken.raw += `
2263
+ ` + token.raw;
2264
+ lastToken.text += `
2265
+ ` + token.text;
2266
+ this.inlineQueue.pop();
2267
+ this.inlineQueue.at(-1).src = lastToken.text;
2268
+ } else {
2269
+ tokens.push(token);
2270
+ }
2271
+ lastParagraphClipped = cutSrc.length !== src.length;
2272
+ src = src.substring(token.raw.length);
2273
+ continue;
2274
+ }
2275
+ if (token = this.tokenizer.text(src)) {
2276
+ src = src.substring(token.raw.length);
2277
+ const lastToken = tokens.at(-1);
2278
+ if (lastToken?.type === "text") {
2279
+ lastToken.raw += `
2280
+ ` + token.raw;
2281
+ lastToken.text += `
2282
+ ` + token.text;
2283
+ this.inlineQueue.pop();
2284
+ this.inlineQueue.at(-1).src = lastToken.text;
2285
+ } else {
2286
+ tokens.push(token);
2287
+ }
2288
+ continue;
2289
+ }
2290
+ if (src) {
2291
+ const errMsg = "Infinite loop on byte: " + src.charCodeAt(0);
2292
+ if (this.options.silent) {
2293
+ console.error(errMsg);
2294
+ break;
2295
+ } else {
2296
+ throw new Error(errMsg);
2297
+ }
2298
+ }
2299
+ }
2300
+ this.state.top = true;
2301
+ return tokens;
2302
+ }
2303
+ inline(src, tokens = []) {
2304
+ this.inlineQueue.push({ src, tokens });
2305
+ return tokens;
2306
+ }
2307
+ inlineTokens(src, tokens = []) {
2308
+ let maskedSrc = src;
2309
+ let match = null;
2310
+ if (this.tokens.links) {
2311
+ const links = Object.keys(this.tokens.links);
2312
+ if (links.length > 0) {
2313
+ while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
2314
+ if (links.includes(match[0].slice(match[0].lastIndexOf("[") + 1, -1))) {
2315
+ maskedSrc = maskedSrc.slice(0, match.index) + "[" + "a".repeat(match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
2316
+ }
2317
+ }
2318
+ }
2319
+ }
2320
+ while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
2321
+ maskedSrc = maskedSrc.slice(0, match.index) + "++" + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
2322
+ }
2323
+ while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
2324
+ maskedSrc = maskedSrc.slice(0, match.index) + "[" + "a".repeat(match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
2325
+ }
2326
+ let keepPrevChar = false;
2327
+ let prevChar = "";
2328
+ while (src) {
2329
+ if (!keepPrevChar) {
2330
+ prevChar = "";
2331
+ }
2332
+ keepPrevChar = false;
2333
+ let token;
2334
+ if (this.options.extensions?.inline?.some((extTokenizer) => {
2335
+ if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
2336
+ src = src.substring(token.raw.length);
2337
+ tokens.push(token);
2338
+ return true;
2339
+ }
2340
+ return false;
2341
+ })) {
2342
+ continue;
2343
+ }
2344
+ if (token = this.tokenizer.escape(src)) {
2345
+ src = src.substring(token.raw.length);
2346
+ tokens.push(token);
2347
+ continue;
2348
+ }
2349
+ if (token = this.tokenizer.tag(src)) {
2350
+ src = src.substring(token.raw.length);
2351
+ tokens.push(token);
2352
+ continue;
2353
+ }
2354
+ if (token = this.tokenizer.link(src)) {
2355
+ src = src.substring(token.raw.length);
2356
+ tokens.push(token);
2357
+ continue;
2358
+ }
2359
+ if (token = this.tokenizer.reflink(src, this.tokens.links)) {
2360
+ src = src.substring(token.raw.length);
2361
+ const lastToken = tokens.at(-1);
2362
+ if (token.type === "text" && lastToken?.type === "text") {
2363
+ lastToken.raw += token.raw;
2364
+ lastToken.text += token.text;
2365
+ } else {
2366
+ tokens.push(token);
2367
+ }
2368
+ continue;
2369
+ }
2370
+ if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
2371
+ src = src.substring(token.raw.length);
2372
+ tokens.push(token);
2373
+ continue;
2374
+ }
2375
+ if (token = this.tokenizer.codespan(src)) {
2376
+ src = src.substring(token.raw.length);
2377
+ tokens.push(token);
2378
+ continue;
2379
+ }
2380
+ if (token = this.tokenizer.br(src)) {
2381
+ src = src.substring(token.raw.length);
2382
+ tokens.push(token);
2383
+ continue;
2384
+ }
2385
+ if (token = this.tokenizer.del(src)) {
2386
+ src = src.substring(token.raw.length);
2387
+ tokens.push(token);
2388
+ continue;
2389
+ }
2390
+ if (token = this.tokenizer.autolink(src)) {
2391
+ src = src.substring(token.raw.length);
2392
+ tokens.push(token);
2393
+ continue;
2394
+ }
2395
+ if (!this.state.inLink && (token = this.tokenizer.url(src))) {
2396
+ src = src.substring(token.raw.length);
2397
+ tokens.push(token);
2398
+ continue;
2399
+ }
2400
+ let cutSrc = src;
2401
+ if (this.options.extensions?.startInline) {
2402
+ let startIndex = Infinity;
2403
+ const tempSrc = src.slice(1);
2404
+ let tempStart;
2405
+ this.options.extensions.startInline.forEach((getStartIndex) => {
2406
+ tempStart = getStartIndex.call({ lexer: this }, tempSrc);
2407
+ if (typeof tempStart === "number" && tempStart >= 0) {
2408
+ startIndex = Math.min(startIndex, tempStart);
2409
+ }
2410
+ });
2411
+ if (startIndex < Infinity && startIndex >= 0) {
2412
+ cutSrc = src.substring(0, startIndex + 1);
2413
+ }
2414
+ }
2415
+ if (token = this.tokenizer.inlineText(cutSrc)) {
2416
+ src = src.substring(token.raw.length);
2417
+ if (token.raw.slice(-1) !== "_") {
2418
+ prevChar = token.raw.slice(-1);
2419
+ }
2420
+ keepPrevChar = true;
2421
+ const lastToken = tokens.at(-1);
2422
+ if (lastToken?.type === "text") {
2423
+ lastToken.raw += token.raw;
2424
+ lastToken.text += token.text;
2425
+ } else {
2426
+ tokens.push(token);
2427
+ }
2428
+ continue;
2429
+ }
2430
+ if (src) {
2431
+ const errMsg = "Infinite loop on byte: " + src.charCodeAt(0);
2432
+ if (this.options.silent) {
2433
+ console.error(errMsg);
2434
+ break;
2435
+ } else {
2436
+ throw new Error(errMsg);
2437
+ }
2438
+ }
2439
+ }
2440
+ return tokens;
2441
+ }
2442
+ }
2443
+
2444
+ class _Renderer {
2445
+ options;
2446
+ parser;
2447
+ constructor(options) {
2448
+ this.options = options || _defaults;
2449
+ }
2450
+ space(token) {
2451
+ return "";
2452
+ }
2453
+ code({ text, lang, escaped }) {
2454
+ const langString = (lang || "").match(other.notSpaceStart)?.[0];
2455
+ const code = text.replace(other.endingNewline, "") + `
2456
+ `;
2457
+ if (!langString) {
2458
+ return "<pre><code>" + (escaped ? code : escape(code, true)) + `</code></pre>
2459
+ `;
2460
+ }
2461
+ return '<pre><code class="language-' + escape(langString) + '">' + (escaped ? code : escape(code, true)) + `</code></pre>
2462
+ `;
2463
+ }
2464
+ blockquote({ tokens }) {
2465
+ const body = this.parser.parse(tokens);
2466
+ return `<blockquote>
2467
+ ${body}</blockquote>
2468
+ `;
2469
+ }
2470
+ html({ text }) {
2471
+ return text;
2472
+ }
2473
+ heading({ tokens, depth }) {
2474
+ return `<h${depth}>${this.parser.parseInline(tokens)}</h${depth}>
2475
+ `;
2476
+ }
2477
+ hr(token) {
2478
+ return `<hr>
2479
+ `;
2480
+ }
2481
+ list(token) {
2482
+ const ordered = token.ordered;
2483
+ const start = token.start;
2484
+ let body = "";
2485
+ for (let j = 0;j < token.items.length; j++) {
2486
+ const item = token.items[j];
2487
+ body += this.listitem(item);
2488
+ }
2489
+ const type = ordered ? "ol" : "ul";
2490
+ const startAttr = ordered && start !== 1 ? ' start="' + start + '"' : "";
2491
+ return "<" + type + startAttr + `>
2492
+ ` + body + "</" + type + `>
2493
+ `;
2494
+ }
2495
+ listitem(item) {
2496
+ let itemBody = "";
2497
+ if (item.task) {
2498
+ const checkbox = this.checkbox({ checked: !!item.checked });
2499
+ if (item.loose) {
2500
+ if (item.tokens[0]?.type === "paragraph") {
2501
+ item.tokens[0].text = checkbox + " " + item.tokens[0].text;
2502
+ if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === "text") {
2503
+ item.tokens[0].tokens[0].text = checkbox + " " + escape(item.tokens[0].tokens[0].text);
2504
+ item.tokens[0].tokens[0].escaped = true;
2505
+ }
2506
+ } else {
2507
+ item.tokens.unshift({
2508
+ type: "text",
2509
+ raw: checkbox + " ",
2510
+ text: checkbox + " ",
2511
+ escaped: true
2512
+ });
2513
+ }
2514
+ } else {
2515
+ itemBody += checkbox + " ";
2516
+ }
2517
+ }
2518
+ itemBody += this.parser.parse(item.tokens, !!item.loose);
2519
+ return `<li>${itemBody}</li>
2520
+ `;
2521
+ }
2522
+ checkbox({ checked }) {
2523
+ return "<input " + (checked ? 'checked="" ' : "") + 'disabled="" type="checkbox">';
2524
+ }
2525
+ paragraph({ tokens }) {
2526
+ return `<p>${this.parser.parseInline(tokens)}</p>
2527
+ `;
2528
+ }
2529
+ table(token) {
2530
+ let header = "";
2531
+ let cell = "";
2532
+ for (let j = 0;j < token.header.length; j++) {
2533
+ cell += this.tablecell(token.header[j]);
2534
+ }
2535
+ header += this.tablerow({ text: cell });
2536
+ let body = "";
2537
+ for (let j = 0;j < token.rows.length; j++) {
2538
+ const row = token.rows[j];
2539
+ cell = "";
2540
+ for (let k = 0;k < row.length; k++) {
2541
+ cell += this.tablecell(row[k]);
2542
+ }
2543
+ body += this.tablerow({ text: cell });
2544
+ }
2545
+ if (body)
2546
+ body = `<tbody>${body}</tbody>`;
2547
+ return `<table>
2548
+ ` + `<thead>
2549
+ ` + header + `</thead>
2550
+ ` + body + `</table>
2551
+ `;
2552
+ }
2553
+ tablerow({ text }) {
2554
+ return `<tr>
2555
+ ${text}</tr>
2556
+ `;
2557
+ }
2558
+ tablecell(token) {
2559
+ const content = this.parser.parseInline(token.tokens);
2560
+ const type = token.header ? "th" : "td";
2561
+ const tag2 = token.align ? `<${type} align="${token.align}">` : `<${type}>`;
2562
+ return tag2 + content + `</${type}>
2563
+ `;
2564
+ }
2565
+ strong({ tokens }) {
2566
+ return `<strong>${this.parser.parseInline(tokens)}</strong>`;
2567
+ }
2568
+ em({ tokens }) {
2569
+ return `<em>${this.parser.parseInline(tokens)}</em>`;
2570
+ }
2571
+ codespan({ text }) {
2572
+ return `<code>${escape(text, true)}</code>`;
2573
+ }
2574
+ br(token) {
2575
+ return "<br>";
2576
+ }
2577
+ del({ tokens }) {
2578
+ return `<del>${this.parser.parseInline(tokens)}</del>`;
2579
+ }
2580
+ link({ href, title, tokens }) {
2581
+ const text = this.parser.parseInline(tokens);
2582
+ const cleanHref = cleanUrl(href);
2583
+ if (cleanHref === null) {
2584
+ return text;
2585
+ }
2586
+ href = cleanHref;
2587
+ let out = '<a href="' + href + '"';
2588
+ if (title) {
2589
+ out += ' title="' + escape(title) + '"';
2590
+ }
2591
+ out += ">" + text + "</a>";
2592
+ return out;
2593
+ }
2594
+ image({ href, title, text, tokens }) {
2595
+ if (tokens) {
2596
+ text = this.parser.parseInline(tokens, this.parser.textRenderer);
2597
+ }
2598
+ const cleanHref = cleanUrl(href);
2599
+ if (cleanHref === null) {
2600
+ return escape(text);
2601
+ }
2602
+ href = cleanHref;
2603
+ let out = `<img src="${href}" alt="${text}"`;
2604
+ if (title) {
2605
+ out += ` title="${escape(title)}"`;
2606
+ }
2607
+ out += ">";
2608
+ return out;
2609
+ }
2610
+ text(token) {
2611
+ return "tokens" in token && token.tokens ? this.parser.parseInline(token.tokens) : ("escaped" in token) && token.escaped ? token.text : escape(token.text);
2612
+ }
2613
+ }
2614
+
2615
+ class _TextRenderer {
2616
+ strong({ text }) {
2617
+ return text;
2618
+ }
2619
+ em({ text }) {
2620
+ return text;
2621
+ }
2622
+ codespan({ text }) {
2623
+ return text;
2624
+ }
2625
+ del({ text }) {
2626
+ return text;
2627
+ }
2628
+ html({ text }) {
2629
+ return text;
2630
+ }
2631
+ text({ text }) {
2632
+ return text;
2633
+ }
2634
+ link({ text }) {
2635
+ return "" + text;
2636
+ }
2637
+ image({ text }) {
2638
+ return "" + text;
2639
+ }
2640
+ br() {
2641
+ return "";
2642
+ }
2643
+ }
2644
+
2645
+ class _Parser {
2646
+ options;
2647
+ renderer;
2648
+ textRenderer;
2649
+ constructor(options) {
2650
+ this.options = options || _defaults;
2651
+ this.options.renderer = this.options.renderer || new _Renderer;
2652
+ this.renderer = this.options.renderer;
2653
+ this.renderer.options = this.options;
2654
+ this.renderer.parser = this;
2655
+ this.textRenderer = new _TextRenderer;
2656
+ }
2657
+ static parse(tokens, options) {
2658
+ const parser = new _Parser(options);
2659
+ return parser.parse(tokens);
2660
+ }
2661
+ static parseInline(tokens, options) {
2662
+ const parser = new _Parser(options);
2663
+ return parser.parseInline(tokens);
2664
+ }
2665
+ parse(tokens, top = true) {
2666
+ let out = "";
2667
+ for (let i = 0;i < tokens.length; i++) {
2668
+ const anyToken = tokens[i];
2669
+ if (this.options.extensions?.renderers?.[anyToken.type]) {
2670
+ const genericToken = anyToken;
2671
+ const ret = this.options.extensions.renderers[genericToken.type].call({ parser: this }, genericToken);
2672
+ if (ret !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "paragraph", "text"].includes(genericToken.type)) {
2673
+ out += ret || "";
2674
+ continue;
2675
+ }
2676
+ }
2677
+ const token = anyToken;
2678
+ switch (token.type) {
2679
+ case "space": {
2680
+ out += this.renderer.space(token);
2681
+ continue;
2682
+ }
2683
+ case "hr": {
2684
+ out += this.renderer.hr(token);
2685
+ continue;
2686
+ }
2687
+ case "heading": {
2688
+ out += this.renderer.heading(token);
2689
+ continue;
2690
+ }
2691
+ case "code": {
2692
+ out += this.renderer.code(token);
2693
+ continue;
2694
+ }
2695
+ case "table": {
2696
+ out += this.renderer.table(token);
2697
+ continue;
2698
+ }
2699
+ case "blockquote": {
2700
+ out += this.renderer.blockquote(token);
2701
+ continue;
2702
+ }
2703
+ case "list": {
2704
+ out += this.renderer.list(token);
2705
+ continue;
2706
+ }
2707
+ case "html": {
2708
+ out += this.renderer.html(token);
2709
+ continue;
2710
+ }
2711
+ case "paragraph": {
2712
+ out += this.renderer.paragraph(token);
2713
+ continue;
2714
+ }
2715
+ case "text": {
2716
+ let textToken = token;
2717
+ let body = this.renderer.text(textToken);
2718
+ while (i + 1 < tokens.length && tokens[i + 1].type === "text") {
2719
+ textToken = tokens[++i];
2720
+ body += `
2721
+ ` + this.renderer.text(textToken);
2722
+ }
2723
+ if (top) {
2724
+ out += this.renderer.paragraph({
2725
+ type: "paragraph",
2726
+ raw: body,
2727
+ text: body,
2728
+ tokens: [{ type: "text", raw: body, text: body, escaped: true }]
2729
+ });
2730
+ } else {
2731
+ out += body;
2732
+ }
2733
+ continue;
2734
+ }
2735
+ default: {
2736
+ const errMsg = 'Token with "' + token.type + '" type was not found.';
2737
+ if (this.options.silent) {
2738
+ console.error(errMsg);
2739
+ return "";
2740
+ } else {
2741
+ throw new Error(errMsg);
2742
+ }
2743
+ }
2744
+ }
2745
+ }
2746
+ return out;
2747
+ }
2748
+ parseInline(tokens, renderer = this.renderer) {
2749
+ let out = "";
2750
+ for (let i = 0;i < tokens.length; i++) {
2751
+ const anyToken = tokens[i];
2752
+ if (this.options.extensions?.renderers?.[anyToken.type]) {
2753
+ const ret = this.options.extensions.renderers[anyToken.type].call({ parser: this }, anyToken);
2754
+ if (ret !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(anyToken.type)) {
2755
+ out += ret || "";
2756
+ continue;
2757
+ }
2758
+ }
2759
+ const token = anyToken;
2760
+ switch (token.type) {
2761
+ case "escape": {
2762
+ out += renderer.text(token);
2763
+ break;
2764
+ }
2765
+ case "html": {
2766
+ out += renderer.html(token);
2767
+ break;
2768
+ }
2769
+ case "link": {
2770
+ out += renderer.link(token);
2771
+ break;
2772
+ }
2773
+ case "image": {
2774
+ out += renderer.image(token);
2775
+ break;
2776
+ }
2777
+ case "strong": {
2778
+ out += renderer.strong(token);
2779
+ break;
2780
+ }
2781
+ case "em": {
2782
+ out += renderer.em(token);
2783
+ break;
2784
+ }
2785
+ case "codespan": {
2786
+ out += renderer.codespan(token);
2787
+ break;
2788
+ }
2789
+ case "br": {
2790
+ out += renderer.br(token);
2791
+ break;
2792
+ }
2793
+ case "del": {
2794
+ out += renderer.del(token);
2795
+ break;
2796
+ }
2797
+ case "text": {
2798
+ out += renderer.text(token);
2799
+ break;
2800
+ }
2801
+ default: {
2802
+ const errMsg = 'Token with "' + token.type + '" type was not found.';
2803
+ if (this.options.silent) {
2804
+ console.error(errMsg);
2805
+ return "";
2806
+ } else {
2807
+ throw new Error(errMsg);
2808
+ }
2809
+ }
2810
+ }
2811
+ }
2812
+ return out;
2813
+ }
2814
+ }
2815
+
2816
+ class _Hooks {
2817
+ options;
2818
+ block;
2819
+ constructor(options) {
2820
+ this.options = options || _defaults;
2821
+ }
2822
+ static passThroughHooks = new Set([
2823
+ "preprocess",
2824
+ "postprocess",
2825
+ "processAllTokens"
2826
+ ]);
2827
+ preprocess(markdown) {
2828
+ return markdown;
2829
+ }
2830
+ postprocess(html2) {
2831
+ return html2;
2832
+ }
2833
+ processAllTokens(tokens) {
2834
+ return tokens;
2835
+ }
2836
+ provideLexer() {
2837
+ return this.block ? _Lexer.lex : _Lexer.lexInline;
2838
+ }
2839
+ provideParser() {
2840
+ return this.block ? _Parser.parse : _Parser.parseInline;
2841
+ }
2842
+ }
2843
+
2844
+ class Marked {
2845
+ defaults = _getDefaults();
2846
+ options = this.setOptions;
2847
+ parse = this.parseMarkdown(true);
2848
+ parseInline = this.parseMarkdown(false);
2849
+ Parser = _Parser;
2850
+ Renderer = _Renderer;
2851
+ TextRenderer = _TextRenderer;
2852
+ Lexer = _Lexer;
2853
+ Tokenizer = _Tokenizer;
2854
+ Hooks = _Hooks;
2855
+ constructor(...args) {
2856
+ this.use(...args);
2857
+ }
2858
+ walkTokens(tokens, callback) {
2859
+ let values = [];
2860
+ for (const token of tokens) {
2861
+ values = values.concat(callback.call(this, token));
2862
+ switch (token.type) {
2863
+ case "table": {
2864
+ const tableToken = token;
2865
+ for (const cell of tableToken.header) {
2866
+ values = values.concat(this.walkTokens(cell.tokens, callback));
2867
+ }
2868
+ for (const row of tableToken.rows) {
2869
+ for (const cell of row) {
2870
+ values = values.concat(this.walkTokens(cell.tokens, callback));
2871
+ }
2872
+ }
2873
+ break;
2874
+ }
2875
+ case "list": {
2876
+ const listToken = token;
2877
+ values = values.concat(this.walkTokens(listToken.items, callback));
2878
+ break;
2879
+ }
2880
+ default: {
2881
+ const genericToken = token;
2882
+ if (this.defaults.extensions?.childTokens?.[genericToken.type]) {
2883
+ this.defaults.extensions.childTokens[genericToken.type].forEach((childTokens) => {
2884
+ const tokens2 = genericToken[childTokens].flat(Infinity);
2885
+ values = values.concat(this.walkTokens(tokens2, callback));
2886
+ });
2887
+ } else if (genericToken.tokens) {
2888
+ values = values.concat(this.walkTokens(genericToken.tokens, callback));
2889
+ }
2890
+ }
2891
+ }
2892
+ }
2893
+ return values;
2894
+ }
2895
+ use(...args) {
2896
+ const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} };
2897
+ args.forEach((pack) => {
2898
+ const opts = { ...pack };
2899
+ opts.async = this.defaults.async || opts.async || false;
2900
+ if (pack.extensions) {
2901
+ pack.extensions.forEach((ext) => {
2902
+ if (!ext.name) {
2903
+ throw new Error("extension name required");
2904
+ }
2905
+ if ("renderer" in ext) {
2906
+ const prevRenderer = extensions.renderers[ext.name];
2907
+ if (prevRenderer) {
2908
+ extensions.renderers[ext.name] = function(...args2) {
2909
+ let ret = ext.renderer.apply(this, args2);
2910
+ if (ret === false) {
2911
+ ret = prevRenderer.apply(this, args2);
2912
+ }
2913
+ return ret;
2914
+ };
2915
+ } else {
2916
+ extensions.renderers[ext.name] = ext.renderer;
2917
+ }
2918
+ }
2919
+ if ("tokenizer" in ext) {
2920
+ if (!ext.level || ext.level !== "block" && ext.level !== "inline") {
2921
+ throw new Error("extension level must be 'block' or 'inline'");
2922
+ }
2923
+ const extLevel = extensions[ext.level];
2924
+ if (extLevel) {
2925
+ extLevel.unshift(ext.tokenizer);
2926
+ } else {
2927
+ extensions[ext.level] = [ext.tokenizer];
2928
+ }
2929
+ if (ext.start) {
2930
+ if (ext.level === "block") {
2931
+ if (extensions.startBlock) {
2932
+ extensions.startBlock.push(ext.start);
2933
+ } else {
2934
+ extensions.startBlock = [ext.start];
2935
+ }
2936
+ } else if (ext.level === "inline") {
2937
+ if (extensions.startInline) {
2938
+ extensions.startInline.push(ext.start);
2939
+ } else {
2940
+ extensions.startInline = [ext.start];
2941
+ }
2942
+ }
2943
+ }
2944
+ }
2945
+ if ("childTokens" in ext && ext.childTokens) {
2946
+ extensions.childTokens[ext.name] = ext.childTokens;
2947
+ }
2948
+ });
2949
+ opts.extensions = extensions;
2950
+ }
2951
+ if (pack.renderer) {
2952
+ const renderer = this.defaults.renderer || new _Renderer(this.defaults);
2953
+ for (const prop in pack.renderer) {
2954
+ if (!(prop in renderer)) {
2955
+ throw new Error(`renderer '${prop}' does not exist`);
2956
+ }
2957
+ if (["options", "parser"].includes(prop)) {
2958
+ continue;
2959
+ }
2960
+ const rendererProp = prop;
2961
+ const rendererFunc = pack.renderer[rendererProp];
2962
+ const prevRenderer = renderer[rendererProp];
2963
+ renderer[rendererProp] = (...args2) => {
2964
+ let ret = rendererFunc.apply(renderer, args2);
2965
+ if (ret === false) {
2966
+ ret = prevRenderer.apply(renderer, args2);
2967
+ }
2968
+ return ret || "";
2969
+ };
2970
+ }
2971
+ opts.renderer = renderer;
2972
+ }
2973
+ if (pack.tokenizer) {
2974
+ const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);
2975
+ for (const prop in pack.tokenizer) {
2976
+ if (!(prop in tokenizer)) {
2977
+ throw new Error(`tokenizer '${prop}' does not exist`);
2978
+ }
2979
+ if (["options", "rules", "lexer"].includes(prop)) {
2980
+ continue;
2981
+ }
2982
+ const tokenizerProp = prop;
2983
+ const tokenizerFunc = pack.tokenizer[tokenizerProp];
2984
+ const prevTokenizer = tokenizer[tokenizerProp];
2985
+ tokenizer[tokenizerProp] = (...args2) => {
2986
+ let ret = tokenizerFunc.apply(tokenizer, args2);
2987
+ if (ret === false) {
2988
+ ret = prevTokenizer.apply(tokenizer, args2);
2989
+ }
2990
+ return ret;
2991
+ };
2992
+ }
2993
+ opts.tokenizer = tokenizer;
2994
+ }
2995
+ if (pack.hooks) {
2996
+ const hooks = this.defaults.hooks || new _Hooks;
2997
+ for (const prop in pack.hooks) {
2998
+ if (!(prop in hooks)) {
2999
+ throw new Error(`hook '${prop}' does not exist`);
3000
+ }
3001
+ if (["options", "block"].includes(prop)) {
3002
+ continue;
3003
+ }
3004
+ const hooksProp = prop;
3005
+ const hooksFunc = pack.hooks[hooksProp];
3006
+ const prevHook = hooks[hooksProp];
3007
+ if (_Hooks.passThroughHooks.has(prop)) {
3008
+ hooks[hooksProp] = (arg) => {
3009
+ if (this.defaults.async) {
3010
+ return Promise.resolve(hooksFunc.call(hooks, arg)).then((ret2) => {
3011
+ return prevHook.call(hooks, ret2);
3012
+ });
3013
+ }
3014
+ const ret = hooksFunc.call(hooks, arg);
3015
+ return prevHook.call(hooks, ret);
3016
+ };
3017
+ } else {
3018
+ hooks[hooksProp] = (...args2) => {
3019
+ let ret = hooksFunc.apply(hooks, args2);
3020
+ if (ret === false) {
3021
+ ret = prevHook.apply(hooks, args2);
3022
+ }
3023
+ return ret;
3024
+ };
3025
+ }
3026
+ }
3027
+ opts.hooks = hooks;
3028
+ }
3029
+ if (pack.walkTokens) {
3030
+ const walkTokens = this.defaults.walkTokens;
3031
+ const packWalktokens = pack.walkTokens;
3032
+ opts.walkTokens = function(token) {
3033
+ let values = [];
3034
+ values.push(packWalktokens.call(this, token));
3035
+ if (walkTokens) {
3036
+ values = values.concat(walkTokens.call(this, token));
3037
+ }
3038
+ return values;
3039
+ };
3040
+ }
3041
+ this.defaults = { ...this.defaults, ...opts };
3042
+ });
3043
+ return this;
3044
+ }
3045
+ setOptions(opt) {
3046
+ this.defaults = { ...this.defaults, ...opt };
3047
+ return this;
3048
+ }
3049
+ lexer(src, options) {
3050
+ return _Lexer.lex(src, options ?? this.defaults);
3051
+ }
3052
+ parser(tokens, options) {
3053
+ return _Parser.parse(tokens, options ?? this.defaults);
3054
+ }
3055
+ parseMarkdown(blockType) {
3056
+ const parse = (src, options) => {
3057
+ const origOpt = { ...options };
3058
+ const opt = { ...this.defaults, ...origOpt };
3059
+ const throwError = this.onError(!!opt.silent, !!opt.async);
3060
+ if (this.defaults.async === true && origOpt.async === false) {
3061
+ return throwError(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
3062
+ }
3063
+ if (typeof src === "undefined" || src === null) {
3064
+ return throwError(new Error("marked(): input parameter is undefined or null"));
3065
+ }
3066
+ if (typeof src !== "string") {
3067
+ return throwError(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected"));
3068
+ }
3069
+ if (opt.hooks) {
3070
+ opt.hooks.options = opt;
3071
+ opt.hooks.block = blockType;
3072
+ }
3073
+ const lexer = opt.hooks ? opt.hooks.provideLexer() : blockType ? _Lexer.lex : _Lexer.lexInline;
3074
+ const parser = opt.hooks ? opt.hooks.provideParser() : blockType ? _Parser.parse : _Parser.parseInline;
3075
+ if (opt.async) {
3076
+ return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src).then((src2) => lexer(src2, opt)).then((tokens) => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens).then((tokens) => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens).then((tokens) => parser(tokens, opt)).then((html2) => opt.hooks ? opt.hooks.postprocess(html2) : html2).catch(throwError);
3077
+ }
3078
+ try {
3079
+ if (opt.hooks) {
3080
+ src = opt.hooks.preprocess(src);
3081
+ }
3082
+ let tokens = lexer(src, opt);
3083
+ if (opt.hooks) {
3084
+ tokens = opt.hooks.processAllTokens(tokens);
3085
+ }
3086
+ if (opt.walkTokens) {
3087
+ this.walkTokens(tokens, opt.walkTokens);
3088
+ }
3089
+ let html2 = parser(tokens, opt);
3090
+ if (opt.hooks) {
3091
+ html2 = opt.hooks.postprocess(html2);
3092
+ }
3093
+ return html2;
3094
+ } catch (e) {
3095
+ return throwError(e);
3096
+ }
3097
+ };
3098
+ return parse;
3099
+ }
3100
+ onError(silent, async) {
3101
+ return (e) => {
3102
+ e.message += `
3103
+ Please report this to https://github.com/markedjs/marked.`;
3104
+ if (silent) {
3105
+ const msg = "<p>An error occurred:</p><pre>" + escape(e.message + "", true) + "</pre>";
3106
+ if (async) {
3107
+ return Promise.resolve(msg);
3108
+ }
3109
+ return msg;
3110
+ }
3111
+ if (async) {
3112
+ return Promise.reject(e);
3113
+ }
3114
+ throw e;
3115
+ };
3116
+ }
3117
+ }
3118
+ var markedInstance = new Marked;
3119
+ function marked(src, opt) {
3120
+ return markedInstance.parse(src, opt);
3121
+ }
3122
+ marked.options = marked.setOptions = function(options) {
3123
+ markedInstance.setOptions(options);
3124
+ marked.defaults = markedInstance.defaults;
3125
+ changeDefaults(marked.defaults);
3126
+ return marked;
3127
+ };
3128
+ marked.getDefaults = _getDefaults;
3129
+ marked.defaults = _defaults;
3130
+ marked.use = function(...args) {
3131
+ markedInstance.use(...args);
3132
+ marked.defaults = markedInstance.defaults;
3133
+ changeDefaults(marked.defaults);
3134
+ return marked;
3135
+ };
3136
+ marked.walkTokens = function(tokens, callback) {
3137
+ return markedInstance.walkTokens(tokens, callback);
3138
+ };
3139
+ marked.parseInline = markedInstance.parseInline;
3140
+ marked.Parser = _Parser;
3141
+ marked.parser = _Parser.parse;
3142
+ marked.Renderer = _Renderer;
3143
+ marked.TextRenderer = _TextRenderer;
3144
+ marked.Lexer = _Lexer;
3145
+ marked.lexer = _Lexer.lex;
3146
+ marked.Tokenizer = _Tokenizer;
3147
+ marked.Hooks = _Hooks;
3148
+ marked.parse = marked;
3149
+ var options = marked.options;
3150
+ var setOptions = marked.setOptions;
3151
+ var use = marked.use;
3152
+ var walkTokens = marked.walkTokens;
3153
+ var parseInline = marked.parseInline;
3154
+ var parser = _Parser.parse;
3155
+ var lexer = _Lexer.lex;
3156
+
3157
+ // src/markdown.ts
3158
+ async function processMarkdownDirectives(template, context, filePath = "") {
3159
+ let output = template;
3160
+ const regex = /@markdown(?:\(([^)]*)\))?([\s\S]*?)@endmarkdown/g;
3161
+ const matches = [];
3162
+ let match;
3163
+ while ((match = regex.exec(template)) !== null) {
3164
+ matches.push({
3165
+ fullMatch: match[0],
3166
+ options: match[1] || "",
3167
+ content: match[2] || "",
3168
+ index: match.index
3169
+ });
3170
+ }
3171
+ for (const { fullMatch, options: options2, content, index } of matches) {
3172
+ try {
3173
+ const optionsObj = {};
3174
+ if (options2) {
3175
+ options2.split(",").forEach((opt) => {
3176
+ const trimmed = opt.trim();
3177
+ if (trimmed)
3178
+ optionsObj[trimmed] = true;
3179
+ });
3180
+ }
3181
+ const markedOptions = {
3182
+ gfm: optionsObj.gfm ?? true,
3183
+ breaks: optionsObj.breaks ?? false,
3184
+ silent: true
3185
+ };
3186
+ const html2 = await marked.parse(content.trim(), markedOptions);
3187
+ output = output.replace(fullMatch, html2);
3188
+ } catch (error) {
3189
+ const errorMessage = error instanceof Error ? error.message : String(error);
3190
+ const errorHtml = createDetailedErrorMessage("Markdown Directive", `Error processing markdown: ${errorMessage}`, filePath, template, index, fullMatch);
3191
+ output = output.replace(fullMatch, errorHtml);
3192
+ }
3193
+ }
3194
+ return output;
3195
+ }
3196
+ async function markdownDirectiveHandler(content, params, _context, _filePath) {
3197
+ const options2 = {
3198
+ gfm: true,
3199
+ breaks: false,
3200
+ silent: true
3201
+ };
3202
+ params.forEach((param) => {
3203
+ const trimmed = param.trim().replace(/['"]/g, "");
3204
+ if (trimmed === "breaks")
3205
+ options2.breaks = true;
3206
+ if (trimmed === "no-gfm")
3207
+ options2.gfm = false;
3208
+ });
3209
+ return await marked.parse(content.trim(), options2);
3210
+ }
3211
+
3212
+ // src/middleware.ts
3213
+ async function processMiddleware(template, context, filePath, options2, timing) {
3214
+ if (!options2.middleware || options2.middleware.length === 0) {
3215
+ return template;
3216
+ }
3217
+ let output = template;
3218
+ const middlewareToRun = options2.middleware.filter((m) => m.timing === timing);
3219
+ if (middlewareToRun.length === 0) {
3220
+ return output;
3221
+ }
3222
+ for (const middleware of middlewareToRun) {
3223
+ if (!middleware.name || typeof middleware.handler !== "function") {
3224
+ if (options2.debug) {
3225
+ console.warn("Invalid middleware:", middleware);
3226
+ }
3227
+ continue;
3228
+ }
3229
+ try {
3230
+ const result = await middleware.handler(output, context, filePath, options2);
3231
+ if (typeof result === "string") {
3232
+ output = result;
3233
+ } else if (options2.debug) {
3234
+ console.warn(`Middleware ${middleware.name} did not return a string`);
3235
+ }
3236
+ } catch (error) {
3237
+ if (options2.debug) {
3238
+ console.error(`Error in middleware ${middleware.name}:`, error);
3239
+ }
3240
+ if (options2.debug) {
3241
+ const errorMessage = createDetailedErrorMessage("Middleware", `Error in middleware '${middleware.name}': ${error instanceof Error ? error.message : String(error)}`, filePath, template);
3242
+ output = output.replace(/<body[^>]*>/, `$&
3243
+ <div style="color:red;background:#ffeeee;padding:10px;border:1px solid #ff0000;margin:10px 0;font-family:monospace;white-space:pre-wrap;">${errorMessage}</div>
3244
+ `);
3245
+ }
3246
+ }
3247
+ }
3248
+ return output;
3249
+ }
3250
+ async function runPreProcessingMiddleware(template, context, filePath, options2) {
3251
+ return processMiddleware(template, context, filePath, options2, "before");
3252
+ }
3253
+ async function runPostProcessingMiddleware(template, context, filePath, options2) {
3254
+ return processMiddleware(template, context, filePath, options2, "after");
3255
+ }
3256
+
3257
+ // src/process.ts
3258
+ async function processDirectives(template, context, filePath, options2, dependencies) {
3259
+ let output = template;
3260
+ output = output.replace(/\{\{--[\s\S]*?--\}\}/g, "");
3261
+ output = output.replace(/@@/g, "@");
3262
+ output = output.replace(/@\{\{([\s\S]*?)\}\}/g, (_, content) => {
3263
+ return `{{ ${content} }}`;
3264
+ });
3265
+ const stacks = {};
3266
+ output = processStackPushDirectives(output, stacks);
3267
+ const sections = {};
3268
+ let layoutPath = "";
3269
+ const layoutMatch = output.match(/@extends\(\s*['"]([^'"]+)['"]\s*\)/);
3270
+ if (layoutMatch) {
3271
+ layoutPath = layoutMatch[1];
3272
+ output = output.replace(/@extends\(\s*['"]([^'"]+)['"]\s*\)/, "");
3273
+ }
3274
+ output = output.replace(/@section\(\s*['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]+)['"]\s*)?\)([\s\S]*?)(?:@endsection|@show)/g, (match, name, value, content) => {
3275
+ if (value) {
3276
+ sections[name] = value;
3277
+ return "";
3278
+ }
3279
+ if (content.includes("@parent")) {
3280
+ sections[name] = content.replace("@parent", "<!--PARENT_CONTENT_PLACEHOLDER-->");
3281
+ } else {
3282
+ sections[name] = content.trim();
3283
+ }
3284
+ return "";
3285
+ });
3286
+ context.__sections = sections;
3287
+ output = output.replace(/@yield\(\s*['"]([^'"]+)['"](?:,\s*['"]([^'"]+)['"])?\)/g, (_, name, defaultContent) => {
3288
+ return sections[name] || defaultContent || "";
3289
+ });
3290
+ output = processStackReplacements(output, stacks);
3291
+ if (layoutPath) {
3292
+ try {
3293
+ if (options2.debug) {
3294
+ console.log(`Processing layout: ${layoutPath} for file ${filePath}`);
3295
+ }
3296
+ const layoutFullPath = await resolveTemplatePath(layoutPath, filePath, options2, dependencies);
3297
+ if (!layoutFullPath) {
3298
+ console.warn(`Layout not found: ${layoutPath} (referenced from ${filePath})`);
3299
+ return output;
3300
+ }
3301
+ const layoutContent = await Bun.file(layoutFullPath).text();
3302
+ const nestedLayoutMatch = layoutContent.match(/@extends\(\s*['"]([^'"]+)['"]\s*\)/);
3303
+ if (nestedLayoutMatch) {
3304
+ if (options2.debug) {
3305
+ console.log(`Found nested layout: ${nestedLayoutMatch[1]} in ${layoutFullPath}`);
3306
+ }
3307
+ const layoutSections2 = {};
3308
+ const processedLayout2 = layoutContent.replace(/@section\(\s*['"]([^'"]+)['"]\s*\)([\s\S]*?)(?:@show|@endsection)/g, (_, name, content) => {
3309
+ layoutSections2[name] = content.trim();
3310
+ return "";
3311
+ });
3312
+ for (const [name, content] of Object.entries(layoutSections2)) {
3313
+ if (sections[name] && sections[name].includes("<!--PARENT_CONTENT_PLACEHOLDER-->")) {
3314
+ sections[name] = sections[name].replace("<!--PARENT_CONTENT_PLACEHOLDER-->", content);
3315
+ } else if (!sections[name]) {
3316
+ sections[name] = content;
3317
+ }
3318
+ }
3319
+ const nestedContext = { ...context, __sections: sections };
3320
+ const nestedTemplate = `@extends('${nestedLayoutMatch[1]}')${processedLayout2}`;
3321
+ return await processDirectives(nestedTemplate, nestedContext, layoutFullPath, options2, dependencies);
3322
+ }
3323
+ let processedLayout = processStackPushDirectives(layoutContent, stacks);
3324
+ const layoutSections = {};
3325
+ processedLayout = processedLayout.replace(/@section\(\s*['"]([^'"]+)['"]\s*\)([\s\S]*?)(?:@show|@endsection)/g, (_, name, content) => {
3326
+ layoutSections[name] = content.trim();
3327
+ return `@yield('${name}')`;
3328
+ });
3329
+ processedLayout = processedLayout.replace(/@yield\(\s*['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]+)['"]\s*)?\)/g, (_, sectionName, defaultContent) => {
3330
+ if (sections[sectionName]) {
3331
+ let sectionContent = sections[sectionName];
3332
+ if (sectionContent.includes("<!--PARENT_CONTENT_PLACEHOLDER-->")) {
3333
+ sectionContent = sectionContent.replace("<!--PARENT_CONTENT_PLACEHOLDER-->", layoutSections[sectionName] || "");
3334
+ }
3335
+ return sectionContent;
3336
+ }
3337
+ return defaultContent || "";
3338
+ });
3339
+ processedLayout = processStackReplacements(processedLayout, stacks);
3340
+ output = await processOtherDirectives(processedLayout, context, layoutFullPath, options2, dependencies);
3341
+ return output;
3342
+ } catch (error) {
3343
+ console.error(`Error processing layout ${layoutPath}:`, error);
3344
+ return `[Error processing layout: ${error instanceof Error ? error.message : String(error)}]`;
3345
+ }
3346
+ }
3347
+ return await processOtherDirectives(output, context, filePath, options2, dependencies);
3348
+ }
3349
+ async function processOtherDirectives(template, context, filePath, options2, dependencies) {
3350
+ let output = template;
3351
+ output = await runPreProcessingMiddleware(output, context, filePath, options2);
3352
+ output = await processCustomDirectives(output, context, filePath, options2);
3353
+ output = processAuthDirectives(output, context);
3354
+ output = await processTranslateDirective(output, context, filePath, options2);
3355
+ output = await processMarkdownDirectives(output, context, filePath);
3356
+ output = processJsonDirective(output, context);
3357
+ output = processOnceDirective(output);
3358
+ output = processEnvDirective(output, context);
3359
+ output = processIssetEmptyDirectives(output, context);
3360
+ const componentsDir = path3.resolve(path3.dirname(filePath), options2.componentsDir || "components");
3361
+ output = await processComponentDirectives(output, context, filePath, componentsDir, options2, dependencies);
3362
+ output = await processCustomElements(output, context, filePath, componentsDir, options2, dependencies);
3363
+ output = await processIncludes(output, context, filePath, options2, dependencies);
3364
+ output = processConditionals(output, context, filePath);
3365
+ output = processLoops(output, context, filePath);
3366
+ output = processFormDirectives(output, context);
3367
+ output = processErrorDirective(output, context);
3368
+ output = processExpressions(output, context, filePath);
3369
+ output = await runPostProcessingMiddleware(output, context, filePath, options2);
3370
+ return output;
3371
+ }
3372
+ async function processComponentDirectives(template, context, filePath, componentsDir, options2, dependencies) {
3373
+ let output = template;
3374
+ const processedComponents = new Set;
3375
+ const componentRegex = /@component\s*\(['"]([^'"]+)['"](?:,\s*(\{[^}]*\}))?\)/g;
3376
+ let match;
3377
+ while (match = componentRegex.exec(output)) {
3378
+ const [fullMatch, componentPath, propsString] = match;
3379
+ let props = {};
3380
+ if (propsString) {
3381
+ try {
3382
+ const propsFn = new Function(...Object.keys(context), `return ${propsString}`);
3383
+ props = propsFn(...Object.values(context));
3384
+ } catch (error) {
3385
+ output = output.replace(fullMatch, `[Error parsing component props: ${error.message}]`);
3386
+ continue;
3387
+ }
3388
+ }
3389
+ const processedContent = await renderComponent(componentPath, props, "", componentsDir, context, filePath, options2, processedComponents, dependencies);
3390
+ output = output.replace(fullMatch, processedContent);
3391
+ componentRegex.lastIndex = 0;
3392
+ }
3393
+ return output;
3394
+ }
3395
+ async function processCustomElements(template, context, filePath, componentsDir, options2, dependencies) {
3396
+ let output = template;
3397
+ const processedComponents = new Set;
3398
+ const kebabSelfClosingRegex = /<([a-z][a-z0-9]*-[a-z0-9-]*)([^>]*?)\s*\/>/g;
3399
+ output = await processTagComponents(kebabSelfClosingRegex, output, false, true);
3400
+ const kebabWithContentRegex = /<([a-z][a-z0-9]*-[a-z0-9-]*)([^>]*)>([\s\S]*?)<\/\1>/g;
3401
+ output = await processTagComponents(kebabWithContentRegex, output, false, false);
3402
+ const pascalCaseMultilineRegex = /<([A-Z][a-zA-Z0-9]*)\s*\n([\s\S]*?)\/>/g;
3403
+ output = await processMultilineTagComponents(pascalCaseMultilineRegex, output, true, true);
3404
+ const pascalCaseSelfClosingRegex = /<([A-Z][a-zA-Z0-9]*)([^>]*?)\s*\/>/g;
3405
+ output = await processTagComponents(pascalCaseSelfClosingRegex, output, true, true);
3406
+ const pascalCaseAllCapsRegex = /<([A-Z][A-Z0-9]+)([^>]*)>([\s\S]*?)<\/\1>/g;
3407
+ output = await processTagComponents(pascalCaseAllCapsRegex, output, true, false);
3408
+ const pascalCaseRegex = /<([A-Z][a-zA-Z0-9]*)([^>]*)>([\s\S]*?)<\/\1>/g;
3409
+ output = await processTagComponents(pascalCaseRegex, output, true, false);
3410
+ return output;
3411
+ async function processMultilineTagComponents(regex, html2, isPascalCase, _isSelfClosing) {
3412
+ let result = html2;
3413
+ let match;
3414
+ while (match = regex.exec(result)) {
3415
+ const fullMatch = match[0];
3416
+ const tagName = match[1];
3417
+ const attributesBlock = match[2] || "";
3418
+ const matchIndex = match.index;
3419
+ let componentPath;
3420
+ if (isPascalCase) {
3421
+ componentPath = tagName.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
3422
+ } else {
3423
+ componentPath = tagName;
3424
+ }
3425
+ const props = {};
3426
+ const attrLines = attributesBlock.split(`
3427
+ `);
3428
+ for (const line of attrLines) {
3429
+ const trimmedLine = line.trim();
3430
+ if (!trimmedLine)
3431
+ continue;
3432
+ const attrMatch = trimmedLine.match(/([^\s=]+)=["'](.+?)["']/);
3433
+ if (attrMatch) {
3434
+ const [, attrName, attrValue] = attrMatch;
3435
+ props[attrName] = attrValue;
3436
+ }
3437
+ }
3438
+ const processedContent = await renderComponent(componentPath, props, "", componentsDir, context, filePath, options2, processedComponents, dependencies);
3439
+ result = result.substring(0, matchIndex) + processedContent + result.substring(matchIndex + fullMatch.length);
3440
+ regex.lastIndex = 0;
3441
+ }
3442
+ return result;
3443
+ }
3444
+ async function processTagComponents(regex, html2, isPascalCase, isSelfClosing) {
3445
+ let result = html2;
3446
+ let match;
3447
+ while (match = regex.exec(result)) {
3448
+ const fullMatch = match[0];
3449
+ const tagName = match[1];
3450
+ const attributesStr = match[2] || "";
3451
+ const content = isSelfClosing ? "" : match[3] || "";
3452
+ const matchIndex = match.index;
3453
+ let componentPath;
3454
+ if (isPascalCase) {
3455
+ componentPath = tagName.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
3456
+ } else {
3457
+ componentPath = tagName;
3458
+ }
3459
+ const props = {};
3460
+ if (attributesStr) {
3461
+ const attrRegex = /(:|v-bind:)?([^\s=]+)(?:=["']([^"']*)["'])?/g;
3462
+ let attrMatch;
3463
+ while (attrMatch = attrRegex.exec(attributesStr)) {
3464
+ const [, bindPrefix, attrName, attrValue] = attrMatch;
3465
+ if (attrName === "class" || attrName.startsWith("on") || attrName === "style" || attrName === "id") {
3466
+ props[attrName] = attrValue !== undefined ? attrValue : true;
3467
+ continue;
3468
+ }
3469
+ if (bindPrefix) {
3470
+ try {
3471
+ const valueFn = new Function(...Object.keys(context), `return ${attrValue}`);
3472
+ props[attrName] = valueFn(...Object.values(context));
3473
+ } catch (error) {
3474
+ console.error(`Error evaluating binding for ${attrName}:`, error);
3475
+ props[attrName] = `[Error evaluating: ${attrValue}]`;
3476
+ }
3477
+ } else {
3478
+ props[attrName] = attrValue !== undefined ? attrValue : true;
3479
+ }
3480
+ }
3481
+ }
3482
+ const isSelfClosingTag = fullMatch.trimEnd().endsWith("/>") || isPascalCase && !fullMatch.includes("</");
3483
+ const processedContent = await renderComponent(componentPath, props, isSelfClosingTag ? "" : content.trim(), componentsDir, context, filePath, options2, processedComponents, dependencies);
3484
+ result = result.substring(0, matchIndex) + processedContent + result.substring(matchIndex + fullMatch.length);
3485
+ regex.lastIndex = 0;
3486
+ }
3487
+ return result;
3488
+ }
3489
+ }
3490
+ function processJsonDirective(template, context) {
3491
+ return template.replace(/@json\(\s*([^,)]+)(?:,\s*(true|false))?\)/g, (match, dataPath, pretty) => {
3492
+ try {
3493
+ const evalFn = new Function(...Object.keys(context), `
3494
+ try { return ${dataPath.trim()}; } catch (e) { return undefined; }
3495
+ `);
3496
+ const data = evalFn(...Object.values(context));
3497
+ if (pretty === "true") {
3498
+ return JSON.stringify(data, null, 2);
3499
+ }
3500
+ return JSON.stringify(data);
3501
+ } catch (error) {
3502
+ console.error(`Error processing @json directive: ${error}`);
3503
+ return match;
3504
+ }
3505
+ });
3506
+ }
3507
+ function processOnceDirective(template) {
3508
+ const onceBlocks = new Map;
3509
+ const onceMatches = [];
3510
+ const regex = /@once\s*([\s\S]*?)@endonce/g;
3511
+ let match = regex.exec(template);
3512
+ while (match !== null) {
3513
+ const fullMatch = match[0];
3514
+ const content = match[1];
3515
+ const start = match.index;
3516
+ const end = start + fullMatch.length;
3517
+ onceMatches.push({
3518
+ match: fullMatch,
3519
+ content: content.trim(),
3520
+ start,
3521
+ end
3522
+ });
3523
+ match = regex.exec(template);
3524
+ }
3525
+ const blocksToRemove = new Set;
3526
+ for (let i = 0;i < onceMatches.length; i++) {
3527
+ const { content } = onceMatches[i];
3528
+ if (onceBlocks.has(content)) {
3529
+ blocksToRemove.add(i);
3530
+ } else {
3531
+ onceBlocks.set(content, { content, index: i });
3532
+ }
3533
+ }
3534
+ let result = template;
3535
+ const sortedMatchesToRemove = Array.from(blocksToRemove).map((index) => onceMatches[index]).sort((a, b) => b.start - a.start);
3536
+ for (const { start, end } of sortedMatchesToRemove) {
3537
+ result = result.substring(0, start) + result.substring(end);
3538
+ }
3539
+ result = result.replace(/@once\s*([\s\S]*?)@endonce/g, "$1");
3540
+ return result;
3541
+ }
3542
+
3543
+ // src/utils.ts
3544
+ var componentsCache = new Map;
3545
+ async function renderComponent(componentPath, props, slotContent, componentsDir, parentContext, parentFilePath, options2, processedComponents = new Set, dependencies) {
3546
+ const components = processedComponents ?? new Set;
3547
+ if (components.has(componentPath)) {
3548
+ return `[Circular component reference: ${componentPath}]`;
3549
+ }
3550
+ components.add(componentPath);
3551
+ try {
3552
+ let componentFilePath = componentPath;
3553
+ if (!componentPath.endsWith(".stx")) {
3554
+ componentFilePath = `${componentPath}.stx`;
3555
+ }
3556
+ if (!componentFilePath.startsWith("./") && !componentFilePath.startsWith("../")) {
3557
+ let resolvedPath = path4.join(componentsDir, componentFilePath);
3558
+ if (!await fileExists(resolvedPath)) {
3559
+ const defaultComponentsDir = path4.join(path4.dirname(parentFilePath), "components");
3560
+ resolvedPath = path4.join(defaultComponentsDir, componentFilePath);
3561
+ if (!await fileExists(resolvedPath)) {
3562
+ if (options2.componentsDir && await fileExists(path4.join(options2.componentsDir, componentFilePath))) {
3563
+ resolvedPath = path4.join(options2.componentsDir, componentFilePath);
3564
+ }
3565
+ }
3566
+ }
3567
+ componentFilePath = resolvedPath;
3568
+ } else {
3569
+ componentFilePath = path4.resolve(path4.dirname(parentFilePath), componentFilePath);
3570
+ }
3571
+ if (!await fileExists(componentFilePath)) {
3572
+ return `[Error loading component: ENOENT: no such file or directory, open '${componentPath}']`;
3573
+ }
3574
+ dependencies.add(componentFilePath);
3575
+ let componentContent;
3576
+ if (componentsCache.has(componentFilePath)) {
3577
+ componentContent = componentsCache.get(componentFilePath);
3578
+ } else {
3579
+ try {
3580
+ componentContent = await Bun.file(componentFilePath).text();
3581
+ componentsCache.set(componentFilePath, componentContent);
3582
+ } catch (error) {
3583
+ return `[Error loading component: ${error.message}]`;
3584
+ }
3585
+ }
3586
+ const componentContext = {
3587
+ ...parentContext,
3588
+ ...props,
3589
+ slot: slotContent
3590
+ };
3591
+ const scriptMatch = componentContent.match(/<script\b[^>]*>([\s\S]*?)<\/script>/i);
3592
+ const scriptContent = scriptMatch ? scriptMatch[1] : "";
3593
+ if (scriptContent) {
3594
+ await extractVariables(scriptContent, componentContext, componentFilePath);
3595
+ }
3596
+ let templateContent = componentContent;
3597
+ if (scriptMatch) {
3598
+ templateContent = templateContent.replace(/<script\b[^>]*>[\s\S]*?<\/script>/i, "");
3599
+ }
3600
+ if (slotContent && templateContent.includes("{{ text || slot }}")) {
3601
+ templateContent = templateContent.replace(/\{\{\s*text\s*\|\|\s*slot\s*\}\}/g, slotContent);
3602
+ }
3603
+ for (const [key, value] of Object.entries(componentContext)) {
3604
+ if (typeof value === "string") {
3605
+ if (value.includes("<") && value.includes(">") || value.includes("&lt;") || value.includes("&quot;")) {
3606
+ const unescaped = unescapeHtml(value);
3607
+ componentContext[key] = unescaped;
3608
+ }
3609
+ }
3610
+ }
3611
+ const componentOptions = {
3612
+ ...options2,
3613
+ componentsDir: path4.dirname(componentFilePath)
3614
+ };
3615
+ const result = await processDirectives(templateContent, componentContext, componentFilePath, componentOptions, dependencies);
3616
+ return result;
3617
+ } catch (error) {
3618
+ return `[Error processing component: ${error.message}]`;
3619
+ } finally {
3620
+ components.delete(componentPath);
3621
+ }
3622
+ }
3623
+ async function fileExists(filePath) {
3624
+ try {
3625
+ const stat = await fs3.promises.stat(filePath);
3626
+ return stat.isFile();
3627
+ } catch {
3628
+ return false;
3629
+ }
3630
+ }
3631
+ async function extractVariables(scriptContent, context, filePath) {
3632
+ try {
3633
+ const scriptFn = new Function("module", "exports", scriptContent);
3634
+ const module = { exports: {} };
3635
+ scriptFn(module, module.exports);
3636
+ const processValues = (obj) => {
3637
+ if (typeof obj !== "object" || obj === null)
3638
+ return obj;
3639
+ const seen = new WeakSet;
3640
+ const innerProcess = (val) => {
3641
+ if (typeof val !== "object" || val === null)
3642
+ return val;
3643
+ if (seen.has(val)) {
3644
+ return "[Circular Reference]";
3645
+ }
3646
+ seen.add(val);
3647
+ if (Array.isArray(val)) {
3648
+ return val.map((item) => innerProcess(item));
3649
+ }
3650
+ const result = {};
3651
+ for (const [key, value] of Object.entries(val)) {
3652
+ result[key] = innerProcess(value);
3653
+ }
3654
+ return result;
3655
+ };
3656
+ return innerProcess(obj);
3657
+ };
3658
+ Object.assign(context, processValues(module.exports));
3659
+ } catch (error) {
3660
+ console.warn(`Failed to execute script as CommonJS module in ${filePath}:`, error);
3661
+ try {
3662
+ const exportPattern = /export\s(const|let|var|function|default)\s([a-zA-Z_$][\w$]*)?(?:\s*=\s*([^;]+))?/g;
3663
+ let match;
3664
+ match = exportPattern.exec(scriptContent);
3665
+ while (match !== null) {
3666
+ const [, type, name, value] = match;
3667
+ if (type === "default") {
3668
+ if (value) {
3669
+ try {
3670
+ const defaultValueFn = new Function(`return ${value}`);
3671
+ const defaultValue = defaultValueFn();
3672
+ if (typeof defaultValue === "object" && defaultValue !== null) {
3673
+ Object.assign(context, defaultValue);
3674
+ }
3675
+ } catch (e) {
3676
+ console.warn(`Failed to process default export in ${filePath}:`, e);
3677
+ }
3678
+ }
3679
+ } else if (name) {
3680
+ try {
3681
+ const extractFn = new Function(`
3682
+ ${type} ${name} = ${value || "undefined"};
3683
+ return ${name};
3684
+ `);
3685
+ context[name] = extractFn();
3686
+ } catch (e) {
3687
+ console.warn(`Failed to process export of ${name} in ${filePath}:`, e);
3688
+ }
3689
+ }
3690
+ match = exportPattern.exec(scriptContent);
3691
+ }
3692
+ } catch (e) {
3693
+ console.warn(`Failed to process ES module exports in ${filePath}:`, e);
3694
+ }
3695
+ }
3696
+ try {
3697
+ const directFn = new Function(`
3698
+ // Execute script content directly but protect against module not defined
3699
+ try {
3700
+ ${scriptContent}
3701
+ } catch (e) {
3702
+ // Ignore module not defined errors
3703
+ if (!e.toString().includes('module is not defined')) {
3704
+ throw e;
3705
+ }
3706
+ }
3707
+
3708
+ // Return all defined variables, scanning window/global scope
3709
+ return Object.fromEntries(
3710
+ Object.getOwnPropertyNames(this)
3711
+ .filter(key =>
3712
+ // Exclude built-in properties and functions
3713
+ !['global', 'globalThis', 'self', 'window', 'console', 'setTimeout', 'setInterval',
3714
+ 'Function', 'Object', 'Array', 'String', 'Number', 'Boolean', 'Error'].includes(key) &&
3715
+ // Only include own properties that aren't functions or built-in properties
3716
+ typeof this[key] !== 'function' &&
3717
+ !key.startsWith('_')
3718
+ )
3719
+ .map(key => [key, this[key]])
3720
+ );
3721
+ `);
3722
+ const vars = directFn();
3723
+ Object.entries(vars).forEach(([key, value]) => {
3724
+ if (value !== undefined && !context[key]) {
3725
+ context[key] = value;
3726
+ }
3727
+ });
3728
+ } catch (error) {
3729
+ if (!error.toString().includes("module is not defined") && !error.toString().includes("Unexpected EOF")) {
3730
+ console.warn(`Variable extraction issue in ${filePath}:`, error);
3731
+ }
3732
+ }
3733
+ }
3734
+ async function resolveTemplatePath(templatePath, currentFilePath, options2, dependencies) {
3735
+ if (options2.debug) {
3736
+ console.log(`Resolving template path: ${templatePath} from ${currentFilePath}`);
3737
+ }
3738
+ const dirPath = path4.dirname(currentFilePath);
3739
+ if (templatePath.startsWith("/")) {
3740
+ const absolutePath = path4.join(process.cwd(), templatePath);
3741
+ if (options2.debug) {
3742
+ console.log(`Checking absolute path: ${absolutePath}`);
3743
+ }
3744
+ if (await fileExists(absolutePath) && dependencies) {
3745
+ dependencies.add(absolutePath);
3746
+ }
3747
+ return absolutePath;
3748
+ }
3749
+ const directPath = path4.join(dirPath, templatePath);
3750
+ if (await fileExists(directPath)) {
3751
+ if (options2.debug) {
3752
+ console.log(`Found direct path: ${directPath}`);
3753
+ }
3754
+ if (dependencies) {
3755
+ dependencies.add(directPath);
3756
+ }
3757
+ return directPath;
3758
+ }
3759
+ if (!templatePath.endsWith(".stx")) {
3760
+ const pathWithExt = `${directPath}.stx`;
3761
+ if (await fileExists(pathWithExt)) {
3762
+ if (options2.debug) {
3763
+ console.log(`Found direct path with extension: ${pathWithExt}`);
3764
+ }
3765
+ if (dependencies) {
3766
+ dependencies.add(pathWithExt);
3767
+ }
3768
+ return pathWithExt;
3769
+ }
3770
+ }
3771
+ let layoutsDir = path4.join(dirPath, "layouts");
3772
+ if (await fileExists(layoutsDir)) {
3773
+ const fromCurrentLayouts = path4.join(layoutsDir, templatePath);
3774
+ if (await fileExists(fromCurrentLayouts)) {
3775
+ if (options2.debug) {
3776
+ console.log(`Found in current layouts dir: ${fromCurrentLayouts}`);
3777
+ }
3778
+ if (dependencies) {
3779
+ dependencies.add(fromCurrentLayouts);
3780
+ }
3781
+ return fromCurrentLayouts;
3782
+ }
3783
+ if (!templatePath.endsWith(".stx")) {
3784
+ const fromCurrentLayoutsWithExt = `${fromCurrentLayouts}.stx`;
3785
+ if (await fileExists(fromCurrentLayoutsWithExt)) {
3786
+ if (options2.debug) {
3787
+ console.log(`Found in current layouts dir with extension: ${fromCurrentLayoutsWithExt}`);
3788
+ }
3789
+ if (dependencies) {
3790
+ dependencies.add(fromCurrentLayoutsWithExt);
3791
+ }
3792
+ return fromCurrentLayoutsWithExt;
3793
+ }
3794
+ }
3795
+ }
3796
+ if (templatePath.startsWith("layouts/") || templatePath.includes("/layouts/")) {
3797
+ const parts = templatePath.split("layouts/");
3798
+ const layoutsPath = path4.join(options2.partialsDir || dirPath, "layouts", parts[1]);
3799
+ if (await fileExists(layoutsPath)) {
3800
+ if (options2.debug) {
3801
+ console.log(`Found in layouts path: ${layoutsPath}`);
3802
+ }
3803
+ if (dependencies) {
3804
+ dependencies.add(layoutsPath);
3805
+ }
3806
+ return layoutsPath;
3807
+ }
3808
+ if (!layoutsPath.endsWith(".stx")) {
3809
+ const layoutsPathWithExt = `${layoutsPath}.stx`;
3810
+ if (await fileExists(layoutsPathWithExt)) {
3811
+ if (options2.debug) {
3812
+ console.log(`Found in layouts path with extension: ${layoutsPathWithExt}`);
3813
+ }
3814
+ if (dependencies) {
3815
+ dependencies.add(layoutsPathWithExt);
3816
+ }
3817
+ return layoutsPathWithExt;
3818
+ }
3819
+ }
3820
+ }
3821
+ if (options2.partialsDir) {
3822
+ layoutsDir = path4.join(options2.partialsDir, "layouts");
3823
+ if (await fileExists(layoutsDir)) {
3824
+ const fromPartialsLayouts = path4.join(layoutsDir, templatePath);
3825
+ if (await fileExists(fromPartialsLayouts)) {
3826
+ if (options2.debug) {
3827
+ console.log(`Found in partials layouts dir: ${fromPartialsLayouts}`);
3828
+ }
3829
+ if (dependencies) {
3830
+ dependencies.add(fromPartialsLayouts);
3831
+ }
3832
+ return fromPartialsLayouts;
3833
+ }
3834
+ if (!templatePath.endsWith(".stx")) {
3835
+ const fromPartialsLayoutsWithExt = `${fromPartialsLayouts}.stx`;
3836
+ if (await fileExists(fromPartialsLayoutsWithExt)) {
3837
+ if (options2.debug) {
3838
+ console.log(`Found in partials layouts dir with extension: ${fromPartialsLayoutsWithExt}`);
3839
+ }
3840
+ if (dependencies) {
3841
+ dependencies.add(fromPartialsLayoutsWithExt);
3842
+ }
3843
+ return fromPartialsLayoutsWithExt;
3844
+ }
3845
+ }
3846
+ }
3847
+ }
3848
+ const viewsPath = options2.partialsDir || path4.join(process.cwd(), "views");
3849
+ const fromRoot = path4.join(viewsPath, templatePath);
3850
+ if (await fileExists(fromRoot)) {
3851
+ if (options2.debug) {
3852
+ console.log(`Found in views path: ${fromRoot}`);
3853
+ }
3854
+ if (dependencies) {
3855
+ dependencies.add(fromRoot);
3856
+ }
3857
+ return fromRoot;
3858
+ }
3859
+ if (!templatePath.endsWith(".stx")) {
3860
+ const fromRootWithExt = `${fromRoot}.stx`;
3861
+ if (await fileExists(fromRootWithExt)) {
3862
+ if (options2.debug) {
3863
+ console.log(`Found in views path with extension: ${fromRootWithExt}`);
3864
+ }
3865
+ if (dependencies) {
3866
+ dependencies.add(fromRootWithExt);
3867
+ }
3868
+ return fromRootWithExt;
3869
+ }
3870
+ }
3871
+ if (dirPath.includes("temp")) {
3872
+ const tempDirLayouts = path4.join(path4.dirname(dirPath), "layouts", templatePath);
3873
+ if (await fileExists(tempDirLayouts)) {
3874
+ if (options2.debug) {
3875
+ console.log(`Found in temp layouts dir: ${tempDirLayouts}`);
3876
+ }
3877
+ if (dependencies) {
3878
+ dependencies.add(tempDirLayouts);
3879
+ }
3880
+ return tempDirLayouts;
3881
+ }
3882
+ if (!templatePath.endsWith(".stx")) {
3883
+ const tempDirLayoutsWithExt = `${tempDirLayouts}.stx`;
3884
+ if (await fileExists(tempDirLayoutsWithExt)) {
3885
+ if (options2.debug) {
3886
+ console.log(`Found in temp layouts dir with extension: ${tempDirLayoutsWithExt}`);
3887
+ }
3888
+ if (dependencies) {
3889
+ dependencies.add(tempDirLayoutsWithExt);
3890
+ }
3891
+ return tempDirLayoutsWithExt;
3892
+ }
3893
+ }
3894
+ }
3895
+ if (options2.debug) {
3896
+ console.warn(`Template not found after trying all paths: ${templatePath} (referenced from ${currentFilePath})`);
3897
+ } else {
3898
+ console.warn(`Template not found: ${templatePath} (referenced from ${currentFilePath})`);
3899
+ }
3900
+ return null;
3901
+ }
3902
+ function getSourceLineInfo(template, errorPosition, errorPattern) {
3903
+ let lineNumber = 0;
3904
+ let lineContent = "";
3905
+ let context = "";
3906
+ try {
3907
+ if (typeof errorPosition === "number" && errorPosition >= 0) {
3908
+ const lines = template.split(`
3909
+ `);
3910
+ let currentPos = 0;
3911
+ for (let i = 0;i < lines.length; i++) {
3912
+ currentPos += lines[i].length + 1;
3913
+ if (currentPos >= errorPosition) {
3914
+ lineNumber = i + 1;
3915
+ lineContent = lines[i].trim();
3916
+ const start = Math.max(0, i - 2);
3917
+ const end = Math.min(lines.length, i + 3);
3918
+ context = lines.slice(start, end).map((line, idx) => {
3919
+ const contextLineNum = start + idx + 1;
3920
+ const marker = contextLineNum === lineNumber ? "> " : " ";
3921
+ return `${marker}${contextLineNum}: ${line}`;
3922
+ }).join(`
3923
+ `);
3924
+ break;
3925
+ }
3926
+ }
3927
+ } else if (errorPattern) {
3928
+ const patternPos = template.indexOf(errorPattern);
3929
+ if (patternPos >= 0) {
3930
+ return getSourceLineInfo(template, patternPos);
3931
+ }
3932
+ }
3933
+ } catch (_err) {}
3934
+ return { lineNumber, lineContent, context };
3935
+ }
3936
+ function createDetailedErrorMessage(errorType, errorMessage, filePath, template, errorPosition, errorPattern) {
3937
+ const { lineNumber, context } = getSourceLineInfo(template, errorPosition, errorPattern);
3938
+ let detailedMessage = `[${errorType} Error`;
3939
+ if (lineNumber > 0) {
3940
+ detailedMessage += ` at line ${lineNumber}`;
3941
+ }
3942
+ detailedMessage += ` in ${filePath.split("/").pop()}]`;
3943
+ detailedMessage += `: ${errorMessage}`;
3944
+ if (context) {
3945
+ detailedMessage += `
3946
+
3947
+ Context:
3948
+ ${context}`;
3949
+ }
3950
+ return detailedMessage;
3951
+ }
3952
+
3953
+ // src/conditionals.ts
3954
+ function processConditionals(template, context, filePath) {
3955
+ let output = template;
3956
+ output = output.replace(/@unless\s*\(([^)]+)\)([\s\S]*?)@endunless/g, (_, condition, content) => {
3957
+ return `@if (!(${condition}))${content}@endif`;
3958
+ });
3959
+ output = processIssetEmptyDirectives(output, context, filePath);
3960
+ output = processEnvDirective(output, context, filePath);
3961
+ output = processAuthDirectives(output, context);
3962
+ const processIfStatements = () => {
3963
+ let hasMatches = false;
3964
+ output = output.replace(/@if\s*\(([^)]+)\)([\s\S]*?)@endif/g, (match, condition, content, offset) => {
3965
+ hasMatches = true;
3966
+ try {
3967
+ const conditionFn = new Function(...Object.keys(context), `return ${condition}`);
3968
+ const result = conditionFn(...Object.values(context));
3969
+ if (result) {
3970
+ const elseParts = content.split(/@else(?:if\s*\([^)]+\))?/);
3971
+ return elseParts[0];
3972
+ } else {
3973
+ const elseifMatches = content.match(/@elseif\s*\(([^)]+)\)([\s\S]*?)(?:@elseif|@else|$)/);
3974
+ if (elseifMatches) {
3975
+ try {
3976
+ const elseifFn = new Function(...Object.keys(context), `return ${elseifMatches[1]}`);
3977
+ if (elseifFn(...Object.values(context))) {
3978
+ return elseifMatches[2];
3979
+ }
3980
+ } catch (error) {
3981
+ return createDetailedErrorMessage("Directive", `Error in @elseif(${elseifMatches[1]}): ${error instanceof Error ? error.message : String(error)}`, filePath, template, offset + match.indexOf("@elseif"), `@elseif(${elseifMatches[1]})`);
3982
+ }
3983
+ }
3984
+ const elseMatch = content.match(/@else([\s\S]*?)(?:@elseif|$)/);
3985
+ if (elseMatch) {
3986
+ return elseMatch[1];
3987
+ }
3988
+ return "";
3989
+ }
3990
+ } catch (error) {
3991
+ return createDetailedErrorMessage("Directive", `Error in @if(${condition}): ${error instanceof Error ? error.message : String(error)}`, filePath, template, offset, `@if(${condition})`);
3992
+ }
3993
+ });
3994
+ return hasMatches;
3995
+ };
3996
+ while (processIfStatements()) {}
3997
+ return output;
3998
+ }
3999
+ function processAuthDirectives(template, context) {
4000
+ let output = template;
4001
+ output = output.replace(/@auth\s*(?:\((.*?)\)\s*)?\n([\s\S]*?)(?:@else\s*\n([\s\S]*?))?@endauth/g, (_, guard, content, elseContent) => {
4002
+ const isAuthenticated = guard ? evaluateAuthExpression(`auth?.check && auth?.user?.[${guard}]`, context) : evaluateAuthExpression("auth?.check", context);
4003
+ return isAuthenticated ? content : elseContent || "";
4004
+ });
4005
+ output = output.replace(/@guest\s*(?:\((.*?)\)\s*)?\n([\s\S]*?)(?:@else\s*\n([\s\S]*?))?@endguest/g, (_, guard, content, elseContent) => {
4006
+ const isGuest = guard ? evaluateAuthExpression(`!auth?.check || !auth?.user?.[${guard}]`, context) : evaluateAuthExpression("!auth?.check", context);
4007
+ return isGuest ? content : elseContent || "";
4008
+ });
4009
+ output = output.replace(/@can\('([^']*)'(?:,\s*'([^']*)')?(?:,\s*([^)]*))?\)\s*\n([\s\S]*?)(?:@elsecan\('([^']*)'(?:,\s*'([^']*)')?(?:,\s*([^)]*))?\)\s*\n([\s\S]*?))?(?:@else\s*\n([\s\S]*?))?@endcan/g, (_, ability, type, id, content, elseAbility, elseType, elseId, elseContent, finalElseContent) => {
4010
+ let can = false;
4011
+ if (context.userCan && typeof context.userCan[ability] === "boolean") {
4012
+ can = context.userCan[ability];
4013
+ } else if (context.permissions?.check && typeof context.permissions.check === "function") {
4014
+ try {
4015
+ const args = [ability];
4016
+ if (type)
4017
+ args.push(type);
4018
+ if (id) {
4019
+ const idValue = evaluateAuthExpression(id, context);
4020
+ args.push(idValue);
4021
+ }
4022
+ can = context.permissions.check(...args);
4023
+ } catch {
4024
+ can = false;
4025
+ }
4026
+ }
4027
+ if (can) {
4028
+ return content;
4029
+ } else if (elseAbility) {
4030
+ let elseCan = false;
4031
+ if (context.userCan && typeof context.userCan[elseAbility] === "boolean") {
4032
+ elseCan = context.userCan[elseAbility];
4033
+ } else if (context.permissions?.check && typeof context.permissions.check === "function") {
4034
+ try {
4035
+ const args = [elseAbility];
4036
+ if (elseType)
4037
+ args.push(elseType);
4038
+ if (elseId) {
4039
+ const elseIdValue = evaluateAuthExpression(elseId, context);
4040
+ args.push(elseIdValue);
4041
+ }
4042
+ elseCan = context.permissions.check(...args);
4043
+ } catch {
4044
+ elseCan = false;
4045
+ }
4046
+ }
4047
+ return elseCan ? elseContent : finalElseContent || "";
4048
+ } else {
4049
+ return finalElseContent || "";
4050
+ }
4051
+ });
4052
+ output = output.replace(/@cannot\('([^']*)'(?:,\s*'([^']*)')?(?:,\s*([^)]*))?\)\s*\n([\s\S]*?)(?:@elsecannot\('([^']*)'(?:,\s*'([^']*)')?(?:,\s*([^)]*))?\)\s*\n([\s\S]*?))?(?:@else\s*\n([\s\S]*?))?@endcannot/g, (_, ability, type, id, content, elseAbility, elseType, elseId, elseContent, finalElseContent) => {
4053
+ let cannot = true;
4054
+ if (context.userCan && typeof context.userCan[ability] === "boolean") {
4055
+ cannot = !context.userCan[ability];
4056
+ } else if (context.permissions?.check && typeof context.permissions.check === "function") {
4057
+ try {
4058
+ const args = [ability];
4059
+ if (type)
4060
+ args.push(type);
4061
+ if (id) {
4062
+ const idValue = evaluateAuthExpression(id, context);
4063
+ args.push(idValue);
4064
+ }
4065
+ cannot = !context.permissions.check(...args);
4066
+ } catch {
4067
+ cannot = true;
4068
+ }
4069
+ }
4070
+ if (cannot) {
4071
+ return content;
4072
+ } else if (elseAbility) {
4073
+ let elseCannot = true;
4074
+ if (context.userCan && typeof context.userCan[elseAbility] === "boolean") {
4075
+ elseCannot = !context.userCan[elseAbility];
4076
+ } else if (context.permissions?.check && typeof context.permissions.check === "function") {
4077
+ try {
4078
+ const args = [elseAbility];
4079
+ if (elseType)
4080
+ args.push(elseType);
4081
+ if (elseId) {
4082
+ const elseIdValue = evaluateAuthExpression(elseId, context);
4083
+ args.push(elseIdValue);
4084
+ }
4085
+ elseCannot = !context.permissions.check(...args);
4086
+ } catch {
4087
+ elseCannot = true;
4088
+ }
4089
+ }
4090
+ return elseCannot ? elseContent : finalElseContent || "";
4091
+ } else {
4092
+ return finalElseContent || "";
4093
+ }
4094
+ });
4095
+ return output;
4096
+ }
4097
+ function processIssetEmptyDirectives(template, context, filePath) {
4098
+ let result = template;
4099
+ result = result.replace(/@isset\(([^)]+)\)((?:.|\n)*?)(?:@else((?:.|\n)*?))?@endisset/g, (match, variable, content, elseContent, offset) => {
4100
+ try {
4101
+ const value = evaluateAuthExpression(variable.trim(), context);
4102
+ if (value !== undefined && value !== null) {
4103
+ return content;
4104
+ }
4105
+ return elseContent || "";
4106
+ } catch (error) {
4107
+ if (filePath) {
4108
+ return createDetailedErrorMessage("Directive", `Error processing @isset directive: ${error.message}`, filePath, template, offset, match);
4109
+ } else {
4110
+ console.error(`Error processing @isset directive:`, error);
4111
+ return match;
4112
+ }
4113
+ }
4114
+ });
4115
+ result = result.replace(/@empty\(([^)]+)\)((?:.|\n)*?)(?:@else((?:.|\n)*?))?@endempty/g, (match, variable, content, elseContent, offset) => {
4116
+ try {
4117
+ const value = evaluateAuthExpression(variable.trim(), context);
4118
+ const isEmpty = value === undefined || value === null || value === "" || Array.isArray(value) && value.length === 0 || typeof value === "object" && value !== null && Object.keys(value).length === 0;
4119
+ if (isEmpty) {
4120
+ return content;
4121
+ }
4122
+ return elseContent || "";
4123
+ } catch (error) {
4124
+ if (filePath) {
4125
+ return createDetailedErrorMessage("Directive", `Error processing @empty directive: ${error.message}`, filePath, template, offset, match);
4126
+ } else {
4127
+ console.error(`Error processing @empty directive:`, error);
4128
+ return match;
4129
+ }
4130
+ }
4131
+ });
4132
+ return result;
4133
+ }
4134
+ function processEnvDirective(template, context, filePath) {
4135
+ const result = template;
4136
+ const envPattern = /@env\((['"]?)(.*?)\1\)((?:.|\n)*?)(?:@elseenv\((['"]?)(.*?)\4\)((?:.|\n)*?))?(?:@else((?:.|\n)*?))?@endenv/g;
4137
+ return result.replace(envPattern, (match, quote1, envValue, content, quote2, elseEnvValue, elseEnvContent, elseContent, offset) => {
4138
+ try {
4139
+ const currentEnv = context.NODE_ENV || "development";
4140
+ let envArray = [];
4141
+ if (envValue.startsWith("[") && envValue.endsWith("]")) {
4142
+ const arrayContent = envValue.slice(1, -1).trim();
4143
+ envArray = arrayContent.split(",").map((e) => e.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean);
4144
+ } else {
4145
+ envArray = [envValue];
4146
+ }
4147
+ if (envArray.includes(currentEnv)) {
4148
+ return content;
4149
+ }
4150
+ if (elseEnvValue && elseEnvContent) {
4151
+ let elseEnvArray = [];
4152
+ if (elseEnvValue.startsWith("[") && elseEnvValue.endsWith("]")) {
4153
+ const arrayContent = elseEnvValue.slice(1, -1).trim();
4154
+ elseEnvArray = arrayContent.split(",").map((e) => e.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean);
4155
+ } else {
4156
+ elseEnvArray = [elseEnvValue];
4157
+ }
4158
+ if (elseEnvArray.includes(currentEnv)) {
4159
+ return elseEnvContent;
4160
+ }
4161
+ }
4162
+ return elseContent || "";
4163
+ } catch (error) {
4164
+ if (filePath) {
4165
+ return createDetailedErrorMessage("Directive", `Error processing @env directive: ${error.message}`, filePath, template, offset, match);
4166
+ } else {
4167
+ console.error(`Error processing @env directive:`, error);
4168
+ return match;
4169
+ }
4170
+ }
4171
+ });
4172
+ }
4173
+
4174
+ // src/loops.ts
4175
+ function processLoops(template, context, filePath) {
4176
+ let output = template;
4177
+ output = output.replace(/@forelse\s*\(([^)]+)as([^)]+)\)([\s\S]*?)@empty([\s\S]*?)@endforelse/g, (match, arrayExpr, itemVar, content, emptyContent, offset) => {
4178
+ try {
4179
+ const arrayFn = new Function(...Object.keys(context), `return ${arrayExpr.trim()}`);
4180
+ const array = arrayFn(...Object.values(context));
4181
+ if (!Array.isArray(array) || array.length === 0) {
4182
+ return emptyContent;
4183
+ }
4184
+ return `@foreach (${arrayExpr.trim()} as ${itemVar.trim()})${content}@endforeach`;
4185
+ } catch (error) {
4186
+ return createDetailedErrorMessage("Directive", `Error in @forelse(${arrayExpr.trim()} as ${itemVar.trim()}): ${error instanceof Error ? error.message : String(error)}`, filePath, template, offset, match);
4187
+ }
4188
+ });
4189
+ const processForeachLoops = () => {
4190
+ let hasMatches = false;
4191
+ output = output.replace(/@foreach\s*\(([^)]+)as([^)]+)\)([\s\S]*?)@endforeach/g, (match, arrayExpr, itemVar, content, offset) => {
4192
+ hasMatches = true;
4193
+ try {
4194
+ const arrayFn = new Function(...Object.keys(context), `return ${arrayExpr.trim()}`);
4195
+ const array = arrayFn(...Object.values(context));
4196
+ if (!Array.isArray(array)) {
4197
+ return createDetailedErrorMessage("Directive", `Error in @foreach: ${arrayExpr.trim()} is not an array`, filePath, template, offset, match);
4198
+ }
4199
+ let result = "";
4200
+ for (let index = 0;index < array.length; index++) {
4201
+ const item = array[index];
4202
+ const itemName = itemVar.trim();
4203
+ const itemContext = {
4204
+ ...context,
4205
+ [itemName]: item,
4206
+ loop: {
4207
+ index,
4208
+ iteration: index + 1,
4209
+ first: index === 0,
4210
+ last: index === array.length - 1,
4211
+ count: array.length
4212
+ }
4213
+ };
4214
+ let processedContent = content;
4215
+ processedContent = processConditionals(processedContent, itemContext, filePath);
4216
+ processedContent = processExpressions(processedContent, itemContext, filePath);
4217
+ result += processedContent;
4218
+ }
4219
+ return result;
4220
+ } catch (error) {
4221
+ return createDetailedErrorMessage("Directive", `Error in @foreach(${arrayExpr.trim()} as ${itemVar.trim()}): ${error instanceof Error ? error.message : String(error)}`, filePath, template, offset, match);
4222
+ }
4223
+ });
4224
+ return hasMatches;
4225
+ };
4226
+ let iterations = 0;
4227
+ const MAX_ITERATIONS = 10;
4228
+ while (processForeachLoops() && iterations < MAX_ITERATIONS) {
4229
+ iterations++;
4230
+ }
4231
+ output = output.replace(/@for\s*\(([^)]+)\)([\s\S]*?)@endfor/g, (match, forExpr, content, offset) => {
4232
+ try {
4233
+ const loopKeys = Object.keys(context);
4234
+ const loopValues = Object.values(context);
4235
+ const loopFn = new Function(...loopKeys, `
4236
+ let result = '';
4237
+ for (${forExpr}) {
4238
+ result += \`${content.replace(/`/g, "\\`").replace(/\{\{([^}]+)\}\}/g, (match2, expr) => {
4239
+ return `\${${expr}}`;
4240
+ })}\`;
4241
+ }
4242
+ return result;
4243
+ `);
4244
+ return loopFn(...loopValues);
4245
+ } catch (error) {
4246
+ return createDetailedErrorMessage("Directive", `Error in @for(${forExpr}): ${error instanceof Error ? error.message : String(error)}`, filePath, template, offset, match);
4247
+ }
4248
+ });
4249
+ output = output.replace(/@while\s*\(([^)]+)\)([\s\S]*?)@endwhile/g, (match, condition, content, offset) => {
4250
+ try {
4251
+ const loopKeys = Object.keys(context);
4252
+ const loopValues = Object.values(context);
4253
+ const whileFn = new Function(...loopKeys, `
4254
+ let result = '';
4255
+ let maxIterations = 1000; // Safety limit
4256
+ let counter = 0;
4257
+ while (${condition} && counter < maxIterations) {
4258
+ counter++;
4259
+ result += \`${content.replace(/`/g, "\\`").replace(/\{\{([^}]+)\}\}/g, (match2, expr) => {
4260
+ return `\${${expr}}`;
4261
+ })}\`;
4262
+ }
4263
+ if (counter >= maxIterations) {
4264
+ result += '[Error: Maximum iterations exceeded in while loop]';
4265
+ }
4266
+ return result;
4267
+ `);
4268
+ return whileFn(...loopValues);
4269
+ } catch (error) {
4270
+ return createDetailedErrorMessage("Directive", `Error in @while(${condition}): ${error instanceof Error ? error.message : String(error)}`, filePath, template, offset, match);
4271
+ }
4272
+ });
4273
+ return output;
4274
+ }
4275
+ export {
4276
+ processLoops
4277
+ };
4278
+
4279
+ export { evaluateAuthExpression, setGlobalContext, defaultFilters, escapeHtml, processExpressions, applyFilters, evaluateExpression, unescapeHtml, processCustomDirectives, processForms, processBasicFormDirectives, processFormInputDirectives, processErrorDirective, processFormDirectives, loadTranslation, getTranslation, processTranslateDirective, createTranslateFilter, processLoops, partialsCache, processIncludes, processStackPushDirectives, processStackReplacements, processMarkdownDirectives, markdownDirectiveHandler, processMiddleware, runPreProcessingMiddleware, runPostProcessingMiddleware, processDirectives, processJsonDirective, processOnceDirective, renderComponent, fileExists, extractVariables, resolveTemplatePath, getSourceLineInfo, createDetailedErrorMessage };