@lucidkiln/core 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/ast-DDhHuwaY.d.ts +350 -0
- package/dist/ast-DDhHuwaY.d.ts.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{environment-BlQ8V4tX.d.ts → environment-DBvRrOn0.d.ts} +51 -80
- package/dist/environment-DBvRrOn0.d.ts.map +1 -0
- package/dist/{format-CJoqhehX.js → format-Di6-GUtH.js} +4 -3
- package/dist/{format-CJoqhehX.js.map → format-Di6-GUtH.js.map} +1 -1
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +76 -158
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/parser-isboTef0.js +2627 -0
- package/dist/parser-isboTef0.js.map +1 -0
- package/dist/{source-BQxJGo5Y.js → source-BbikGqIb.js} +40 -2765
- package/dist/source-BbikGqIb.js.map +1 -0
- package/dist/syntax.d.ts +22 -0
- package/dist/syntax.d.ts.map +1 -0
- package/dist/syntax.js +1 -0
- package/package.json +5 -1
- package/dist/environment-BlQ8V4tX.d.ts.map +0 -1
- package/dist/source-BQxJGo5Y.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as compare, $t as escapeUrl, A as consume, At as additionsIn, B as loadTemplate, Bt as fillScope, C as getAttr, Ct as contentSets, D as after, Dt as passesFrom, E as addSlotFlags, Et as passesAhead, F as fail, Ft as RenderState, G as renderTemplate, Gt as sectionCopy, H as locating, Ht as childScope, I as hold, It as Run, J as unhold, Jt as suggest, K as silence, Kt as sectionScope, L as holdData, Lt as blockScope, M as embed, Mt as closeOutlets, N as embedKeyed, Nt as recordAddition, O as all, Ot as runAhead, P as embedScope, Pt as takeOutput, Q as MISSING, Qt as escapeHtml, R as importsFor, Rt as emptyOut, S as toTime, St as atFront, T as readableNames, Tt as mayRunAhead, U as markCaller, Ut as lookup$1, V as locate, Vt as startCapture, W as passData, Wt as ownerOf, X as write, Xt as isSafe, Y as withCaller, Yt as Markup, Z as FORMATTERS, Zt as safe, _ as markupText, _t as unwrap, a as operatorFunction, an as KilnSyntaxError, at as isHashLike, b as toPieces, bt as expose, c as checkDepth, ct as mapKeys, d as functionArgument, dt as templateFunctions, en as escapeWith, et as describeType, f as insertedPiece, ft as toNumber, g as mapContents, gt as typeName, h as listOf$1, ht as truthy, i as contains, in as KilnRenderError, it as isEmpty, j as consumeAt, jt as checkLate, k as checkLength, kt as runSequence, l as entriesOf, lt as matchesType, m as isHtmlStrategy, mt as toStringArgument, n as builtinFunctions, nn as resolveTemplateName, nt as equals, o as rangeOperator, on as createDiagnostic, ot as isPlainObject, p as integerArgument, pt as toStr, q as step, qt as variableNames, r as builtinTests, rn as KilnIssue, rt as hashKeys, s as Kept, sn as issue, st as literalOptions, t as Source, tn as TEMPLATE_EXTENSION, tt as describeValue, u as fromPieces, ut as setOwn, v as readProperty, vt as valueLabel, w as getMethod, wt as isRoot, x as toPlainData, xt as lookup, y as scanHtml, yt as BLOCKED_NAMES, z as isPromise, zt as endCapture } from "./source-BbikGqIb.js";
|
|
2
|
+
import { a as ESCAPE_STRATEGIES, i as DEFAULT_SLOT, r as scanParts, t as parse } from "./parser-isboTef0.js";
|
|
2
3
|
//#region src/analyzer.ts
|
|
3
4
|
const MAX_DEPTH$1 = 1e3;
|
|
4
5
|
/** The statement lists nested inside a statement. */
|
|
@@ -1565,9 +1566,9 @@ const checkReferences = async (env, template) => {
|
|
|
1565
1566
|
};
|
|
1566
1567
|
//#endregion
|
|
1567
1568
|
//#region src/runtime/cache.ts
|
|
1568
|
-
const VERSION =
|
|
1569
|
+
const VERSION = 3;
|
|
1569
1570
|
/** Makes the value a store saves. */
|
|
1570
|
-
const packSaved = ({ html, additions, islands, islandScript }) => JSON.stringify({
|
|
1571
|
+
const packSaved = ({ html, additions, islands, islandScript, tags }) => JSON.stringify({
|
|
1571
1572
|
v: VERSION,
|
|
1572
1573
|
html,
|
|
1573
1574
|
add: additions.map((addition) => [
|
|
@@ -1576,7 +1577,8 @@ const packSaved = ({ html, additions, islands, islandScript }) => JSON.stringify
|
|
|
1576
1577
|
addition.once
|
|
1577
1578
|
]),
|
|
1578
1579
|
isl: islands.map((island) => [island.template, island.props]),
|
|
1579
|
-
scr: islandScript
|
|
1580
|
+
scr: islandScript,
|
|
1581
|
+
tag: tags
|
|
1580
1582
|
});
|
|
1581
1583
|
/** Reads a value a store returned, or returns null when it isn't one `packSaved` made. */
|
|
1582
1584
|
const unpackSaved = (value) => {
|
|
@@ -1587,8 +1589,8 @@ const unpackSaved = (value) => {
|
|
|
1587
1589
|
return null;
|
|
1588
1590
|
}
|
|
1589
1591
|
if (typeof parsed !== "object" || parsed === null) return null;
|
|
1590
|
-
const { v, html, add, isl, scr } = parsed;
|
|
1591
|
-
if (v !== VERSION || typeof html !== "string" || !Array.isArray(add) || !Array.isArray(isl) || typeof scr !== "boolean") return null;
|
|
1592
|
+
const { v, html, add, isl, scr, tag } = parsed;
|
|
1593
|
+
if (v !== VERSION || typeof html !== "string" || !Array.isArray(add) || !Array.isArray(isl) || typeof scr !== "boolean" || !Array.isArray(tag) || tag.some((item) => typeof item !== "string")) return null;
|
|
1592
1594
|
const additions = [];
|
|
1593
1595
|
for (const item of add) {
|
|
1594
1596
|
if (!Array.isArray(item)) return null;
|
|
@@ -1614,7 +1616,8 @@ const unpackSaved = (value) => {
|
|
|
1614
1616
|
html,
|
|
1615
1617
|
additions,
|
|
1616
1618
|
islands,
|
|
1617
|
-
islandScript: scr
|
|
1619
|
+
islandScript: scr,
|
|
1620
|
+
tags: tag
|
|
1618
1621
|
};
|
|
1619
1622
|
};
|
|
1620
1623
|
//#endregion
|
|
@@ -2094,18 +2097,14 @@ const printParts = (list) => {
|
|
|
2094
2097
|
const parts = [];
|
|
2095
2098
|
for (const part of list) {
|
|
2096
2099
|
const last = parts.at(-1);
|
|
2097
|
-
if (part.text !== null && last && last.text !== null) {
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
end: part.span.end
|
|
2106
|
-
}
|
|
2107
|
-
};
|
|
2108
|
-
} else parts.push(part);
|
|
2100
|
+
if (part.text !== null && last && last.text !== null) parts[parts.length - 1] = {
|
|
2101
|
+
text: last.text + part.text,
|
|
2102
|
+
span: {
|
|
2103
|
+
start: last.span.start,
|
|
2104
|
+
end: part.span.end
|
|
2105
|
+
}
|
|
2106
|
+
};
|
|
2107
|
+
else parts.push(part);
|
|
2109
2108
|
}
|
|
2110
2109
|
const first = parts[0];
|
|
2111
2110
|
const span = {
|
|
@@ -2114,18 +2113,12 @@ const printParts = (list) => {
|
|
|
2114
2113
|
};
|
|
2115
2114
|
if (parts.length === 1 && first.text !== null) {
|
|
2116
2115
|
const text = first.text;
|
|
2117
|
-
if (!first.lines) return (run, _scope, out) => {
|
|
2118
|
-
write(run, out, text, span);
|
|
2119
|
-
};
|
|
2120
|
-
const entry = indentedText(text, first.lines);
|
|
2121
2116
|
return (run, _scope, out) => {
|
|
2122
|
-
|
|
2123
|
-
write(run, out, indent === "" ? text : indentText(entry, indent, out.inline), span);
|
|
2117
|
+
write(run, out, text, span);
|
|
2124
2118
|
};
|
|
2125
2119
|
}
|
|
2126
2120
|
const count = parts.length;
|
|
2127
2121
|
const texts = [];
|
|
2128
|
-
const indented = [];
|
|
2129
2122
|
const reads = [];
|
|
2130
2123
|
const evs = [];
|
|
2131
2124
|
const emits = [];
|
|
@@ -2143,7 +2136,6 @@ const printParts = (list) => {
|
|
|
2143
2136
|
const root = compiled?.variable ?? path?.root.variable ?? null;
|
|
2144
2137
|
const choice = compiled?.choice ? emitChoice(compiled.choice, emit) : null;
|
|
2145
2138
|
texts.push(part.text);
|
|
2146
|
-
indented.push(part.text !== null && part.lines ? indentedText(part.text, part.lines) : null);
|
|
2147
2139
|
reads.push(root !== null ? "path" : choice ? "choice" : "other");
|
|
2148
2140
|
evs.push(compiled?.ev ?? null);
|
|
2149
2141
|
emits.push(emit);
|
|
@@ -2155,13 +2147,11 @@ const printParts = (list) => {
|
|
|
2155
2147
|
spans.push(part.span);
|
|
2156
2148
|
}
|
|
2157
2149
|
return (run, scope, out) => {
|
|
2158
|
-
const indent = out.indent;
|
|
2159
2150
|
let text = "";
|
|
2160
2151
|
for (let i = 0; i < count; i++) {
|
|
2161
2152
|
const part = texts[i];
|
|
2162
2153
|
if (part !== null) {
|
|
2163
|
-
|
|
2164
|
-
text += indent === "" || !entry ? part : entry.indent === indent && !out.inline ? entry.indented : indentText(entry, indent, text === "" && out.inline);
|
|
2154
|
+
text += part;
|
|
2165
2155
|
continue;
|
|
2166
2156
|
}
|
|
2167
2157
|
const at = spans[i];
|
|
@@ -2645,7 +2635,6 @@ var Compiler = class {
|
|
|
2645
2635
|
if (parts.length === 0) partsStart = i;
|
|
2646
2636
|
parts.push({
|
|
2647
2637
|
text: statement.value,
|
|
2648
|
-
lines: statement.lines,
|
|
2649
2638
|
span: statement.span
|
|
2650
2639
|
});
|
|
2651
2640
|
continue;
|
|
@@ -2777,15 +2766,13 @@ var Compiler = class {
|
|
|
2777
2766
|
const env = this.#env;
|
|
2778
2767
|
/**
|
|
2779
2768
|
* Runs passes `index` to `end`. When a pass waits, the passes after it run as `passesFrom` runs them: ahead of
|
|
2780
|
-
* it when they may. `ahead` is whether they may, found the first time a pass waits
|
|
2781
|
-
* output's indentation when the loop started.
|
|
2769
|
+
* it when they may. `ahead` is whether they may, found the first time a pass waits.
|
|
2782
2770
|
*/
|
|
2783
|
-
const iterate = (run, scope, out, values, keys, index, end, reused,
|
|
2771
|
+
const iterate = (run, scope, out, values, keys, index, end, reused, ahead) => {
|
|
2784
2772
|
const length = values.length;
|
|
2785
2773
|
for (let i = index; i < end; i++) {
|
|
2786
2774
|
step(run, span);
|
|
2787
2775
|
const inner = reused ?? childScope(scope);
|
|
2788
|
-
const inline = out.inline;
|
|
2789
2776
|
inner[valueName] = values[i] ?? null;
|
|
2790
2777
|
if (keyName !== null) inner[keyName] = keys ? keys[i] ?? null : i;
|
|
2791
2778
|
if (usesLoop) inner.loop = {
|
|
@@ -2808,14 +2795,14 @@ var Compiler = class {
|
|
|
2808
2795
|
};
|
|
2809
2796
|
}
|
|
2810
2797
|
const may = ahead ??= passesAhead(run, scope, effects.sets, effects.elsewhere);
|
|
2811
|
-
return passesFrom(run, out, result,
|
|
2798
|
+
return passesFrom(run, out, result, i + 1, end, (aheadRun, aheadOut, at) => iterate(aheadRun, scope, aheadOut, values, keys, at, at + 1, shared ? childScope(scope) : null, may), span, may);
|
|
2812
2799
|
}
|
|
2813
2800
|
};
|
|
2814
2801
|
const start = (run, scope, out, value) => {
|
|
2815
2802
|
const { values, keys } = loopItems(run, span, value, keyName !== null);
|
|
2816
2803
|
if (values.length === 0) return alternate?.(run, scope, out);
|
|
2817
2804
|
const reused = shared ? childScope(scope) : null;
|
|
2818
|
-
return iterate(run, scope, out, values, keys, 0, values.length, reused,
|
|
2805
|
+
return iterate(run, scope, out, values, keys, 0, values.length, reused, null);
|
|
2819
2806
|
};
|
|
2820
2807
|
const ev = iterable.ev;
|
|
2821
2808
|
if (!iterable.async) return (run, scope, out) => {
|
|
@@ -2942,31 +2929,20 @@ var Compiler = class {
|
|
|
2942
2929
|
}
|
|
2943
2930
|
#blockStatement(node) {
|
|
2944
2931
|
this.#defineBlock(node);
|
|
2945
|
-
const { name, span
|
|
2932
|
+
const { name, span } = node;
|
|
2946
2933
|
return (run, scope, out) => {
|
|
2947
2934
|
const entry = run.blocks.get(name)?.[0];
|
|
2948
2935
|
if (!entry) return;
|
|
2949
2936
|
const render = () => entry.def.body(entry.run.within(run.capture, run.blockDepth), blockScope(entry.def, scope), out);
|
|
2950
|
-
|
|
2951
|
-
if (indent === "") return own ? render() : withCaller(run, span, render);
|
|
2952
|
-
const saved = out.indent;
|
|
2953
|
-
const inline = out.inline;
|
|
2954
|
-
startPlace(out, indent);
|
|
2955
|
-
return endPlace(out, saved, inline, own ? render() : withCaller(run, span, render));
|
|
2937
|
+
return entry.run.template === run.template ? render() : withCaller(run, span, render);
|
|
2956
2938
|
};
|
|
2957
2939
|
}
|
|
2958
2940
|
#include(node) {
|
|
2959
|
-
const { ignoreMissing, span
|
|
2960
|
-
return this.#embedding(node.template, node.with, span, (run, out, name, variables) =>
|
|
2961
|
-
if (indent === "") return embed(run, out, span, name, variables, null, ignoreMissing);
|
|
2962
|
-
const saved = out.indent;
|
|
2963
|
-
const inline = out.inline;
|
|
2964
|
-
startPlace(out, indent);
|
|
2965
|
-
return endPlace(out, saved, inline, embed(run, out, span, name, variables, null, ignoreMissing));
|
|
2966
|
-
});
|
|
2941
|
+
const { ignoreMissing, span } = node;
|
|
2942
|
+
return this.#embedding(node.template, node.with, span, (run, out, name, variables) => embed(run, out, span, name, variables, null, ignoreMissing));
|
|
2967
2943
|
}
|
|
2968
2944
|
#component(node) {
|
|
2969
|
-
const { span
|
|
2945
|
+
const { span } = node;
|
|
2970
2946
|
const fills = node.fills.map((fill) => ({
|
|
2971
2947
|
name: fill.name,
|
|
2972
2948
|
body: this.#body(fill.body),
|
|
@@ -2988,11 +2964,7 @@ var Compiler = class {
|
|
|
2988
2964
|
scope: callerScope,
|
|
2989
2965
|
sets: fill.sets
|
|
2990
2966
|
});
|
|
2991
|
-
|
|
2992
|
-
const saved = out.indent;
|
|
2993
|
-
const inline = out.inline;
|
|
2994
|
-
startPlace(out, indent);
|
|
2995
|
-
return endPlace(out, saved, inline, embed(run, out, span, name, variables, slots, false));
|
|
2967
|
+
return embed(run, out, span, name, variables, slots, false);
|
|
2996
2968
|
});
|
|
2997
2969
|
}
|
|
2998
2970
|
/**
|
|
@@ -3010,11 +2982,10 @@ var Compiler = class {
|
|
|
3010
2982
|
opening = ISLAND_SCRIPT + opening;
|
|
3011
2983
|
if (isRoot(state, out)) state.islandScript = true;
|
|
3012
2984
|
}
|
|
3013
|
-
|
|
3014
|
-
write(run, out, indent === void 0 ? opening : `${lead(indent)}${opening}${closing?.indent === null ? "" : "\n"}`, span);
|
|
2985
|
+
write(run, out, indent === void 0 ? opening : `${indent}${opening}${closing?.indent === null ? "" : "\n"}`, span);
|
|
3015
2986
|
return after(fallback(run, childScope(scope), out), () => {
|
|
3016
2987
|
if (!closing) return write(run, out, ISLAND_CLOSING, span);
|
|
3017
|
-
const start = closing.indent
|
|
2988
|
+
const start = closing.indent ?? "";
|
|
3018
2989
|
const end = closing.newline ? "\n" : "";
|
|
3019
2990
|
return write(run, out, `${start}${ISLAND_CLOSING}${end}`, span);
|
|
3020
2991
|
});
|
|
@@ -3037,11 +3008,7 @@ var Compiler = class {
|
|
|
3037
3008
|
const state = run.state;
|
|
3038
3009
|
const islands = state.islands;
|
|
3039
3010
|
if (islands !== null && (islands.mode === "defer" || state.stream !== null && isRoot(state, out) && !run.capture?.section)) return after(loadTemplate(run, name, span), (template) => template ? render(run, out, scope, islands, template, props) : void 0);
|
|
3040
|
-
|
|
3041
|
-
const saved = out.indent;
|
|
3042
|
-
const inline = out.inline;
|
|
3043
|
-
startPlace(out, indent);
|
|
3044
|
-
return endPlace(out, saved, inline, embed(run, out, span, name, props, null, false));
|
|
3011
|
+
return embed(run, out, span, name, props, null, false);
|
|
3045
3012
|
};
|
|
3046
3013
|
return this.#embedding(node.template, node.with, span, (run, out, name, variables, scope) => run.state.islands === null ? place(run, out, name, variables, scope) : atFront(run, () => place(run, out, name, variables, scope)));
|
|
3047
3014
|
}
|
|
@@ -3068,8 +3035,8 @@ var Compiler = class {
|
|
|
3068
3035
|
}
|
|
3069
3036
|
#slot(node) {
|
|
3070
3037
|
const fallback = this.#body(node.body);
|
|
3071
|
-
const { name, span
|
|
3072
|
-
|
|
3038
|
+
const { name, span } = node;
|
|
3039
|
+
return (run, scope, out) => {
|
|
3073
3040
|
const fill = run.slots?.get(name);
|
|
3074
3041
|
if (!fill) return fallback(run, childScope(scope), out);
|
|
3075
3042
|
try {
|
|
@@ -3082,13 +3049,6 @@ var Compiler = class {
|
|
|
3082
3049
|
throw markCaller(run, span, error);
|
|
3083
3050
|
}
|
|
3084
3051
|
};
|
|
3085
|
-
if (indent === "") return render;
|
|
3086
|
-
return (run, scope, out) => {
|
|
3087
|
-
const saved = out.indent;
|
|
3088
|
-
const inline = out.inline;
|
|
3089
|
-
startPlace(out, indent);
|
|
3090
|
-
return endPlace(out, saved, inline, render(run, scope, out));
|
|
3091
|
-
};
|
|
3092
3052
|
}
|
|
3093
3053
|
#with(node) {
|
|
3094
3054
|
const value = this.#expr(node.value);
|
|
@@ -3131,11 +3091,10 @@ var Compiler = class {
|
|
|
3131
3091
|
if (value instanceof Markup) return value.value;
|
|
3132
3092
|
throw fail(run, span, "type-error", `"cache" keys are made of strings, numbers, booleans, dates and null, but got a ${typeName(value)}`);
|
|
3133
3093
|
};
|
|
3134
|
-
const fullKey = (run,
|
|
3094
|
+
const fullKey = (run, value) => {
|
|
3135
3095
|
const parts = Array.isArray(value) ? value.map((item) => part(run, item)) : [part(run, value)];
|
|
3136
3096
|
const { locale, timeZone, islands } = run.state;
|
|
3137
|
-
|
|
3138
|
-
if (out.indent !== "") key += `|indent|${JSON.stringify([out.indent, out.inline])}`;
|
|
3097
|
+
const key = `${JSON.stringify(run.state.env.cacheNamespace)}|${templateName}|${locale}|${timeZone}|${JSON.stringify(parts)}`;
|
|
3139
3098
|
return islands?.mode === "defer" ? `${key}|islands|${JSON.stringify([islands.url, islands.script])}` : key;
|
|
3140
3099
|
};
|
|
3141
3100
|
const lifetime = (run, value) => {
|
|
@@ -3144,7 +3103,7 @@ var Compiler = class {
|
|
|
3144
3103
|
return value;
|
|
3145
3104
|
};
|
|
3146
3105
|
const save = (run, scope, out, keyValue, secondsValue) => {
|
|
3147
|
-
const name = fullKey(run,
|
|
3106
|
+
const name = fullKey(run, keyValue);
|
|
3148
3107
|
const time = lifetime(run, secondsValue);
|
|
3149
3108
|
const state = run.state;
|
|
3150
3109
|
const store = state.env.cache;
|
|
@@ -3152,7 +3111,8 @@ var Compiler = class {
|
|
|
3152
3111
|
const inner = sectionScope(scope);
|
|
3153
3112
|
const capture = startCapture(run, {
|
|
3154
3113
|
scope: inner,
|
|
3155
|
-
deferred: []
|
|
3114
|
+
deferred: [],
|
|
3115
|
+
tags: /* @__PURE__ */ new Set()
|
|
3156
3116
|
});
|
|
3157
3117
|
return after(body(run.within(capture), inner, out), () => {
|
|
3158
3118
|
endCapture(run, capture);
|
|
@@ -3164,6 +3124,8 @@ var Compiler = class {
|
|
|
3164
3124
|
return after(found, (value) => {
|
|
3165
3125
|
const saved = typeof value === "string" ? unpackSaved(value) : null;
|
|
3166
3126
|
if (saved) {
|
|
3127
|
+
const around = run.capture?.section;
|
|
3128
|
+
if (around) for (const tag of saved.tags) around.tags.add(tag);
|
|
3167
3129
|
const replay = (front) => {
|
|
3168
3130
|
const islands = state.islands;
|
|
3169
3131
|
if (islands?.mode === "defer" && saved.islands.length > 0) {
|
|
@@ -3185,17 +3147,20 @@ var Compiler = class {
|
|
|
3185
3147
|
const start = out.s.length;
|
|
3186
3148
|
const hadScript = state.islandScript;
|
|
3187
3149
|
return after(fresh(), (capture) => {
|
|
3150
|
+
const tags = [...capture.section?.tags ?? []].sort();
|
|
3188
3151
|
const manifest = state.islands?.mode === "defer" ? state.islands.manifest : null;
|
|
3189
3152
|
const value = packSaved({
|
|
3190
3153
|
html: out.s.slice(start),
|
|
3191
3154
|
additions: additionsIn(capture.additions ?? []),
|
|
3192
3155
|
islands: manifest ? (capture.section?.deferred ?? []).flatMap((id) => manifest[id] ?? []) : [],
|
|
3193
|
-
islandScript: !hadScript && state.islandScript
|
|
3156
|
+
islandScript: !hadScript && state.islandScript,
|
|
3157
|
+
tags
|
|
3194
3158
|
});
|
|
3195
3159
|
return locating(run, span, () => store.set({
|
|
3196
3160
|
key: name,
|
|
3197
3161
|
value,
|
|
3198
|
-
seconds: time
|
|
3162
|
+
seconds: time,
|
|
3163
|
+
tags
|
|
3199
3164
|
}), "The cache store");
|
|
3200
3165
|
});
|
|
3201
3166
|
});
|
|
@@ -3220,7 +3185,7 @@ var Compiler = class {
|
|
|
3220
3185
|
* so the outlet must write to that output, not to a capture or a cached section.
|
|
3221
3186
|
*/
|
|
3222
3187
|
#outlet(node) {
|
|
3223
|
-
const { name, span
|
|
3188
|
+
const { name, span } = node;
|
|
3224
3189
|
const mark = (run, out) => {
|
|
3225
3190
|
const state = run.state;
|
|
3226
3191
|
if (!isRoot(state, out) || run.capture?.section) throw fail(run, span, "misplaced-outlet", `Outlet "${name}" can't be inside "cache", "set", "apply" or a macro`);
|
|
@@ -3229,8 +3194,6 @@ var Compiler = class {
|
|
|
3229
3194
|
state.outlets.set(name, {
|
|
3230
3195
|
out,
|
|
3231
3196
|
offset: out.s.length,
|
|
3232
|
-
indent: indent === void 0 ? out.indent : out.indent + indent,
|
|
3233
|
-
inline: indent === void 0,
|
|
3234
3197
|
content: null
|
|
3235
3198
|
});
|
|
3236
3199
|
};
|
|
@@ -3258,9 +3221,8 @@ var Compiler = class {
|
|
|
3258
3221
|
};
|
|
3259
3222
|
}
|
|
3260
3223
|
/**
|
|
3261
|
-
* `add to`: renders its content and records it for the outlet.
|
|
3262
|
-
*
|
|
3263
|
-
* section saves it.
|
|
3224
|
+
* `add to`: renders its content and records it for the outlet. A `once` tag that already added doesn't render again,
|
|
3225
|
+
* but is still recorded, so a cached section saves it.
|
|
3264
3226
|
*/
|
|
3265
3227
|
#add(node) {
|
|
3266
3228
|
const body = this.#body(node.body);
|
|
@@ -3276,12 +3238,7 @@ var Compiler = class {
|
|
|
3276
3238
|
}, front);
|
|
3277
3239
|
return;
|
|
3278
3240
|
}
|
|
3279
|
-
const capture =
|
|
3280
|
-
s: "",
|
|
3281
|
-
indent: OUTLET_INDENT,
|
|
3282
|
-
inline: false,
|
|
3283
|
-
ahead: null
|
|
3284
|
-
};
|
|
3241
|
+
const capture = emptyOut();
|
|
3285
3242
|
return after(body(run, childScope(scope), capture), () => recordAddition(run, span, {
|
|
3286
3243
|
outlet,
|
|
3287
3244
|
html: capture.s,
|
|
@@ -4199,7 +4156,7 @@ const isPrecompiled = (value) => typeof value === "object" && value !== null &&
|
|
|
4199
4156
|
const mismatch = (name, detail) => new KilnRenderError("precompiled-mismatch", `Precompiled template "${name}" ${detail}. Precompile it again`, name);
|
|
4200
4157
|
/** Compiles a precompiled template: its source, with the generated statements in place of the ones they cover. */
|
|
4201
4158
|
const compilePrecompiled = (env, name, template) => {
|
|
4202
|
-
if (template.kiln !==
|
|
4159
|
+
if (template.kiln !== 5) throw mismatch(name, "was made by another version of Kiln");
|
|
4203
4160
|
if (template.autoescape !== env.autoescape) throw mismatch(name, "was compiled with another \"autoescape\" option");
|
|
4204
4161
|
const runs = /* @__PURE__ */ new Map();
|
|
4205
4162
|
const create = template.create;
|
|
@@ -4279,30 +4236,29 @@ const runtime = {
|
|
|
4279
4236
|
unhold,
|
|
4280
4237
|
/**
|
|
4281
4238
|
* Continues a generated run after a statement that returned a promise, `pending`: the rest of the run starts at
|
|
4282
|
-
* once, ahead of it, when it may, or else once the statement is done.
|
|
4283
|
-
* function started. See `runAhead`.
|
|
4239
|
+
* once, ahead of it, when it may, or else once the statement is done. See `runAhead`.
|
|
4284
4240
|
*/
|
|
4285
|
-
restAhead: (run, out, pending,
|
|
4241
|
+
restAhead: (run, out, pending, rest, span) => mayRunAhead(run.state) ? runAhead(run, out, pending, rest, span) : pending.then(() => rest(run, out)),
|
|
4286
4242
|
contentSets,
|
|
4287
4243
|
/**
|
|
4288
4244
|
* Continues a generated loop after a pass that returned a promise, `pending`: passes `from` to `to` run one at a
|
|
4289
4245
|
* time with `pass`, ahead of it when they may, see `passesAhead`. `sets` are the variables the loop's body sets,
|
|
4290
4246
|
* and `elsewhere` whether it places content from elsewhere.
|
|
4291
4247
|
*/
|
|
4292
|
-
passAhead: (run, scope, out, pending,
|
|
4248
|
+
passAhead: (run, scope, out, pending, sets, elsewhere, from, to, pass, span) => passesFrom(run, out, pending, from, to, pass, span, passesAhead(run, scope, sets, elsewhere)),
|
|
4293
4249
|
/**
|
|
4294
4250
|
* For a generated loop that pauses inside a pass: starts passes `from` to `to` ahead of it when they may, and returns
|
|
4295
4251
|
* what the loop calls once the pass is done. Returns null when they may not, and the loop carries on as usual.
|
|
4296
4252
|
*/
|
|
4297
|
-
startAhead: (run, scope, out,
|
|
4298
|
-
if (!mayRunAhead(run.state
|
|
4253
|
+
startAhead: (run, scope, out, sets, elsewhere, from, to, pass, span) => {
|
|
4254
|
+
if (!mayRunAhead(run.state) || !passesAhead(run, scope, sets, elsewhere)) return null;
|
|
4299
4255
|
let done = NOTHING;
|
|
4300
4256
|
let failed = NOTHING;
|
|
4301
4257
|
const pending = new Promise((resolve, reject) => {
|
|
4302
4258
|
done = resolve;
|
|
4303
4259
|
failed = reject;
|
|
4304
4260
|
});
|
|
4305
|
-
const joined = passesFrom(run, out, pending,
|
|
4261
|
+
const joined = passesFrom(run, out, pending, from, to, pass, span, true);
|
|
4306
4262
|
return {
|
|
4307
4263
|
join: () => {
|
|
4308
4264
|
done();
|
|
@@ -4314,10 +4270,6 @@ const runtime = {
|
|
|
4314
4270
|
}
|
|
4315
4271
|
};
|
|
4316
4272
|
},
|
|
4317
|
-
startPlace,
|
|
4318
|
-
endPlace,
|
|
4319
|
-
indentText,
|
|
4320
|
-
indentedText,
|
|
4321
4273
|
embed,
|
|
4322
4274
|
embedScope,
|
|
4323
4275
|
embedKeyed,
|
|
@@ -4662,10 +4614,6 @@ const HELPERS = [
|
|
|
4662
4614
|
"contentSets",
|
|
4663
4615
|
"passAhead",
|
|
4664
4616
|
"startAhead",
|
|
4665
|
-
"startPlace",
|
|
4666
|
-
"endPlace",
|
|
4667
|
-
"indentText",
|
|
4668
|
-
"indentedText",
|
|
4669
4617
|
"truthy",
|
|
4670
4618
|
"isEmpty",
|
|
4671
4619
|
"equals",
|
|
@@ -4852,7 +4800,7 @@ var Generator = class {
|
|
|
4852
4800
|
return [
|
|
4853
4801
|
"// Precompiled by Kiln. Don't edit this file: precompile the template again.",
|
|
4854
4802
|
"export default {",
|
|
4855
|
-
`\tkiln:
|
|
4803
|
+
`\tkiln: 5,`,
|
|
4856
4804
|
`\tautoescape: ${JSON.stringify(this.#env.autoescape)},`,
|
|
4857
4805
|
`\tsource: ${JSON.stringify(source)},`,
|
|
4858
4806
|
" create(rt) {",
|
|
@@ -4979,7 +4927,7 @@ var Generator = class {
|
|
|
4979
4927
|
const next = `${base}_${index + 1}(run, scope, out)`;
|
|
4980
4928
|
const body = lines.map((line) => line.replace(WAIT_LINE, (_, tabs, result, ahead) => {
|
|
4981
4929
|
const then = `${result}.then(() => ${next})`;
|
|
4982
|
-
const rest = `restAhead(run, out, ${result},
|
|
4930
|
+
const rest = `restAhead(run, out, ${result}, (run, out) => ${next}, ${span})`;
|
|
4983
4931
|
return `${tabs}if (${result} !== undefined) return ${ahead === AHEAD ? rest : ahead === GUARDED ? `contentSets(run) ? ${then} : ${rest}` : then};`;
|
|
4984
4932
|
}));
|
|
4985
4933
|
const last = index === segments.length - 1;
|
|
@@ -5030,8 +4978,6 @@ var Generator = class {
|
|
|
5030
4978
|
"let steps = state.steps;",
|
|
5031
4979
|
"const signal = state.signal;",
|
|
5032
4980
|
`signal !== undefined && signal.aborted && aborted(run, ${span});`,
|
|
5033
|
-
"const ind = out.indent;",
|
|
5034
|
-
"const inl = out.inline;",
|
|
5035
4981
|
"let s = \"\";",
|
|
5036
4982
|
`let ${[
|
|
5037
4983
|
"q",
|
|
@@ -5179,7 +5125,7 @@ var Generator = class {
|
|
|
5179
5125
|
}
|
|
5180
5126
|
#statement(statement, context) {
|
|
5181
5127
|
switch (statement.type) {
|
|
5182
|
-
case "Text": return [
|
|
5128
|
+
case "Text": return [`s += ${JSON.stringify(statement.value)};`];
|
|
5183
5129
|
case "Output": return this.#output(statement.expression, statement.span, context);
|
|
5184
5130
|
case "If": return this.#if(statement, context);
|
|
5185
5131
|
case "For": return this.#for(statement, context);
|
|
@@ -5196,26 +5142,6 @@ var Generator = class {
|
|
|
5196
5142
|
default: return unsupported();
|
|
5197
5143
|
}
|
|
5198
5144
|
}
|
|
5199
|
-
/** Text, with its lines indented to where it is inserted. See `indentText`. */
|
|
5200
|
-
#text(statement) {
|
|
5201
|
-
const text = JSON.stringify(statement.value);
|
|
5202
|
-
if (!statement.lines) return `s += ${text};`;
|
|
5203
|
-
const lines = JSON.stringify(statement.lines);
|
|
5204
|
-
const entry = this.#constant(`text:${statement.span.start}:${statement.span.end}`, "T", `indentedText(${text}, ${lines})`);
|
|
5205
|
-
return `s += ind === "" ? ${text} : ${entry}.indent === ind && !out.inline ? ${entry}.indented : indentText(${entry}, ind, s === "" && out.inline);`;
|
|
5206
|
-
}
|
|
5207
|
-
/**
|
|
5208
|
-
* Inserts content at the indentation of the tag that inserts it, with `startPlace` and `endPlace`. Tags at the start
|
|
5209
|
-
* of a line need nothing. Saved values go in temporaries rather than a closure, so the function's locals stay fast.
|
|
5210
|
-
*/
|
|
5211
|
-
#place(at, call) {
|
|
5212
|
-
if (at === "") return call;
|
|
5213
|
-
const [saved, inline] = [this.#temp(), this.#temp()];
|
|
5214
|
-
return `(${saved} = out.indent, ${inline} = out.inline, startPlace(out, ${this.#at(at)}), endPlace(out, ${saved}, ${inline}, ${call}))`;
|
|
5215
|
-
}
|
|
5216
|
-
#at(at) {
|
|
5217
|
-
return at === void 0 ? "undefined" : JSON.stringify(at);
|
|
5218
|
-
}
|
|
5219
5145
|
/** Statements inside another, such as a loop's body. */
|
|
5220
5146
|
#body(list, context) {
|
|
5221
5147
|
const inner = {
|
|
@@ -5504,7 +5430,7 @@ var Generator = class {
|
|
|
5504
5430
|
const call = (part, value) => `${name}_${part}(${partParams}${value === void 0 ? "" : `, ${value}`})`;
|
|
5505
5431
|
const one = `(run, out, j) => ${name}(run, scope, out, ${loop.values}, ${loop.length}, j, j + 1${keys})`;
|
|
5506
5432
|
const { sets, elsewhere } = this.#setsOf(statement);
|
|
5507
|
-
const handOff = (from, tabs, rest) => from === 0 ? `${tabs}return ${loop.index} + 1 < stop ? passAhead(run, scope, out, ${rest},
|
|
5433
|
+
const handOff = (from, tabs, rest) => from === 0 ? `${tabs}return ${loop.index} + 1 < stop ? passAhead(run, scope, out, ${rest}, ${sets}, ${elsewhere}, ${loop.index} + 1, stop, ${one}, ${loop.span}) : ${rest};` : `${tabs}return ${rest};`;
|
|
5508
5434
|
const continued = (from) => segments.slice(from).flatMap((lines, offset) => this.#forgetLines(lines).flatMap((line) => {
|
|
5509
5435
|
const next = from + offset + 1;
|
|
5510
5436
|
const value = VALUE_LINE.exec(line);
|
|
@@ -5593,7 +5519,7 @@ var Generator = class {
|
|
|
5593
5519
|
const ahead = `a${loop.id}`;
|
|
5594
5520
|
const { index, span } = loop;
|
|
5595
5521
|
const { sets, elsewhere } = this.#setsOf(statement);
|
|
5596
|
-
const fork = `if (${ahead} === null && ${index} + 1 < stop) ${ahead} = startAhead(run, ${loop.outer}, out,
|
|
5522
|
+
const fork = `if (${ahead} === null && ${index} + 1 < stop) ${ahead} = startAhead(run, ${loop.outer}, out, ${sets}, ${elsewhere}, ${index} + 1, stop, (run, out, j) => drive(${name}(run, out, j, j + 1)), ${span});`;
|
|
5597
5523
|
const body = this.#forgetLines(this.#setFlags(lines)).flatMap((line) => {
|
|
5598
5524
|
if (line.trim() === FORK) return [line.replace(FORK, fork)];
|
|
5599
5525
|
const wait = WAIT_LINE.exec(line);
|
|
@@ -5758,7 +5684,7 @@ var Generator = class {
|
|
|
5758
5684
|
...target.lines,
|
|
5759
5685
|
...variables.lines,
|
|
5760
5686
|
...variables.charge(span),
|
|
5761
|
-
...this.#wait(span,
|
|
5687
|
+
...this.#wait(span, variables.embed(span, target.name, "null", statement.ignoreMissing), context.top)
|
|
5762
5688
|
];
|
|
5763
5689
|
}
|
|
5764
5690
|
/**
|
|
@@ -5846,7 +5772,7 @@ var Generator = class {
|
|
|
5846
5772
|
`${slots} = new Map();`,
|
|
5847
5773
|
...fills.map((fill) => `${slots}.set(${JSON.stringify(fill.name)}, { body: ${this.#nested(fill.body, statement.span, context)}, run, scope: ${context.scope}, sets: ${mayWrite(fill.body)} });`),
|
|
5848
5774
|
...variables.charge(span),
|
|
5849
|
-
...this.#wait(span,
|
|
5775
|
+
...this.#wait(span, variables.embed(span, target.name, slots, false), context.top),
|
|
5850
5776
|
...fills.some((fill) => setsVariables(fill.body)) ? this.#forgetAll() : fills.some((fill) => containsNode(fill.body, (record) => record.type === "Block")) ? this.#afterBlocks() : []
|
|
5851
5777
|
];
|
|
5852
5778
|
}
|
|
@@ -5854,7 +5780,6 @@ var Generator = class {
|
|
|
5854
5780
|
#slot(statement, context) {
|
|
5855
5781
|
const span = this.#span(statement.span);
|
|
5856
5782
|
const fill = this.#temp();
|
|
5857
|
-
const at = statement.indent;
|
|
5858
5783
|
const sets = [...setsIn(statement.body)];
|
|
5859
5784
|
const scope = sets.length > 0 ? this.#temp() : context.scope;
|
|
5860
5785
|
let fallback = this.#body(statement.body, {
|
|
@@ -5866,23 +5791,10 @@ var Generator = class {
|
|
|
5866
5791
|
...fallback,
|
|
5867
5792
|
...sets.flatMap((name) => this.#forget(name))
|
|
5868
5793
|
];
|
|
5869
|
-
if (at !== "" && !statement.body.every(isBlank)) {
|
|
5870
|
-
const [saved, inline] = [this.#temp(), this.#temp()];
|
|
5871
|
-
fallback = [
|
|
5872
|
-
`${saved} = out.indent;`,
|
|
5873
|
-
`${inline} = out.inline;`,
|
|
5874
|
-
`startPlace(out, ${this.#at(at)});`,
|
|
5875
|
-
"{",
|
|
5876
|
-
...indent(["const ind = out.indent;", ...fallback]),
|
|
5877
|
-
"}",
|
|
5878
|
-
`out.indent = ${saved};`,
|
|
5879
|
-
`if (out.inline) out.inline = ${inline};`
|
|
5880
|
-
];
|
|
5881
|
-
}
|
|
5882
5794
|
return [
|
|
5883
5795
|
`${fill} = run.slots === null ? undefined : run.slots.get(${JSON.stringify(statement.name)});`,
|
|
5884
5796
|
`if (${fill} !== undefined) {`,
|
|
5885
|
-
...indent(this.#wait(span,
|
|
5797
|
+
...indent(this.#wait(span, `fillSlot(run, ${span}, ${fill}, out)`, context.top)),
|
|
5886
5798
|
"} else {",
|
|
5887
5799
|
...indent(fallback),
|
|
5888
5800
|
"}"
|
|
@@ -5896,7 +5808,7 @@ var Generator = class {
|
|
|
5896
5808
|
if (context.inLoop) return unsupported();
|
|
5897
5809
|
this.#pending.push([statement.body, context.strategy]);
|
|
5898
5810
|
const span = this.#span(statement.span);
|
|
5899
|
-
return [...this.#wait(span,
|
|
5811
|
+
return [...this.#wait(span, `placeBlock(run, ${span}, ${JSON.stringify(statement.name)}, ${context.scope}, out)`, context.top), ...this.#afterBlocks()];
|
|
5900
5812
|
}
|
|
5901
5813
|
/** Forgets every variable lookup after a block is placed when the block, perhaps a child template's version, may set any variable. */
|
|
5902
5814
|
#afterBlocks() {
|
|
@@ -8565,7 +8477,7 @@ const memoryLoader = (templates) => {
|
|
|
8565
8477
|
};
|
|
8566
8478
|
/**
|
|
8567
8479
|
* A store for the `cache` tag that keeps output in memory, for a long-running server. Holds up to `max` copies, 1,000
|
|
8568
|
-
* by default, and drops the oldest first.
|
|
8480
|
+
* by default, and drops the oldest first. `clear` removes every copy, or those with any of the tags passed.
|
|
8569
8481
|
*
|
|
8570
8482
|
* ```ts
|
|
8571
8483
|
* const kiln = createKiln({ loader, cache: memoryCache() });
|
|
@@ -8581,14 +8493,20 @@ const memoryCache = ({ max = 1e3 } = {}) => {
|
|
|
8581
8493
|
entries.delete(key);
|
|
8582
8494
|
return null;
|
|
8583
8495
|
},
|
|
8584
|
-
set: ({ key, value, seconds }) => {
|
|
8496
|
+
set: ({ key, value, seconds, tags }) => {
|
|
8585
8497
|
entries.delete(key);
|
|
8586
8498
|
entries.set(key, {
|
|
8587
8499
|
value,
|
|
8588
|
-
expires: seconds === null ? Infinity : Date.now() + seconds * 1e3
|
|
8500
|
+
expires: seconds === null ? Infinity : Date.now() + seconds * 1e3,
|
|
8501
|
+
tags
|
|
8589
8502
|
});
|
|
8590
8503
|
const oldest = entries.keys().next();
|
|
8591
8504
|
if (entries.size > max && !oldest.done) entries.delete(oldest.value);
|
|
8505
|
+
},
|
|
8506
|
+
/** Removes every copy, or with `tags`, the copies that have any of them. */
|
|
8507
|
+
clear: ({ tags } = {}) => {
|
|
8508
|
+
if (!tags) return entries.clear();
|
|
8509
|
+
for (const [key, entry] of entries) if (entry.tags.some((tag) => tags.includes(tag))) entries.delete(key);
|
|
8592
8510
|
}
|
|
8593
8511
|
};
|
|
8594
8512
|
};
|