From 9a1b10c51f257b4ac4dd67732b880f3a8949992d Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Tue, 6 Jan 2026 21:41:56 -0500 Subject: [PATCH] Update embedded version to v4-alpha6; finish first cut of attrs/evts --- src/Common/wwwroot/htmx.min.js | 2 +- src/Tests/ViewEngine.fs | 293 ++++++++++++++++++++++++++------- src/ViewEngine.Htmx/Htmx.fs | 173 ++++++++++++------- 3 files changed, 350 insertions(+), 118 deletions(-) diff --git a/src/Common/wwwroot/htmx.min.js b/src/Common/wwwroot/htmx.min.js index faafa3e..ffbd347 100644 --- a/src/Common/wwwroot/htmx.min.js +++ b/src/Common/wwwroot/htmx.min.js @@ -1 +1 @@ -var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=dn(e,t||"post");return n.values},remove:null,addClass:null,removeClass:null,toggleClass:null,takeClass:null,swap:null,defineExtension:null,removeExtension:null,logAll:null,logNone:null,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:true,allowScriptTags:true,inlineScriptNonce:"",inlineStyleNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:false,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",scrollBehavior:"instant",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false,methodsThatUseUrlParams:["get","delete"],selfRequestsOnly:true,ignoreTitle:false,scrollIntoViewOnBoost:true,triggerSpecsCache:null,disableInheritance:false,responseHandling:[{code:"204",swap:false},{code:"[23]..",swap:true},{code:"[45]..",swap:false,error:true}],allowNestedOobSwaps:true,historyRestoreAsHxRequest:true,reportValidityOfForms:false},parseInterval:null,location:location,_:null,version:"2.0.8"};Q.onLoad=V;Q.process=Ft;Q.on=xe;Q.off=be;Q.trigger=ae;Q.ajax=Ln;Q.find=f;Q.findAll=x;Q.closest=g;Q.remove=_;Q.addClass=K;Q.removeClass=G;Q.toggleClass=W;Q.takeClass=Z;Q.swap=ze;Q.defineExtension=_n;Q.removeExtension=zn;Q.logAll=j;Q.logNone=$;Q.parseInterval=d;Q._=e;const n={addTriggerHandler:St,bodyContains:se,canAccessLocalStorage:X,findThisElement:Se,filterValues:yn,swap:ze,hasAttribute:s,getAttributeValue:a,getClosestAttributeValue:ne,getClosestMatch:q,getExpressionVars:Rn,getHeaders:mn,getInputValues:dn,getInternalData:oe,getSwapSpecification:bn,getTriggerSpecs:st,getTarget:Ee,makeFragment:D,mergeObjects:le,makeSettleInfo:Sn,oobSwap:Te,querySelectorExt:ue,settleImmediately:Yt,shouldCancel:ht,triggerEvent:ae,triggerErrorEvent:fe,withExtensions:Vt};const de=["get","post","put","delete","patch"];const R=de.map(function(e){return"[hx-"+e+"], [data-hx-"+e+"]"}).join(", ");function d(e){if(e==undefined){return undefined}let t=NaN;if(e.slice(-2)=="ms"){t=parseFloat(e.slice(0,-2))}else if(e.slice(-1)=="s"){t=parseFloat(e.slice(0,-1))*1e3}else if(e.slice(-1)=="m"){t=parseFloat(e.slice(0,-1))*1e3*60}else{t=parseFloat(e)}return isNaN(t)?undefined:t}function ee(e,t){return e instanceof Element&&e.getAttribute(t)}function s(e,t){return!!e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute("data-"+t))}function a(e,t){return ee(e,t)||ee(e,"data-"+t)}function u(e){const t=e.parentElement;if(!t&&e.parentNode instanceof ShadowRoot)return e.parentNode;return t}function te(){return document}function y(e,t){return e.getRootNode?e.getRootNode({composed:t}):te()}function q(e,t){while(e&&!t(e)){e=u(e)}return e||null}function o(e,t,n){const r=a(t,n);const o=a(t,"hx-disinherit");var i=a(t,"hx-inherit");if(e!==t){if(Q.config.disableInheritance){if(i&&(i==="*"||i.split(" ").indexOf(n)>=0)){return r}else{return null}}if(o&&(o==="*"||o.split(" ").indexOf(n)>=0)){return"unset"}}return r}function ne(t,n){let r=null;q(t,function(e){return!!(r=o(t,ce(e),n))});if(r!=="unset"){return r}}function h(e,t){return e instanceof Element&&e.matches(t)}function A(e){const t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i;const n=t.exec(e);if(n){return n[1].toLowerCase()}else{return""}}function L(e){if("parseHTMLUnsafe"in Document){return Document.parseHTMLUnsafe(e)}const t=new DOMParser;return t.parseFromString(e,"text/html")}function N(e,t){while(t.childNodes.length>0){e.append(t.childNodes[0])}}function r(e){const t=te().createElement("script");ie(e.attributes,function(e){t.setAttribute(e.name,e.value)});t.textContent=e.textContent;t.async=false;if(Q.config.inlineScriptNonce){t.nonce=Q.config.inlineScriptNonce}return t}function i(e){return e.matches("script")&&(e.type==="text/javascript"||e.type==="module"||e.type==="")}function I(e){Array.from(e.querySelectorAll("script")).forEach(e=>{if(i(e)){const t=r(e);const n=e.parentNode;try{n.insertBefore(t,e)}catch(e){H(e)}finally{e.remove()}}})}function D(e){const t=e.replace(/]*)?>[\s\S]*?<\/head>/i,"");const n=A(t);let r;if(n==="html"){r=new DocumentFragment;const i=L(e);N(r,i.body);r.title=i.title}else if(n==="body"){r=new DocumentFragment;const i=L(t);N(r,i.body);r.title=i.title}else{const i=L('");r=i.querySelector("template").content;r.title=i.title;var o=r.querySelector("title");if(o&&o.parentNode===r){o.remove();r.title=o.innerText}}if(r){if(Q.config.allowScriptTags){I(r)}else{r.querySelectorAll("script").forEach(e=>e.remove())}}return r}function re(e){if(e){e()}}function t(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function P(e){return typeof e==="function"}function k(e){return t(e,"Object")}function oe(e){const t="htmx-internal-data";let n=e[t];if(!n){n=e[t]={}}return n}function M(t){const n=[];if(t){for(let e=0;e=0}function se(e){return e.getRootNode({composed:true})===document}function B(e){return e.trim().split(/\s+/)}function le(e,t){for(const n in t){if(t.hasOwnProperty(n)){e[n]=t[n]}}return e}function v(e){try{return JSON.parse(e)}catch(e){H(e);return null}}function X(){const e="htmx:sessionStorageTest";try{sessionStorage.setItem(e,e);sessionStorage.removeItem(e);return true}catch(e){return false}}function U(e){const t=new URL(e,"http://x");if(t){e=t.pathname+t.search}if(e!="/"){e=e.replace(/\/+$/,"")}return e}function e(e){return On(te().body,function(){return eval(e)})}function V(t){const e=Q.on("htmx:load",function(e){t(e.detail.elt)});return e}function j(){Q.logger=function(e,t,n){if(console){console.log(t,e,n)}}}function $(){Q.logger=null}function f(e,t){if(typeof e!=="string"){return e.querySelector(t)}else{return f(te(),e)}}function x(e,t){if(typeof e!=="string"){return e.querySelectorAll(t)}else{return x(te(),e)}}function b(){return window}function _(e,t){e=w(e);if(t){b().setTimeout(function(){_(e);e=null},t)}else{u(e).removeChild(e)}}function ce(e){return e instanceof Element?e:null}function z(e){return e instanceof HTMLElement?e:null}function J(e){return typeof e==="string"?e:null}function p(e){return e instanceof Element||e instanceof Document||e instanceof DocumentFragment?e:null}function K(e,t,n){e=ce(w(e));if(!e){return}if(n){b().setTimeout(function(){K(e,t);e=null},n)}else{e.classList&&e.classList.add(t)}}function G(e,t,n){let r=ce(w(e));if(!r){return}if(n){b().setTimeout(function(){G(r,t);r=null},n)}else{if(r.classList){r.classList.remove(t);if(r.classList.length===0){r.removeAttribute("class")}}}}function W(e,t){e=w(e);e.classList.toggle(t)}function Z(e,t){e=w(e);ie(e.parentElement.children,function(e){G(e,t)});K(ce(e),t)}function g(e,t){e=ce(w(e));if(e){return e.closest(t)}return null}function l(e,t){return e.substring(0,t.length)===t}function Y(e,t){return e.substring(e.length-t.length)===t}function pe(e){const t=e.trim();if(l(t,"<")&&Y(t,"/>")){return t.substring(1,t.length-2)}else{return t}}function m(t,r,n){if(r.indexOf("global ")===0){return m(t,r.slice(7),true)}t=w(t);const o=[];{let t=0;let n=0;for(let e=0;e"){t--}}if(n0){const r=pe(o.shift());let e;if(r.indexOf("closest ")===0){e=g(ce(t),pe(r.slice(8)))}else if(r.indexOf("find ")===0){e=f(p(t),pe(r.slice(5)))}else if(r==="next"||r==="nextElementSibling"){e=ce(t).nextElementSibling}else if(r.indexOf("next ")===0){e=ge(t,pe(r.slice(5)),!!n)}else if(r==="previous"||r==="previousElementSibling"){e=ce(t).previousElementSibling}else if(r.indexOf("previous ")===0){e=me(t,pe(r.slice(9)),!!n)}else if(r==="document"){e=document}else if(r==="window"){e=window}else if(r==="body"){e=document.body}else if(r==="root"){e=y(t,!!n)}else if(r==="host"){e=t.getRootNode().host}else{s.push(r)}if(e){i.push(e)}}if(s.length>0){const e=s.join(",");const c=p(y(t,!!n));i.push(...M(c.querySelectorAll(e)))}return i}var ge=function(t,e,n){const r=p(y(t,n)).querySelectorAll(e);for(let e=0;e=0;e--){const o=r[e];if(o.compareDocumentPosition(t)===Node.DOCUMENT_POSITION_FOLLOWING){return o}}};function ue(e,t){if(typeof e!=="string"){return m(e,t)[0]}else{return m(te().body,e)[0]}}function w(e,t){if(typeof e==="string"){return f(p(t)||document,e)}else{return e}}function ye(e,t,n,r){if(P(t)){return{target:te().body,event:J(e),listener:t,options:n}}else{return{target:w(e),event:J(t),listener:n,options:r}}}function xe(t,n,r,o){Gn(function(){const e=ye(t,n,r,o);e.target.addEventListener(e.event,e.listener,e.options)});const e=P(n);return e?n:r}function be(t,n,r){Gn(function(){const e=ye(t,n,r);e.target.removeEventListener(e.event,e.listener)});return P(n)?n:r}const ve=te().createElement("output");function we(t,n){const e=ne(t,n);if(e){if(e==="this"){return[Se(t,n)]}else{const r=m(t,e);const o=/(^|,)(\s*)inherit(\s*)($|,)/.test(e);if(o){const i=ce(q(t,function(e){return e!==t&&s(ce(e),n)}));if(i){r.push(...we(i,n))}}if(r.length===0){H('The selector "'+e+'" on '+n+" returned no matches!");return[ve]}else{return r}}}}function Se(e,t){return ce(q(e,function(e){return a(ce(e),t)!=null}))}function Ee(e){const t=ne(e,"hx-target");if(t){if(t==="this"){return Se(e,"hx-target")}else{return ue(e,t)}}else{const n=oe(e);if(n.boosted){return te().body}else{return e}}}function Ce(e){return Q.config.attributesToSettle.includes(e)}function Oe(t,n){ie(Array.from(t.attributes),function(e){if(!n.hasAttribute(e.name)&&Ce(e.name)){t.removeAttribute(e.name)}});ie(n.attributes,function(e){if(Ce(e.name)){t.setAttribute(e.name,e.value)}})}function He(t,e){const n=Jn(e);for(let e=0;e0){s=e.substring(0,e.indexOf(":"));n=e.substring(e.indexOf(":")+1)}else{s=e}o.removeAttribute("hx-swap-oob");o.removeAttribute("data-hx-swap-oob");const r=m(t,n,false);if(r.length){ie(r,function(e){let t;const n=o.cloneNode(true);t=te().createDocumentFragment();t.appendChild(n);if(!He(s,e)){t=p(n)}const r={shouldSwap:true,target:e,fragment:t};if(!ae(e,"htmx:oobBeforeSwap",r))return;e=r.target;if(r.shouldSwap){qe(t);$e(s,e,e,t,i);Re()}ie(i.elts,function(e){ae(e,"htmx:oobAfterSwap",r)})});o.parentNode.removeChild(o)}else{o.parentNode.removeChild(o);fe(te().body,"htmx:oobErrorNoTarget",{content:o})}return e}function Re(){const e=f("#--htmx-preserve-pantry--");if(e){for(const t of[...e.children]){const n=f("#"+t.id);n.parentNode.moveBefore(t,n);n.remove()}e.remove()}}function qe(e){ie(x(e,"[hx-preserve], [data-hx-preserve]"),function(e){const t=a(e,"id");const n=te().getElementById(t);if(n!=null){if(e.moveBefore){let e=f("#--htmx-preserve-pantry--");if(e==null){te().body.insertAdjacentHTML("afterend","
");e=f("#--htmx-preserve-pantry--")}e.moveBefore(n,null)}else{e.parentNode.replaceChild(n,e)}}})}function Ae(l,e,c){ie(e.querySelectorAll("[id]"),function(t){const n=ee(t,"id");if(n&&n.length>0){const r=n.replace("'","\\'");const o=t.tagName.replace(":","\\:");const e=p(l);const i=e&&e.querySelector(o+"[id='"+r+"']");if(i&&i!==e){const s=t.cloneNode();Oe(t,i);c.tasks.push(function(){Oe(t,s)})}}})}function Le(e){return function(){G(e,Q.config.addedClass);Ft(ce(e));Ne(p(e));ae(e,"htmx:load")}}function Ne(e){const t="[autofocus]";const n=z(h(e,t)?e:e.querySelector(t));if(n!=null){n.focus()}}function c(e,t,n,r){Ae(e,n,r);while(n.childNodes.length>0){const o=n.firstChild;K(ce(o),Q.config.addedClass);e.insertBefore(o,t);if(o.nodeType!==Node.TEXT_NODE&&o.nodeType!==Node.COMMENT_NODE){r.tasks.push(Le(o))}}}function Ie(e,t){let n=0;while(n0}function ze(h,d,p,g){if(!g){g={}}let m=null;let n=null;let e=function(){re(g.beforeSwapCallback);h=w(h);const r=g.contextElement?y(g.contextElement,false):te();const e=document.activeElement;let t={};t={elt:e,start:e?e.selectionStart:null,end:e?e.selectionEnd:null};const o=Sn(h);if(p.swapStyle==="textContent"){h.textContent=d}else{let n=D(d);o.title=g.title||n.title;if(g.historyRequest){n=n.querySelector("[hx-history-elt],[data-hx-history-elt]")||n}if(g.selectOOB){const i=g.selectOOB.split(",");for(let t=0;t0){b().setTimeout(n,p.settleDelay)}else{n()}};let t=Q.config.globalViewTransitions;if(p.hasOwnProperty("transition")){t=p.transition}const r=g.contextElement||te();if(t&&ae(r,"htmx:beforeTransition",g.eventInfo)&&typeof Promise!=="undefined"&&document.startViewTransition){const o=new Promise(function(e,t){m=e;n=t});const i=e;e=function(){document.startViewTransition(function(){i();return o})}}try{if(p?.swapDelay&&p.swapDelay>0){b().setTimeout(e,p.swapDelay)}else{e()}}catch(e){fe(r,"htmx:swapError",g.eventInfo);re(n);throw e}}function Je(e,t,n){const r=e.getResponseHeader(t);if(r.indexOf("{")===0){const o=v(r);for(const i in o){if(o.hasOwnProperty(i)){let e=o[i];if(k(e)){n=e.target!==undefined?e.target:n}else{e={value:e}}ae(n,i,e)}}}else{const s=r.split(",");for(let e=0;e0){const s=o[0];if(s==="]"){e--;if(e===0){if(n===null){t=t+"true"}o.shift();t+=")})";try{const l=On(r,function(){return Function(t)()},function(){return true});l.source=t;return l}catch(e){fe(te().body,"htmx:syntax:error",{error:e,source:t});return null}}}else if(s==="["){e++}if(tt(s,n,i)){t+="(("+i+"."+s+") ? ("+i+"."+s+") : (window."+s+"))"}else{t=t+s}n=o.shift()}}}function O(e,t){let n="";while(e.length>0&&!t.test(e[0])){n+=e.shift()}return n}function rt(e){let t;if(e.length>0&&Ye.test(e[0])){e.shift();t=O(e,Qe).trim();e.shift()}else{t=O(e,E)}return t}const ot="input, textarea, select";function it(e,t,n){const r=[];const o=et(t);do{O(o,C);const l=o.length;const c=O(o,/[,\[\s]/);if(c!==""){if(c==="every"){const u={trigger:"every"};O(o,C);u.pollInterval=d(O(o,/[,\[\s]/));O(o,C);var i=nt(e,o,"event");if(i){u.eventFilter=i}r.push(u)}else{const f={trigger:c};var i=nt(e,o,"event");if(i){f.eventFilter=i}O(o,C);while(o.length>0&&o[0]!==","){const a=o.shift();if(a==="changed"){f.changed=true}else if(a==="once"){f.once=true}else if(a==="consume"){f.consume=true}else if(a==="delay"&&o[0]===":"){o.shift();f.delay=d(O(o,E))}else if(a==="from"&&o[0]===":"){o.shift();if(Ye.test(o[0])){var s=rt(o)}else{var s=O(o,E);if(s==="closest"||s==="find"||s==="next"||s==="previous"){o.shift();const h=rt(o);if(h.length>0){s+=" "+h}}}f.from=s}else if(a==="target"&&o[0]===":"){o.shift();f.target=rt(o)}else if(a==="throttle"&&o[0]===":"){o.shift();f.throttle=d(O(o,E))}else if(a==="queue"&&o[0]===":"){o.shift();f.queue=O(o,E)}else if(a==="root"&&o[0]===":"){o.shift();f[a]=rt(o)}else if(a==="threshold"&&o[0]===":"){o.shift();f[a]=O(o,E)}else{fe(e,"htmx:syntax:error",{token:o.shift()})}O(o,C)}r.push(f)}}if(o.length===l){fe(e,"htmx:syntax:error",{token:o.shift()})}O(o,C)}while(o[0]===","&&o.shift());if(n){n[t]=r}return r}function st(e){const t=a(e,"hx-trigger");let n=[];if(t){const r=Q.config.triggerSpecsCache;n=r&&r[t]||it(e,t,r)}if(n.length>0){return n}else if(h(e,"form")){return[{trigger:"submit"}]}else if(h(e,'input[type="button"], input[type="submit"]')){return[{trigger:"click"}]}else if(h(e,ot)){return[{trigger:"change"}]}else{return[{trigger:"click"}]}}function lt(e){oe(e).cancelled=true}function ct(e,t,n){const r=oe(e);r.timeout=b().setTimeout(function(){if(se(e)&&r.cancelled!==true){if(!pt(n,e,Xt("hx:poll:trigger",{triggerSpec:n,target:e}))){t(e)}ct(e,t,n)}},n.pollInterval)}function ut(e){return location.hostname===e.hostname&&ee(e,"href")&&ee(e,"href").indexOf("#")!==0}function ft(e){return g(e,Q.config.disableSelector)}function at(t,n,e){if(t instanceof HTMLAnchorElement&&ut(t)&&(t.target===""||t.target==="_self")||t.tagName==="FORM"&&String(ee(t,"method")).toLowerCase()!=="dialog"){n.boosted=true;let r,o;if(t.tagName==="A"){r="get";o=ee(t,"href")}else{const i=ee(t,"method");r=i?i.toLowerCase():"get";o=ee(t,"action");if(o==null||o===""){o=location.href}if(r==="get"&&o.includes("?")){o=o.replace(/\?[^#]+/,"")}}e.forEach(function(e){gt(t,function(e,t){const n=ce(e);if(ft(n)){S(n);return}he(r,o,n,t)},n,e,true)})}}function ht(e,t){if(e.type==="submit"&&t.tagName==="FORM"){return true}else if(e.type==="click"){const n=t.closest('input[type="submit"], button');if(n&&n.form&&n.type==="submit"){return true}const r=t.closest("a");const o=/^#.+/;if(r&&r.href&&!o.test(r.getAttribute("href"))){return true}}return false}function dt(e,t){return oe(e).boosted&&e instanceof HTMLAnchorElement&&t.type==="click"&&(t.ctrlKey||t.metaKey)}function pt(e,t,n){const r=e.eventFilter;if(r){try{return r.call(t,n)!==true}catch(e){const o=r.source;fe(te().body,"htmx:eventFilter:error",{error:e,source:o});return true}}return false}function gt(l,c,e,u,f){const a=oe(l);let t;if(u.from){t=m(l,u.from)}else{t=[l]}if(u.changed){if(!("lastValue"in a)){a.lastValue=new WeakMap}t.forEach(function(e){if(!a.lastValue.has(u)){a.lastValue.set(u,new WeakMap)}a.lastValue.get(u).set(e,e.value)})}ie(t,function(i){const s=function(e){if(!se(l)){i.removeEventListener(u.trigger,s);return}if(dt(l,e)){return}if(f||ht(e,i)){e.preventDefault()}if(pt(u,l,e)){return}const t=oe(e);t.triggerSpec=u;if(t.handledFor==null){t.handledFor=[]}if(t.handledFor.indexOf(l)<0){t.handledFor.push(l);if(u.consume){e.stopPropagation()}if(u.target&&e.target){if(!h(ce(e.target),u.target)){return}}if(u.once){if(a.triggeredOnce){return}else{a.triggeredOnce=true}}if(u.changed){const n=e.target;const r=n.value;const o=a.lastValue.get(u);if(o.has(n)&&o.get(n)===r){return}o.set(n,r)}if(a.delayed){clearTimeout(a.delayed)}if(a.throttle){return}if(u.throttle>0){if(!a.throttle){ae(l,"htmx:trigger");c(l,e);a.throttle=b().setTimeout(function(){a.throttle=null},u.throttle)}}else if(u.delay>0){a.delayed=b().setTimeout(function(){ae(l,"htmx:trigger");c(l,e)},u.delay)}else{ae(l,"htmx:trigger");c(l,e)}}};if(e.listenerInfos==null){e.listenerInfos=[]}e.listenerInfos.push({trigger:u.trigger,listener:s,on:i});i.addEventListener(u.trigger,s)})}let mt=false;let yt=null;function xt(){if(!yt){yt=function(){mt=true};window.addEventListener("scroll",yt);window.addEventListener("resize",yt);setInterval(function(){if(mt){mt=false;ie(te().querySelectorAll("[hx-trigger*='revealed'],[data-hx-trigger*='revealed']"),function(e){bt(e)})}},200)}}function bt(e){if(!s(e,"data-hx-revealed")&&F(e)){e.setAttribute("data-hx-revealed","true");const t=oe(e);if(t.initHash){ae(e,"revealed")}else{e.addEventListener("htmx:afterProcessNode",function(){ae(e,"revealed")},{once:true})}}}function vt(e,t,n,r){const o=function(){if(!n.loaded){n.loaded=true;ae(e,"htmx:trigger");t(e)}};if(r>0){b().setTimeout(o,r)}else{o()}}function wt(t,n,e){let i=false;ie(de,function(r){if(s(t,"hx-"+r)){const o=a(t,"hx-"+r);i=true;n.path=o;n.verb=r;e.forEach(function(e){St(t,e,n,function(e,t){const n=ce(e);if(ft(n)){S(n);return}he(r,o,n,t)})})}});return i}function St(r,e,t,n){if(e.trigger==="revealed"){xt();gt(r,n,t,e);bt(ce(r))}else if(e.trigger==="intersect"){const o={};if(e.root){o.root=ue(r,e.root)}if(e.threshold){o.threshold=parseFloat(e.threshold)}const i=new IntersectionObserver(function(t){for(let e=0;e0){t.polling=true;ct(ce(r),n,e)}else{gt(r,n,t,e)}}function Et(e){const t=ce(e);if(!t){return false}const n=t.attributes;for(let e=0;e", "+e).join(""));return o}else{return[]}}function Rt(e){const t=At(e.target);const n=Nt(e);if(n){n.lastButtonClicked=t}}function qt(e){const t=Nt(e);if(t){t.lastButtonClicked=null}}function At(e){return g(ce(e),"button, input[type='submit']")}function Lt(e){return e.form||g(e,"form")}function Nt(e){const t=At(e.target);if(!t){return}const n=Lt(t);if(!n){return}return oe(n)}function It(e){e.addEventListener("click",Rt);e.addEventListener("focusin",Rt);e.addEventListener("focusout",qt)}function Dt(t,e,n){const r=oe(t);if(!Array.isArray(r.onHandlers)){r.onHandlers=[]}let o;const i=function(e){On(t,function(){if(ft(t)){return}if(!o){o=new Function("event",n)}o.call(t,e)})};t.addEventListener(e,i);r.onHandlers.push({event:e,listener:i})}function Pt(t){Pe(t);for(let e=0;eQ.config.historyCacheSize){i.shift()}while(i.length>0){try{sessionStorage.setItem("htmx-history-cache",JSON.stringify(i));break}catch(e){fe(te().body,"htmx:historyCacheError",{cause:e,cache:i});i.shift()}}}function Jt(t){if(!X()){return null}t=U(t);const n=v(sessionStorage.getItem("htmx-history-cache"))||[];for(let e=0;e=200&&this.status<400){r.response=this.response;ae(te().body,"htmx:historyCacheMissLoad",r);ze(r.historyElt,r.response,n,{contextElement:r.historyElt,historyRequest:true});$t(r.path);ae(te().body,"htmx:historyRestore",{path:e,cacheMiss:true,serverResponse:r.response})}else{fe(te().body,"htmx:historyCacheMissLoadError",r)}};if(ae(te().body,"htmx:historyCacheMiss",r)){t.send()}}function en(e){Gt();e=e||location.pathname+location.search;const t=Jt(e);if(t){const n={swapStyle:"innerHTML",swapDelay:0,settleDelay:0,scroll:t.scroll};const r={path:e,item:t,historyElt:_t(),swapSpec:n};if(ae(te().body,"htmx:historyCacheHit",r)){ze(r.historyElt,t.content,n,{contextElement:r.historyElt,title:t.title});$t(r.path);ae(te().body,"htmx:historyRestore",r)}}else{if(Q.config.refreshOnHistoryMiss){Q.location.reload(true)}else{Qt(e)}}}function tn(e){let t=we(e,"hx-indicator");if(t==null){t=[e]}ie(t,function(e){const t=oe(e);t.requestCount=(t.requestCount||0)+1;e.classList.add.call(e.classList,Q.config.requestClass)});return t}function nn(e){let t=we(e,"hx-disabled-elt");if(t==null){t=[]}ie(t,function(e){const t=oe(e);t.requestCount=(t.requestCount||0)+1;e.setAttribute("disabled","");e.setAttribute("data-disabled-by-htmx","")});return t}function rn(e,t){ie(e.concat(t),function(e){const t=oe(e);t.requestCount=(t.requestCount||1)-1});ie(e,function(e){const t=oe(e);if(t.requestCount===0){e.classList.remove.call(e.classList,Q.config.requestClass)}});ie(t,function(e){const t=oe(e);if(t.requestCount===0){e.removeAttribute("disabled");e.removeAttribute("data-disabled-by-htmx")}})}function on(t,n){for(let e=0;en.indexOf(e)<0)}else{e=e.filter(e=>e!==n)}r.delete(t);ie(e,e=>r.append(t,e))}}function un(e){if(e instanceof HTMLSelectElement&&e.multiple){return M(e.querySelectorAll("option:checked")).map(function(e){return e.value})}if(e instanceof HTMLInputElement&&e.files){return M(e.files)}return e.value}function fn(t,n,r,e,o){if(e==null||on(t,e)){return}else{t.push(e)}if(sn(e)){const i=ee(e,"name");ln(i,un(e),n);if(o){an(e,r)}}if(e instanceof HTMLFormElement){ie(e.elements,function(e){if(t.indexOf(e)>=0){cn(e.name,un(e),n)}else{t.push(e)}if(o){an(e,r)}});new FormData(e).forEach(function(e,t){if(e instanceof File&&e.name===""){return}ln(t,e,n)})}}function an(e,t){const n=e;if(n.willValidate){ae(n,"htmx:validation:validate");if(!n.checkValidity()){if(ae(n,"htmx:validation:failed",{message:n.validationMessage,validity:n.validity})&&!t.length&&Q.config.reportValidityOfForms){n.reportValidity()}t.push({elt:n,message:n.validationMessage,validity:n.validity})}}}function hn(n,e){for(const t of e.keys()){n.delete(t)}e.forEach(function(e,t){n.append(t,e)});return n}function dn(e,t){const n=[];const r=new FormData;const o=new FormData;const i=[];const s=oe(e);if(s.lastButtonClicked&&!se(s.lastButtonClicked)){s.lastButtonClicked=null}let l=e instanceof HTMLFormElement&&e.noValidate!==true||a(e,"hx-validate")==="true";if(s.lastButtonClicked){l=l&&s.lastButtonClicked.formNoValidate!==true}if(t!=="get"){fn(n,o,i,Lt(e),l)}fn(n,r,i,e,l);if(s.lastButtonClicked||e.tagName==="BUTTON"||e.tagName==="INPUT"&&ee(e,"type")==="submit"){const u=s.lastButtonClicked||e;const f=ee(u,"name");ln(f,u.value,o)}const c=we(e,"hx-include");ie(c,function(e){fn(n,r,i,ce(e),l);if(!h(e,"form")){ie(p(e).querySelectorAll(ot),function(e){fn(n,r,i,e,l)})}});hn(r,o);return{errors:i,formData:r,values:kn(r)}}function pn(e,t,n){if(e!==""){e+="&"}if(String(n)==="[object Object]"){n=JSON.stringify(n)}const r=encodeURIComponent(n);e+=encodeURIComponent(t)+"="+r;return e}function gn(e){e=Dn(e);let n="";e.forEach(function(e,t){n=pn(n,t,e)});return n}function mn(e,t,n){const r={"HX-Request":"true","HX-Trigger":ee(e,"id"),"HX-Trigger-Name":ee(e,"name"),"HX-Target":a(t,"id"),"HX-Current-URL":location.href};Cn(e,"hx-headers",false,r);if(n!==undefined){r["HX-Prompt"]=n}if(oe(e).boosted){r["HX-Boosted"]="true"}return r}function yn(n,e){const t=ne(e,"hx-params");if(t){if(t==="none"){return new FormData}else if(t==="*"){return n}else if(t.indexOf("not ")===0){ie(t.slice(4).split(","),function(e){e=e.trim();n.delete(e)});return n}else{const r=new FormData;ie(t.split(","),function(t){t=t.trim();if(n.has(t)){n.getAll(t).forEach(function(e){r.append(t,e)})}});return r}}else{return n}}function xn(e){return!!ee(e,"href")&&ee(e,"href").indexOf("#")>=0}function bn(e,t){const n=t||ne(e,"hx-swap");const r={swapStyle:oe(e).boosted?"innerHTML":Q.config.defaultSwapStyle,swapDelay:Q.config.defaultSwapDelay,settleDelay:Q.config.defaultSettleDelay};if(Q.config.scrollIntoViewOnBoost&&oe(e).boosted&&!xn(e)){r.show="top"}if(n){const s=B(n);if(s.length>0){for(let e=0;e0?o.join(":"):null;r.scroll=u;r.scrollTarget=i}else if(l.indexOf("show:")===0){const f=l.slice(5);var o=f.split(":");const a=o.pop();var i=o.length>0?o.join(":"):null;r.show=a;r.showTarget=i}else if(l.indexOf("focus-scroll:")===0){const h=l.slice("focus-scroll:".length);r.focusScroll=h=="true"}else if(e==0){r.swapStyle=l}else{H("Unknown modifier in hx-swap: "+l)}}}}return r}function vn(e){return ne(e,"hx-encoding")==="multipart/form-data"||h(e,"form")&&ee(e,"enctype")==="multipart/form-data"}function wn(t,n,r){let o=null;Vt(n,function(e){if(o==null){o=e.encodeParameters(t,r,n)}});if(o!=null){return o}else{if(vn(n)){return hn(new FormData,Dn(r))}else{return gn(r)}}}function Sn(e){return{tasks:[],elts:[e]}}function En(e,t){const n=e[0];const r=e[e.length-1];if(t.scroll){var o=null;if(t.scrollTarget){o=ce(ue(n,t.scrollTarget))}if(t.scroll==="top"&&(n||o)){o=o||n;o.scrollTop=0}if(t.scroll==="bottom"&&(r||o)){o=o||r;o.scrollTop=o.scrollHeight}if(typeof t.scroll==="number"){b().setTimeout(function(){window.scrollTo(0,t.scroll)},0)}}if(t.show){var o=null;if(t.showTarget){let e=t.showTarget;if(t.showTarget==="window"){e="body"}o=ce(ue(n,e))}if(t.show==="top"&&(n||o)){o=o||n;o.scrollIntoView({block:"start",behavior:Q.config.scrollBehavior})}if(t.show==="bottom"&&(r||o)){o=o||r;o.scrollIntoView({block:"end",behavior:Q.config.scrollBehavior})}}}function Cn(r,e,o,i,s){if(i==null){i={}}if(r==null){return i}const l=a(r,e);if(l){let e=l.trim();let t=o;if(e==="unset"){return null}if(e.indexOf("javascript:")===0){e=e.slice(11);t=true}else if(e.indexOf("js:")===0){e=e.slice(3);t=true}if(e.indexOf("{")!==0){e="{"+e+"}"}let n;if(t){n=On(r,function(){if(s){return Function("event","return ("+e+")").call(r,s)}else{return Function("return ("+e+")").call(r)}},{})}else{n=v(e)}for(const c in n){if(n.hasOwnProperty(c)){if(i[c]==null){i[c]=n[c]}}}}return Cn(ce(u(r)),e,o,i,s)}function On(e,t,n){if(Q.config.allowEval){return t()}else{fe(e,"htmx:evalDisallowedError");return n}}function Hn(e,t,n){return Cn(e,"hx-vars",true,n,t)}function Tn(e,t,n){return Cn(e,"hx-vals",false,n,t)}function Rn(e,t){return le(Hn(e,t),Tn(e,t))}function qn(t,n,r){if(r!==null){try{t.setRequestHeader(n,r)}catch(e){t.setRequestHeader(n,encodeURIComponent(r));t.setRequestHeader(n+"-URI-AutoEncoded","true")}}}function An(t){if(t.responseURL){try{const e=new URL(t.responseURL);return e.pathname+e.search}catch(e){fe(te().body,"htmx:badResponseUrl",{url:t.responseURL})}}}function T(e,t){return t.test(e.getAllResponseHeaders())}function Ln(t,n,r){t=t.toLowerCase();if(r){if(r instanceof Element||typeof r==="string"){return he(t,n,null,null,{targetOverride:w(r)||ve,returnPromise:true})}else{let e=w(r.target);if(r.target&&!e||r.source&&!e&&!w(r.source)){e=ve}return he(t,n,w(r.source),r.event,{handler:r.handler,headers:r.headers,values:r.values,targetOverride:e,swapOverride:r.swap,select:r.select,returnPromise:true,push:r.push,replace:r.replace,selectOOB:r.selectOOB})}}else{return he(t,n,null,null,{returnPromise:true})}}function Nn(e){const t=[];while(e){t.push(e);e=e.parentElement}return t}function In(e,t,n){const r=new URL(t,location.protocol!=="about:"?location.href:window.origin);const o=location.protocol!=="about:"?location.origin:window.origin;const i=o===r.origin;if(Q.config.selfRequestsOnly){if(!i){return false}}return ae(e,"htmx:validateUrl",le({url:r,sameHost:i},n))}function Dn(e){if(e instanceof FormData)return e;const t=new FormData;for(const n in e){if(e.hasOwnProperty(n)){if(e[n]&&typeof e[n].forEach==="function"){e[n].forEach(function(e){t.append(n,e)})}else if(typeof e[n]==="object"&&!(e[n]instanceof Blob)){t.append(n,JSON.stringify(e[n]))}else{t.append(n,e[n])}}}return t}function Pn(r,o,e){return new Proxy(e,{get:function(t,e){if(typeof e==="number")return t[e];if(e==="length")return t.length;if(e==="push"){return function(e){t.push(e);r.append(o,e)}}if(typeof t[e]==="function"){return function(){t[e].apply(t,arguments);r.delete(o);t.forEach(function(e){r.append(o,e)})}}if(t[e]&&t[e].length===1){return t[e][0]}else{return t[e]}},set:function(e,t,n){e[t]=n;r.delete(o);e.forEach(function(e){r.append(o,e)});return true}})}function kn(o){return new Proxy(o,{get:function(e,t){if(typeof t==="symbol"){const r=Reflect.get(e,t);if(typeof r==="function"){return function(){return r.apply(o,arguments)}}else{return r}}if(t==="toJSON"){return()=>Object.fromEntries(o)}if(t in e){if(typeof e[t]==="function"){return function(){return o[t].apply(o,arguments)}}}const n=o.getAll(t);if(n.length===0){return undefined}else if(n.length===1){return n[0]}else{return Pn(e,t,n)}},set:function(t,n,e){if(typeof n!=="string"){return false}t.delete(n);if(e&&typeof e.forEach==="function"){e.forEach(function(e){t.append(n,e)})}else if(typeof e==="object"&&!(e instanceof Blob)){t.append(n,JSON.stringify(e))}else{t.append(n,e)}return true},deleteProperty:function(e,t){if(typeof t==="string"){e.delete(t)}return true},ownKeys:function(e){return Reflect.ownKeys(Object.fromEntries(e))},getOwnPropertyDescriptor:function(e,t){return Reflect.getOwnPropertyDescriptor(Object.fromEntries(e),t)}})}function he(t,n,r,o,i,k){let s=null;let l=null;i=i!=null?i:{};if(i.returnPromise&&typeof Promise!=="undefined"){var e=new Promise(function(e,t){s=e;l=t})}if(r==null){r=te().body}const M=i.handler||Vn;const F=i.select||null;if(!se(r)){re(s);return e}const c=i.targetOverride||ce(Ee(r));if(c==null||c==ve){fe(r,"htmx:targetError",{target:ne(r,"hx-target")});re(l);return e}let u=oe(r);const f=u.lastButtonClicked;if(f){const A=ee(f,"formaction");if(A!=null){n=A}const L=ee(f,"formmethod");if(L!=null){if(de.includes(L.toLowerCase())){t=L}else{re(s);return e}}}const a=ne(r,"hx-confirm");if(k===undefined){const K=function(e){return he(t,n,r,o,i,!!e)};const G={target:c,elt:r,path:n,verb:t,triggeringEvent:o,etc:i,issueRequest:K,question:a};if(ae(r,"htmx:confirm",G)===false){re(s);return e}}let h=r;let d=ne(r,"hx-sync");let p=null;let B=false;if(d){const N=d.split(":");const I=N[0].trim();if(I==="this"){h=Se(r,"hx-sync")}else{h=ce(ue(r,I))}d=(N[1]||"drop").trim();u=oe(h);if(d==="drop"&&u.xhr&&u.abortable!==true){re(s);return e}else if(d==="abort"){if(u.xhr){re(s);return e}else{B=true}}else if(d==="replace"){ae(h,"htmx:abort")}else if(d.indexOf("queue")===0){const W=d.split(" ");p=(W[1]||"last").trim()}}if(u.xhr){if(u.abortable){ae(h,"htmx:abort")}else{if(p==null){if(o){const D=oe(o);if(D&&D.triggerSpec&&D.triggerSpec.queue){p=D.triggerSpec.queue}}if(p==null){p="last"}}if(u.queuedRequests==null){u.queuedRequests=[]}if(p==="first"&&u.queuedRequests.length===0){u.queuedRequests.push(function(){he(t,n,r,o,i)})}else if(p==="all"){u.queuedRequests.push(function(){he(t,n,r,o,i)})}else if(p==="last"){u.queuedRequests=[];u.queuedRequests.push(function(){he(t,n,r,o,i)})}re(s);return e}}const g=new XMLHttpRequest;u.xhr=g;u.abortable=B;const m=function(){u.xhr=null;u.abortable=false;if(u.queuedRequests!=null&&u.queuedRequests.length>0){const e=u.queuedRequests.shift();e()}};const X=ne(r,"hx-prompt");if(X){var y=prompt(X);if(y===null||!ae(r,"htmx:prompt",{prompt:y,target:c})){re(s);m();return e}}if(a&&!k){if(!confirm(a)){re(s);m();return e}}let x=mn(r,c,y);if(t!=="get"&&!vn(r)){x["Content-Type"]="application/x-www-form-urlencoded"}if(i.headers){x=le(x,i.headers)}const U=dn(r,t);let b=U.errors;const V=U.formData;if(i.values){hn(V,Dn(i.values))}const j=Dn(Rn(r,o));const v=hn(V,j);let w=yn(v,r);if(Q.config.getCacheBusterParam&&t==="get"){w.set("org.htmx.cache-buster",ee(c,"id")||"true")}if(n==null||n===""){n=location.href}const S=Cn(r,"hx-request");const $=oe(r).boosted;let E=Q.config.methodsThatUseUrlParams.indexOf(t)>=0;const C={boosted:$,useUrlParams:E,formData:w,parameters:kn(w),unfilteredFormData:v,unfilteredParameters:kn(v),headers:x,elt:r,target:c,verb:t,errors:b,withCredentials:i.credentials||S.credentials||Q.config.withCredentials,timeout:i.timeout||S.timeout||Q.config.timeout,path:n,triggeringEvent:o};if(!ae(r,"htmx:configRequest",C)){re(s);m();return e}n=C.path;t=C.verb;x=C.headers;w=Dn(C.parameters);b=C.errors;E=C.useUrlParams;if(b&&b.length>0){ae(r,"htmx:validation:halted",C);re(s);m();return e}const _=n.split("#");const z=_[0];const O=_[1];let H=n;if(E){H=z;const Z=!w.keys().next().done;if(Z){if(H.indexOf("?")<0){H+="?"}else{H+="&"}H+=gn(w);if(O){H+="#"+O}}}if(!In(r,H,C)){fe(r,"htmx:invalidPath",C);re(l);m();return e}g.open(t.toUpperCase(),H,true);g.overrideMimeType("text/html");g.withCredentials=C.withCredentials;g.timeout=C.timeout;if(S.noHeaders){}else{for(const P in x){if(x.hasOwnProperty(P)){const Y=x[P];qn(g,P,Y)}}}const T={xhr:g,target:c,requestConfig:C,etc:i,boosted:$,select:F,pathInfo:{requestPath:n,finalRequestPath:H,responsePath:null,anchor:O}};g.onload=function(){try{const t=Nn(r);T.pathInfo.responsePath=An(g);M(r,T);if(T.keepIndicators!==true){rn(R,q)}ae(r,"htmx:afterRequest",T);ae(r,"htmx:afterOnLoad",T);if(!se(r)){let e=null;while(t.length>0&&e==null){const n=t.shift();if(se(n)){e=n}}if(e){ae(e,"htmx:afterRequest",T);ae(e,"htmx:afterOnLoad",T)}}re(s)}catch(e){fe(r,"htmx:onLoadError",le({error:e},T));throw e}finally{m()}};g.onerror=function(){rn(R,q);fe(r,"htmx:afterRequest",T);fe(r,"htmx:sendError",T);re(l);m()};g.onabort=function(){rn(R,q);fe(r,"htmx:afterRequest",T);fe(r,"htmx:sendAbort",T);re(l);m()};g.ontimeout=function(){rn(R,q);fe(r,"htmx:afterRequest",T);fe(r,"htmx:timeout",T);re(l);m()};if(!ae(r,"htmx:beforeRequest",T)){re(s);m();return e}var R=tn(r);var q=nn(r);ie(["loadstart","loadend","progress","abort"],function(t){ie([g,g.upload],function(e){e.addEventListener(t,function(e){ae(r,"htmx:xhr:"+t,{lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total})})})});ae(r,"htmx:beforeSend",T);const J=E?null:wn(g,r,w);g.send(J);return e}function Mn(e,t){const n=t.xhr;let r=null;let o=null;if(T(n,/HX-Push:/i)){r=n.getResponseHeader("HX-Push");o="push"}else if(T(n,/HX-Push-Url:/i)){r=n.getResponseHeader("HX-Push-Url");o="push"}else if(T(n,/HX-Replace-Url:/i)){r=n.getResponseHeader("HX-Replace-Url");o="replace"}if(r){if(r==="false"){return{}}else{return{type:o,path:r}}}const i=t.pathInfo.finalRequestPath;const s=t.pathInfo.responsePath;const l=t.etc.push||ne(e,"hx-push-url");const c=t.etc.replace||ne(e,"hx-replace-url");const u=oe(e).boosted;let f=null;let a=null;if(l){f="push";a=l}else if(c){f="replace";a=c}else if(u){f="push";a=s||i}if(a){if(a==="false"){return{}}if(a==="true"){a=s||i}if(t.pathInfo.anchor&&a.indexOf("#")===-1){a=a+"#"+t.pathInfo.anchor}return{type:f,path:a}}else{return{}}}function Fn(e,t){var n=new RegExp(e.code);return n.test(t.toString(10))}function Bn(e){for(var t=0;t`+`.${t}{opacity:0;visibility: hidden} `+`.${n} .${t}, .${n}.${t}{opacity:1;visibility: visible;transition: opacity 200ms ease-in}`+"")}}function Zn(){const e=te().querySelector('meta[name="htmx-config"]');if(e){return v(e.content)}else{return null}}function Yn(){const e=Zn();if(e){Q.config=le(Q.config,e)}}Gn(function(){Yn();Wn();let e=te().body;Ft(e);const t=te().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");e.addEventListener("htmx:abort",function(e){const t=e.detail.elt||e.target;const n=oe(t);if(n&&n.xhr){n.xhr.abort()}});const n=window.onpopstate?window.onpopstate.bind(window):null;window.onpopstate=function(e){if(e.state&&e.state.htmx){en();ie(t,function(e){ae(e,"htmx:restored",{document:te(),triggerEvent:ae})})}else{if(n){n(e)}}};b().setTimeout(function(){ae(e,"htmx:load",{});e=null},0)});return Q}(); \ No newline at end of file +var htmx=(()=>{class e{#e=null;#t=[];issue(e,t){return e.queueStrategy=t,this.#e?"replace"===t||"abort"!==t&&"abort"===this.#e.queueStrategy?(this.#t.map(e=>e.status="dropped"),this.#t=[],this.#e.request.abort(),this.#e=e,!0):("queue all"===t?(this.#t.push(e),e.status="queued"):"drop"===t?e.status="dropped":"queue last"===t?(this.#t.map(e=>e.status="dropped"),this.#t=[e],e.status="queued"):0===this.#t.length&&"abort"!==t?(this.#t.push(e),e.status="queued"):e.status="dropped",!1):(this.#e=e,!0)}finish(){this.#e=null}next(){return this.#t.shift()}abort(){this.#e?.abort?.()}more(){return this.#t?.length}}return new class{#r=new Map;#i="";#s=new Set;#n;#a;#o="a,form";#l=["get","post","put","patch","delete"];#h;#c;#u;constructor(){this.#d(),this.#f(),this.#a=`[${this.#m("hx-action")}],[${this.#m("hx-get")}],[${this.#m("hx-post")}],[${this.#m("hx-put")}],[${this.#m("hx-patch")}],[${this.#m("hx-delete")}]`,this.#h=(new XPathEvaluator).createExpression(`.//*[@*[ starts-with(name(), "${this.#m("hx-on")}")]]`),this.#n={attributeValue:this.#p.bind(this),parseTriggerSpecs:this.#g.bind(this),determineMethodAndAction:this.#x.bind(this),createRequestContext:this.#b.bind(this),collectFormData:this.#y.bind(this),handleHxVals:this.#v.bind(this),insertContent:this.#S.bind(this),morph:this.#E.bind(this)},document.addEventListener("DOMContentLoaded",()=>{this.#w(),this.process(document.body)})}#d(){this.config={version:"4.0.0-alpha6",logAll:!1,prefix:"",transitions:!1,history:!0,mode:"same-origin",defaultSwap:"innerHTML",indicatorClass:"htmx-indicator",requestClass:"htmx-request",includeIndicatorCSS:!0,defaultTimeout:6e4,extensions:"",sse:{reconnect:!1,reconnectDelay:500,reconnectMaxDelay:6e4,reconnectMaxAttempts:10,reconnectJitter:.3,pauseInBackground:!1},morphIgnore:["data-htmx-powered"],morphScanLimit:10,noSwap:[204,304],implicitInheritance:!1};let e=document.querySelector('meta[name="htmx-config"]');e&&this.#C(e.content,this.config),this.#i=this.config.extensions}#f(){if(!1!==this.config.includeIndicatorCSS){let e="";this.config.inlineStyleNonce&&(e=` nonce="${this.config.inlineStyleNonce}"`);let t=this.config.indicatorClass,r=this.config.requestClass;document.head.insertAdjacentHTML("beforeend",`.${t}{opacity:0;visibility: hidden} .${r} .${t}, .${r}.${t}{opacity:1;visibility: visible;transition: opacity 200ms ease-in}`)}}registerExtension(e,t){return!(this.#i&&!this.#i.split(/,\s*/).includes(e))&&(!this.#s.has(e)&&(this.#s.add(e),t.init&&t.init(this.#n),void Object.entries(t).forEach(([e,t])=>{this.#r.get(e)?.push(t)||this.#r.set(e,[t])})))}#q(e){return!e.closest||null!=e.closest(`[${this.#m("hx-ignore")}]`)}#m(e){return this.config.prefix?e.replace("hx-",this.config.prefix):e}#A(e,t){let r=[...e.querySelectorAll(t)];return e.matches?.(t)&&r.unshift(e),r}#T(e){return"before"===e?"beforebegin":"after"===e?"afterend":"prepend"===e?"afterbegin":"append"===e?"beforeend":e}#M(e,t){let r=[];return this.#p(e,t,void 0,(e,t)=>{e?.split(/\s*,\s*/).includes("this")&&r.push(t)}),r}#p(e,t,r,i){let s=(t=this.#m(t))+this.#N(":append"),n=t+(this.config.implicitInheritance?"":this.#N(":inherited")),a=t+this.#N(":inherited:append");if(e.hasAttribute(t)){let r=e.getAttribute(t);return i?i(r,e):r}if(e.hasAttribute(n)){let t=e.getAttribute(n);return i?i(t,e):t}if(e.hasAttribute(s)||e.hasAttribute(a)){let r=e.getAttribute(s)||e.getAttribute(a),o=e.parentNode?.closest?.(`[${CSS.escape(n)}],[${CSS.escape(a)}]`);if(i&&i(r,e),o){let e=this.#p(o,t,void 0,i);return e?(e+","+r).replace(/[{}]/g,""):r}return r}let o=e.parentNode?.closest?.(`[${CSS.escape(n)}],[${CSS.escape(a)}]`);if(o){let r=this.#p(o,t,void 0,i);return!i&&r&&this.config.implicitInheritance&&this.#I(e,"htmx:after:implicitInheritance",{elt:e,name:t,parent:o}),r}return r}#H(e){if("{"===e[0])return JSON.parse(e);return[...e.matchAll(/(?:"([^"]+)"|([^\s,:]+))(?:\s*:\s*(?:"([^"]*)"|'([^']*)'|<([^>]+)\/>|([^\s,]+)))?(?=\s|,|$)/g)].reduce((e,t)=>{let r=(t[1]??t[2]).split("."),i=(t[3]??t[4]??t[5]??t[6]??"true").trim();return"true"===i?i=!0:"false"===i?i=!1:/^\d+$/.test(i)&&(i=parseInt(i)),r.slice(0,-1).reduce((e,t)=>e[t]??={},e)[r.at(-1)]=i,e},{})}#C(e,t){let r=this.#H(e);for(let e in r){let i=r[e];i&&"object"==typeof i&&!Array.isArray(i)&&t[e]?Object.assign(t[e],i):t[e]=i}return t}#g(e){return e.split(",").map(e=>{let t=e.match(/^\s*(\S+\[[^\]]*\]|\S+)\s*(.*?)\s*$/);if(!t||!t[1])return null;if(t[1].includes("[")&&!t[1].includes("]"))throw"unterminated:"+t[1];let r=t[2]?this.#H(t[2]):{};return r.name=t[1],r}).filter(e=>e)}#x(e,t){if(this.#O(e))return this.#L(e,t);{let t=this.#p(e,"hx-method")||"GET",r=this.#p(e,"hx-action");if(!r)for(let i of this.#l){let s=this.#p(e,"hx-"+i);if(s){r=s,t=i;break}}return t=t.toUpperCase(),{action:r,method:t}}}#L(e,t){if(e.matches("a"))return{action:e.getAttribute("href"),method:"GET"};return{action:t.submitter?.getAttribute?.("formAction")||e.getAttribute("action"),method:t.submitter?.getAttribute?.("formMethod")||e.getAttribute("method")||"GET"}}#k(e){this.#V(e)&&this.#R(e,"htmx:before:init",{},!0)&&(e._htmx={eventHandler:this.#_(e)},e.setAttribute("data-htmx-powered","true"),this.#B(e),this.#j(e),this.#R(e,"htmx:after:init",{},!0),this.#R(e,"load",{},!1))}#_(e){return async t=>{try{let r=this.#b(e,t);await this.#D(r)}catch(e){console.error(e)}}}#b(e,t){let{action:r,method:i}=this.#x(e,t),[s,n]=(r||"").split("#"),a=new AbortController,o={sourceElement:e,sourceEvent:t,status:"created",select:this.#p(e,"hx-select"),selectOOB:this.#p(e,"hx-select-oob"),target:this.#p(e,"hx-target"),swap:this.#p(e,"hx-swap")??this.config.defaultSwap,push:this.#p(e,"hx-push-url"),replace:this.#p(e,"hx-replace-url"),transition:this.config.transitions,confirm:this.#p(e,"hx-confirm"),request:{validate:"true"===this.#p(e,"hx-validate",!e.matches("form")||e.noValidate||t.submitter?.formNoValidate?"false":"true"),action:s,anchor:n,method:i,headers:this.#$(e),abort:a.abort.bind(a),credentials:"same-origin",signal:a.signal,mode:this.config.mode}};e._htmx?.boosted&&this.#C(e._htmx.boosted,o),o.target=this.#P(e,o.target);let l=this.#p(e,"hx-config");return l&&(this.#C(l,o.request),o.request.etag&&((e._htmx||={}).etag||=o.request.etag)),e._htmx?.etag&&(o.request.headers["If-none-match"]=e._htmx.etag),o}#F(e){return`${e.tagName.toLowerCase()}${e.id?"#"+e.id:""}`}#$(e){let t={"HX-Request":"true","HX-Source":this.#F(e),"HX-Current-URL":location.href,Accept:"text/html, text/event-stream"};return this.#O(e)&&(t["HX-Boosted"]="true"),t}#z(e,t){return this.#U(e,"hx-headers",e=>{for(let r in e)t[r]=String(e[r])})}#P(e,t){return t instanceof Element?t:null!=t?this.#W(e,t,"hx-target"):this.#O(e)?document.body:e}#O(e){return e?._htmx?.boosted}async#D(e){let t=e.sourceElement,r=e.sourceEvent;if(!t.isConnected)return;if(this.#Q(r))return;this.#J(r)&&r.preventDefault();let i=t.form||t.closest("form"),s=this.#y(t,i,r.submitter,e.request.validate);if(!s)return;let n=this.#v(t,s);if(n&&await n,e.values)for(let t in e.values)s.delete(t),s.append(t,e.values[t]);let a=this.#z(t,e.request.headers);if(a&&await a,e.request.headers["HX-Request-Type"]=e.target===document.body||e.select?"full":"partial",e.target&&(e.request.headers["HX-Target"]=this.#F(e.target)),Object.assign(e.request,{form:i,submitter:r.submitter,body:s}),!this.#R(t,"htmx:config:request",{ctx:e}))return;if(!this.#l.includes(e.request.method.toLowerCase()))return;let o=this.#G(e.request.action);if(null!=o){let t=Object.fromEntries(e.request.body);return void await this.#X(e.sourceElement,t,o,!1)}if(/GET|DELETE/.test(e.request.method)){let t=new URL(e.request.action,document.baseURI);for(let r of e.request.body.keys())t.searchParams.delete(r);for(let[r,i]of e.request.body)t.searchParams.append(r,i);t.origin===location.origin?e.request.action=t.pathname+t.search:e.request.action=t.href,e.request.body=null}else"multipart/form-data"!==this.#p(t,"hx-encoding")&&(e.request.body=new URLSearchParams(e.request.body));await this.#K(e)}async#K(e){let t=e.sourceElement,r=this.#Y(t),i=this.#Z(t);if(!i.issue(e,r))return;e.status="issuing",this.#ee(e);let s=this.#te(t),n=this.#re(t);try{if(e.confirm){let r=null;if(!await new Promise(i=>{if(r=i,this.#R(t,"htmx:confirm",{ctx:e,issueRequest:e=>r?.(!1!==e)})){let r=this.#G(e.confirm);i(r?this.#X(t,{},r,!0):window.confirm(e.confirm))}}))return}if(e.fetch||=window.fetch.bind(window),!this.#R(t,"htmx:before:request",{ctx:e}))return;let r=await e.fetch(e.request.action,e.request);if(e.response={raw:r,status:r.status,headers:r.headers},this.#ie(e),e.isSSE=r.headers.get("Content-Type")?.includes("text/event-stream"),e.isSSE||(e.text=await r.text()),!this.#R(t,"htmx:after:request",{ctx:e}))return;if(this.#se(e))return;let i=r.headers.get("Content-Type")?.includes("text/event-stream");i?await this.#ne(e,t,r):"issuing"===e.status&&(e.hx.retarget&&(e.target=e.hx.retarget),e.hx.reswap&&(e.swap=e.hx.reswap),e.hx.reselect&&(e.select=e.hx.reselect),e.status="response received",this.#ae(e),await this.swap(e),e.status="swapped")}catch(r){e.status="error: "+r,this.#R(t,"htmx:error",{ctx:e,error:r})}finally{this.#oe(s),this.#le(n),this.#R(t,"htmx:finally:request",{ctx:e}),i.finish(),i.more()&&this.#K(i.next())}}#ie(e){e.hx={};for(let[t,r]of e.response.raw.headers)t.toLowerCase().startsWith("hx-")&&(e.hx[t.slice(3).toLowerCase().replace(/-/g,"")]=r)}#se(e){if(e.hx.trigger&&this.#he(e.hx.trigger,e.sourceElement),"true"===e.hx.refresh)return location.reload(),!0;if(e.hx.redirect)return location.href=e.hx.redirect,!0;if(e.hx.location){let t=e.hx.location,r={};return("{"===t[0]||/[\s,]/.test(t))&&(r=this.#H(t),t=r.path,delete r.path),r.push=r.push||"true",this.ajax("GET",t,r),!0}e.response?.headers?.get?.("Etag")&&(e.sourceElement._htmx||={},e.sourceElement._htmx.etag=e.response.headers.get("Etag"))}async#ne(e,t,r){let i={...this.config.sse,...e.request.sse},s=()=>new Promise(e=>{let t=()=>!document.hidden&&(document.removeEventListener("visibilitychange",t),e());document.addEventListener("visibilitychange",t)}),n=null,a=0,o=r;for(;t.isConnected;){if(a>0){if(!i.reconnect||a>i.reconnectMaxAttempts)break;if(i.pauseInBackground&&document.hidden&&(await s(),!t.isConnected))break;let r=Math.min(this.parseInterval(i.reconnectDelay)*Math.pow(2,a-1),this.parseInterval(i.reconnectMaxDelay));if(i.reconnectJitter>0){let e=r*i.reconnectJitter,t=(2*Math.random()-1)*e;r=Math.max(0,r+t)}let l={attempt:a,delay:r,lastEventId:n,cancelled:!1};if(e.status="reconnecting to stream",!this.#R(t,"htmx:before:sse:reconnect",{ctx:e,reconnect:l})||l.cancelled)break;if(await new Promise(e=>setTimeout(e,l.delay)),!t.isConnected)break;try{n&&((e.request.headers=e.request.headers||{})["Last-Event-ID"]=n),o=await fetch(e.request.action,e.request)}catch(r){e.status="stream error",this.#R(t,"htmx:error",{ctx:e,error:r}),a++;continue}}if(!this.#R(t,"htmx:before:sse:stream",{ctx:e}))break;e.status="streaming",a=0;try{for await(const r of this.#ce(o)){if(!t.isConnected)break;if(i.pauseInBackground&&document.hidden&&(await s(),!t.isConnected))break;let a={data:r.data,event:r.event,id:r.id,cancelled:!1};this.#R(t,"htmx:before:sse:message",{ctx:e,message:a})&&!a.cancelled&&(r.id&&(n=r.id),r.event?(this.#R(t,r.event,{data:r.data,id:r.id}),this.#R(t,"htmx:after:sse:message",{ctx:e,message:a})):(e.text=r.data,e.status="stream message received",e.response.cancelled||(await this.swap(e),e.status="swapped"),this.#R(t,"htmx:after:sse:message",{ctx:e,message:a})))}}catch(r){e.status="stream error",this.#R(t,"htmx:error",{ctx:e,error:r})}if(!t.isConnected)break;this.#R(t,"htmx:after:sse:stream",{ctx:e}),a++}}async*#ce(e){let t=e.body.getReader(),r=new TextDecoder,i="",s={data:"",event:"",id:"",retry:null};try{for(;;){let{done:e,value:n}=await t.read();if(e)break;i+=r.decode(n,{stream:!0});let a=i.split("\n");i=a.pop()||"";for(let e of a){if(!e||"\r"===e){s.data&&(yield s,s={data:"",event:"",id:"",retry:null});continue}let t=e.indexOf(":");if(t<=0)continue;let r=e.slice(0,t),i=e.slice(t+1).trimStart();if("data"===r)s.data+=(s.data?"\n":"")+i;else if("event"===r)s.event=i;else if("id"===r)s.id=i;else if("retry"===r){let e=parseInt(i,10);isNaN(e)||(s.retry=e)}}}}finally{t.releaseLock()}}#ee(e){let t;t=e.request.timeout?this.parseInterval(e.request.timeout):this.config.defaultTimeout,e.requestTimeout=setTimeout(()=>e.abort?.(),t)}#Y(e){let t=this.#p(e,"hx-sync");return t?.split(":")[1]||"queue first"}#Z(t){let r=this.#p(t,"hx-sync"),i=t;if(r&&r.includes(":")){let e=r.split(":")[0];i=this.#W(t,e,"hx-sync")}return i._htmxRequestQueue||=new e}#Q(e){return"click"===e.type&&(e.ctrlKey||e.metaKey||e.shiftKey)}#J(e){let t=e.currentTarget;if("submit"===e.type&&"FORM"===t?.tagName)return!0;if(!("click"===e.type&&0===e.button))return!1;let r=t?.closest?.('button, input[type="submit"], input[type="image"]'),i=r?.form||r?.closest("form");if(r&&!r.disabled&&i&&("submit"===r.type||"image"===r.type||!r.type&&"BUTTON"===r.tagName))return!0;let s=t?.closest?.("a");if(!s||!s.href)return!1;let n=s.getAttribute("href");return!(n&&n.startsWith("#")&&n.length>1)}#B(e,t=e._htmx.eventHandler){let r=this.#p(e,"hx-trigger");r||(r=e.matches("form")?"submit":e.matches("input:not([type=button]),select,textarea")?"change":"click"),e._htmx.triggerSpecs=this.#g(r),e._htmx.listeners=[];for(let r of e._htmx.triggerSpecs){r.handler=t,r.listeners=[],r.values={};let[i,s]=this.#ue(r.name);if(r.once){let e=r.handler;r.handler=t=>{e(t);for(let e of r.listeners)e.fromElt.removeEventListener(e.eventName,e.handler)}}if("intersect"===i||"revealed"===i){let t={};r.opts?.root&&(t.root=this.#W(e,r.opts.root)),r.opts?.threshold&&(t.threshold=parseFloat(r.opts.threshold));let s="revealed"===i;r.observer=new IntersectionObserver(t=>{for(let i=0;i{clearTimeout(r.timeout),r.timeout=setTimeout(()=>e(t),this.parseInterval(r.delay))}}if(r.throttle){let e=r.handler;r.handler=t=>{r.throttled?r.throttledEvent=t:(r.throttled=!0,e(t),r.throttleTimeout=setTimeout(()=>{if(r.throttled=!1,r.throttledEvent){let e=r.throttledEvent;r.throttledEvent=null,r.handler(e)}},this.parseInterval(r.throttle)))}}if(r.target){let e=r.handler;r.handler=t=>{t.target?.matches?.(r.target)&&e(t)}}if("every"===i){let t=Object.keys(r).find(e=>"name"!==e);r.interval=setInterval(()=>{e.isConnected?this.#R(e,"every",{},!1):clearInterval(r.interval)},this.parseInterval(t))}if(s){let t=r.handler;r.handler=r=>{this.#J(r)&&r.preventDefault(),this.#de(e,r,s)&&t(r)}}let n=[e];if(r.from&&(n=this.#fe(e,r.from)),r.consume){let e=r.handler;r.handler=t=>{t.stopPropagation(),e(t)}}if(r.changed){let e=r.handler;r.handler=t=>{let i=!1;for(let e of n)r.values[e]!==e.value&&(i=!0,r.values[e]=e.value);i&&e(t)}}for(let t of n){let s={fromElt:t,eventName:i,handler:r.handler};e._htmx.listeners.push(s),r.listeners.push(s),t.addEventListener(i,r.handler)}}}#ue(e){let t=e.match(/^([^\[]*)\[([^\]]*)]/);return t?[t[1],t[2]]:[e,null]}#he(e,t){if("{"===e[0]){let r=this.#H(e);for(let e in r){let i=r[e];i?.target&&(t=this.find(i.target)||t),this.trigger(t,e,"object"==typeof i?i:{value:i})}}else e.split(",").forEach(e=>this.trigger(t,e.trim(),{}))}#me(e){let t={},r=Object.getPrototypeOf(this);for(let i of Object.getOwnPropertyNames(r))"constructor"!==i&&"function"==typeof this[i]&&(["find","findAll"].includes(i)?t[i]=(t,r)=>void 0===r?this[i](e,t):this[i](t,r):t[i]=this[i].bind(this));return t}async#X(e,t,r,i=!0){let s={};Object.assign(s,this.#me(e)),Object.assign(s,t);let n=Object.keys(s),a=Object.values(s),o=new(0,Object.getPrototypeOf(async function(){}).constructor)(...n,i?`return (${r})`:r);return await o.call(e,...a)}#de(e,t,r){let i={};Object.assign(i,this.#me(e));for(let e in t)i[e]=t[e];let s=Object.keys(i),n=Object.values(i);return new Function(...s,`return (${r})`).call(e,...n)}process(e){if(!e||this.#q(e))return;if(!this.#R(e,"htmx:before:process"))return;for(let t of this.#A(e,this.#a))this.#k(t);for(let t of this.#A(e,this.#o))this.#pe(t);this.#ge(e);let t=this.#h.evaluate(e),r=null;for(;r=t.iterateNext();)this.#ge(r);this.#R(e,"htmx:after:process")}#pe(e){let t=this.#p(e,"hx-boost");t&&"false"!==t&&this.#xe(e)&&(e._htmx={eventHandler:this.#_(e),requests:[],boosted:t},e.setAttribute("data-htmx-powered","true"),e.matches("a")&&!e.hasAttribute("target")?e.addEventListener("click",t=>{e._htmx.eventHandler(t)}):e.addEventListener("submit",t=>{e._htmx.eventHandler(t)}),this.#R(e,"htmx:after:init",{},!0))}#xe(e){if(this.#V(e))if("A"===e.tagName){if(""===e.target||"_self"===e.target)return!e.getAttribute("href")?.startsWith?.("#")&&this.#be(e.href)}else if("FORM"===e.tagName)return"dialog"!==e.method&&this.#be(e.action)}#be(e){try{return new URL(e,window.location.href).origin===window.location.origin}catch(e){return!1}}#V(e){return!e._htmx&&!this.#q(e)}#ye(e){if(e._htmx){this.#R(e,"htmx:before:cleanup"),e._htmx.interval&&clearInterval(e._htmx.interval);for(let t of e._htmx.triggerSpecs||[])t.interval&&clearInterval(t.interval),t.timeout&&clearTimeout(t.timeout);for(let t of e._htmx.listeners||[])t.fromElt.removeEventListener(t.eventName,t.handler);this.#R(e,"htmx:after:cleanup")}if(e.firstChild)for(let t of e.querySelectorAll("[data-htmx-powered]"))this.#ye(t)}#ve(e){let t=document.createElement("div");t.style.display="none",document.body.appendChild(t);let r=e.querySelectorAll?.(`[${this.#m("hx-preserve")}]`)||[];for(let e of r){let r=document.getElementById(e.id);r&&(t.moveBefore?t.moveBefore(r,null):t.appendChild(r))}return t}#Se(e){for(let t of e.children){let e=document.getElementById(t.id);e&&(e.parentNode.moveBefore?e.parentNode.moveBefore(t,e):e.replaceWith(t),this.#ye(e),e.remove())}e.remove()}#Ee(e){return Document.parseHTMLUnsafe?.(e)||(new DOMParser).parseFromString(e,"text/html")}#we(e){let t=e.replace(/)/gi,'"),r="";t=t.replace(/]*>[\s\S]*?<\/title>/i,e=>(r=this.#Ee(e).title,""));let i,s,n=t.replace(/]*)?>[\s\S]*?<\/head>/i,""),a=n.match(/<([a-z][^\/>\x20\t\r\n\f]*)/i)?.[1]?.toLowerCase();return"html"===a?(i=this.#Ee(t),s=i.body):"body"===a?(i=this.#Ee(n),s=i.body):(i=this.#Ee(``),s=i.querySelector("template").content),this.#Ce(s),{fragment:s,title:r}}#qe(e,t,r,i){let s=t.id?"#"+CSS.escape(t.id):null;"true"!==r&&r&&!r.includes(" ")&&([r,s=s]=r.split(/:(.*)/)),"true"!==r&&r||(r="outerHTML");let n=this.#Ae(r);if(s=n.target||s,n.strip??=!n.style.startsWith("outer"),!s)return;let a=document.createDocumentFragment();a.append(t),e.push({type:"oob",fragment:a,target:s,swapSpec:n,sourceElement:i})}#Te(e,t,r){let i=[];if(r)for(let s of r.split(",")){let[r,n="true"]=s.split(/:(.*)/);for(let s of e.querySelectorAll(r))this.#qe(i,s,n,t)}for(let r of e.querySelectorAll(`[${this.#m("hx-swap-oob")}]`)){let e=r.getAttribute(this.#m("hx-swap-oob"));r.removeAttribute(this.#m("hx-swap-oob")),this.#qe(i,r,e,t)}return i}#Me(e,t,r){t?t.before(...r.childNodes):e.append(...r.childNodes)}#Ae(e){e=e.trim();let t=this.config.defaultSwap;if(e&&!/^\S*:/.test(e)){let r=e.match(/^(\S+)\s*(.*)$/);t=r[1],e=r[2]}return{style:this.#T(t),...this.#H(e)}}#Ne(e,t){let r=[];for(let i of e.querySelectorAll("template[hx]")){let e=i.getAttribute("type");"partial"===e?r.push({type:"partial",fragment:i.content.cloneNode(!0),target:i.getAttribute(this.#m("hx-target")),swapSpec:this.#Ae(i.getAttribute(this.#m("hx-swap"))||this.config.defaultSwap),sourceElement:t.sourceElement}):this.#I(i,"htmx:process:"+e,{ctx:t,tasks:r}),i.remove()}return r}#Ie(e){let t=this.find(e,"[autofocus]");t?.focus?.()}#He(e,t){if(e.scroll){let r=e.scrollTarget?this.#W(e.scrollTarget):t;"top"===e.scroll?r.scrollTop=0:"bottom"===e.scroll&&(r.scrollTop=r.scrollHeight)}if(e.show){(e.showTarget?this.#W(e.showTarget):t).scrollIntoView("top"===e.show)}}#Oe(e){e.request?.anchor&&document.getElementById(e.request.anchor)?.scrollIntoView({block:"start",behavior:"auto"})}#Ce(e){let t=this.#A(e,"script");for(let e of t){let t=document.createElement("script");for(let r of e.attributes)t.setAttribute(r.name,r.value);this.config.inlineScriptNonce&&(t.nonce=this.config.inlineScriptNonce),t.textContent=e.textContent,e.replaceWith(t)}}async swap(e){this.#Le(e);let{fragment:t,title:r}=this.#we(e.text);e.title=r;let i=[],s=this.#Te(t,e.sourceElement,e.selectOOB),n=this.#Ne(t,e);i.push(...s,...n);let a=this.#ke(e,t,n);if(a&&i.unshift(a),!this.#R(document,"htmx:before:swap",{ctx:e,tasks:i}))return;let o=[],l=[];for(let e of i)e.swapSpec?.transition??a?.transition?l.push(e):o.push(this.#S(e));if(l.length>0){let e=async()=>{for(let e of l)await this.#S(e,!1)};o.push(this.#Ve(e))}await Promise.all(o),this.#R(document,"htmx:after:swap",{ctx:e}),e.title&&!a?.swapSpec?.ignoreTitle&&(document.title=e.title),this.#Oe(e)}#ke(e,t,r){let i=this.#Ae(e.swap||this.config.defaultSwap);if("delete"===i.style||t.childElementCount>0||/\S/.test(t.textContent)||!r.length){if(e.select){let r=t.querySelectorAll(e.select);(t=document.createDocumentFragment()).append(...r)}return this.#O(e.sourceElement)&&(i.show||="top"),{type:"main",fragment:t,target:this.#P(e.sourceElement||document.body,i.target||e.target),swapSpec:i,sourceElement:e.sourceElement,transition:!1!==e.transition&&!1!==i.transition}}}async#S(e,t=!0){let{target:r,swapSpec:i,fragment:s}=e;if("string"==typeof r&&(r=document.querySelector(r)),!r)return;if("string"==typeof i&&(i=this.#Ae(i)),"none"===i.style)return;if(i.strip&&s.firstElementChild&&(s=document.createDocumentFragment(),s.append(...(e.fragment.firstElementChild.content||e.fragment.firstElementChild).childNodes)),r.classList.add("htmx-swapping"),t&&e.swapSpec?.swap&&await this.timeout(e.swapSpec?.swap),"delete"===i.style)return void(r.parentNode&&(this.#ye(r),r.parentNode.removeChild(r)));if("textContent"===i.style)return r.textContent=s.textContent,void r.classList.remove("htmx-swapping");let n=this.#ve(s),a=r.parentNode,o=[...s.childNodes],l=[];try{if("innerHTML"===i.style){l=t?this.#Re(s,r):[];for(const e of r.children)this.#ye(e);r.replaceChildren(...s.childNodes)}else if("outerHTML"===i.style)a&&(l=t?this.#Re(s,r):[],this.#Me(a,r,s),this.#ye(r),a.removeChild(r));else if("innerMorph"===i.style)this.#E(r,s,!0),o=[...r.childNodes];else if("outerMorph"===i.style)this.#E(r,s,!1),o.push(r);else if("beforebegin"===i.style)a&&this.#Me(a,r,s);else if("afterbegin"===i.style)this.#Me(r,r.firstChild,s);else if("beforeend"===i.style)this.#Me(r,null,s);else if("afterend"===i.style)a&&this.#Me(a,r.nextSibling,s);else{let e=this.#r.get("handle_swap"),t=!1;for(const n of e){let e=n(i.style,r,s,i);if(e){t=!0,Array.isArray(e)&&(o=e);break}}if(!t)throw new Error(`Unknown swap style: ${i.style}`)}}finally{r.classList.remove("htmx-swapping")}this.#Se(n),this.#R(r,"htmx:before:settle",{task:e,newContent:o,settleTasks:l});for(const e of o)e.classList?.add?.("htmx-added");if(t){r.classList.add("htmx-settling"),await this.timeout(i.settle??1);for(let e of l)e();r.classList.remove("htmx-settling")}this.#R(r,"htmx:after:settle",{task:e,newContent:o,settleTasks:l});for(const e of o)e.classList?.remove?.("htmx-added"),this.process(e),this.#Ie(e);this.#He(i,r)}#R(e,t,r={},i=!0){return this.config.logAll&&console.log(t,r,e),e=this.#_e(e),this.#I(e,t,r),this.trigger(e,this.#N(t),r,i)}#I(e,t,r={}){let i=this.#r.get(t.replace(/:/g,"_"));if(i){r.cancelled=!1;for(const t of i)if(!1===t(e,r)||r.cancelled)return r.cancelled=!0,!1}return!0}timeout(e){if((e=this.parseInterval(e))>0)return new Promise(t=>setTimeout(t,e))}forEvent(e,t,r=document){return new Promise((i,s)=>{let n=e=>{clearTimeout(a),i(e)},a=t&&setTimeout(()=>{r.removeEventListener(e,n),i(null)},t);r.addEventListener(e,n,{once:!0})})}onLoad(e){this.on("htmx:after:process",t=>{e(t.target)})}takeClass(e,t,r=e.parentElement){for(let e of this.#fe(this.#_e(r),"."+t))e.classList.remove(t);e.classList.add(t)}on(e,t,r){let i,s=document;return void 0===r?(i=e,r=t):(s=this.#_e(e),i=t),s.addEventListener(i,r),r}find(e,t){return this.#W(e,t)}findAll(e,t){return this.#fe(e,t)}parseInterval(e){if("number"==typeof e)return e;let[,t,r]=e?.match(/^([\d.]+)(ms|s|m)?$/)||[],i=parseFloat(t)*({ms:1,s:1e3,m:6e4}[r]||1);return isNaN(i)?void 0:i}trigger(e,t,r={},i=!0){e=this.#_e(e);let s=new CustomEvent(t,{detail:r,cancelable:!0,bubbles:i,composed:!0,originalTarget:e}),n=e.isConnected?e:document;return!r.cancelled&&n.dispatchEvent(s)}ajax(e,t,r){(!r||r instanceof Element||"string"==typeof r)&&(r={target:r});let i="string"==typeof r.source?document.querySelector(r.source):r.source;if("string"==typeof r.source&&!i)return Promise.reject(new Error("Source not found"));let s=this.#P(document.body,r.target||i);if(!s)return Promise.reject(new Error("Target not found"));i||=s;let n=this.#b(i,r.event||{});return Object.assign(n,r,{target:s}),Object.assign(n.request,{action:t,method:e.toUpperCase()}),r.headers&&Object.assign(n.request.headers,r.headers),this.#D(n)}#w(){this.config.history&&(history.state||history.replaceState({htmx:!0},"",location.pathname+location.search),window.addEventListener("popstate",e=>{e.state&&e.state.htmx&&this.#Be()}))}#je(e){this.config.history&&(history.pushState({htmx:!0},"",e),this.#R(document,"htmx:after:push:into:history",{path:e}))}#De(e){this.config.history&&(history.replaceState({htmx:!0},"",e),this.#R(document,"htmx:after:replace:into:history",{path:e}))}#Be(e){if(e=e||location.pathname+location.search,this.#R(document,"htmx:before:restore:history",{path:e,cacheMiss:!0}))"reload"===this.config.history?location.reload():this.ajax("GET",e,{target:"body",request:{headers:{"HX-History-Restore-Request":"true"}}});else if("FORM"===elt.tagName)return"dialog"!==elt.method&&this.#be(elt.action)}#Le(e){let{sourceElement:t,push:r,replace:i,hx:s,response:n}=e;(s?.push||s?.pushurl||s?.replaceurl)&&(r=s.push||s.pushurl,i=s.replaceurl),r||i||!this.#O(t)||(r="true");let a=r||i;if(!a||"false"===a||!1===a)return;if("true"===a){let t=n?.raw?.url||e.request.action,r=new URL(t,location.href);a=r.pathname+r.search+(e.request.anchor?"#"+e.request.anchor:"")}let o=r?"push":"replace",l={history:{type:o,path:a},sourceElement:t,response:n};this.#R(document,"htmx:before:history:update",l)&&("push"===o?this.#je(a):this.#De(a),this.#R(document,"htmx:after:history:update",l))}#ge(e){for(let r of e.getAttributeNames()){var t=this.#N(this.#m("hx-on:"));if(r.startsWith(t)){let i=r.substring(t.length),s=e.getAttribute(r);e.addEventListener(i,async t=>{try{await this.#X(e,{event:t},s,!1)}catch(e){console.log(e)}})}}}#te(e){let t,r=this.#p(e,"hx-indicator");t=r?this.#fe(e,r,"hx-indicator"):[e];for(const e of t)e._htmxReqCount||=0,e._htmxReqCount++,e.classList.add(this.config.requestClass);return t}#oe(e){for(let t of e)t._htmxReqCount&&(t._htmxReqCount--,t._htmxReqCount<=0&&(t.classList.remove(this.config.requestClass),delete t._htmxReqCount))}#re(e){let t=this.#p(e,"hx-disable"),r=[];if(t){r=this.#fe(e,t,"hx-disable");for(let e of r)e._htmxDisableCount||=0,e._htmxDisableCount++,e.disabled=!0}return r}#le(e){for(const t of e)t._htmxDisableCount&&(t._htmxDisableCount--,t._htmxDisableCount<=0&&(t.disabled=!1,delete t._htmxDisableCount))}#y(e,t,r,i){if(i&&t&&!t.reportValidity())return;let s=t?new FormData(t):new FormData,n=t?new Set(t.elements):new Set;if(!t&&e.name){if(i&&e.reportValidity&&!e.reportValidity())return;s.append(e.name,e.value),n.add(e)}r&&r.name&&(s.append(r.name,r.value),n.add(r));let a=this.#p(e,"hx-include");if(a)for(let t of this.#fe(e,a)){if(i&&t.reportValidity&&!t.reportValidity())return;this.#$e(t,n,s)}return s}#$e(e,t,r){let i=this.#A(e,"input:not([disabled]), select:not([disabled]), textarea:not([disabled])");for(let e of i){if(!e.name||t.has(e))continue;t.add(e);let i=e.type;if("checkbox"===i||"radio"===i)e.checked&&r.append(e.name,e.value);else if("file"===i)for(let t of e.files)r.append(e.name,t);else if("select-multiple"===i)for(let t of e.selectedOptions)r.append(e.name,t.value);else e.matches("select, textarea, input")&&r.append(e.name,e.value)}}#U(e,t,r){let i=this.#p(e,t);if(!i)return null;let s=this.#G(i);if(s)return 0!==s.indexOf("{")&&(s="{"+s+"}"),this.#X(e,{},s,!0).then(e=>{r(e)});r(this.#H(i))}#v(e,t){return this.#U(e,"hx-vals",e=>{for(let r in e)t.set(r,e[r])})}#Pe(e){let t=e.trim();return t.startsWith("<")&&t.endsWith("/>")?t.slice(1,-2):t}#fe(e,t,r,i){let s=t??e,n=t?this.#_e(e):document;if(s.startsWith("global "))return this.#fe(n,s.slice(7),r,!0);let a=s?s.replace(/<[^>]+\/>/g,e=>e.replace(/,/g,"%2C")).split(",").map(e=>e.replace(/%2C/g,",")):[],o=[],l=[];for(const e of a){let t,s=this.#Pe(e);if(s.startsWith("closest "))t=n.closest(s.slice(8));else if(s.startsWith("find "))t=n.querySelector(s.slice(5));else if(s.startsWith("findAll "))o.push(...n.querySelectorAll(s.slice(8)));else if("next"===s||"nextElementSibling"===s)t=n.nextElementSibling;else if(s.startsWith("next "))t=this.#Fe(n,s.slice(5),!!i);else if("previous"===s||"previousElementSibling"===s)t=n.previousElementSibling;else if(s.startsWith("previous "))t=this.#ze(n,s.slice(9),!!i);else if("document"===s)t=document;else if("window"===s)t=window;else if("body"===s)t=document.body;else if("host"===s)t=n.getRootNode().host;else if("this"===s){if(r){o.push(...this.#M(n,r));continue}t=n}else l.push(s);t&&o.push(t)}if(l.length>0){let e=l.join(","),t=this.#Ue(n,!!i);o.push(...t.querySelectorAll(e))}return[...new Set(o)]}#Fe(e,t,r){return this.#We(this.#Ue(e,r).querySelectorAll(t),e,Node.DOCUMENT_POSITION_PRECEDING)}#ze(e,t,r){let i=[...this.#Ue(e,r).querySelectorAll(t)].reverse();return this.#We(i,e,Node.DOCUMENT_POSITION_FOLLOWING)}#We(e,t,r){for(const i of e)if(i.compareDocumentPosition(t)===r)return i}#Ue(e,t){return e.isConnected&&e.getRootNode?e.getRootNode?.({composed:t}):document}#W(e,t,r){return this.#fe(e,t,r)[0]}#G(e){if(null!=e){if(e.startsWith("js:"))return e.substring(3);if(e.startsWith("javascript:"))return e.substring(11)}}#j(e){e.addEventListener("htmx:abort",()=>{this.#Z(e).abort()})}#E(e,t,r){let{persistentIds:i,idMap:s}=this.#Qe(e,t),n=document.createElement("div");n.hidden=!0,document.body.after(n);let a={target:e,idMap:s,persistentIds:i,pantry:n};r?this.#Je(a,e,t):this.#Je(a,e.parentNode,t,e,e.nextSibling),this.#ye(n),n.remove()}#Je(e,t,r,i=null,s=null){t instanceof HTMLTemplateElement&&r instanceof HTMLTemplateElement&&(t=t.content,r=r.content),i||=t.firstChild;for(const n of r.childNodes){if(i&&i!=s){let t=this.#Ge(e,n,i,s);if(t){if(t!==i){let r=i;for(;r&&r!==t;){let t=r;r=r.nextSibling,this.#Xe(e,t)}}this.#Ke(t,n,e),i=t.nextSibling;continue}}if(n instanceof Element&&e.persistentIds.has(n.id)){let r=e.target.id===n.id&&e.target||e.target.querySelector(`[id="${n.id}"]`)||e.pantry.querySelector(`[id="${n.id}"]`),s=r.id,a=r;for(;a=a.parentNode;){let t=e.idMap.get(a);t&&(t.delete(s),t.size||e.idMap.delete(a))}this.#Ye(t,r,i),this.#Ke(r,n,e),i=r.nextSibling;continue}let r;e.idMap.has(n)?(r=document.createElement(n.tagName),t.insertBefore(r,i),this.#Ke(r,n,e)):(r=document.importNode(n,!0),t.insertBefore(r,i)),i=r.nextSibling}for(;i&&i!=s;){let t=i;i=i.nextSibling,this.#Xe(e,t)}}#Ge(e,t,r,i){let s=null,n=t.nextSibling,a=0,o=0,l=this.config.morphScanLimit,h=e.idMap.get(t),c=h?.size||0,u=r;for(;u&&u!=i;){let r=e.idMap.get(u);if(this.#Ze(u,t)){if(r&&h&&[...r].some(e=>h.has(e)))return u;if(!r){if(l>0&&u.isEqualNode(t))return u;s||(s=u)}}if(o+=r?.size||0,o>c)break;if(n&&l>0&&u.isEqualNode(n)&&(a++,n=n.nextSibling,a>=2))return null;if(u.contains(document.activeElement))break;if(--l<1&&0===c)break;u=u.nextSibling}return s||null}#Ze(e,t){return e.nodeType===t.nodeType&&e.tagName===t.tagName&&(!e.id||e.id===t.id)}#Xe(e,t){e.idMap.has(t)?this.#Ye(e.pantry,t,null):(this.#ye(t),t.remove())}#Ye(e,t,r){if(e.moveBefore)try{return void e.moveBefore(t,r)}catch(e){}e.insertBefore(t,r)}#Ke(e,t,r){let i=t.nodeType;if(1===i){if(this.config.morphSkip&&e.matches?.(this.config.morphSkip))return;this.#et(e,t),e instanceof HTMLTextAreaElement&&e.defaultValue!=t.defaultValue&&(e.value=t.value)}8!==i&&3!==i||e.nodeValue===t.nodeValue||(e.nodeValue=t.nodeValue),this.config.morphSkipChildren&&e.matches?.(this.config.morphSkipChildren)||e.isEqualNode(t)||this.#Je(r,e,t)}#et(e,t){let r=this.config.morphIgnore||[];for(const i of t.attributes)r.includes(i.name)||e.getAttribute(i.name)===i.value||(e.setAttribute(i.name,i.value),"value"===i.name&&e instanceof HTMLInputElement&&"file"!==e.type&&(e.value=i.value));for(let i=e.attributes.length-1;i>=0;i--){let s=e.attributes[i];!s||t.hasAttribute(s.name)||r.includes(s.name)||e.removeAttribute(s.name)}}#tt(e,t,r,i){for(const s of i)if(t.has(s.id)){let t=s;for(;t&&t!==r;){let r=e.get(t);null==r&&(r=new Set,e.set(t,r)),r.add(s.id),t=t.parentElement}}}#Qe(e,t){let r=this.#A(e,"[id]"),i=t.querySelectorAll("[id]"),s=this.#rt(r,i),n=new Map;return this.#tt(n,s,e.parentElement,r),this.#tt(n,s,t,i),{persistentIds:s,idMap:n}}#rt(e,t){let r=new Set,i=new Map;for(const{id:t,tagName:s}of e)i.has(t)?r.add(t):i.set(t,s);let s=new Set;for(const{id:e,tagName:n}of t)s.has(e)?r.add(e):i.get(e)===n&&s.add(e);for(const e of r)s.delete(e);return s}#ae(e){let t=e.response.raw.status,r=this.config.noSwap.map(e=>e+""),i=t+"";for(let t of[i,i.slice(0,2)+"x",i[0]+"xx"]){if(r.includes(t))return void(e.swap="none");let i=this.#p(e.sourceElement,"hx-status:"+t);if(i)return void this.#C(i,e)}}#Ve(e){return new Promise(t=>{this.#c||=[],this.#c.push({task:e,resolve:t}),this.#u||this.#it()})}async#it(){if(0===this.#c.length||this.#u)return;this.#u=!0;let{task:e,resolve:t}=this.#c.shift();try{document.startViewTransition?(this.#R(document,"htmx:before:viewTransition",{task:e}),await document.startViewTransition(e).finished,this.#R(document,"htmx:after:viewTransition",{task:e})):e()}catch(e){}finally{this.#u=!1,t(),this.#it()}}#Re(e,t){let r=t.querySelectorAll("[id]"),i=Object.fromEntries([...r].map(e=>[e.id,e])),s=e.querySelectorAll("[id]"),n=[];for(let e of s){let t=i[e.id];if(t?.tagName===e.tagName){let r=e.cloneNode(!1);this.#et(e,t),n.push(()=>{this.#et(e,r)})}}return n}#_e(e){return"string"==typeof e?this.find(e):e}#N(e){return this.config.metaCharacter?e.replace(/:/g,this.config.metaCharacter):e}}})(); \ No newline at end of file diff --git a/src/Tests/ViewEngine.fs b/src/Tests/ViewEngine.fs index e6e58a4..9f71f09 100644 --- a/src/Tests/ViewEngine.fs +++ b/src/Tests/ViewEngine.fs @@ -15,6 +15,7 @@ let hxEncoding = } ] +#nowarn 44 // Obsolete events still have tests let hxEvent = testList "HxEvent" [ testList "Abort" [ @@ -25,12 +26,40 @@ let hxEvent = Expect.equal (Abort.ToHxOnString()) "abort" "Abort hx-on event name not correct" } ] + testList "AfterCleanup" [ + test "ToString succeeds" { + Expect.equal (string AfterCleanup) "afterCleanup" "AfterCleanup event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (AfterCleanup.ToHxOnString()) "after:cleanup" "AfterCleanup hx-on event name not correct" + } + ] + testList "AfterHistoryUpdate" [ + test "ToString succeeds" { + Expect.equal + (string AfterHistoryUpdate) "afterHistoryUpdate" "AfterHistoryUpdate event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (AfterHistoryUpdate.ToHxOnString()) + "after:history:update" + "AfterHistoryUpdate hx-on event name not correct" + } + ] + testList "AfterInit" [ + test "ToString succeeds" { + Expect.equal (string AfterInit) "afterInit" "AfterInit event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (AfterInit.ToHxOnString()) "after:init" "AfterInit hx-on event name not correct" + } + ] testList "AfterOnLoad" [ test "ToString succeeds" { Expect.equal (string AfterOnLoad) "afterOnLoad" "AfterOnLoad event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (AfterOnLoad.ToHxOnString()) "after-on-load" "AfterOnLoad hx-on event name not correct" + Expect.equal (AfterOnLoad.ToHxOnString()) "after:init" "AfterOnLoad hx-on event name not correct" } ] testList "AfterProcessNode" [ @@ -39,9 +68,33 @@ let hxEvent = } test "ToHxOnString succeeds" { Expect.equal - (AfterProcessNode.ToHxOnString()) - "after-process-node" - "AfterProcessNode hx-on event name not correct" + (AfterProcessNode.ToHxOnString()) "after:init" "AfterProcessNode hx-on event name not correct" + } + ] + testList "AfterPushIntoHistory" [ + test "ToString succeeds" { + Expect.equal + (string AfterPushIntoHistory) "afterPushIntoHistory" "AfterPushIntoHistory event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (AfterPushIntoHistory.ToHxOnString()) + "after:push:into:history" + "AfterOnLoad hx-on event name not correct" + } + ] + testList "AfterReplaceIntoHistory" [ + test "ToString succeeds" { + Expect.equal + (string AfterReplaceIntoHistory) + "afterReplaceIntoHistory" + "AfterReplaceIntoHistory event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (AfterPushIntoHistory.ToHxOnString()) + "after:push:into:history" + "AfterOnLoad hx-on event name not correct" } ] testList "AfterRequest" [ @@ -49,7 +102,7 @@ let hxEvent = Expect.equal (string AfterRequest) "afterRequest" "AfterRequest event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (AfterRequest.ToHxOnString()) "after-request" "AfterRequest hx-on event name not correct" + Expect.equal (AfterRequest.ToHxOnString()) "after:request" "AfterRequest hx-on event name not correct" } ] testList "AfterSettle" [ @@ -57,7 +110,25 @@ let hxEvent = Expect.equal (string AfterSettle) "afterSettle" "AfterSettle event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (AfterSettle.ToHxOnString()) "after-settle" "AfterSettle hx-on event name not correct" + Expect.equal (AfterSettle.ToHxOnString()) "after:swap" "AfterSettle hx-on event name not correct" + } + ] + testList "AfterSseMessage" [ + test "ToString succeeds" { + Expect.equal (string AfterSseMessage) "afterSseMessage" "AfterSseMessage event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (AfterSseMessage.ToHxOnString()) "after:sse:message" "AfterSseMessage hx-on event name not correct" + } + ] + testList "AfterSseStream" [ + test "ToString succeeds" { + Expect.equal (string AfterSseStream) "afterSseStream" "AfterSseStream event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (AfterSseStream.ToHxOnString()) "after:sse:stream" "AfterSseStream hx-on event name not correct" } ] testList "AfterSwap" [ @@ -65,7 +136,16 @@ let hxEvent = Expect.equal (string AfterSwap) "afterSwap" "AfterSwap event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (AfterSwap.ToHxOnString()) "after-swap" "AfterSwap hx-on event name not correct" + Expect.equal (AfterSwap.ToHxOnString()) "after:swap" "AfterSwap hx-on event name not correct" + } + ] + testList "BeforeCleanup" [ + test "ToString succeeds" { + Expect.equal (string BeforeCleanup) "beforeCleanup" "BeforeCleanup event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeCleanup.ToHxOnString()) "before:cleanup" "BeforeCleanup hx-on event name not correct" } ] testList "BeforeCleanupElement" [ @@ -76,16 +156,47 @@ let hxEvent = test "ToHxOnString succeeds" { Expect.equal (BeforeCleanupElement.ToHxOnString()) - "before-cleanup-element" + "before:cleanup" "BeforeCleanupElement hx-on event name not correct" } ] + testList "BeforeHistorySave" [ + test "ToString succeeds" { + Expect.equal (string BeforeHistorySave) "beforeHistorySave" "BeforeHistorySave event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeHistorySave.ToHxOnString()) + "before:history:update" + "BeforeHistorySave hx-on event name not correct" + } + ] + testList "BeforeHistoryUpdate" [ + test "ToString succeeds" { + Expect.equal + (string BeforeHistoryUpdate) "beforeHistoryUpdate" "BeforeHistoryUpdate event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeHistoryUpdate.ToHxOnString()) + "before:history:update" + "BeforeHistoryUpdate hx-on event name not correct" + } + ] + testList "BeforeInit" [ + test "ToString succeeds" { + Expect.equal (string BeforeInit) "beforeInit" "BeforeInit event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (BeforeInit.ToHxOnString()) "before:init" "BeforeInit hx-on event name not correct" + } + ] testList "BeforeOnLoad" [ test "ToString succeeds" { Expect.equal (string BeforeOnLoad) "beforeOnLoad" "BeforeOnLoad event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (BeforeOnLoad.ToHxOnString()) "before-on-load" "BeforeOnLoad hx-on event name not correct" + Expect.equal (BeforeOnLoad.ToHxOnString()) "before:init" "BeforeOnLoad hx-on event name not correct" } ] testList "BeforeProcessNode" [ @@ -94,9 +205,19 @@ let hxEvent = } test "ToHxOnString succeeds" { Expect.equal - (BeforeProcessNode.ToHxOnString()) - "before-process-node" - "BeforeProcessNode hx-on event name not correct" + (BeforeProcessNode.ToHxOnString()) "before:init" "BeforeProcessNode hx-on event name not correct" + } + ] + testList "BeforeRestoreHistory" [ + test "ToString succeeds" { + Expect.equal + (string BeforeRestoreHistory) "beforeRestoreHistory" "BeforeRestoreHistory event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeRestoreHistory.ToHxOnString()) + "before:restore:history" + "BeforeRestoreHistory hx-on event name not correct" } ] testList "BeforeRequest" [ @@ -105,15 +226,39 @@ let hxEvent = } test "ToHxOnString succeeds" { Expect.equal - (BeforeRequest.ToHxOnString()) "before-request" "BeforeRequest hx-on event name not correct" + (BeforeRequest.ToHxOnString()) "before:request" "BeforeRequest hx-on event name not correct" } ] - testList "BeforeSwap" [ + testList "BeforeSseMessage" [ test "ToString succeeds" { - Expect.equal (string BeforeSwap) "beforeSwap" "BeforeSwap event name not correct" + Expect.equal (string BeforeSseMessage) "beforeSseMessage" "BeforeSseMessage event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (BeforeSwap.ToHxOnString()) "before-swap" "BeforeSwap hx-on event name not correct" + Expect.equal + (BeforeSseMessage.ToHxOnString()) + "before:sse:message" + "BeforeSseMessage hx-on event name not correct" + } + ] + testList "BeforeSseReconnect" [ + test "ToString succeeds" { + Expect.equal + (string BeforeSseReconnect) "beforeSseReconnect" "BeforeSseReconnect event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeSseReconnect.ToHxOnString()) + "before:sse:reconnect" + "BeforeSseReconnect hx-on event name not correct" + } + ] + testList "BeforeSseStream" [ + test "ToString succeeds" { + Expect.equal (string BeforeSseStream) "beforeSseStream" "BeforeSseStream event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeSseStream.ToHxOnString()) "before:sse:stream" "BeforeSseStream hx-on event name not correct" } ] testList "BeforeSend" [ @@ -121,7 +266,15 @@ let hxEvent = Expect.equal (string BeforeSend) "beforeSend" "BeforeSend event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (BeforeSend.ToHxOnString()) "before-send" "BeforeSend hx-on event name not correct" + Expect.equal (BeforeSend.ToHxOnString()) "before:request" "BeforeSend hx-on event name not correct" + } + ] + testList "BeforeSwap" [ + test "ToString succeeds" { + Expect.equal (string BeforeSwap) "beforeSwap" "BeforeSwap event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (BeforeSwap.ToHxOnString()) "before:swap" "BeforeSwap hx-on event name not correct" } ] testList "ConfigRequest" [ @@ -130,7 +283,7 @@ let hxEvent = } test "ToHxOnString succeeds" { Expect.equal - (ConfigRequest.ToHxOnString()) "config-request" "ConfigRequest hx-on event name not correct" + (ConfigRequest.ToHxOnString()) "config:request" "ConfigRequest hx-on event name not correct" } ] testList "Confirm" [ @@ -141,6 +294,23 @@ let hxEvent = Expect.equal (Confirm.ToHxOnString()) "confirm" "Confirm hx-on event name not correct" } ] + testList "Error" [ + test "ToString succeeds" { + Expect.equal (string Error) "error" "Error event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (Error.ToHxOnString()) "error" "Error hx-on event name not correct" + } + ] + testList "FinallyRequest" [ + test "ToString succeeds" { + Expect.equal (string FinallyRequest) "finallyRequest" "FinallyRequest event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (FinallyRequest.ToHxOnString()) "finally:request" "FinallyRequest hx-on event name not correct" + } + ] testList "HistoryCacheError" [ test "ToString succeeds" { Expect.equal (string HistoryCacheError) "historyCacheError" "HistoryCacheError event name not correct" @@ -159,7 +329,7 @@ let hxEvent = test "ToHxOnString succeeds" { Expect.equal (HistoryCacheMiss.ToHxOnString()) - "history-cache-miss" + "before:history:restore" "HistoryCacheMiss hx-on event name not correct" } ] @@ -185,7 +355,7 @@ let hxEvent = test "ToHxOnString succeeds" { Expect.equal (HistoryCacheMissLoad.ToHxOnString()) - "history-cache-miss-load" + "before:history:restore" "HistoryCacheMissLoad hx-on event name not correct" } ] @@ -195,18 +365,9 @@ let hxEvent = } test "ToHxOnString succeeds" { Expect.equal - (HistoryRestore.ToHxOnString()) "history-restore" "HistoryRestore hx-on event name not correct" - } - ] - testList "BeforeHistorySave" [ - test "ToString succeeds" { - Expect.equal (string BeforeHistorySave) "beforeHistorySave" "BeforeHistorySave event name not correct" - } - test "ToHxOnString succeeds" { - Expect.equal - (BeforeHistorySave.ToHxOnString()) - "before-history-save" - "BeforeHistorySave hx-on event name not correct" + (HistoryRestore.ToHxOnString()) + "before:history:restore" + "HistoryRestore hx-on event name not correct" } ] testList "Load" [ @@ -214,7 +375,7 @@ let hxEvent = Expect.equal (string Load) "load" "Load event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (Load.ToHxOnString()) "load" "Load hx-on event name not correct" + Expect.equal (Load.ToHxOnString()) "after:init" "Load hx-on event name not correct" } ] testList "NoSseSourceError" [ @@ -222,10 +383,7 @@ let hxEvent = Expect.equal (string NoSseSourceError) "noSSESourceError" "NoSseSourceError event name not correct" } test "ToHxOnString succeeds" { - Expect.equal - (NoSseSourceError.ToHxOnString()) - "no-sse-source-error" - "NoSseSourceError hx-on event name not correct" + Expect.equal (NoSseSourceError.ToHxOnString()) "error" "NoSseSourceError hx-on event name not correct" } ] testList "OnLoadError" [ @@ -233,7 +391,7 @@ let hxEvent = Expect.equal (string OnLoadError) "onLoadError" "OnLoadError event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (OnLoadError.ToHxOnString()) "on-load-error" "OnLoadError hx-on event name not correct" + Expect.equal (OnLoadError.ToHxOnString()) "error" "OnLoadError hx-on event name not correct" } ] testList "OobAfterSwap" [ @@ -241,7 +399,7 @@ let hxEvent = Expect.equal (string OobAfterSwap) "oobAfterSwap" "OobAfterSwap event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (OobAfterSwap.ToHxOnString()) "oob-after-swap" "OobAfterSwap hx-on event name not correct" + Expect.equal (OobAfterSwap.ToHxOnString()) "after:swap" "OobAfterSwap hx-on event name not correct" } ] testList "OobBeforeSwap" [ @@ -249,8 +407,7 @@ let hxEvent = Expect.equal (string OobBeforeSwap) "oobBeforeSwap" "OobBeforeSwap event name not correct" } test "ToHxOnString succeeds" { - Expect.equal - (OobBeforeSwap.ToHxOnString()) "oob-before-swap" "OobBeforeSwap hx-on event name not correct" + Expect.equal (OobBeforeSwap.ToHxOnString()) "before:swap" "OobBeforeSwap hx-on event name not correct" } ] testList "OobErrorNoTarget" [ @@ -258,10 +415,7 @@ let hxEvent = Expect.equal (string OobErrorNoTarget) "oobErrorNoTarget" "OobErrorNoTarget event name not correct" } test "ToHxOnString succeeds" { - Expect.equal - (OobErrorNoTarget.ToHxOnString()) - "oob-error-no-target" - "OobErrorNoTarget hx-on event name not correct" + Expect.equal (OobErrorNoTarget.ToHxOnString()) "error" "OobErrorNoTarget hx-on event name not correct" } ] testList "Prompt" [ @@ -279,7 +433,7 @@ let hxEvent = test "ToHxOnString succeeds" { Expect.equal (PushedIntoHistory.ToHxOnString()) - "pushed-into-history" + "after:push:into:history" "PushedIntoHistory hx-on event name not correct" } ] @@ -288,8 +442,7 @@ let hxEvent = Expect.equal (string ResponseError) "responseError" "ResponseError event name not correct" } test "ToHxOnString succeeds" { - Expect.equal - (ResponseError.ToHxOnString()) "response-error" "ResponseError hx-on event name not correct" + Expect.equal (ResponseError.ToHxOnString()) "error" "ResponseError hx-on event name not correct" } ] testList "SendError" [ @@ -297,7 +450,7 @@ let hxEvent = Expect.equal (string SendError) "sendError" "SendError event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (SendError.ToHxOnString()) "send-error" "SendError hx-on event name not correct" + Expect.equal (SendError.ToHxOnString()) "error" "SendError hx-on event name not correct" } ] testList "SseError" [ @@ -305,7 +458,7 @@ let hxEvent = Expect.equal (string SseError) "sseError" "SseError event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (SseError.ToHxOnString()) "sse-error" "SseError hx-on event name not correct" + Expect.equal (SseError.ToHxOnString()) "error" "SseError hx-on event name not correct" } ] testList "SseOpen" [ @@ -321,7 +474,7 @@ let hxEvent = Expect.equal (string SwapError) "swapError" "SwapError event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (SwapError.ToHxOnString()) "swap-error" "SwapError hx-on event name not correct" + Expect.equal (SwapError.ToHxOnString()) "error" "SwapError hx-on event name not correct" } ] testList "TargetError" [ @@ -329,7 +482,7 @@ let hxEvent = Expect.equal (string TargetError) "targetError" "TargetError event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (TargetError.ToHxOnString()) "target-error" "TargetError hx-on event name not correct" + Expect.equal (TargetError.ToHxOnString()) "error" "TargetError hx-on event name not correct" } ] testList "Timeout" [ @@ -337,7 +490,7 @@ let hxEvent = Expect.equal (string Timeout) "timeout" "Timeout event name not correct" } test "ToHxOnString succeeds" { - Expect.equal (Timeout.ToHxOnString()) "timeout" "Timeout hx-on event name not correct" + Expect.equal (Timeout.ToHxOnString()) "error" "Timeout hx-on event name not correct" } ] testList "ValidationValidate" [ @@ -407,6 +560,7 @@ let hxEvent = } ] ] +#warn 44 // Obsolete should be flagged from here on /// Tests for the HxHeaders module let hxHeaders = @@ -719,13 +873,21 @@ let hxVals = let shouldRender expected node = Expect.equal (RenderView.AsString.htmlNode node) expected "Rendered HTML incorrect" +#nowarn 44 // Still have tests for obsolete attributes /// Tests for the HtmxAttrs module let attributes = testList "Attributes" [ + test "_hxAction succeeds" { + form [ _hxAction "/endpoint/1" ] [] |> shouldRender """
""" + } test "_hxBoost succeeds" { div [ _hxBoost ] [] |> shouldRender """
""" } + test "_hxConfig succeeds" { + body [ _hxConfig [ ("test", "that") ] ] [] + |> shouldRender """""" + } test "_hxConfirm succeeds" { button [ _hxConfirm "REALLY?!?" ] [] |> shouldRender """""" } @@ -733,7 +895,7 @@ let attributes = span [ _hxDelete "/this-endpoint" ] [] |> shouldRender """""" } test "_hxDisable succeeds" { - p [ _hxDisable ] [] |> shouldRender """

""" + p [ _hxDisable "#that" ] [] |> shouldRender """

""" } test "_hxDisabledElt succeeds" { button [ _hxDisabledElt "this" ] [] |> shouldRender """""" @@ -760,12 +922,19 @@ let attributes = test "_hxHistoryElt succeeds" { table [ _hxHistoryElt ] [] |> shouldRender """
""" } + test "_hxIgnore succeeds" { + span [ _hxIgnore ] [] |> shouldRender """""" + } test "_hxInclude succeeds" { a [ _hxInclude ".extra-stuff" ] [] |> shouldRender """""" } test "_hxIndicator succeeds" { aside [ _hxIndicator "#spinner" ] [] |> shouldRender """""" } + test "_hxMethod succeeds" { + div [ _hxMethod System.Net.Http.HttpMethod.Options ] [] + |> shouldRender """
""" + } test "_hxNoBoost succeeds" { td [ _hxNoBoost ] [] |> shouldRender """""" } @@ -774,7 +943,7 @@ let attributes = } test "_hxOnHxEvent succeeds" { strong [ _hxOnHxEvent BeforeSwap "changeStuff()" ] [] - |> shouldRender """""" + |> shouldRender """""" } test "_hxParams succeeds" { br [ _hxParams "[p1,p2]" ] |> shouldRender """
""" @@ -830,17 +999,21 @@ let attributes = test "_hxTrigger succeeds" { figcaption [ _hxTrigger "load" ] [] |> shouldRender """
""" } + test "_hxValidate succeeds" { + form [ _hxValidate ] [] |> shouldRender """
""" + } test "_hxVals succeeds" { dt [ _hxVals """{ "extra": "values" }""" ] [] |> shouldRender """
""" } - test "_sseSwap succeeds" { - ul [ _sseSwap "sseMessageName" ] [] |> shouldRender """
    """ - } test "_sseConnect succeeds" { div [ _sseConnect "/gps/sse" ] [] |> shouldRender """
    """ } + test "_sseSwap succeeds" { + ul [ _sseSwap "sseMessageName" ] [] |> shouldRender """
      """ + } ] +#warn 44 // Obsolete should be flagged from here on open Giraffe.Htmx.Common @@ -858,14 +1031,14 @@ let script = let html = RenderView.AsString.htmlNode Script.cdnMinified Expect.equal html - $"""""" + $"""""" "CDN minified script tag is incorrect" } test "cdnUnminified succeeds" { let html = RenderView.AsString.htmlNode Script.cdnUnminified Expect.equal html - $"""""" + $"""""" "CDN unminified script tag is incorrect" } ] diff --git a/src/ViewEngine.Htmx/Htmx.fs b/src/ViewEngine.Htmx/Htmx.fs index 8ea89bd..77614dd 100644 --- a/src/ViewEngine.Htmx/Htmx.fs +++ b/src/ViewEngine.Htmx/Htmx.fs @@ -16,13 +16,21 @@ module HxEncoding = let MultipartForm = "multipart/form-data" +#nowarn 44 // Obsolete elements still have entries in the conversion map; will be removed for v4 final /// The events recognized by htmx +/// Documentation [] type HxEvent = /// Send this event to an element to abort a request | Abort + /// Triggered after htmx disables an element or removes it from the DOM + | AfterCleanup + + /// Triggered after content is saved to the history cache + | AfterHistoryUpdate + /// Triggered after a request has initialized | AfterInit @@ -32,17 +40,35 @@ type HxEvent = /// Triggered after htmx has initialized a node | [] AfterProcessNode - /// Triggered after an AJAX request has completed + /// Triggered after new content is saved to the history cache + | AfterPushIntoHistory + + /// Triggered after updated content is saved to the history cache + | AfterReplaceIntoHistory + + /// Triggered after an HTTP request has completed successfully | AfterRequest /// Triggered after the DOM has settled | [] AfterSettle + /// Triggered after a Server Sent Events (SSE) message is read + | AfterSseMessage + + /// Triggered after a Server Sent Events (SSE) stream is closed + | AfterSseStream + /// Triggered after new content has been swapped in | AfterSwap + /// Triggered after a CSS view transition completes + | AfterViewTransition + /// Triggered before htmx disables an element or removes it from the DOM - | BeforeCleanupElement + | BeforeCleanup + + /// Triggered before htmx disables an element or removes it from the DOM + | [] BeforeCleanupElement /// Triggered before content is saved to the history cache | [] BeforeHistorySave @@ -57,19 +83,31 @@ type HxEvent = | [] BeforeOnLoad /// Triggered before htmx initializes a node - | BeforeProcessNode + | [] BeforeProcessNode /// Triggered before an HTTP request is made | BeforeRequest + /// Triggered before a history restore request is made + | BeforeRestoreHistory + /// Triggered just before an ajax request is sent | [] BeforeSend + /// Triggered before a Server Sent Events (SSE) message is read + | BeforeSseMessage + + /// Triggered before a Server Sent Events (SSE) connection is reconnected + | BeforeSseReconnect + + /// Triggered before a Server Sent Events (SSE) stream is opened + | BeforeSseStream + /// Triggered before a swap is done, allows you to configure the swap | BeforeSwap /// Triggered before a CSS view transition starts - | BeforeTransition + | BeforeViewTransition /// Triggered before the request, allows you to customize parameters, headers | ConfigRequest @@ -79,130 +117,150 @@ type HxEvent = /// | Confirm + /// Triggered when an error occurs + | Error + + /// Triggered after an HTTP request is made, whether it was successful or not + | FinallyRequest + /// Triggered on an error during cache writing - | HistoryCacheError + | [] HistoryCacheError /// Triggered on a cache miss in the history subsystem - | HistoryCacheMiss + | [] HistoryCacheMiss /// Triggered on a unsuccessful remote retrieval - | HistoryCacheMissError + | [] HistoryCacheMissError /// Triggered on a successful remote retrieval - | HistoryCacheMissLoad + | [] HistoryCacheMissLoad /// Triggered when htmx handles a history restoration action - | HistoryRestore + | [] HistoryRestore /// Triggered when new content is added to the DOM - | Load + | [] Load /// /// Triggered when an element refers to a SSE event in its trigger, but no parent SSE source has been defined /// - | NoSseSourceError + | [] NoSseSourceError /// Triggered when an exception occurs during the onLoad handling in htmx - | OnLoadError + | [] OnLoadError /// Triggered after an out of band element as been swapped in - | OobAfterSwap + | [] OobAfterSwap /// Triggered before an out of band element swap is done, allows you to configure the swap - | OobBeforeSwap + | [] OobBeforeSwap /// Triggered when an out of band element does not have a matching ID in the current DOM - | OobErrorNoTarget + | [] OobErrorNoTarget /// Triggered after a prompt is shown - | Prompt + | [] Prompt /// Triggered after an url is pushed into history - | PushedIntoHistory + | [] PushedIntoHistory /// Triggered when an HTTP response error (non-200 or 300 response code) occurs - | ResponseError + | [] ResponseError /// Triggered when a network error prevents an HTTP request from happening - | SendError + | [] SendError /// Triggered when an error occurs with a SSE source - | SseError + | [] SseError - /// Triggered when a SSE source is opened - | SseOpen + /// Triggered when an SSE source is opened + | [] SseOpen /// Triggered when an error occurs during the swap phase - | SwapError + | [] SwapError /// Triggered when an invalid target is specified - | TargetError + | [] TargetError /// Triggered when a request timeout occurs - | Timeout + | [] Timeout /// Triggered before an element is validated - | ValidationValidate + | [] ValidationValidate /// Triggered when an element fails validation - | ValidationFailed + | [] ValidationFailed /// Triggered when a request is halted due to validation errors - | ValidationHalted + | [] ValidationHalted /// Triggered when an ajax request aborts - | XhrAbort + | [] XhrAbort /// Triggered when an ajax request ends - | XhrLoadEnd + | [] XhrLoadEnd /// Triggered when an ajax request starts - | XhrLoadStart + | [] XhrLoadStart /// Triggered periodically during an ajax request that supports progress events - | XhrProgress + | [] XhrProgress /// The htmx event name (fst) and kebab-case name (snd, for use with hx-on) static member private Values = Map [ Abort, ("abort", "abort") + AfterCleanup, ("afterCleanup", "after:cleanup") + AfterHistoryUpdate, ("afterHistoryUpdate", "after:history:update") AfterInit, ("afterInit", "after:init") AfterOnLoad, ("afterOnLoad", "after:init") AfterProcessNode, ("afterProcessNode", "after:init") + AfterPushIntoHistory, ("afterPushIntoHistory", "after:push:into:history") + AfterReplaceIntoHistory, ("afterReplaceIntoHistory", "after:replace:into:history") AfterRequest, ("afterRequest", "after:request") AfterSettle, ("afterSettle", "after:swap") + AfterSseMessage, ("afterSseMessage", "after:sse:message") + AfterSseStream, ("afterSseStream", "after:sse:stream") AfterSwap, ("afterSwap", "after:swap") - BeforeCleanupElement, ("beforeCleanupElement", "before:cleanup:element") + AfterViewTransition, ("afterViewTransition", "after:viewTransition") + BeforeCleanup, ("beforeCleanup", "before:cleanup") + BeforeCleanupElement, ("beforeCleanupElement", "before:cleanup") BeforeHistorySave, ("beforeHistorySave", "before:history:update") BeforeHistoryUpdate, ("beforeHistoryUpdate", "before:history:update") BeforeInit, ("beforeInit", "before:init") BeforeOnLoad, ("beforeOnLoad", "before:init") - BeforeProcessNode, ("beforeProcessNode", "before:process") + BeforeProcessNode, ("beforeProcessNode", "before:init") + BeforeRestoreHistory, ("beforeRestoreHistory", "before:restore:history") BeforeRequest, ("beforeRequest", "before:request") - BeforeSend, ("beforeSend", "before:send") + BeforeSend, ("beforeSend", "before:request") + BeforeSseMessage, ("beforeSseMessage", "before:sse:message") + BeforeSseReconnect, ("beforeSseReconnect", "before:sse:reconnect") + BeforeSseStream, ("beforeSseStream", "before:sse:stream") BeforeSwap, ("beforeSwap", "before:swap") - BeforeTransition, ("beforeTransition", "before:viewTransition") + BeforeViewTransition, ("beforeTransition", "before:viewTransition") ConfigRequest, ("configRequest", "config:request") Confirm, ("confirm", "confirm") + Error, ("error", "error") + FinallyRequest, ("finallyRequest", "finally:request") HistoryCacheError, ("historyCacheError", "history-cache-error") - HistoryCacheMiss, ("historyCacheMiss", "history-cache-miss") + HistoryCacheMiss, ("historyCacheMiss", "before:history:restore") HistoryCacheMissError, ("historyCacheMissError", "history-cache-miss-error") - HistoryCacheMissLoad, ("historyCacheMissLoad", "history-cache-miss-load") - HistoryRestore, ("historyRestore", "history-restore") - Load, ("load", "load") - NoSseSourceError, ("noSSESourceError", "no-sse-source-error") - OnLoadError, ("onLoadError", "on-load-error") - OobAfterSwap, ("oobAfterSwap", "oob-after-swap") - OobBeforeSwap, ("oobBeforeSwap", "oob-before-swap") - OobErrorNoTarget, ("oobErrorNoTarget", "oob-error-no-target") + HistoryCacheMissLoad, ("historyCacheMissLoad", "before:history:restore") + HistoryRestore, ("historyRestore", "before:history:restore") + Load, ("load", "after:init") + NoSseSourceError, ("noSSESourceError", "error") + OnLoadError, ("onLoadError", "error") + OobAfterSwap, ("oobAfterSwap", "after:swap") + OobBeforeSwap, ("oobBeforeSwap", "before:swap") + OobErrorNoTarget, ("oobErrorNoTarget", "error") Prompt, ("prompt", "prompt") - PushedIntoHistory, ("pushedIntoHistory", "pushed-into-history") - ResponseError, ("responseError", "response-error") - SendError, ("sendError", "send-error") - SseError, ("sseError", "sse-error") + PushedIntoHistory, ("pushedIntoHistory", "after:push:into:history") + ResponseError, ("responseError", "error") + SendError, ("sendError", "error") + SseError, ("sseError", "error") SseOpen, ("sseOpen", "sse-open") - SwapError, ("swapError", "swap-error") - TargetError, ("targetError", "target-error") - Timeout, ("timeout", "timeout") + SwapError, ("swapError", "error") + TargetError, ("targetError", "error") + Timeout, ("timeout", "error") ValidationValidate, ("validation:validate", "validation:validate") ValidationFailed, ("validation:failed", "validation:failed") ValidationHalted, ("validation:halted", "validation:halted") @@ -211,12 +269,13 @@ type HxEvent = XhrLoadStart, ("xhr:loadstart", "xhr:loadstart") XhrProgress, ("xhr:progress", "xhr:progress") ] - + /// The htmx event name override this.ToString() = fst HxEvent.Values[this] /// The hx-on variant of the htmx event name member this.ToHxOnString() = snd HxEvent.Values[this] +#warn 44 // restore obsolete warning /// Helper to create the hx-headers attribute @@ -882,15 +941,15 @@ module Script = /// Script tag to load the minified version from jsdelivr.net /// Ensure cdn.jsdelivr.net is in your CSP script-src list (if applicable) let cdnMinified = - script [ _src "https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js" - _integrity "sha256-Iig+9oy3VFkU8KiKG97cclanA9HVgMHSVSF9ClDTExM=" + script [ _src "https://cdn.jsdelivr.net/npm/htmx.org@4.0.0-alpha6/dist/htmx.min.js" + _integrity "sha384-/5n21KGM472oBhvzUrvju8FRDq/4WNMS3TGw5RWFkZR/kq+sCevqNXFcakqRtaHu" _crossorigin "anonymous" ] [] /// Script tag to load the unminified version from jsdelivr.net /// Ensure cdn.jsdelivr.net is in your CSP script-src list (if applicable) let cdnUnminified = - script [ _src "https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.js" - _integrity "sha256-upUwYnay6R+DA68rROTAP+EdfO3NvOqtE513PgDyAYM=" + script [ _src "https://cdn.jsdelivr.net/npm/htmx.org@4.0.0-alpha6/dist/htmx.js" + _integrity "sha384-I3uRy2RjSNcS8Oi2SNWZD9IrafyrrrBb4QaHNA9pWVWfJuKtL0p8qAwHSrEyXoKh" _crossorigin "anonymous" ] [] /// Script tag to load the minified version from jsdelivr.net