@forinda/kickjs-view 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -2
- package/dist/edge.d.ts +3 -3
- package/dist/edge.js +2 -2
- package/dist/exports-D1QawoF2.js +15 -0
- package/dist/exports-D1QawoF2.js.map +1 -0
- package/dist/file-loader.d.ts +1 -1
- package/dist/file-loader.js +1 -1
- package/dist/{format-DXbIGfMX.js → format-DOPzX3FB.js} +3 -3
- package/dist/{format-DXbIGfMX.js.map → format-DOPzX3FB.js.map} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/{read-exports-DhS-hmBe.js → read-exports-CvEZWKzJ.js} +3 -3
- package/dist/{read-exports-DhS-hmBe.js.map → read-exports-CvEZWKzJ.js.map} +1 -1
- package/dist/{serve-DWPn81IT.d.ts → serve-XP3MXIN8.d.ts} +2 -2
- package/dist/{serve-DWPn81IT.d.ts.map → serve-XP3MXIN8.d.ts.map} +1 -1
- package/dist/{views-DHep2pMC.d.ts → views-CgI6icpT.d.ts} +20 -2
- package/dist/{views-DHep2pMC.d.ts.map → views-CgI6icpT.d.ts.map} +1 -1
- package/package.json +1 -1
- package/virtual.d.ts +10 -1
- package/dist/exports-Dr0XJ2Uv.js +0 -14
- package/dist/exports-Dr0XJ2Uv.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as ViewsOptions, r as Views } from "./views-
|
|
2
|
+
import { a as ViewsOptions, r as Views } from "./views-CgI6icpT.js";
|
|
3
3
|
import { _ as TemplateAst, s as CheckedTemplate, u as Expr, v as Diagnostic, y as Pos } from "./ast-CDfapRqX.js";
|
|
4
4
|
import { t as Project } from "./project-BTsPTbZU.js";
|
|
5
5
|
//#region src/parse/expression.d.ts
|
|
@@ -95,4 +95,4 @@ declare function assetTags(entry: string, mode: AssetsMode, nonce?: string): str
|
|
|
95
95
|
declare function clientScriptResponse(views: Views, request: Request): Promise<Response | undefined>;
|
|
96
96
|
//#endregion
|
|
97
97
|
export { parseExpression as _, assetTags as a, viewsMiddleware as c, isUrlAttr as d, CheckResult as f, FORBIDDEN_NAMES as g, parse as h, ViteManifestChunk as i, readPipeExports as l, ParseResult as m, AssetsMode as n, KickView as o, check as p, ViteManifest as r, KickViewOptions as s, clientScriptResponse as t, URL_ATTRS as u };
|
|
98
|
-
//# sourceMappingURL=serve-
|
|
98
|
+
//# sourceMappingURL=serve-XP3MXIN8.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve-
|
|
1
|
+
{"version":3,"file":"serve-XP3MXIN8.d.ts","names":[],"sources":["../src/parse/expression.ts","../src/parse/template.ts","../src/check/check.ts","../src/urls.ts","../src/pipes/read-exports.ts","../src/adapter.ts","../src/assets.ts","../src/serve.ts"],"mappings":";;;;;;cAWa,iBAAiB;;;;;iBA+Yd,gBACd,aACA,cACA,MAAM;EACH,OAAO;EAAM,aAAa;;;;UCzYd;EACf,KAAK;EACL,aAAa;;;iBAq4BC,MAAM,gBAAgB,eAAe;;;UCx3BpC;EACf,WAAW;EACX,aAAa;;;iBA+vBC,MAAM,cAAc,SAAS,UAAU;;;;;;;cCjyB1C,WAAW;iBAaR,UAAU,aAAa;;;iBC6DvB,gBACd,gBACA;EACG;EAAiB,aAAa;;;;KCtE9B,QAAQ;;;;;iBAsEG,gBACd,OAAO,SACL;EAAO;GAAe;UAQT,wBAAwB;;EAEvC,QAAQ;;iBAsBM,SAAS,UAAS;;;;IA/DM,UAAA,aAAM,cAAc,MAAQ;IAwE3B;;;;;UCrHxB;EACf;EACA;EACA;EACA;;KAGU,eAAe,eAAe;KAE9B;EACN;EAAW;;EACX;EAAY,UAAU;EAAc;;iBAE1B,UAAU,eAAe,MAAM,YAAY;;;;;;;;;;iBCiBrC,qBACpB,OAAO,OACP,SAAS,UACR,QAAQ"}
|
|
@@ -107,6 +107,16 @@ interface Loader {
|
|
|
107
107
|
interface ViewsBundle {
|
|
108
108
|
v: number;
|
|
109
109
|
templates: Record<string, CheckedTemplate>;
|
|
110
|
+
/** Client scripts bundled by the build: each component's entry file, and every file (entries and shared chunks). */
|
|
111
|
+
client?: {
|
|
112
|
+
entries: Record<string, string>;
|
|
113
|
+
/** Each entry's stylesheets, by component tag. */
|
|
114
|
+
css?: Record<string, string[]>;
|
|
115
|
+
/** Files kept in the bundle (`clientFiles: 'bundle'`). */
|
|
116
|
+
files?: Record<string, string>;
|
|
117
|
+
/** Files the build wrote to disk, under `clientDir` (`clientFiles: 'disk'`). */
|
|
118
|
+
disk?: string[];
|
|
119
|
+
};
|
|
110
120
|
}
|
|
111
121
|
interface RenderOptions {
|
|
112
122
|
/** A layout for this render, or `false` for none at all (htmx and other partial responses). */
|
|
@@ -154,6 +164,8 @@ interface ViewsOptions {
|
|
|
154
164
|
stripTypes?: (code: string) => string | Promise<string>;
|
|
155
165
|
/** Where component scripts are served. Default `'/_kick/c'`. */
|
|
156
166
|
clientScriptPath?: string;
|
|
167
|
+
/** A `file:` URL of the folder holding the bundle's `disk` files; `virtual:kick-views` exports it. */
|
|
168
|
+
clientDir?: string;
|
|
157
169
|
}
|
|
158
170
|
interface Views {
|
|
159
171
|
render(name: string, data?: object, opts?: RenderOptions & {
|
|
@@ -161,6 +173,11 @@ interface Views {
|
|
|
161
173
|
}): Promise<string>;
|
|
162
174
|
/** A component's script by its served file name (`<tag>.<hash>.js`); `undefined` when there's none by that name. */
|
|
163
175
|
clientScript(file: string): Promise<string | undefined>;
|
|
176
|
+
/** A client file (script, stylesheet, asset) by its served name, with its content type. */
|
|
177
|
+
clientFile(file: string): Promise<{
|
|
178
|
+
body: string | Uint8Array;
|
|
179
|
+
type: string;
|
|
180
|
+
} | undefined>;
|
|
164
181
|
/** The path component scripts are served under (`clientScriptPath`). */
|
|
165
182
|
readonly clientScriptPath: string;
|
|
166
183
|
/** Whether `name` is one of these views — `ctx.render` falls through to another engine when not. */
|
|
@@ -170,7 +187,8 @@ declare function bundleLoader(bundle: ViewsBundle): Loader;
|
|
|
170
187
|
type FileLoaderModule = typeof file_d_exports;
|
|
171
188
|
declare function useFileLoader(load: () => Promise<FileLoaderModule>): void;
|
|
172
189
|
declare function useStripTypes(strip: (code: string) => string): void;
|
|
190
|
+
declare function useClientFiles(read: ((url: URL) => Promise<Uint8Array>) | undefined): void;
|
|
173
191
|
declare function createViews(options?: ViewsOptions): Views;
|
|
174
192
|
//#endregion
|
|
175
|
-
export {
|
|
176
|
-
//# sourceMappingURL=views-
|
|
193
|
+
export { sanitizeSrcset as A, RenderError as C, escapeJsonForScript as D, escapeHtml as E, read as O, RenderEnv as S, SafeHtml as T, BUILTIN_PIPES as _, ViewsOptions as a, MAX_DEPTH as b, useClientFiles as c, fileLoader as d, loadPipesFile as f, withEnv as g, safeHtml as h, ViewsBundle as i, sanitizeUrl as j, safeStyleValue as k, useFileLoader as l, pipesFor as m, RenderOptions as n, bundleLoader as o, EnvPipe as p, Views as r, createViews as s, Loader as t, useStripTypes as u, PipeEnv as v, render as w, Pipe as x, builtinPipes as y };
|
|
194
|
+
//# sourceMappingURL=views-CgI6icpT.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"views-
|
|
1
|
+
{"version":3,"file":"views-CgI6icpT.d.ts","names":["_$__loaders_file0"],"sources":["../src/render/safe.ts","../src/render/render.ts","../src/pipes/builtins.ts","../src/pipes/env.ts","../src/loaders/file.ts","../src/views.ts"],"mappings":";;;;;cAUa;WACU;EAArB,YAAqB;EACrB;;;;;;;iBAUc,KAAK,cAAc;cAgBtB,aAAU;;;;;;iBASP,YAAY;;iBASZ,eAAe;;cAoBlB,sBAAmB;;iBAIhB,eAAe;;;KC7DnB,QAAQ,mBAAmB;UAEtB;EACf;EACA;EACA;EACA,OAAO,eAAe;EACtB,KAAK;;EAEL,QAAQ,eAAe;;EAEvB,WAAW;;EAEX;;EAEA,QAAQ,eAAe,MAAM;;EAE7B,cAAc,GAAG;;EAEjB;;cAGW,oBAAoB;WACV,YAAY;EAAjC,YAAqB,YAAY;;;cAQtB;;;;;;;iBA2aG,OACd,UAAU,iBACV,cACA,KAAK,WACL;EAAQ;;;;cC1dG;UAgBI;EACf;EACA;;iBAsDc,aAAa,KAAK,UAAU,eAAe;;;cCzErD;;UAGW;GACd,YAAY,KAAK,YAAY;;;;;;iBAOhB,QAAQ,OAAO,KAAK,YAAY,OAAO;;cAK1C,WAAQ,iBAAmB;;iBAKxB,SAAS,KAAK,eAAe,OAAO,UAAU,KAAK,UAAU,eAAe;;;;iBCnB5E,WAAW,mBAAmB;;iBAsBxB,cAAc,eAAe,QAAQ;;;UCF1C;;EAEf,QAAQ;EACR,KAAK,eAAe;;EAEpB,SAAS,eAAe;;;UAIT;EACf;EACA,WAAW,eAAe;;EAE1B;IACE,SAAS;;IAET,MAAM;;IAEN,QAAQ;;IAER;;;UAIa;;EAEf;EACA;EACA;;UAGe;;EAEf;;EAEA;;EAEA;EACA,QAAQ,eAAe,OAAO;;;;;EAK9B,kBAAkB;;EAElB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,SAAS,0BAA0B;EACnC,SAAS;;EAET,SAAS;;EAET;;;;;EAKA,UAAU,eAAe,MAAM;EAC/B,QAAQ;;EAER,cAAc,0BAA0B;;EAExC;;EAEA;;UAGe;EACf,OAAO,cAAc,eAAe,OAAO;IAAkB;MAAkB;;EAE/E,aAAa,eAAe;;EAE5B,WAAW,eAAe;IAAU,eAAe;IAAY;;;WAEtD;;EAET,IAAI,eAAe;;iBAGL,aAAa,QAAQ,cAAc;KAoB9C,0BAAAA;iBASW,cAAc,YAAY,QAAQ;iBAOlC,cAAc,QAAQ;iBAOtB,eAAe,QAAQ,KAAK,QAAQ,QAAQ;iBAe5C,YAAY,UAAS,eAAoB"}
|
package/package.json
CHANGED
package/virtual.d.ts
CHANGED
|
@@ -13,6 +13,15 @@ declare module 'virtual:kick-views' {
|
|
|
13
13
|
import type { EnvPipe, Pipe, ViewsBundle } from '@forinda/kickjs-view'
|
|
14
14
|
export const bundle: ViewsBundle | null
|
|
15
15
|
export const pipes: Record<string, Pipe | EnvPipe>
|
|
16
|
-
|
|
16
|
+
/** Where component scripts are served: the Vite plugin's `clientScriptPath`. */
|
|
17
|
+
export const clientScriptPath: string
|
|
18
|
+
/** A `file:` URL of the folder `kick build` wrote client files to; `undefined` in dev. */
|
|
19
|
+
export const clientDir: string | undefined
|
|
20
|
+
const views: {
|
|
21
|
+
bundle: ViewsBundle | null
|
|
22
|
+
pipes: Record<string, Pipe | EnvPipe>
|
|
23
|
+
clientScriptPath: string
|
|
24
|
+
clientDir: string | undefined
|
|
25
|
+
}
|
|
17
26
|
export default views
|
|
18
27
|
}
|
package/dist/exports-Dr0XJ2Uv.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @forinda/kickjs-view v0.2.0
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) Felix Orinda
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
* @license MIT
|
|
10
|
-
*/
|
|
11
|
-
import{D as emptyFormState,E as FORM_GLOBALS,O as rememberPage,S as error,_ as templateName,a as escapeHtml,b as decodeEntities,c as safeStyleValue,d as parse,g as layoutResolver,h as componentTag,i as SafeHtml,k as takeFormState,l as sanitizeSrcset,m as check,n as BUILTIN_PIPES,o as escapeJsonForScript,r as builtinPipes,s as read,u as sanitizeUrl,x as VALIDATORS}from"./read-exports-DhS-hmBe.js";function fnv1a(s){let h=2166136261;for(let i=0;i<s.length;i++)h^=s.charCodeAt(i),h=Math.imul(h,16777619);return(h>>>0).toString(16).padStart(8,`0`)}const CLIENT_SCRIPT_FILE=/^([a-z][a-z0-9-]*)\.([0-9a-f]{8})\.js$/;function injectScripts(html,tags){let at=-1;for(let m of html.matchAll(/<\/body\s*>/gi))at=m.index;return at<0?html+tags:html.slice(0,at)+tags+html.slice(at)}const NO_STRIPPER=`client scripts need Node 22.13+ to strip TypeScript, or a kick build`;function runtime(messages,doc){let say=(name,args)=>messages[name].replace(/\{(\d+)\}/g,(_m,i)=>String(args[Number(i)])),valueOf=el=>{if(el.type!==`checkbox`&&el.type!==`radio`)return String(el.value??``);for(let other of(el.form||doc).querySelectorAll(`input`))if((other.type===`checkbox`||other.type===`radio`)&&other.name===el.name&&other.checked)return String(other.value||`on`);return``};function message(el){let rules;try{rules=JSON.parse(el.getAttribute(`data-kick-validate`)||`[]`)}catch{return``}let value=valueOf(el);for(let[name,...args]of rules){if(name===`required`){if(value.trim()===``)return say(name,args);continue}if(value===``)continue;let n=Number(value),ok=!0;if(name===`email`)ok=/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);else if(name===`url`)try{ok=/^https?:$/.test(new URL(value).protocol)}catch{ok=!1}else if(name===`minLength`)ok=value.length>=Number(args[0]);else if(name===`maxLength`)ok=value.length<=Number(args[0]);else if(name===`min`)ok=!Number.isNaN(n)&&n>=Number(args[0]);else if(name===`max`)ok=!Number.isNaN(n)&&n<=Number(args[0]);else if(name===`pattern`)try{ok=RegExp(`^(?:${args[0]})$`).test(value)}catch{ok=!0}else name===`in`&&(ok=String(args[0]).split(`,`).map(s=>s.trim()).includes(value));if(!ok)return say(name,args)}return``}let spotFor=el=>{let name=el.getAttribute(`name`);if(!name)return null;let root=el.form||doc;for(let s of root.querySelectorAll(`[data-kick-error]`))if(s.getAttribute(`data-kick-error`)===name)return s;return null},ids=0;function run(el){let msg=message(el);el.setCustomValidity?.(msg),el.setAttribute(`data-kick-checked`,``);let spot=spotFor(el);if(spot){spot.textContent=msg,spot.hidden=msg===``,spot.id||=`kick-error-${++ids}`;let described=(el.getAttribute(`aria-describedby`)||``).split(/\s+/).filter(Boolean);described.includes(spot.id)||el.setAttribute(`aria-describedby`,[...described,spot.id].join(` `))}return msg?el.setAttribute(`aria-invalid`,`true`):el.removeAttribute(`aria-invalid`),msg===``}let field=t=>t&&t.matches&&t.matches(`[data-kick-validate]`)?t:null,quiet=()=>{for(let el of doc.querySelectorAll(`[data-kick-validate]`))el.form&&(el.form.noValidate=!0)};quiet();let Observer=globalThis.MutationObserver;Observer&&new Observer(quiet).observe(doc.documentElement,{childList:!0,subtree:!0}),doc.addEventListener(`focusin`,e=>{let el=field(e.target);el?.form&&(el.form.noValidate=!0)}),doc.addEventListener(`focusout`,e=>{let el=field(e.target);el&&run(el)}),doc.addEventListener(`input`,e=>{let el=field(e.target);el?.hasAttribute(`data-kick-checked`)&&run(el)}),doc.addEventListener(`submit`,e=>{if(e.submitter?.formNoValidate)return;let form=e.target,fields=form.querySelectorAll(`[data-kick-validate]`);if(!fields.length)return;form.noValidate=!0;let first=null;for(let el of fields)!run(el)&&!first&&(first=el);first?(e.preventDefault(),first.focus()):form.reportValidity&&!form.reportValidity()&&e.preventDefault()},!0)}const MESSAGES=Object.fromEntries(Object.entries(VALIDATORS).map(([k,v])=>[k,v.message])),VALIDATE_RUNTIME=`(${runtime.toString()})(${JSON.stringify(MESSAGES)}, document);\n`,ENV_PIPE=Symbol.for(`kickjs.view.envPipe`);function withEnv(make){return{[ENV_PIPE]:make}}const safeHtml=html=>new SafeHtml(html),isEnvPipe=p=>typeof p==`object`&&!!p&&ENV_PIPE in p;function pipesFor(app,env){let out=builtinPipes(env);for(let[name,p]of Object.entries(app))isEnvPipe(p)?out[name]=p[ENV_PIPE](env):typeof p==`function`&&(out[name]=p);return out}var RenderError=class extends Error{diagnostic;constructor(diagnostic){let{file,span,message}=diagnostic;super(`${file}:${span.start.line}:${span.start.column} — ${message}`),this.diagnostic=diagnostic,this.name=`RenderError`}};const MAX_DEPTH=64,warnedNames=/* @__PURE__ */ new WeakMap;var Renderer=class{env;out=[];constructor(env){this.env=env}rootData=Object.create(null);html(){return this.out.join(``)}fail(inst,message){let[line,column]=inst.at??[1,1],pos={offset:0,line,column},d=error(inst.t.file,{start:pos,end:pos},message);throw d.stack=inst.stack,new RenderError(d)}path(value,p,inst){for(let seg of p){if(value==null)return;value=read(value,`n`in seg?seg.n:this.value(seg.e,inst))}return value}value(e,inst){switch(e.k){case`l`:return e.v;case`x`:return;case`d`:{let data=FORM_GLOBALS.has(e.n)&&!(e.n in inst.data)?this.rootData:inst.data;if(!(e.n in data)){if(FORM_GLOBALS.has(e.n))return this.path({},e.p,inst);this.unresolved(e.n,inst)}return this.path(read(data,e.n),e.p,inst)}case`v`:return this.path(inst.slots[e.s],e.p,inst);case`m`:return loopVar(inst.slots[e.s],e.w);case`u`:{let a=this.value(e.a,inst);return e.o===`!`?!a:-a}case`b`:{if(e.o===`&&`)return this.value(e.l,inst)&&this.value(e.r,inst);if(e.o===`||`)return this.value(e.l,inst)||this.value(e.r,inst);if(e.o===`??`)return this.value(e.l,inst)??this.value(e.r,inst);let l=this.value(e.l,inst),r=this.value(e.r,inst);switch(e.o){case`==`:case`===`:return l===r;case`!=`:case`!==`:return l!==r;case`<`:return l<r;case`>`:return l>r;case`<=`:return l<=r;case`>=`:return l>=r;case`+`:return l+r;case`-`:return l-r}return}case`c`:return this.value(e.t,inst)?this.value(e.y,inst):this.value(e.n,inst);case`p`:{let pipe=this.env.pipes[e.n];pipe||this.fail(inst,`unknown pipe '${e.n}'`);let input=this.value(e.i,inst),args=e.a.map(a=>this.value(a,inst)),result;try{result=pipe(input,...args)}catch(err){if(err instanceof RenderError)throw err;this.fail(inst,`pipe '${e.n}' failed: ${err instanceof Error?err.message:String(err)}`)}return result&&typeof result.then==`function`&&this.fail(inst,`pipe '${e.n}' returned a Promise — pipes must be synchronous`),result}}}unresolved(name,inst){this.env.strict&&this.fail(inst,`'${name}' isn't in the data`);let seen=warnedNames.get(inst.t);seen||warnedNames.set(inst.t,seen=/* @__PURE__ */ new Set),!seen.has(name)&&(seen.add(name),this.env.warn(`${inst.t.file}: '${name}' isn't in the data passed to render`))}text(v,inst){if(v==null)return``;switch(typeof v){case`string`:return v;case`number`:case`bigint`:case`boolean`:return String(v)}if(v instanceof Date)return Number.isNaN(v.getTime())?``:v.toISOString();if(v instanceof SafeHtml)return v.html;let what=v&&typeof v.then==`function`?`a Promise — await it in the controller`:Array.isArray(v)?`an array — loop over it with @for, or use | json`:`an object — print one of its properties, or use | json`;return this.env.strict&&this.fail(inst,`can't print ${what}`),this.env.warn(`${inst.t.file}:${inst.at?.[0]??1}: can't print ${what}`),``}nodes(list,inst){for(let n of list)this.node(n,inst)}node(n,inst){switch(n.k){case`s`:this.out.push(n.t);return;case`i`:{inst.at=n.at;let v=this.value(n.e,inst);n.c===`json`?this.out.push(escapeJsonForScript(typeof v==`string`?v:JSON.stringify(v)??`null`)):v instanceof SafeHtml&&n.c===`text`?this.out.push(v.html):this.out.push(escapeHtml(v instanceof SafeHtml?v.html:this.text(v,inst)));return}case`A`:inst.at=n.at,this.attrs(this.resolve(n.a,inst),n.f?inst.fall:void 0);return;case`if`:for(let br of n.br){let v=!br.c||this.value(br.c,inst);if(v){br.a!==void 0&&(inst.slots[br.a]=v),this.nodes(br.b,inst);return}}return;case`for`:{inst.at=n.at;let items=this.iterable(this.value(n.e,inst),inst);if(!items.length){n.em&&this.nodes(n.em,inst);return}let meta={i:0,n:items.length};inst.slots[n.m]=meta;for(let i=0;i<items.length;i++){meta.i=i;let item=items[i];typeof n.it==`number`?inst.slots[n.it]=item:(inst.slots[n.it[0]]=item?.[0],inst.slots[n.it[1]]=item?.[1]),this.nodes(n.b,inst)}return}case`sw`:{let v=this.value(n.e,inst),hit=n.cs.find(c=>this.value(c.e,inst)===v);hit?this.nodes(hit.b,inst):n.d&&this.nodes(n.d,inst);return}case`let`:inst.slots[n.s]=this.value(n.e,inst);return;case`cmp`:inst.at=n.at,this.component(n,inst);return;case`o`:{let fill=inst.fills[n.n];fill?this.nodes(fill.nodes,fill.inst):this.nodes(n.fb,inst);return}case`as`:this.env.assets?this.out.push(this.env.assets(n.en,inst.data)):this.env.warn(`${inst.t.file}: @assets('${n.en}') needs the Vite plugin or an assets option`)}}iterable(v,inst){if(v==null)return[];if(Array.isArray(v))return v;if(typeof v==`string`)return[...v];if(v instanceof Map)return[...v.entries()];if(v instanceof Set)return[...v];this.fail(inst,`@for can't loop over ${typeof v==`object`?`an object — use | entries`:`a ${typeof v}`}`)}attrValue(v,inst){return escapeHtml(this.plain(v,inst))}plain(v,inst){return v instanceof SafeHtml?v.html:this.text(v,inst)}resolve(list,inst){let r={attrs:[],cls:[],style:[]},put=(name,value)=>{let lower=name.toLowerCase();lower===`class`?value!==!0&&value.trim()&&r.cls.push(value.trim()):lower===`style`?value!==!0&&value.trim()&&r.style.push(value.trim().replace(/;\s*$/,``)):r.attrs.push([name,value])};for(let a of list)switch(a.t){case`s`:put(a.n,a.v===!0||a.v.replace(/"/g,`"`));break;case`i`:{let values=a.p.map(p=>typeof p==`string`?void 0:this.value(p,inst)),html=a.p.map((p,i)=>typeof p==`string`?p.replace(/"/g,`"`):this.attrValue(values[i],inst)).join(``);if(!a.u){put(a.n,html);break}let plain=decodeEntities(html),safe=a.u===`url`?sanitizeUrl(plain):sanitizeSrcset(plain);put(a.n,safe===plain?html:escapeHtml(safe));break}case`b`:{let v=this.value(a.e,inst);if(v==null||v===!1)break;if(v===!0){put(a.n,!0);break}let plain=this.plain(v,inst);put(a.n,escapeHtml(a.u===`url`?sanitizeUrl(plain):a.u===`srcset`?sanitizeSrcset(plain):plain));break}case`c`:this.value(a.e,inst)&&r.cls.push(escapeHtml(a.n));break;case`y`:{let v=this.value(a.e,inst);if(v==null||v===!1)break;let value=safeStyleValue(`${this.text(v,inst)}${a.x??``}`);if(value===void 0){this.env.warn(`${inst.t.file}:${inst.at?.[0]??1}: dropped an unsafe value for [style.${a.n}]`);break}r.style.push(`${escapeHtml(a.n)}:${escapeHtml(value)}`);break}}return r}attrs(own,fall){let attrs=own.attrs,cls=own.cls,style=own.style;if(fall){let names=new Set(fall.attrs.map(([n])=>n.toLowerCase()));attrs=[...attrs.filter(([n])=>!names.has(n.toLowerCase())),...fall.attrs],cls=[...cls,...fall.cls],style=[...style,...fall.style]}for(let[n,v]of attrs)this.out.push(v===!0?` ${n}`:` ${n}="${v}"`);cls.length&&this.out.push(` class="${cls.join(` `)}"`),style.length&&this.out.push(` style="${style.join(`;`)}"`)}component(n,caller){caller.depth>=64&&this.fail(caller,`components nest more than 64 deep — is ${n.n} including itself?`);let t=this.env.resolve(n.n);t.client&&this.env.clientScript?.(t),t.validates&&this.env.validation?.();let slots=Array.from({length:t.slots});for(let i of t.inputs)i.d!==void 0&&(slots[i.s]=i.d);for(let i of n.in)slots[i.s]=this.value(i.e,caller);let fills={};for(let[name,nodes]of Object.entries(n.f))fills[name]={nodes,inst:caller};let inst={t,data:Object.create(null),slots,fills,fall:this.resolve(n.fa,caller),stack:[...caller.stack,n.n],depth:caller.depth+1};this.nodes(t.body,inst)}};function loopVar(m,w){switch(w){case`$index`:return m.i;case`$first`:return m.i===0;case`$last`:return m.i===m.n-1;case`$even`:return m.i%2==0;case`$odd`:return m.i%2==1;case`$count`:return m.n}}function render(template,data,env,opts={}){let r=new Renderer(env);r.rootData=data;let page={t:template,data,slots:Array.from({length:template.slots}),fills:{},stack:[template.name],depth:0},none=opts.layout===!1||opts.layout===void 0&&template.layout===null,chain=[];if(!none){let next=typeof opts.layout==`string`?opts.layout:template.layout??env.layoutFor?.(template.name);for(;next&&next!==template.name&&!chain.some(t=>t.name===next);){let t=env.resolve(next);chain.push(t),next=t.layout??void 0}let base=env.baseLayout;base&&base!==template.name&&!chain.some(t=>t.name===base)&&chain.push(env.resolve(base))}if((template.validates||chain.some(t=>t.validates))&&env.validation?.(),!chain.length)return r.nodes(template.body,page),r.html();let fills={"":{nodes:template.body,inst:page}};for(let[name,nodes]of Object.entries(template.fills))fills[name]={nodes,inst:page};let inst=page;for(let[i,t]of chain.entries()){if(inst={t,data:page.data,slots:Array.from({length:t.slots}),fills,stack:[...inst.stack,t.name],depth:0},i===chain.length-1)break;let outer={...fills,"":{nodes:t.body,inst}};for(let[name,nodes]of Object.entries(t.fills))outer[name]={nodes,inst};fills=outer}return r.nodes(inst.t.body,inst),r.html()}const VALIDATE_TAG=`kick-validate`,VALIDATE_HASH=fnv1a(VALIDATE_RUNTIME);function bundleLoader(bundle){if(bundle.v!==1)throw Error(`views bundle format v${bundle.v}, this runtime reads v1`);return{list:async()=>Object.keys(bundle.templates),read:async()=>{throw Error(`a bundled template has no source`)}}}let fileLoaderModule;function useFileLoader(load){fileLoaderModule=load}let typeStripper;function useStripTypes(strip){typeStripper=strip}function fileLoaders(){return fileLoaderModule?fileLoaderModule():Promise.reject(/* @__PURE__ */ Error(`createViews has no templates: pass the build's bundle (import kickViews from 'virtual:kick-views') or a loader`))}function createViews(options={}){let bundle=options.bundle??void 0,dev=options.dev??options.bundle===null;bundle&&bundleLoader(bundle);let componentsDir=options.componentsDir??`components`,scriptPath=(options.clientScriptPath??`/_kick/c`).replace(/\/+$/,``),stripTypes=options.stripTypes??(code=>{if(!typeStripper)throw Error(`client scripts need Node 22.13+ to strip TypeScript, or a kick build`);return typeStripper(code)}),scripts=/* @__PURE__ */ new Map,scriptFor=t=>{let client=t.client,hit=scripts.get(t.name);if(hit?.code===client.code)return hit.js;let js=Promise.resolve(client.js?client.code:stripTypes(client.code)).then(code=>({js:code,hash:fnv1a(code)}));return js.catch(()=>scripts.get(t.name)?.js===js&&scripts.delete(t.name)),scripts.set(t.name,{code:client.code,js}),js},layoutFor=layoutResolver(options.layout),warn=options.warn??(m=>console.warn(`[kick/view] ${m}`)),loader,appPipes,state,settle=(p,forget)=>p.catch(err=>{throw forget(),err}),getLoader=()=>loader??=settle(options.loader?Promise.resolve(options.loader):fileLoaders().then(m=>m.fileLoader(options.viewsDir??`src/views`)),()=>loader=void 0),getPipes=()=>appPipes??=settle(options.pipes||bundle?Promise.resolve(options.pipes??{}):fileLoaders().then(m=>m.loadPipesFile(options.pipesFile??`src/views/pipes.ts`)).then(mod=>mod??{}),()=>appPipes=void 0),reload=()=>state=settle(load(),()=>state=void 0);async function load(){let l=await getLoader(),pipes=await getPipes(),names=await l.list(),templates=/* @__PURE__ */ new Map,versions=/* @__PURE__ */ new Map,parseErrors=/* @__PURE__ */ new Map;return await Promise.all(names.map(async name=>{let r=parse(await l.read(name),`${name}.kick`);templates.set(name,r.ast);let first=r.diagnostics.find(d=>d.severity===`error`);first&&parseErrors.set(name,first),dev&&l.version&&versions.set(name,await l.version(name))})),{project:{templates,pipes:/* @__PURE__ */ new Set([...BUILTIN_PIPES,...Object.keys(pipes)]),componentsDir,layouts:options.layout,baseLayout:options.baseLayout},versions,parseErrors,checked:/* @__PURE__ */ new Map}}async function current(){if(options.cache===!1)return reload();let s=await(state??reload());if(!dev)return s;let l=await getLoader();if(!l.version)return s;let names=await l.list();return names.length!==s.project.templates.size||(await Promise.all(names.map(async n=>await l.version(n)!==s.versions.get(n)))).some(Boolean)?reload():s}function checked(s,name){let t=s.checked.get(name);if(t)return t;let syntax=s.parseErrors.get(name);if(syntax)throw new RenderError(syntax);let r=check(name,s.project);if(!r.template)throw new RenderError(r.diagnostics.find(x=>x.severity===`error`));for(let w of r.diagnostics)warn(`${w.file}:${w.span.start.line}:${w.span.start.column} — ${w.message}`);return t=r.template,s.checked.set(name,t),t}async function has(name){return templateName(name)?bundle?Object.hasOwn(bundle.templates,name):(await current()).project.templates.has(name):!1}return{has,async render(name,data={},opts={}){if(!templateName(name))throw Error(`invalid template name '${name}'`);if(!await has(name))throw Error(`template '${name}' not found`);let resolve=bundle?n=>{let t=Object.hasOwn(bundle.templates,n)?bundle.templates[n]:void 0;if(!t)throw new RenderError(error(`${n}.kick`,zeroSpan,`template '${n}' not found`));return t}:await current().then(s=>n=>checked(s,n)),template=resolve(name);rememberPage(opts.ctx,opts.layout);let shared=options.share?await options.share(opts.ctx):{},locale=opts.locale??options.locale??`en-US`,timeZone=opts.timeZone??options.timeZone??`UTC`,used=/* @__PURE__ */ new Map,validation=!1,page={...emptyFormState(),...shared,...takeFormState(opts.ctx),...data},html=render(template,page,{locale,timeZone,strict:options.strict??!1,pipes:pipesFor(await getPipes(),{locale,timeZone}),warn,resolve,layoutFor,baseLayout:options.baseLayout,assets:options.assets,clientScript:t=>used.set(t.name,t),validation:()=>validation=!0},{layout:opts.layout});if(!used.size&&!validation)return html;let nonce=page.cspNonce,nonceAttr=typeof nonce==`string`?` nonce="${nonce.replace(/"/g,`"`)}"`:``,tags=await Promise.all([...used.values()].map(async t=>{let{hash}=await scriptFor(t),file=`${componentTag(t.name,componentsDir)}.${hash}.js`;return`<script type="module" src="${scriptPath}/${file}"${nonceAttr}><\/script>`}));return validation&&tags.push(`<script type="module" src="${scriptPath}/${VALIDATE_TAG}.${VALIDATE_HASH}.js"${nonceAttr}><\/script>`),injectScripts(html,tags.join(``))},clientScriptPath:scriptPath,async clientScript(file){let m=CLIENT_SCRIPT_FILE.exec(file);if(!m)return;if(m[1]===VALIDATE_TAG)return m[2]===VALIDATE_HASH?VALIDATE_RUNTIME:void 0;let name=(bundle?Object.keys(bundle.templates):[...(await current()).project.templates.keys()]).find(n=>n.startsWith(`${componentsDir}/`)&&componentTag(n,componentsDir)===m[1]);if(!name)return;let t=bundle?bundle.templates[name]:checked(await current(),name);if(!t.client)return;let{js,hash}=await scriptFor(t);return hash===m[2]?js:void 0}}}const zeroSpan={start:{offset:0,line:1,column:1},end:{offset:0,line:1,column:1}},CLIENT_SCRIPT_HEADERS={"content-type":`text/javascript; charset=utf-8`,"cache-control":`public, max-age=31536000, immutable`};function clientScriptFile(views,method,url){let m=String(method??`GET`).toUpperCase();if(m!==`GET`&&m!==`HEAD`)return;let path=url.split(`?`)[0],prefix=`${views.clientScriptPath}/`;if(!path.startsWith(prefix))return;let file=path.slice(prefix.length);return CLIENT_SCRIPT_FILE.test(file)?file:void 0}async function clientScriptResponse(views,request){let file=clientScriptFile(views,request.method,new URL(request.url).pathname);if(!file)return;let js=await views.clientScript(file);if(js!==void 0)return new Response(request.method===`HEAD`?null:js,{status:200,headers:CLIENT_SCRIPT_HEADERS})}const VIEW_RENDERER=Symbol.for(`kickjs.viewRenderer`);function rendererFor(views){return async(name,data,opts,ctx)=>await views.has(name)?views.render(name,data,{layout:opts.layout,locale:opts.locale,timeZone:opts.timeZone,ctx}):void 0}function bindViews(views){let renderer=rendererFor(views);return(req,res,next)=>{let r=req,file=clientScriptFile(views,r.method,r.url??`/`);if(!file)return r[VIEW_RENDERER]=renderer,next();views.clientScript(file).then(js=>{if(js===void 0)return r[VIEW_RENDERER]=renderer,next();let out=res;out.statusCode=200;for(let[k,v]of Object.entries(CLIENT_SCRIPT_HEADERS))out.setHeader(k,v);out.end(String(r.method).toUpperCase()===`HEAD`?void 0:js)},err=>next(err))}}function viewsMiddleware(views){let renderer=rendererFor(views);return(ctx,next)=>(ctx.req[VIEW_RENDERER]=renderer,next())}function kickViewDev(options,nodeEnv){return options.dev??(nodeEnv===`development`||options.bundle===null)}function KickView(options={}){let views=options.views??createViews({...options,dev:kickViewDev(options,globalThis.process?.env?.NODE_ENV)}),handler=bindViews(views);return{name:`KickView`,views,middleware:()=>[{handler,phase:`beforeGlobal`}]}}function assetTags(entry,mode,nonce){let base=mode.base.endsWith(`/`)?mode.base:`${mode.base}/`,n=nonce?` nonce="${escapeHtml(nonce)}"`:``,url=file=>escapeHtml(`${base}${file.replace(/^\//,``)}`);if(mode.dev)return[`<script type="module"${n} src="${url(`@vite/client`)}"><\/script>`,`<script type="module"${n} src="${url(entry)}"><\/script>`].join(`
|
|
12
|
-
`);let chunk=mode.manifest[entry];if(!chunk)throw Error(`@assets: '${entry}' isn't an entry in the Vite manifest`);let css=new Set(chunk.css??[]),preload=/* @__PURE__ */ new Set,walk=key=>{let c=mode.manifest[key];if(c&&!preload.has(c.file)){preload.add(c.file);for(let s of c.css??[])css.add(s);for(let i of c.imports??[])walk(i)}};for(let i of chunk.imports??[])walk(i);return[...[...css].map(f=>`<link rel="stylesheet"${n} href="${url(f)}">`),...[...preload].map(f=>`<link rel="modulepreload"${n} href="${url(f)}">`),`<script type="module"${n} src="${url(chunk.file)}"><\/script>`].join(`
|
|
13
|
-
`)}export{bundleLoader as a,useStripTypes as c,render as d,pipesFor as f,NO_STRIPPER as h,clientScriptResponse as i,MAX_DEPTH as l,withEnv as m,KickView as n,createViews as o,safeHtml as p,viewsMiddleware as r,useFileLoader as s,assetTags as t,RenderError as u};
|
|
14
|
-
//# sourceMappingURL=exports-Dr0XJ2Uv.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exports-Dr0XJ2Uv.js","names":[],"sources":["../src/client-scripts.ts","../src/validate-runtime.ts","../src/pipes/env.ts","../src/render/render.ts","../src/views.ts","../src/serve.ts","../src/adapter.ts","../src/assets.ts"],"sourcesContent":["/**\n * Client scripts: a component's `<script client>`, served as a module of its\n * own. A build ships them as plain JS; otherwise the Node entry's stripper\n * (`./strip-types`) strips their types the first time a page needs one.\n */\n\n/** FNV-1a, 32-bit, as 8 hex characters: names a script by its content. */\nexport function fnv1a(s: string): string {\n let h = 0x811c9dc5\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i)\n h = Math.imul(h, 0x01000193)\n }\n return (h >>> 0).toString(16).padStart(8, '0')\n}\n\n/** `<tag>.<hash>.js` */\nexport const CLIENT_SCRIPT_FILE = /^([a-z][a-z0-9-]*)\\.([0-9a-f]{8})\\.js$/\n\n/** Insert `tags` before the last `</body>`, or at the end when there's none. */\nexport function injectScripts(html: string, tags: string): string {\n // A case-insensitive search of the text itself: lowercasing can change its\n // length (`İ` becomes two units) and move the offset.\n let at = -1\n for (const m of html.matchAll(/<\\/body\\s*>/gi)) at = m.index\n return at < 0 ? html + tags : html.slice(0, at) + tags + html.slice(at)\n}\n\nexport const NO_STRIPPER = 'client scripts need Node 22.13+ to strip TypeScript, or a kick build'\n","/**\n * The validator script: checks `[data-kick-validate]` fields in the browser\n * and writes each message into the field's `[data-kick-error]` spot — the\n * same spot `@error` renders the server's message into. Served as plain JS\n * (`kick-validate.<hash>.js`): the function below is compiled with the\n * package and sent as its source, called with the message table as data.\n * No `eval`: rules are JSON, and a `pattern` is a regular expression's source.\n */\nimport { VALIDATORS } from './validators'\n\ntype Rule = [string, ...Array<string | number>]\n// Typed loosely: the package compiles without the DOM library.\ntype El = any\n\nfunction runtime(messages: Record<string, string>, doc: any): void {\n const say = (name: string, args: Array<string | number>) =>\n messages[name]!.replace(/\\{(\\d+)\\}/g, (_m: string, i: string) => String(args[Number(i)]))\n\n /** A field's value; for a radio or checkbox, its group's: any checked one with the same name. */\n const valueOf = (el: El): string => {\n if (el.type !== 'checkbox' && el.type !== 'radio') return String(el.value ?? '')\n for (const other of (el.form || doc).querySelectorAll('input'))\n if (\n (other.type === 'checkbox' || other.type === 'radio') &&\n other.name === el.name &&\n other.checked\n )\n return String(other.value || 'on')\n return ''\n }\n\n /** The first failing rule's message, or ''. */\n function message(el: El): string {\n let rules: Rule[]\n try {\n rules = JSON.parse(el.getAttribute('data-kick-validate') || '[]')\n } catch {\n return ''\n }\n const value = valueOf(el)\n for (const [name, ...args] of rules) {\n if (name === 'required') {\n if (value.trim() === '') return say(name, args)\n continue\n }\n // Optional and empty: nothing else applies.\n if (value === '') continue\n const n = Number(value)\n let ok = true\n if (name === 'email') ok = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n else if (name === 'url') {\n try {\n ok = /^https?:$/.test(new URL(value).protocol)\n } catch {\n ok = false\n }\n // UTF-16 units, as server schemas count: never refuse what the server accepts.\n } else if (name === 'minLength') ok = value.length >= Number(args[0])\n else if (name === 'maxLength') ok = value.length <= Number(args[0])\n else if (name === 'min') ok = !Number.isNaN(n) && n >= Number(args[0])\n else if (name === 'max') ok = !Number.isNaN(n) && n <= Number(args[0])\n else if (name === 'pattern') {\n try {\n ok = new RegExp(`^(?:${args[0]})$`).test(value)\n } catch {\n ok = true\n }\n } else if (name === 'in')\n ok = String(args[0])\n .split(',')\n .map((s) => s.trim())\n .includes(value)\n if (!ok) return say(name, args)\n }\n return ''\n }\n\n const spotFor = (el: El): El => {\n const name = el.getAttribute('name')\n if (!name) return null\n const root = el.form || doc\n for (const s of root.querySelectorAll('[data-kick-error]'))\n if (s.getAttribute('data-kick-error') === name) return s\n return null\n }\n\n let ids = 0\n\n /** Check `el`, show or clear its message; true when it passes. */\n function run(el: El): boolean {\n const msg = message(el)\n el.setCustomValidity?.(msg)\n el.setAttribute('data-kick-checked', '')\n const spot = spotFor(el)\n if (spot) {\n spot.textContent = msg\n spot.hidden = msg === ''\n // Screen readers read the message with the field.\n if (!spot.id) spot.id = `kick-error-${++ids}`\n const described = (el.getAttribute('aria-describedby') || '').split(/\\s+/).filter(Boolean)\n if (!described.includes(spot.id))\n el.setAttribute('aria-describedby', [...described, spot.id].join(' '))\n }\n if (msg) el.setAttribute('aria-invalid', 'true')\n else el.removeAttribute('aria-invalid')\n return msg === ''\n }\n\n const field = (t: El): El => (t && t.matches && t.matches('[data-kick-validate]') ? t : null)\n\n // The browser's own bubbles would stop a submit before ours runs.\n const quiet = () => {\n for (const el of doc.querySelectorAll('[data-kick-validate]'))\n if (el.form) el.form.noValidate = true\n }\n quiet()\n // Forms swapped in later (htmx, Turbo) get the same treatment before a submit.\n const Observer = (globalThis as any).MutationObserver\n if (Observer) new Observer(quiet).observe(doc.documentElement, { childList: true, subtree: true })\n doc.addEventListener('focusin', (e: El) => {\n const el = field(e.target)\n if (el?.form) el.form.noValidate = true\n })\n doc.addEventListener('focusout', (e: El) => {\n const el = field(e.target)\n if (el) run(el)\n })\n doc.addEventListener('input', (e: El) => {\n const el = field(e.target)\n // Once a field has been checked, it re-checks as it changes.\n if (el?.hasAttribute('data-kick-checked')) run(el)\n })\n doc.addEventListener(\n 'submit',\n (e: El) => {\n // A `formnovalidate` button (\"Save draft\") submits without checks.\n if (e.submitter?.formNoValidate) return\n const form = e.target\n const fields = form.querySelectorAll('[data-kick-validate]')\n // Forms without validate fields are the browser's to check.\n if (!fields.length) return\n form.noValidate = true\n let first: El = null\n for (const el of fields) if (!run(el) && !first) first = el\n if (first) {\n e.preventDefault()\n first.focus()\n return\n }\n // The browser's own checks (a plain `required`, `type=email`) still apply.\n if (form.reportValidity && !form.reportValidity()) e.preventDefault()\n },\n true,\n )\n}\n\nconst MESSAGES = Object.fromEntries(Object.entries(VALIDATORS).map(([k, v]) => [k, v.message]))\n\n/** The script's source: the compiled function, called with the messages as JSON. */\nexport const VALIDATE_RUNTIME = `(${runtime.toString()})(${JSON.stringify(MESSAGES)}, document);\\n`\n","import type { Pipe } from '../render/render'\nimport { SafeHtml } from '../render/safe'\nimport { builtinPipes, type PipeEnv } from './builtins'\n\nexport { BUILTIN_PIPES, builtinPipes, type PipeEnv } from './builtins'\n\nconst ENV_PIPE = Symbol.for('kickjs.view.envPipe')\n\n/** A pipe built per render from the render's locale and time zone. */\nexport interface EnvPipe {\n [ENV_PIPE]: (env: PipeEnv) => Pipe\n}\n\n/**\n * A pipe that needs the render's locale or time zone:\n * `export const ago = withEnv(({ locale }) => (date: Date) => …)`.\n */\nexport function withEnv(make: (env: PipeEnv) => Pipe): EnvPipe {\n return { [ENV_PIPE]: make }\n}\n\n/** Mark HTML as trusted: a pipe returning it prints unescaped, in text only. */\nexport const safeHtml = (html: string): SafeHtml => new SafeHtml(html)\n\nconst isEnvPipe = (p: unknown): p is EnvPipe => typeof p === 'object' && p !== null && ENV_PIPE in p\n\n/** The pipes for one render: the built-ins and the app's, with env pipes built for `env`. */\nexport function pipesFor(app: Record<string, Pipe | EnvPipe>, env: PipeEnv): Record<string, Pipe> {\n const out = builtinPipes(env)\n for (const [name, p] of Object.entries(app)) {\n if (isEnvPipe(p)) out[name] = p[ENV_PIPE](env)\n else if (typeof p === 'function') out[name] = p\n }\n return out\n}\n","/**\n * The renderer: walks a checked template over the data and writes HTML.\n * Synchronous, no `eval` — every value goes through `read` and the escaper\n * for where it lands.\n */\nimport { FORM_GLOBALS } from '../form-state'\nimport type { At, CAttr, CExpr, CNode, CheckedTemplate, CSeg, LoopVar } from '../ast'\nimport { error, type Diagnostic } from '../diagnostics'\nimport {\n SafeHtml,\n escapeHtml,\n escapeJsonForScript,\n read,\n safeStyleValue,\n sanitizeSrcset,\n sanitizeUrl,\n} from './safe'\nimport { decodeEntities } from '../entities'\n\nexport type Pipe = (value: unknown, ...args: unknown[]) => unknown\n\nexport interface RenderEnv {\n locale: string\n timeZone: string\n strict: boolean\n pipes: Record<string, Pipe>\n warn(message: string): void\n /** A checked template by name: layouts and components. */\n resolve(name: string): CheckedTemplate\n /** The layout a page gets when it declares none (a folder mapping, usually). */\n layoutFor?(page: string): string | undefined\n /** The shell wrapped around every page's outermost layout. */\n baseLayout?: string\n /** `@assets('entry')`: the tags for a Vite entry; `data` is the page's (for a CSP nonce). */\n assets?(entry: string, data: Record<string, unknown>): string\n /** A component with a `<script client>` rendered: the page ships its script. */\n clientScript?(t: CheckedTemplate): void\n /** A template with a `validate` field rendered: the page ships the validator script. */\n validation?(): void\n}\n\nexport class RenderError extends Error {\n constructor(readonly diagnostic: Diagnostic) {\n const { file, span, message } = diagnostic\n super(`${file}:${span.start.line}:${span.start.column} — ${message}`)\n this.name = 'RenderError'\n }\n}\n\n/** The most components one render may nest — a self-including component stops here. */\nexport const MAX_DEPTH = 64\n\ninterface LoopMeta {\n i: number\n n: number\n}\n\ninterface Resolved {\n attrs: Array<[string, string | true]>\n cls: string[]\n style: string[]\n}\n\n/** One template being rendered: its scope slots, data, slot fills and the template stack. */\ninterface Inst {\n t: CheckedTemplate\n data: Record<string, unknown>\n slots: unknown[]\n fills: Record<string, { nodes: CNode[]; inst: Inst }>\n fall?: Resolved\n stack: string[]\n depth: number\n /** The node being rendered, for error positions. */\n at?: At\n}\n\nconst warnedNames = new WeakMap<CheckedTemplate, Set<string>>()\n\nclass Renderer {\n private readonly out: string[] = []\n\n constructor(private readonly env: RenderEnv) {}\n\n /** The page's data, for the request-wide names. */\n rootData: Record<string, unknown> = Object.create(null)\n\n html(): string {\n return this.out.join('')\n }\n\n fail(inst: Inst, message: string): never {\n const [line, column] = inst.at ?? [1, 1]\n const pos = { offset: 0, line, column }\n const d = error(inst.t.file, { start: pos, end: pos }, message)\n d.stack = inst.stack\n throw new RenderError(d)\n }\n\n // ── values ────────────────────────────────────────────────────────────\n\n private path(value: unknown, p: CSeg[], inst: Inst): unknown {\n for (const seg of p) {\n if (value === null || value === undefined) return undefined\n value = read(value, 'n' in seg ? seg.n : this.value(seg.e, inst))\n }\n return value\n }\n\n value(e: CExpr, inst: Inst): unknown {\n switch (e.k) {\n case 'l':\n return e.v\n case 'x':\n return undefined\n case 'd': {\n // `$errors`, `$old`, `$flash` are request-wide: components read the page's.\n const data = FORM_GLOBALS.has(e.n) && !(e.n in inst.data) ? this.rootData : inst.data\n if (!(e.n in data)) {\n // Rendered without form state (render() on its own): empty, not missing.\n if (FORM_GLOBALS.has(e.n)) return this.path({}, e.p, inst)\n this.unresolved(e.n, inst)\n }\n return this.path(read(data, e.n), e.p, inst)\n }\n case 'v':\n return this.path(inst.slots[e.s], e.p, inst)\n case 'm':\n return loopVar(inst.slots[e.s] as LoopMeta, e.w)\n case 'u': {\n const a = this.value(e.a, inst)\n return e.o === '!' ? !a : -(a as number)\n }\n case 'b': {\n if (e.o === '&&') return this.value(e.l, inst) && this.value(e.r, inst)\n if (e.o === '||') return this.value(e.l, inst) || this.value(e.r, inst)\n if (e.o === '??') return this.value(e.l, inst) ?? this.value(e.r, inst)\n const l = this.value(e.l, inst) as never\n const r = this.value(e.r, inst) as never\n switch (e.o) {\n case '==':\n case '===':\n return l === r\n case '!=':\n case '!==':\n return l !== r\n case '<':\n return l < r\n case '>':\n return l > r\n case '<=':\n return l <= r\n case '>=':\n return l >= r\n case '+':\n return (l as number) + (r as number)\n case '-':\n return (l as number) - (r as number)\n }\n return undefined\n }\n case 'c':\n return this.value(e.t, inst) ? this.value(e.y, inst) : this.value(e.n, inst)\n case 'p': {\n const pipe = this.env.pipes[e.n]\n if (!pipe) this.fail(inst, `unknown pipe '${e.n}'`)\n const input = this.value(e.i, inst)\n const args = e.a.map((a) => this.value(a, inst))\n let result: unknown\n try {\n result = pipe(input, ...args)\n } catch (err) {\n if (err instanceof RenderError) throw err\n this.fail(\n inst,\n `pipe '${e.n}' failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n if (result && typeof (result as PromiseLike<unknown>).then === 'function') {\n this.fail(inst, `pipe '${e.n}' returned a Promise — pipes must be synchronous`)\n }\n return result\n }\n }\n }\n\n private unresolved(name: string, inst: Inst): void {\n if (this.env.strict) this.fail(inst, `'${name}' isn't in the data`)\n let seen = warnedNames.get(inst.t)\n if (!seen) warnedNames.set(inst.t, (seen = new Set()))\n if (seen.has(name)) return\n seen.add(name)\n this.env.warn(`${inst.t.file}: '${name}' isn't in the data passed to render`)\n }\n\n /** A value as text, unescaped; `undefined` when it has no text form. */\n private text(v: unknown, inst: Inst): string {\n if (v === null || v === undefined) return ''\n switch (typeof v) {\n case 'string':\n return v\n case 'number':\n case 'bigint':\n case 'boolean':\n return String(v)\n }\n if (v instanceof Date) return Number.isNaN(v.getTime()) ? '' : v.toISOString()\n if (v instanceof SafeHtml) return v.html\n const what =\n v && typeof (v as PromiseLike<unknown>).then === 'function'\n ? 'a Promise — await it in the controller'\n : Array.isArray(v)\n ? 'an array — loop over it with @for, or use | json'\n : 'an object — print one of its properties, or use | json'\n if (this.env.strict) this.fail(inst, `can't print ${what}`)\n this.env.warn(`${inst.t.file}:${inst.at?.[0] ?? 1}: can't print ${what}`)\n return ''\n }\n\n // ── nodes ─────────────────────────────────────────────────────────────\n\n nodes(list: CNode[], inst: Inst): void {\n for (const n of list) this.node(n, inst)\n }\n\n private node(n: CNode, inst: Inst): void {\n switch (n.k) {\n case 's':\n this.out.push(n.t)\n return\n case 'i': {\n inst.at = n.at\n const v = this.value(n.e, inst)\n if (n.c === 'json') {\n this.out.push(\n escapeJsonForScript(typeof v === 'string' ? v : (JSON.stringify(v) ?? 'null')),\n )\n } else if (v instanceof SafeHtml && n.c === 'text') {\n // Trusted HTML prints as is in text — never in <title>/<textarea>,\n // where it could close the element.\n this.out.push(v.html)\n } else {\n this.out.push(escapeHtml(v instanceof SafeHtml ? v.html : this.text(v, inst)))\n }\n return\n }\n case 'A':\n inst.at = n.at\n this.attrs(this.resolve(n.a, inst), n.f ? inst.fall : undefined)\n return\n case 'if':\n for (const br of n.br) {\n const v = br.c ? this.value(br.c, inst) : true\n if (!v) continue\n if (br.a !== undefined) inst.slots[br.a] = v\n this.nodes(br.b, inst)\n return\n }\n return\n case 'for': {\n inst.at = n.at\n const items = this.iterable(this.value(n.e, inst), inst)\n if (!items.length) {\n if (n.em) this.nodes(n.em, inst)\n return\n }\n const meta: LoopMeta = { i: 0, n: items.length }\n inst.slots[n.m] = meta\n for (let i = 0; i < items.length; i++) {\n meta.i = i\n const item = items[i]\n if (typeof n.it === 'number') inst.slots[n.it] = item\n else {\n inst.slots[n.it[0]] = (item as unknown[] | undefined)?.[0]\n inst.slots[n.it[1]] = (item as unknown[] | undefined)?.[1]\n }\n this.nodes(n.b, inst)\n }\n return\n }\n case 'sw': {\n const v = this.value(n.e, inst)\n const hit = n.cs.find((c) => this.value(c.e, inst) === v)\n if (hit) this.nodes(hit.b, inst)\n else if (n.d) this.nodes(n.d, inst)\n return\n }\n case 'let':\n inst.slots[n.s] = this.value(n.e, inst)\n return\n case 'cmp':\n inst.at = n.at\n this.component(n, inst)\n return\n case 'o': {\n const fill = inst.fills[n.n]\n if (fill) this.nodes(fill.nodes, fill.inst)\n else this.nodes(n.fb, inst)\n return\n }\n case 'as':\n if (this.env.assets) this.out.push(this.env.assets(n.en, inst.data))\n else\n this.env.warn(\n `${inst.t.file}: @assets('${n.en}') needs the Vite plugin or an assets option`,\n )\n }\n }\n\n private iterable(v: unknown, inst: Inst): unknown[] {\n if (v === null || v === undefined) return []\n if (Array.isArray(v)) return v\n if (typeof v === 'string') return [...v]\n if (v instanceof Map) return [...v.entries()]\n if (v instanceof Set) return [...v]\n this.fail(\n inst,\n `@for can't loop over ${typeof v === 'object' ? 'an object — use | entries' : `a ${typeof v}`}`,\n )\n }\n\n // ── attributes ────────────────────────────────────────────────────────\n\n /** A value for an attribute: text form, HTML-escaped. */\n private attrValue(v: unknown, inst: Inst): string {\n return escapeHtml(this.plain(v, inst))\n }\n\n /** A value's text, unescaped (trusted HTML as its source). */\n private plain(v: unknown, inst: Inst): string {\n return v instanceof SafeHtml ? v.html : this.text(v, inst)\n }\n\n /**\n * Values in `Resolved` are ready to write between double quotes: the\n * author's static text as written (entities kept), interpolated values\n * escaped once.\n */\n resolve(list: CAttr[], inst: Inst): Resolved {\n const r: Resolved = { attrs: [], cls: [], style: [] }\n const put = (name: string, value: string | true) => {\n const lower = name.toLowerCase()\n if (lower === 'class') {\n if (value !== true && value.trim()) r.cls.push(value.trim())\n } else if (lower === 'style') {\n if (value !== true && value.trim()) r.style.push(value.trim().replace(/;\\s*$/, ''))\n } else {\n r.attrs.push([name, value])\n }\n }\n for (const a of list) {\n switch (a.t) {\n case 's':\n put(a.n, a.v === true ? true : a.v.replace(/\"/g, '"'))\n break\n case 'i': {\n const values = a.p.map((p) => (typeof p === 'string' ? undefined : this.value(p, inst)))\n const html = a.p\n .map((p, i) =>\n typeof p === 'string' ? p.replace(/\"/g, '"') : this.attrValue(values[i], inst),\n )\n .join('')\n if (!a.u) {\n put(a.n, html)\n break\n }\n // The scheme check reads what the browser will: the whole value as\n // written out, entities decoded — so a reference left unfinished in\n // static text (`
`) and completed by a value is read as one.\n const plain = decodeEntities(html)\n const safe = a.u === 'url' ? sanitizeUrl(plain) : sanitizeSrcset(plain)\n put(a.n, safe === plain ? html : escapeHtml(safe))\n break\n }\n case 'b': {\n const v = this.value(a.e, inst)\n if (v === null || v === undefined || v === false) break\n if (v === true) {\n put(a.n, true)\n break\n }\n const plain = this.plain(v, inst)\n put(\n a.n,\n escapeHtml(\n a.u === 'url' ? sanitizeUrl(plain) : a.u === 'srcset' ? sanitizeSrcset(plain) : plain,\n ),\n )\n break\n }\n case 'c':\n if (this.value(a.e, inst)) r.cls.push(escapeHtml(a.n))\n break\n case 'y': {\n const v = this.value(a.e, inst)\n if (v === null || v === undefined || v === false) break\n const value = safeStyleValue(`${this.text(v, inst)}${a.x ?? ''}`)\n if (value === undefined) {\n this.env.warn(\n `${inst.t.file}:${inst.at?.[0] ?? 1}: dropped an unsafe value for [style.${a.n}]`,\n )\n break\n }\n r.style.push(`${escapeHtml(a.n)}:${escapeHtml(value)}`)\n break\n }\n }\n }\n return r\n }\n\n private attrs(own: Resolved, fall?: Resolved): void {\n let attrs = own.attrs\n let cls = own.cls\n let style = own.style\n if (fall) {\n // The caller's attributes win over the root's own, except class and\n // style, which merge.\n const names = new Set(fall.attrs.map(([n]) => n.toLowerCase()))\n attrs = [...attrs.filter(([n]) => !names.has(n.toLowerCase())), ...fall.attrs]\n cls = [...cls, ...fall.cls]\n style = [...style, ...fall.style]\n }\n for (const [n, v] of attrs) this.out.push(v === true ? ` ${n}` : ` ${n}=\"${v}\"`)\n if (cls.length) this.out.push(` class=\"${cls.join(' ')}\"`)\n if (style.length) this.out.push(` style=\"${style.join(';')}\"`)\n }\n\n // ── components and layouts ────────────────────────────────────────────\n\n private component(n: Extract<CNode, { k: 'cmp' }>, caller: Inst): void {\n if (caller.depth >= MAX_DEPTH) {\n this.fail(caller, `components nest more than ${MAX_DEPTH} deep — is ${n.n} including itself?`)\n }\n const t = this.env.resolve(n.n)\n if (t.client) this.env.clientScript?.(t)\n if (t.validates) this.env.validation?.()\n const slots: unknown[] = Array.from({ length: t.slots })\n for (const i of t.inputs) if (i.d !== undefined) slots[i.s] = i.d\n for (const i of n.in) slots[i.s] = this.value(i.e, caller)\n const fills: Inst['fills'] = {}\n for (const [name, nodes] of Object.entries(n.f)) fills[name] = { nodes, inst: caller }\n const inst: Inst = {\n t,\n data: Object.create(null),\n slots,\n fills,\n fall: this.resolve(n.fa, caller),\n stack: [...caller.stack, n.n],\n depth: caller.depth + 1,\n }\n this.nodes(t.body, inst)\n }\n}\n\nfunction loopVar(m: LoopMeta, w: LoopVar): unknown {\n switch (w) {\n case '$index':\n return m.i\n case '$first':\n return m.i === 0\n case '$last':\n return m.i === m.n - 1\n case '$even':\n return m.i % 2 === 0\n case '$odd':\n return m.i % 2 === 1\n case '$count':\n return m.n\n }\n}\n\n/**\n * Render a checked page with `data`. Its layouts wrap it, outermost last:\n * `opts.layout` (a name, or `false` for none), else the page's `@layout`, else\n * the environment's mapping — then the base layout around the outermost one.\n * `@layout(none)` and `layout: false` skip the base too.\n */\nexport function render(\n template: CheckedTemplate,\n data: object,\n env: RenderEnv,\n opts: { layout?: boolean | string } = {},\n): string {\n const r = new Renderer(env)\n r.rootData = data as Record<string, unknown>\n const page: Inst = {\n t: template,\n data: data as Record<string, unknown>,\n slots: Array.from({ length: template.slots }),\n fills: {},\n stack: [template.name],\n depth: 0,\n }\n const none = opts.layout === false || (opts.layout === undefined && template.layout === null)\n const chain: CheckedTemplate[] = []\n if (!none) {\n let next =\n typeof opts.layout === 'string'\n ? opts.layout\n : (template.layout ?? env.layoutFor?.(template.name))\n while (next && next !== template.name && !chain.some((t) => t.name === next)) {\n const t = env.resolve(next)\n chain.push(t)\n next = t.layout ?? undefined\n }\n const base = env.baseLayout\n if (base && base !== template.name && !chain.some((t) => t.name === base))\n chain.push(env.resolve(base))\n }\n // The page and its layouts always render; components report as they do.\n if (template.validates || chain.some((t) => t.validates)) env.validation?.()\n if (!chain.length) {\n r.nodes(template.body, page)\n return r.html()\n }\n // Each layout renders the one inside it into its default slot; named fills\n // pass outward until a layout's own fill replaces them.\n let fills: Inst['fills'] = { '': { nodes: template.body, inst: page } }\n for (const [name, nodes] of Object.entries(template.fills)) fills[name] = { nodes, inst: page }\n let inst: Inst = page\n for (const [i, t] of chain.entries()) {\n inst = {\n t,\n data: page.data,\n slots: Array.from({ length: t.slots }),\n fills,\n stack: [...inst.stack, t.name],\n depth: 0,\n }\n if (i === chain.length - 1) break\n const outer: Inst['fills'] = { ...fills, '': { nodes: t.body, inst } }\n for (const [name, nodes] of Object.entries(t.fills)) outer[name] = { nodes, inst }\n fills = outer\n }\n r.nodes(inst.t.body, inst)\n return r.html()\n}\n","/**\n * `createViews`: templates from a loader or a build's bundle, checked once\n * and cached, rendered with the app's pipes and shared data.\n */\nimport { emptyFormState, rememberPage, takeFormState } from './form-state'\nimport { AST_FORMAT_VERSION, type CheckedTemplate, type TemplateAst } from './ast'\nimport { error, type Diagnostic } from './diagnostics'\nimport { check } from './check/check'\nimport { componentTag, layoutResolver, templateName, type Project } from './check/project'\nimport { CLIENT_SCRIPT_FILE, NO_STRIPPER, fnv1a, injectScripts } from './client-scripts'\nimport { VALIDATE_RUNTIME } from './validate-runtime'\n\n/** The validator script's served name; component tags can't take it. */\nconst VALIDATE_TAG = 'kick-validate'\nconst VALIDATE_HASH = fnv1a(VALIDATE_RUNTIME)\nimport { parse } from './parse/template'\nimport { BUILTIN_PIPES } from './pipes/builtins'\nimport { pipesFor, type EnvPipe } from './pipes/env'\nimport { render, RenderError, type Pipe } from './render/render'\n\nexport interface Loader {\n /** Every template name (`users/show`, `components/user-card`). */\n list(): Promise<string[]>\n read(name: string): Promise<string>\n /** Changes when the source changes (an mtime); checked on every render in dev. */\n version?(name: string): Promise<number>\n}\n\n/** What a build emits: checked templates as data. */\nexport interface ViewsBundle {\n v: number\n templates: Record<string, CheckedTemplate>\n}\n\nexport interface RenderOptions {\n /** A layout for this render, or `false` for none at all (htmx and other partial responses). */\n layout?: boolean | string\n locale?: string\n timeZone?: string\n}\n\nexport interface ViewsOptions {\n /** Default `src/views`. */\n viewsDir?: string\n /** Default `components`, inside the views folder. */\n componentsDir?: string\n /** Default `src/views/pipes.ts`. Read when `pipes` isn't given and there is no bundle. */\n pipesFile?: string\n pipes?: Record<string, Pipe | EnvPipe>\n /**\n * The layout a page gets when it declares none: one name, or folder prefix →\n * layout (`{ admin: 'layouts/admin', '': 'layouts/main' }`; the longest prefix wins).\n */\n layout?: string | Record<string, string>\n /** The shell (CSS, assets, SEO tags) wrapped around every page's outermost layout. */\n baseLayout?: string\n /** Default `en-US`. */\n locale?: string\n /** Default `UTC`. */\n timeZone?: string\n /** Unresolved names and values that can't print become errors. */\n strict?: boolean\n /** Default `true`. `false` re-reads and re-checks on every render. */\n cache?: boolean\n /** Data every render gets, under the page's own: the current user, a CSP nonce. */\n share?: (ctx: unknown) => object | Promise<object>\n loader?: Loader\n /** Checked templates from the build (`virtual:kick-views`); `null` in dev. */\n bundle?: ViewsBundle | null\n /** Re-check templates whose source changed, on every render. Default: on when `bundle` is `null` (`kick dev`). */\n dev?: boolean\n /**\n * `@assets('entry')`: usually `(entry, data) => assetTags(entry, mode, data.cspNonce)`.\n * `data` is the page's data with shared data merged in.\n */\n assets?: (entry: string, data: Record<string, unknown>) => string\n warn?: (message: string) => void\n /** Strips a `<script client>`'s TypeScript when a build hasn't. Default: Node's `stripTypeScriptTypes` (22.13+), on the Node entry. */\n stripTypes?: (code: string) => string | Promise<string>\n /** Where component scripts are served. Default `'/_kick/c'`. */\n clientScriptPath?: string\n}\n\nexport interface Views {\n render(name: string, data?: object, opts?: RenderOptions & { ctx?: unknown }): Promise<string>\n /** A component's script by its served file name (`<tag>.<hash>.js`); `undefined` when there's none by that name. */\n clientScript(file: string): Promise<string | undefined>\n /** The path component scripts are served under (`clientScriptPath`). */\n readonly clientScriptPath: string\n /** Whether `name` is one of these views — `ctx.render` falls through to another engine when not. */\n has(name: string): Promise<boolean>\n}\n\nexport function bundleLoader(bundle: ViewsBundle): Loader {\n if (bundle.v !== AST_FORMAT_VERSION) {\n throw new Error(`views bundle format v${bundle.v}, this runtime reads v${AST_FORMAT_VERSION}`)\n }\n return {\n list: async () => Object.keys(bundle.templates),\n read: async () => {\n throw new Error('a bundled template has no source')\n },\n }\n}\n\ninterface State {\n project: Project\n /** Syntax errors from parsing, raised when the template is first used. */\n parseErrors: Map<string, Diagnostic>\n versions: Map<string, number>\n checked: Map<string, CheckedTemplate>\n}\n\ntype FileLoaderModule = typeof import('./loaders/file')\n\n/**\n * How `createViews` reaches the file loader when it's given neither a loader\n * nor a bundle. The Node entry sets it; the edge entry (`workerd`, `worker`,\n * `browser` conditions) doesn't, so an edge build never contains `node:fs`.\n */\nlet fileLoaderModule: (() => Promise<FileLoaderModule>) | undefined\n\nexport function useFileLoader(load: () => Promise<FileLoaderModule>): void {\n fileLoaderModule = load\n}\n\n/** The TypeScript stripper for `<script client>`; the Node entry sets it. */\nlet typeStripper: ((code: string) => string) | undefined\n\nexport function useStripTypes(strip: (code: string) => string): void {\n typeStripper = strip\n}\n\nfunction fileLoaders(): Promise<FileLoaderModule> {\n if (!fileLoaderModule) {\n return Promise.reject(\n new Error(\n \"createViews has no templates: pass the build's bundle (import kickViews from 'virtual:kick-views') or a loader\",\n ),\n )\n }\n return fileLoaderModule()\n}\n\nexport function createViews(options: ViewsOptions = {}): Views {\n const bundle = options.bundle ?? undefined\n // `kick dev` hands over `bundle: null`: the sources change under us there.\n const dev = options.dev ?? options.bundle === null\n if (bundle) bundleLoader(bundle) // version check\n const componentsDir = options.componentsDir ?? 'components'\n const scriptPath = (options.clientScriptPath ?? '/_kick/c').replace(/\\/+$/, '')\n const stripTypes =\n options.stripTypes ??\n ((code: string) => {\n if (!typeStripper) throw new Error(NO_STRIPPER)\n return typeStripper(code)\n })\n /** Each component's served script, kept while its source stays the same. */\n const scripts = new Map<string, { code: string; js: Promise<{ js: string; hash: string }> }>()\n const scriptFor = (t: CheckedTemplate) => {\n const client = t.client!\n const hit = scripts.get(t.name)\n if (hit?.code === client.code) return hit.js\n const js = Promise.resolve(client.js ? client.code : stripTypes(client.code)).then((code) => ({\n js: code,\n hash: fnv1a(code),\n }))\n // A failed strip isn't kept: the next render tries again.\n js.catch(() => scripts.get(t.name)?.js === js && scripts.delete(t.name))\n scripts.set(t.name, { code: client.code, js })\n return js\n }\n const layoutFor = layoutResolver(options.layout)\n const warn = options.warn ?? ((m: string) => console.warn(`[kick/view] ${m}`))\n let loader: Promise<Loader> | undefined\n let appPipes: Promise<Record<string, Pipe | EnvPipe>> | undefined\n let state: Promise<State> | undefined\n /**\n * A memoised promise forgets itself when it rejects: a load that failed\n * once (a file mid-save, too many open files) is retried on the next\n * render rather than failing every render after it.\n */\n const settle = <T>(p: Promise<T>, forget: () => void): Promise<T> =>\n p.catch((err: unknown) => {\n forget()\n throw err\n })\n\n const getLoader = (): Promise<Loader> =>\n (loader ??= settle(\n options.loader\n ? Promise.resolve(options.loader)\n : fileLoaders().then((m) => m.fileLoader(options.viewsDir ?? 'src/views')),\n () => (loader = undefined),\n ))\n\n const getPipes = (): Promise<Record<string, Pipe | EnvPipe>> =>\n (appPipes ??= settle(\n options.pipes || bundle\n ? Promise.resolve(options.pipes ?? {})\n : fileLoaders()\n .then((m) => m.loadPipesFile(options.pipesFile ?? 'src/views/pipes.ts'))\n .then((mod) => (mod ?? {}) as Record<string, Pipe | EnvPipe>),\n () => (appPipes = undefined),\n ))\n\n /** A fresh load, forgotten if it fails. */\n const reload = (): Promise<State> => (state = settle(load(), () => (state = undefined)))\n\n async function load(): Promise<State> {\n const l = await getLoader()\n const pipes = await getPipes()\n const names = await l.list()\n const templates = new Map<string, TemplateAst>()\n const versions = new Map<string, number>()\n const parseErrors = new Map<string, Diagnostic>()\n await Promise.all(\n names.map(async (name) => {\n const r = parse(await l.read(name), `${name}.kick`)\n templates.set(name, r.ast)\n const first = r.diagnostics.find((d) => d.severity === 'error')\n if (first) parseErrors.set(name, first)\n if (dev && l.version) versions.set(name, await l.version(name))\n }),\n )\n return {\n project: {\n templates,\n pipes: new Set([...BUILTIN_PIPES, ...Object.keys(pipes)]),\n componentsDir,\n layouts: options.layout,\n baseLayout: options.baseLayout,\n },\n versions,\n parseErrors,\n checked: new Map(),\n }\n }\n\n /** The current state, reloaded in dev when a source changed. */\n async function current(): Promise<State> {\n if (options.cache === false) return reload()\n const s = await (state ?? reload())\n if (!dev) return s\n const l = await getLoader()\n if (!l.version) return s\n const names = await l.list()\n const stale =\n names.length !== s.project.templates.size ||\n (await Promise.all(names.map(async (n) => (await l.version!(n)) !== s.versions.get(n)))).some(\n Boolean,\n )\n if (!stale) return s\n return reload()\n }\n\n function checked(s: State, name: string): CheckedTemplate {\n let t = s.checked.get(name)\n if (t) return t\n const syntax = s.parseErrors.get(name)\n if (syntax) throw new RenderError(syntax)\n const r = check(name, s.project)\n if (!r.template) {\n const d = r.diagnostics.find((x) => x.severity === 'error')!\n throw new RenderError(d)\n }\n for (const w of r.diagnostics) {\n warn(`${w.file}:${w.span.start.line}:${w.span.start.column} — ${w.message}`)\n }\n t = r.template\n s.checked.set(name, t)\n return t\n }\n\n async function has(name: string): Promise<boolean> {\n if (!templateName(name)) return false\n if (bundle) return Object.hasOwn(bundle.templates, name)\n return (await current()).project.templates.has(name)\n }\n\n return {\n has,\n async render(name, data = {}, opts = {}) {\n if (!templateName(name)) throw new Error(`invalid template name '${name}'`)\n if (!(await has(name))) throw new Error(`template '${name}' not found`)\n const resolve = bundle\n ? (n: string) => {\n const t = Object.hasOwn(bundle.templates, n) ? bundle.templates[n] : undefined\n if (!t) throw new RenderError(error(`${n}.kick`, zeroSpan, `template '${n}' not found`))\n return t\n }\n : await current().then((s) => (n: string) => checked(s, n))\n const template = resolve(name)\n rememberPage(opts.ctx, opts.layout)\n const shared = options.share ? await options.share(opts.ctx) : {}\n const locale = opts.locale ?? options.locale ?? 'en-US'\n const timeZone = opts.timeZone ?? options.timeZone ?? 'UTC'\n const used = new Map<string, CheckedTemplate>()\n let validation = false\n // A controller's own `$errors` / `$old` (a re-render) win over the session's.\n const page = { ...emptyFormState(), ...shared, ...takeFormState(opts.ctx), ...data }\n const html = render(\n template,\n page,\n {\n locale,\n timeZone,\n strict: options.strict ?? false,\n pipes: pipesFor(await getPipes(), { locale, timeZone }),\n warn,\n resolve,\n layoutFor,\n baseLayout: options.baseLayout,\n assets: options.assets,\n clientScript: (t) => used.set(t.name, t),\n validation: () => (validation = true),\n },\n { layout: opts.layout },\n )\n if (!used.size && !validation) return html\n // The nonce `@assets` gets too: often from share().\n const nonce = (page as { cspNonce?: unknown }).cspNonce\n const nonceAttr = typeof nonce === 'string' ? ` nonce=\"${nonce.replace(/\"/g, '"')}\"` : ''\n const tags = await Promise.all(\n [...used.values()].map(async (t) => {\n const { hash } = await scriptFor(t)\n const file = `${componentTag(t.name, componentsDir)}.${hash}.js`\n return `<script type=\"module\" src=\"${scriptPath}/${file}\"${nonceAttr}></script>`\n }),\n )\n if (validation)\n tags.push(\n `<script type=\"module\" src=\"${scriptPath}/${VALIDATE_TAG}.${VALIDATE_HASH}.js\"${nonceAttr}></script>`,\n )\n return injectScripts(html, tags.join(''))\n },\n clientScriptPath: scriptPath,\n async clientScript(file) {\n const m = CLIENT_SCRIPT_FILE.exec(file)\n if (!m) return undefined\n if (m[1] === VALIDATE_TAG) return m[2] === VALIDATE_HASH ? VALIDATE_RUNTIME : undefined\n const names = bundle\n ? Object.keys(bundle.templates)\n : [...(await current()).project.templates.keys()]\n const name = names.find(\n (n) => n.startsWith(`${componentsDir}/`) && componentTag(n, componentsDir) === m[1],\n )\n if (!name) return undefined\n const t = bundle ? bundle.templates[name]! : checked(await current(), name)\n if (!t.client) return undefined\n const { js, hash } = await scriptFor(t)\n return hash === m[2] ? js : undefined\n },\n }\n}\n\nconst zeroSpan = {\n start: { offset: 0, line: 1, column: 1 },\n end: { offset: 0, line: 1, column: 1 },\n}\n","/**\n * Serving component scripts: `<clientScriptPath>/<tag>.<hash>.js`. `KickView`\n * answers them on Express, Fastify and h3; on the web fetch entry, whose\n * middlewares only run for matched routes, call `clientScriptResponse` ahead\n * of the router.\n */\nimport { CLIENT_SCRIPT_FILE } from './client-scripts'\nimport type { Views } from './views'\n\n/** A script's name never changes with its content, so it caches forever. */\nexport const CLIENT_SCRIPT_HEADERS: Record<string, string> = {\n 'content-type': 'text/javascript; charset=utf-8',\n 'cache-control': 'public, max-age=31536000, immutable',\n}\n\n/** The script file a GET / HEAD asks for under `views.clientScriptPath`, if any. */\nexport function clientScriptFile(\n views: Views,\n method: string | undefined,\n url: string,\n): string | undefined {\n const m = String(method ?? 'GET').toUpperCase()\n if (m !== 'GET' && m !== 'HEAD') return undefined\n const path = url.split('?')[0]!\n const prefix = `${views.clientScriptPath}/`\n if (!path.startsWith(prefix)) return undefined\n const file = path.slice(prefix.length)\n return CLIENT_SCRIPT_FILE.test(file) ? file : undefined\n}\n\n/**\n * A component script's response, or `undefined` for anything else:\n *\n * ```ts\n * export default { fetch: async (req) => (await clientScriptResponse(views, req)) ?? web.fetch(req) }\n * ```\n */\nexport async function clientScriptResponse(\n views: Views,\n request: Request,\n): Promise<Response | undefined> {\n const file = clientScriptFile(views, request.method, new URL(request.url).pathname)\n if (!file) return undefined\n const js = await views.clientScript(file)\n if (js === undefined) return undefined\n return new Response(request.method === 'HEAD' ? null : js, {\n status: 200,\n headers: CLIENT_SCRIPT_HEADERS,\n })\n}\n","/**\n * `KickView`: makes `ctx.render()` render `.kick` templates on every\n * runtime. It binds a renderer onto each request through the slot core reads\n * (`Symbol.for('kickjs.viewRenderer')`), so this module never imports\n * `@forinda/kickjs` at runtime — it stays edge-safe.\n */\nimport { CLIENT_SCRIPT_HEADERS, clientScriptFile } from './serve'\nimport { createViews, type Views, type ViewsOptions } from './views'\n\nconst VIEW_RENDERER = Symbol.for('kickjs.viewRenderer')\n\ntype Next = (err?: unknown) => void\n\n/** What `ctx.render` passes a bound renderer. Mirrors core's `ViewRenderOptions`. */\ninterface ViewRenderOptions {\n status?: number\n headers?: Record<string, string>\n layout?: boolean | string\n locale?: string\n timeZone?: string\n}\n\ntype Renderer = (\n name: string,\n data: Record<string, unknown>,\n opts: ViewRenderOptions,\n ctx: unknown,\n) => Promise<string | undefined>\n\nfunction rendererFor(views: Views): Renderer {\n return async (name, data, opts, ctx) =>\n (await views.has(name))\n ? views.render(name, data, {\n layout: opts.layout,\n locale: opts.locale,\n timeZone: opts.timeZone,\n ctx,\n })\n : undefined\n}\n\n/** Node's response, which every runtime's middleware gets (Express's adds to it). */\ninterface ScriptResponse {\n statusCode: number\n setHeader(name: string, value: string): unknown\n end(body?: string): unknown\n}\n\n/**\n * Connect middleware binding `views` to each request (what the adapter\n * mounts), and answering component script requests.\n */\nfunction bindViews(views: Views): (req: object, res: unknown, next: Next) => void {\n const renderer = rendererFor(views)\n return (req, res, next) => {\n const r = req as { method?: string; url?: string } & Record<symbol, unknown>\n const file = clientScriptFile(views, r.method, r.url ?? '/')\n if (!file) {\n r[VIEW_RENDERER] = renderer\n return next()\n }\n views.clientScript(file).then(\n (js) => {\n if (js === undefined) {\n r[VIEW_RENDERER] = renderer\n return next()\n }\n const out = res as ScriptResponse\n out.statusCode = 200\n for (const [k, v] of Object.entries(CLIENT_SCRIPT_HEADERS)) out.setHeader(k, v)\n out.end(String(r.method).toUpperCase() === 'HEAD' ? undefined : js)\n },\n (err: unknown) => next(err),\n )\n }\n}\n\n/**\n * The web fetch entry's middleware (`createWebApp({ middlewares: [viewsMiddleware(views)] })`),\n * which takes `(ctx, next)` middleware rather than adapters.\n */\nexport function viewsMiddleware(\n views: Views,\n): (ctx: { req: object }, next: () => unknown) => unknown {\n const renderer = rendererFor(views)\n return (ctx, next) => {\n ;(ctx.req as Record<symbol, unknown>)[VIEW_RENDERER] = renderer\n return next()\n }\n}\n\nexport interface KickViewOptions extends ViewsOptions {\n /** A views instance to use — share it with error pages and emails. */\n views?: Views\n}\n\n/**\n * The `.kick` view engine for `bootstrap({ adapters })`.\n *\n * ```ts\n * const views = createViews({ layout: 'layouts/main' })\n * bootstrap({ modules, adapters: [KickView({ views })] })\n * // in a controller\n * await ctx.render('users/show', { user })\n * ```\n */\n/**\n * Re-check templates on every render only in development: NODE_ENV is\n * `development`, or the views come from `kick dev` (the virtual module hands\n * over `bundle: null` there). An unset NODE_ENV in production stays fast.\n */\nexport function kickViewDev(options: KickViewOptions, nodeEnv: string | undefined): boolean {\n return options.dev ?? (nodeEnv === 'development' || options.bundle === null)\n}\n\nexport function KickView(options: KickViewOptions = {}) {\n const views =\n options.views ??\n createViews({ ...options, dev: kickViewDev(options, globalThis.process?.env?.NODE_ENV) })\n const handler = bindViews(views)\n return {\n name: 'KickView',\n views,\n // Before any other middleware, so error pages and early answers can render too.\n middleware: () => [{ handler, phase: 'beforeGlobal' as const }],\n }\n}\n","/**\n * `@assets('src/client/main.ts')`: the tags a page needs for a Vite entry —\n * the dev client and module in dev, the hashed files from the build's\n * manifest in production.\n */\nimport { escapeHtml } from './render/safe'\n\nexport interface ViteManifestChunk {\n file: string\n css?: string[]\n imports?: string[]\n isEntry?: boolean\n}\n\nexport type ViteManifest = Record<string, ViteManifestChunk>\n\nexport type AssetsMode =\n | { dev: true; base: string }\n | { dev: false; manifest: ViteManifest; base: string }\n\nexport function assetTags(entry: string, mode: AssetsMode, nonce?: string): string {\n const base = mode.base.endsWith('/') ? mode.base : `${mode.base}/`\n const n = nonce ? ` nonce=\"${escapeHtml(nonce)}\"` : ''\n const url = (file: string) => escapeHtml(`${base}${file.replace(/^\\//, '')}`)\n if (mode.dev) {\n return [\n `<script type=\"module\"${n} src=\"${url('@vite/client')}\"></script>`,\n `<script type=\"module\"${n} src=\"${url(entry)}\"></script>`,\n ].join('\\n')\n }\n const chunk = mode.manifest[entry]\n if (!chunk) throw new Error(`@assets: '${entry}' isn't an entry in the Vite manifest`)\n const css = new Set<string>(chunk.css ?? [])\n const preload = new Set<string>()\n const walk = (key: string) => {\n const c = mode.manifest[key]\n if (!c || preload.has(c.file)) return\n preload.add(c.file)\n for (const s of c.css ?? []) css.add(s)\n for (const i of c.imports ?? []) walk(i)\n }\n for (const i of chunk.imports ?? []) walk(i)\n return [\n ...[...css].map((f) => `<link rel=\"stylesheet\"${n} href=\"${url(f)}\">`),\n ...[...preload].map((f) => `<link rel=\"modulepreload\"${n} href=\"${url(f)}\">`),\n `<script type=\"module\"${n} src=\"${url(chunk.file)}\"></script>`,\n ].join('\\n')\n}\n"],"mappings":"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"}
|