@ztimson/utils 0.28.3 → 0.28.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +139 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +139 -53
- package/dist/index.mjs.map +1 -1
- package/dist/path-events.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1884,6 +1884,8 @@ class PathEvent {
|
|
|
1884
1884
|
module;
|
|
1885
1885
|
/** Entire path, including the module & name */
|
|
1886
1886
|
fullPath;
|
|
1887
|
+
/** Parent directory, excludes module & name */
|
|
1888
|
+
dir;
|
|
1887
1889
|
/** Path including the name, excluding the module */
|
|
1888
1890
|
path;
|
|
1889
1891
|
/** Last segment of path */
|
|
@@ -1961,6 +1963,7 @@ class PathEvent {
|
|
|
1961
1963
|
if (p === "" || p === void 0 || p === "*") {
|
|
1962
1964
|
this.module = "";
|
|
1963
1965
|
this.path = "";
|
|
1966
|
+
this.dir = "";
|
|
1964
1967
|
this.fullPath = "**";
|
|
1965
1968
|
this.name = "";
|
|
1966
1969
|
this.methods = new ASet(p === "*" ? ["*"] : method.split(""));
|
|
@@ -1971,6 +1974,7 @@ class PathEvent {
|
|
|
1971
1974
|
let temp = p.split("/").filter((p2) => !!p2);
|
|
1972
1975
|
this.module = temp.splice(0, 1)[0] || "";
|
|
1973
1976
|
this.path = temp.join("/");
|
|
1977
|
+
this.dir = temp.length > 2 ? temp.slice(0, -1).join("/") : "";
|
|
1974
1978
|
this.fullPath = `${this.module}${this.module && this.path ? "/" : ""}${this.path}`;
|
|
1975
1979
|
this.name = temp.pop() || "";
|
|
1976
1980
|
this.hasGlob = this.fullPath.includes("*");
|
|
@@ -2352,8 +2356,11 @@ function findTemplateVars(html) {
|
|
|
2352
2356
|
return result;
|
|
2353
2357
|
}
|
|
2354
2358
|
async function renderTemplate(template, data, fetch2) {
|
|
2355
|
-
|
|
2356
|
-
|
|
2359
|
+
if (!fetch2) fetch2 = (file) => {
|
|
2360
|
+
throw new TemplateError(`Unable to fetch template: ${file}`);
|
|
2361
|
+
};
|
|
2362
|
+
const now = /* @__PURE__ */ new Date();
|
|
2363
|
+
const d = {
|
|
2357
2364
|
date: {
|
|
2358
2365
|
day: now.getDate(),
|
|
2359
2366
|
month: now.toLocaleString("default", { month: "long" }),
|
|
@@ -2363,65 +2370,144 @@ async function renderTemplate(template, data, fetch2) {
|
|
|
2363
2370
|
},
|
|
2364
2371
|
...data || {}
|
|
2365
2372
|
};
|
|
2366
|
-
if (!fetch2) fetch2 = (file) => {
|
|
2367
|
-
throw new TemplateError(`Unable to fetch template: ${file}`);
|
|
2368
|
-
};
|
|
2369
2373
|
const evaluate = (code, data2, fatal = true) => {
|
|
2370
2374
|
try {
|
|
2371
2375
|
return Function("data", `with(data) { return ${code}; }`)(data2);
|
|
2372
|
-
} catch {
|
|
2373
|
-
if (fatal) throw new TemplateError(`Failed to evaluate: ${code}
|
|
2374
|
-
|
|
2376
|
+
} catch (err) {
|
|
2377
|
+
if (fatal) throw new TemplateError(`Failed to evaluate: ${code}
|
|
2378
|
+
${err.message || err.toString()}`);
|
|
2379
|
+
return false;
|
|
2375
2380
|
}
|
|
2376
2381
|
};
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2382
|
+
async function process(content, ctx = d) {
|
|
2383
|
+
let result = content;
|
|
2384
|
+
const extendsMatch = result.match(/\{\{\s*>\s*(.+?):(.+?)\s*}}([\s\S]*?)\{\{\s*\/>\s*}}/);
|
|
2385
|
+
if (extendsMatch) {
|
|
2386
|
+
const parentTemplate = await fetch2(extendsMatch[1].trim());
|
|
2387
|
+
if (!parentTemplate) throw new TemplateError(`Unknown extended template: ${extendsMatch[1].trim()}`);
|
|
2388
|
+
const slotName = extendsMatch[2].trim();
|
|
2389
|
+
const slotContent = await process(extendsMatch[3], ctx);
|
|
2390
|
+
return process(parentTemplate, { ...ctx, [slotName]: slotContent });
|
|
2391
|
+
}
|
|
2392
|
+
let changed = true;
|
|
2393
|
+
while (changed) {
|
|
2394
|
+
changed = false;
|
|
2395
|
+
const before = result;
|
|
2396
|
+
const importMatch = result.match(/\{\{\s*<\s*(.+?)\s*}}/);
|
|
2397
|
+
if (importMatch) {
|
|
2398
|
+
const t = await fetch2(importMatch[1].trim());
|
|
2399
|
+
if (!t) throw new TemplateError(`Unknown imported template: ${importMatch[1].trim()}`);
|
|
2400
|
+
const rendered = await process(t, ctx);
|
|
2401
|
+
result = result.replace(importMatch[0], rendered);
|
|
2402
|
+
changed = true;
|
|
2403
|
+
continue;
|
|
2404
|
+
}
|
|
2405
|
+
const forMatch = findInnermostFor(result);
|
|
2406
|
+
if (forMatch) {
|
|
2407
|
+
const { full, vars, array, body, start } = forMatch;
|
|
2408
|
+
const [element, index = "index"] = vars.split(",").map((v) => v.trim());
|
|
2409
|
+
const arr = dotNotation(ctx, array);
|
|
2410
|
+
if (!arr || typeof arr != "object") throw new TemplateError(`Cannot iterate: ${array}`);
|
|
2411
|
+
let output = [];
|
|
2412
|
+
for (let i = 0; i < arr.length; i++)
|
|
2413
|
+
output.push(await process(body, { ...ctx, [element]: arr[i], [index]: i }));
|
|
2414
|
+
result = result.slice(0, start) + output.join("\n") + result.slice(start + full.length);
|
|
2415
|
+
changed = true;
|
|
2416
|
+
continue;
|
|
2417
|
+
}
|
|
2418
|
+
const ifMatch = findInnermostIf(result);
|
|
2419
|
+
if (ifMatch) {
|
|
2420
|
+
const { full, condition, body, start } = ifMatch;
|
|
2421
|
+
const branches = parseIfBranches(body);
|
|
2422
|
+
let output = "";
|
|
2423
|
+
if (evaluate(condition, ctx, false)) {
|
|
2424
|
+
output = branches.if;
|
|
2425
|
+
} else {
|
|
2426
|
+
for (const branch of branches.elseIf) {
|
|
2427
|
+
if (evaluate(branch.condition, ctx, false)) {
|
|
2428
|
+
output = branch.body;
|
|
2429
|
+
break;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
if (!output && branches.else) output = branches.else;
|
|
2392
2433
|
}
|
|
2434
|
+
result = result.slice(0, start) + output + result.slice(start + full.length);
|
|
2435
|
+
changed = true;
|
|
2436
|
+
continue;
|
|
2437
|
+
}
|
|
2438
|
+
if (before === result) changed = false;
|
|
2439
|
+
}
|
|
2440
|
+
return processVariables(result, ctx);
|
|
2441
|
+
}
|
|
2442
|
+
function processVariables(content, data2) {
|
|
2443
|
+
return content.replace(/\{\{\s*([^<>\*\?!/}\s][^{}]*?)\s*}}/g, (match, code) => {
|
|
2444
|
+
return evaluate(code.trim(), data2) ?? "";
|
|
2445
|
+
});
|
|
2446
|
+
}
|
|
2447
|
+
function findInnermostIf(content) {
|
|
2448
|
+
const regex = /\{\{\s*\?\s*(.+?)\s*}}/g;
|
|
2449
|
+
let match, lastMatch = null;
|
|
2450
|
+
while ((match = regex.exec(content)) !== null) {
|
|
2451
|
+
const start = match.index;
|
|
2452
|
+
const condition = match[1];
|
|
2453
|
+
const bodyStart = match.index + match[0].length;
|
|
2454
|
+
const end = findMatchingClose(content, bodyStart, /\{\{\s*\?\s*/, /\{\{\s*\/\?\s*}}/);
|
|
2455
|
+
if (end === -1) throw new TemplateError(`Unmatched if-statement at position ${start}`);
|
|
2456
|
+
const closeTag = content.slice(end).match(/\{\{\s*\/\?\s*}}/);
|
|
2457
|
+
const full = content.slice(start, end + closeTag[0].length);
|
|
2458
|
+
const body = content.slice(bodyStart, end);
|
|
2459
|
+
lastMatch = { full, condition, body, start };
|
|
2460
|
+
}
|
|
2461
|
+
return lastMatch;
|
|
2462
|
+
}
|
|
2463
|
+
function findInnermostFor(content) {
|
|
2464
|
+
const regex = /\{\{\s*\*\s*(.+?)\s+in\s+(.+?)\s*}}/g;
|
|
2465
|
+
let match, lastMatch = null;
|
|
2466
|
+
while ((match = regex.exec(content)) !== null) {
|
|
2467
|
+
const start = match.index;
|
|
2468
|
+
const vars = match[1].replaceAll(/[()\s]/g, "");
|
|
2469
|
+
const array = match[2];
|
|
2470
|
+
const bodyStart = match.index + match[0].length;
|
|
2471
|
+
const end = findMatchingClose(content, bodyStart, /\{\{\s*\*\s*/, /\{\{\s*\/\*\s*}}/);
|
|
2472
|
+
if (end === -1) throw new TemplateError(`Unmatched for-loop at position ${start}`);
|
|
2473
|
+
const closeTag = content.slice(end).match(/\{\{\s*\/\*\s*}}/);
|
|
2474
|
+
const full = content.slice(start, end + closeTag[0].length);
|
|
2475
|
+
const body = content.slice(bodyStart, end);
|
|
2476
|
+
lastMatch = { full, vars, array, body, start };
|
|
2477
|
+
}
|
|
2478
|
+
return lastMatch;
|
|
2479
|
+
}
|
|
2480
|
+
function findMatchingClose(content, startIndex, openTag, closeTag) {
|
|
2481
|
+
let depth = 1, pos = startIndex;
|
|
2482
|
+
while (depth > 0 && pos < content.length) {
|
|
2483
|
+
const remaining = content.slice(pos);
|
|
2484
|
+
const nextOpen = remaining.search(openTag);
|
|
2485
|
+
const nextClose = remaining.search(closeTag);
|
|
2486
|
+
if (nextClose === -1) return -1;
|
|
2487
|
+
if (nextOpen !== -1 && nextOpen < nextClose) {
|
|
2488
|
+
depth++;
|
|
2489
|
+
pos += nextOpen + 1;
|
|
2490
|
+
} else {
|
|
2491
|
+
depth--;
|
|
2492
|
+
if (depth === 0) return pos + nextClose;
|
|
2493
|
+
pos += nextClose + 1;
|
|
2393
2494
|
}
|
|
2394
2495
|
}
|
|
2395
|
-
|
|
2396
|
-
}
|
|
2397
|
-
|
|
2398
|
-
const
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
compiled.push(await renderTemplate(found[3], { ...d, [element]: array[i], [index]: i }, fetch2));
|
|
2411
|
-
content = content.replace(found[0], compiled.join("\n"));
|
|
2412
|
-
}
|
|
2413
|
-
while (!!(found = /\{\{\s*([^<>\*\?!/}\s][^}]*?)\s*}}/g.exec(content))) {
|
|
2414
|
-
content = content.replace(found[0], evaluate(found[1].trim(), d) ?? "");
|
|
2415
|
-
}
|
|
2416
|
-
while (!!(found = /\{\{\s*?>\s*?(.+?):(.+?)\s*?}}([\s\S]*?)\{\{\s*?\/>\s*?}}/g.exec(content))) {
|
|
2417
|
-
const t = await fetch2(found[1].trim());
|
|
2418
|
-
if (!t) throw new TemplateError(`Unknown extended templated: ${found[1].trim()}`);
|
|
2419
|
-
content = content.replace(found[0], await renderTemplate(t, {
|
|
2420
|
-
...d,
|
|
2421
|
-
[found[2].trim()]: found[3]
|
|
2422
|
-
}, fetch2));
|
|
2423
|
-
}
|
|
2424
|
-
return content;
|
|
2496
|
+
return -1;
|
|
2497
|
+
}
|
|
2498
|
+
function parseIfBranches(body) {
|
|
2499
|
+
const parts = body.split(/\{\{\s*!\?\s*/);
|
|
2500
|
+
const result = { if: parts[0], elseIf: [], else: "" };
|
|
2501
|
+
for (let i = 1; i < parts.length; i++) {
|
|
2502
|
+
const closeBrace = parts[i].indexOf("}}");
|
|
2503
|
+
const condition = parts[i].slice(0, closeBrace).trim();
|
|
2504
|
+
const branchBody = parts[i].slice(closeBrace + 2);
|
|
2505
|
+
if (!condition) result.else = branchBody;
|
|
2506
|
+
else result.elseIf.push({ condition, body: branchBody });
|
|
2507
|
+
}
|
|
2508
|
+
return result;
|
|
2509
|
+
}
|
|
2510
|
+
return process(template);
|
|
2425
2511
|
}
|
|
2426
2512
|
var dist = {};
|
|
2427
2513
|
var persist = {};
|