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