hyper-html-api 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,10 +12,11 @@ npm install hyper-html-api
12
12
 
13
13
  ## Rules tag
14
14
 
15
- Pages describe their data layer with a single script tag:
15
+ Pages describe their data layer with a script tag labeled by one or more
16
+ space-separated tokens in a single `data-rules-name` attribute:
16
17
 
17
18
  ```html
18
- <script type="application/hyper-html-api" id="hyper-html-api" data-rules-version="1">
19
+ <script type="application/json" data-rules-name="api cms collection" data-rules-version="1">
19
20
  {
20
21
  "title": "h1",
21
22
  "user": { "name": ".user-name", "role": ".user-role" },
@@ -25,24 +26,37 @@ Pages describe their data layer with a single script tag:
25
26
  </script>
26
27
  ```
27
28
 
29
+ Tokens are looked up with the CSS word-match selector
30
+ `script[data-rules-name~="<token>"]`, so a single tag can serve several roles at
31
+ once. There is no implicit unnamed tag: a consumer matches its token or finds
32
+ nothing.
33
+
28
34
  ## Browser API
29
35
 
30
36
  ```js
31
- HyperHtmlApi.engine.extract(root, rules) // → JSON
32
- HyperHtmlApi.engine.apply(root, rules, data) // mutates the DOM
33
- HyperHtmlApi.engine.findRulesIn(root) // → { rules, tagNode } | null
34
- HyperHtmlApi.engine.errors // error class refs
37
+ HyperHtmlApi.engine.extract(root, rules) // → JSON
38
+ HyperHtmlApi.engine.apply(root, rules, data) // mutates the DOM
39
+ HyperHtmlApi.engine.findRulesIn(root, token?) // → { rules, tagNode } | null
40
+ HyperHtmlApi.engine.findRules(root, source) // object | token → { rules, tagNode } | null
41
+ HyperHtmlApi.engine.bind(root, source, opts?) // → { rules, tagNode, get(), set(data) }
42
+ HyperHtmlApi.engine.errors // error class refs
35
43
  ```
36
44
 
45
+ `bind` accepts a source that is either a literal rules object, a token string
46
+ (a tag with `data-rules-name~="token"`), and returns a small port whose `get()`
47
+ extracts data and `set(data)` writes it back. Token resolution is
48
+ document-scoped, so a tag mounted in `<head>` is found even when `bind` is given
49
+ a body or form element; `get()`/`set()` stay scoped to that element.
50
+
37
51
  ## Node API
38
52
 
39
53
  ```js
40
- import { extract, apply, findRulesIn, errors } from 'hyper-html-api/engine'
54
+ import { extract, apply, findRulesIn, bind, errors } from 'hyper-html-api/engine'
41
55
  import cheerioAdapter from 'hyper-html-api/cheerio'
42
56
  import * as cheerio from 'cheerio'
43
57
 
44
58
  const $ = cheerio.load(html)
45
- const { rules } = findRulesIn(cheerioAdapter, $.root())
59
+ const { rules } = findRulesIn(cheerioAdapter, $.root(), 'api')
46
60
  const data = extract(cheerioAdapter, $.root(), rules)
47
61
  ```
48
62
 
@@ -1,2 +1,3 @@
1
- var HyperHtmlApi=(()=>{var B=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var ae=Object.prototype.hasOwnProperty;var ee=(e,t)=>{for(var r in t)B(e,r,{get:t[r],enumerable:!0})},ue=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of le(t))!ae.call(e,n)&&n!==r&&B(e,n,{get:()=>t[n],enumerable:!(o=ce(t,n))||o.enumerable});return e};var de=e=>ue(B({},"__esModule",{value:!0}),e);var Be={};ee(Be,{cms:()=>ie,default:()=>qe,engine:()=>se,upgrade:()=>fe});var C=["textContent","innerText","innerHTML","outerHTML","value","checked","selected","disabled","readOnly","type","tagName","nodeName","nodeType","nodeValue","childElementCount","id","className","classList","href","src","action","baseURI","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","dataset","currentSrc","duration","paused","title","documentURI","contentType"],O=new Set(C);var D={};ee(D,{EmptyListInsert:()=>b,MaxRuleDepthExceeded:()=>E,RulesParseError:()=>x,ShapeMismatch:()=>M,UnknownRulesVersion:()=>T,UpgradeAlreadyRegistered:()=>w});var x=class extends Error{constructor(t,r){super(t),this.name="RulesParseError",this.cause=r}},T=class extends Error{constructor(t){super(`unknown rules version: ${t}. Library supports "1".`),this.name="UnknownRulesVersion",this.version=t}},E=class extends Error{constructor(t){super(`rule depth exceeded 20 at path: ${t.join(".")}`),this.name="MaxRuleDepthExceeded",this.path=t}},M=class extends Error{constructor(t){super(`shape mismatch: ${t.length} field(s) failed validation`),this.name="ShapeMismatch",this.mismatches=t}},b=class extends Error{constructor(t){super(`cannot add items to empty list at "${t.join(".")}" \u2014 no sibling to clone as template. Seed the list with a hidden item first.`),this.name="EmptyListInsert",this.path=t}},w=class extends Error{constructor(){super("upgrade transform already registered; only one registration is allowed per page."),this.name="UpgradeAlreadyRegistered"}};var pe=20;function A(e,t,r){return $(e,t,r,{depth:0,path:[]})}function $(e,t,r,o){if(o.depth>pe)throw new E(o.path);if(typeof r=="string")return he(e,t,r);if(Array.isArray(r)){let[n,s]=r;return e.find(t,n).map((i,f)=>$(e,i,s,{depth:o.depth+1,path:[...o.path,f]}))}if(typeof r=="object"&&r!==null){let n={};for(let[s,c]of Object.entries(r))n[s]=$(e,t,c,{depth:o.depth+1,path:[...o.path,s]});return n}return null}function he(e,t,r){if(r.endsWith("[]")){let n=r.slice(0,-2);return e.find(t,n).map(s=>e.text(s))}if(r.startsWith("@"))return te(e,t,r.slice(1));if(r.includes("@")){let[n,s]=r.split("@"),c=n?e.find(t,n):[t];return c.length===0?null:te(e,c[0],s)}if(r===".")return e.text(t);let o=e.find(t,r);return o.length===0?null:e.text(o[0])}function te(e,t,r){if(O.has(r)){let n=e.prop(t,r);return n==null?null:String(n)}let o=e.attr(t,r);return o||null}var ye=.5;function W(e,t,r,o,n,s,c){let i=e.find(t,r);if(n.length===0){i.forEach(d=>e.remove(d));return}if(n.length>i.length&&i.length===0)throw new b(s.path);let a=i.map(d=>me(e,d,o)),u=null;if(i.length>0){u=e.clone(i[0]);let d=e.stripIds(u);d>0&&console.warn(`[hyper-html-api] stripped ${d} id attribute(s) from cloned template at "${s.path.join(".")||"(root)"}"`)}let p=ge(n,a,o),l=e.parent(i[0]),R=Ae(e,l,i[0]),y=new Set,h=n.map((d,m)=>{let S=p[m];if(S>=0)return y.add(S),i[S];let v=e.clone(u);return e.stripIds(v),v});i.forEach((d,m)=>{y.has(m)||e.remove(d)}),y.forEach(d=>e.remove(i[d])),h.forEach((d,m)=>{e.insertAt(l,d,R+m)}),h.forEach((d,m)=>{if(o===null){let S=n[m];e.text(d,S==null?"":String(S))}else c(e,d,o,n[m],{depth:s.depth+1,path:[...s.path,m]})})}function me(e,t,r){return r===null?e.text(t):A(e,t,r)}function ge(e,t,r){let o=new Array(e.length).fill(-1),n=new Set;return e.forEach((s,c)=>{let i=-1,f=-1;t.forEach((a,u)=>{if(n.has(u))return;let p=Ee(s,a,r),l=p===f&&i>=0?Math.abs(u-c)<Math.abs(i-c):!1;(p>f||l)&&(f=p,i=u)}),f>=ye&&(o[c]=i,n.add(i))}),o}function Ee(e,t,r){if(r===null)return e===t?1:0;let o=Object.keys(r||{});if(o.length===0)return 0;let n=0;for(let s of o)JSON.stringify(e?.[s])===JSON.stringify(t?.[s])&&n++;return n/o.length}function Ae(e,t,r){let o=e.children(t);for(let n=0;n<o.length;n++)if(e.sameNode(o[n],r))return n;return-1}var Re=20,re=new Set(["checked","selected","disabled","readOnly","paused"]);function L(e,t,r,o){let n=[];if(F(r,o,[],n),n.length)throw new M(n);j(e,t,r,o,{depth:0,path:[]})}function j(e,t,r,o,n){if(n.depth>Re)throw new E(n.path);if(o!==void 0){if(typeof r=="string")return Se(e,t,r,o,n);if(Array.isArray(r)){let[s,c]=r;return W(e,t,s,c,o,n,j)}if(typeof r=="object"&&r!==null)for(let[s,c]of Object.entries(r))j(e,t,c,o==null?o:o[s],{depth:n.depth+1,path:[...n.path,s]})}}function Se(e,t,r,o,n){if(r.endsWith("[]")){let c=r.slice(0,-2);return W(e,t,c,null,o,n,j)}if(r.startsWith("@"))return ne(e,t,r.slice(1),o);if(r.includes("@")){let[c,i]=r.split("@"),f=c?e.find(t,c):[t];return f.length===0?void 0:ne(e,f[0],i,o)}if(r==="."){e.text(t,o==null?"":String(o));return}let s=e.find(t,r);s.length!==0&&e.text(s[0],o==null?"":String(o))}function ne(e,t,r,o){O.has(r)?e.prop(t,r,xe(r,o)):e.attr(t,r,o==null?"":String(o))}function xe(e,t){return t==null?re.has(e)?!1:"":re.has(e)?!!t:t}function F(e,t,r,o){if(!(t==null||t==="")){if(typeof e=="string"){if(e.endsWith("[]")){Array.isArray(t)?t.forEach((n,s)=>{typeof n=="object"&&n!==null&&o.push({path:N([...r,s]),expected:"scalar",got:I(n)})}):o.push({path:N(r),expected:"array",got:I(t)});return}typeof t=="object"&&o.push({path:N(r),expected:"scalar",got:I(t)});return}if(Array.isArray(e)){if(!Array.isArray(t)){o.push({path:N(r),expected:"array",got:I(t)});return}let n=e[1];t.forEach((s,c)=>F(n,s,[...r,c],o));return}if(typeof e=="object"&&e!==null){if(Array.isArray(t)||typeof t!="object"){o.push({path:N(r),expected:"object",got:I(t)});return}for(let[n,s]of Object.entries(e))F(s,t[n],[...r,n],o)}}}function I(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function N(e){return e.join(".")}function P(e){try{return JSON.parse(e)}catch(t){throw new x(`hyper-html-api script tags require strict JSON. Relaxed JSON (unquoted keys, single quotes, trailing commas) is only supported in the ?data= URL parameter. Original error: ${t.message}`,t)}}function J(e){try{return JSON.parse(e)}catch{}let t={BRACE_OPEN:"{",BRACE_CLOSE:"}",BRACKET_OPEN:"[",BRACKET_CLOSE:"]",COLON:":",COMMA:",",STRING:"STRING",SELECTOR:"SELECTOR",IDENTIFIER:"IDENTIFIER",NUMBER:"NUMBER",BOOLEAN:"BOOLEAN"};function r(n){let s=[],c=0;for(;c<n.length;){let i=n[c];if(/\s/.test(i)){c++;continue}if("{}".includes(i)){s.push({type:i,value:i}),c++;continue}if(i==="["){let p=!1,l=c+1;for(;l<n.length&&/\s/.test(n[l]);)l++;if(l<n.length&&/[a-zA-Z_]/.test(n[l])&&(p=!0),!p){s.push({type:i,value:i}),c++;continue}}if(i==="]"){s.push({type:i,value:i}),c++;continue}if(i===":"){s.push({type:t.COLON,value:i}),c++;continue}if(i===","){s.push({type:t.COMMA,value:i}),c++;continue}if(i==='"'||i==="'"){let p=i,l=c+1;for(;l<n.length&&n[l]!==p;)n[l]==="\\"&&l++,l++;s.push({type:t.STRING,value:n.substring(c+1,l),quoted:!0}),c=l+1;continue}let f=c,a;for(;f<n.length&&!/[{},]/.test(n[f]);)if(n[f]===":"){let p=[":first",":last",":nth-child",":nth-of-type",":first-child",":last-child",":first-of-type",":last-of-type",":only-child",":only-of-type",":hover",":focus",":active",":visited",":disabled",":enabled",":checked",":empty",":root",":target",":not",":before",":after",":nth-last-child",":nth-last-of-type"],l=!1;for(let R of p){let y=R.substring(1);if(n.substring(f+1,f+1+y.length)===y){l=!0,f+=y.length;break}}if(!l)break}else if(n[f]==="["){for(f++;f<n.length&&n[f]!=="]";){if(n[f]==='"'||n[f]==="'"){let p=n[f];for(f++;f<n.length&&n[f]!==p;)n[f]==="\\"&&f++,f++}f++}f<n.length&&n[f]==="]"&&f++}else f++;a=n.substring(c,f);let u=t.IDENTIFIER;/^-?\d+(\.\d+)?$/.test(a)?u=t.NUMBER:a==="true"||a==="false"||a==="null"?u=t.BOOLEAN:/^[.#@\[]|[.#@\[]| /.test(a)&&(u=t.SELECTOR),s.push({type:u,value:a,quoted:!1}),c=f}return s}function o(n){let s="";for(let c=0;c<n.length;c++){let i=n[c];if("{}".includes(i.type)||"[]".includes(i.type)){s+=i.value;continue}if(i.type===t.COLON){s+=i.value;continue}if(i.type===t.COMMA){s+=i.value;continue}if(i.type===t.STRING&&i.quoted){s+=`"${i.value}"`;continue}if(i.type===t.NUMBER||i.type===t.BOOLEAN){s+=i.value;continue}if(i.type===t.SELECTOR||i.type===t.IDENTIFIER){s+=`"${i.value}"`;continue}s+=`"${i.value}"`}return s}try{let n=r(e),s=o(n);return JSON.parse(s)}catch(n){throw new x("Invalid extraction rules syntax: "+n.message,n)}}var Oe="hyper-html-api",Te="1";function _(e,t){let r=e.find(t,`script#${Oe}`,{includeRulesTag:!0});if(r.length===0)return null;let o=r[0],n=e.attr(o,"data-rules-version");if(n!==Te)throw new T(n);let s=e.text(o);return{rules:P(s),tagNode:o}}var G=null;function V(e){if(typeof e!="function")throw new TypeError("registerUpgrade expects a function (v1Data) => v2Data");if(G)throw new w;G=e}function H(){return G}function U(e,t){let r={carriedOver:0,discarded:0,listItems:0},o=Y(t,e,r);return X(t,e,r),{data:o,summary:r}}function Y(e,t,r){if(typeof e=="string")return e.endsWith("[]")?Array.isArray(t)?(r.listItems+=t.length,r.carriedOver+=t.length,t):void 0:t==null?void 0:(r.carriedOver++,t);if(Array.isArray(e)){let[,o]=e;return Array.isArray(t)?(r.listItems+=t.length,t.map(n=>Y(o,n,r))):void 0}if(typeof e=="object"&&e!==null){let o={};for(let[n,s]of Object.entries(e)){let c=Y(s,t?.[n],r);c!==void 0&&(o[n]=c)}return o}}function X(e,t,r){if(t!=null){if(typeof e=="object"&&e!==null&&!Array.isArray(e)){if(typeof t!="object"||Array.isArray(t))return;let o=new Set(Object.keys(e));for(let n of Object.keys(t))o.has(n)?X(e[n],t[n],r):r.discarded+=k(t[n]);return}if(Array.isArray(e)&&Array.isArray(t)){let o=e[1];t.forEach(n=>X(o,n,r));return}typeof e=="string"&&!e.endsWith("[]")&&typeof t=="object"&&t!==null&&(r.discarded+=k(t))}}function k(e){return e==null?0:Array.isArray(e)?e.reduce((t,r)=>t+k(r),0):typeof e=="object"?Object.values(e).reduce((t,r)=>t+k(r),0):1}async function z({sourceUrl:e,v1Data:t,v1Version:r=null,parent:o=typeof window<"u"?window:null,timeoutMs:n=15e3,hidden:s=!0}={}){if(!o)throw new Error("upgrade.run requires a window context");if(!e)throw new Error("upgrade.run requires sourceUrl");let c=be(e,o.location.origin),i=new URL(c,o.location.href).origin,f=o.document.createElement("iframe");s&&(f.style.cssText="position:absolute;left:-9999px;top:-9999px;width:1px;height:1px;border:0;"),f.setAttribute("aria-hidden","true"),f.src=c,o.document.body.appendChild(f);let a=()=>{};try{return await new Promise((u,p)=>{let l=setTimeout(()=>{p(new Error(`upgrade.run: helper iframe timed out after ${n}ms`))},n),R=y=>{if(y.source!==f.contentWindow||y.origin!==i)return;let h=y.data;if(!(!h||typeof h!="object")){if(h.type==="hha:upgrade-ready"){f.contentWindow.postMessage({type:"hha:upgrade-data",v1Data:t,v1Version:r},i);return}if(h.type==="hha:upgrade-result"){clearTimeout(l),u({html:h.html,summary:h.summary});return}if(h.type==="hha:upgrade-error"){clearTimeout(l);let d=new Error(h.message||"helper error");d.name=h.name||"UpgradeHelperError",p(d);return}}};o.addEventListener("message",R),a=()=>{o.removeEventListener("message",R),clearTimeout(l),f.parentNode&&f.parentNode.removeChild(f)}})}finally{a()}}function be(e,t){let r=new URL(e,typeof location<"u"?location.href:void 0);return r.searchParams.set("_hyperHtmlApi","upgrade-helper"),r.searchParams.set("parentOrigin",t),r.toString()}var we="hyper-html-api";function Ie(e){return e&&e.nodeType===1&&e.id===we&&e.tagName==="SCRIPT"}function Ne(e){return e?(e.nodeType===9||e.nodeType===11,e):null}var Le={find(e,t,r={}){let o=Ne(e);if(!o||!o.querySelectorAll)return[];let n=Array.from(o.querySelectorAll(t));return r.includeRulesTag?n:n.filter(s=>!Ie(s))},parent(e){return e?e.parentElement:null},children(e){return e?Array.from(e.children):[]},text(e,t){if(t===void 0)return(e.textContent||"").trim();e.textContent=t},attr(e,t,r){if(r===void 0)return e.hasAttribute&&e.hasAttribute(t)?e.getAttribute(t):null;e.setAttribute(t,r)},prop(e,t,r){if(r===void 0){let o=e?e[t]:void 0;return o!==void 0?o:null}e[t]=r},clone(e){return e.cloneNode(!0)},insertAt(e,t,r){let o=e.children[r]||null;e.insertBefore(t,o)},remove(e){e&&e.parentNode&&e.parentNode.removeChild(e)},stripIds(e){let t=0;return e.id&&(e.removeAttribute("id"),t++),(e.querySelectorAll?e.querySelectorAll("[id]"):[]).forEach(o=>{o.removeAttribute("id"),t++}),t},sameNode(e,t){return e===t}},g=Le;var Pe="_hyperHtmlApi",_e="upgrade-helper",Ue="parentOrigin";function q(e=typeof location<"u"?location:null){if(!e)return!1;try{return new URLSearchParams(e.search).get(Pe)===_e}catch{return!1}}function oe(e=typeof location<"u"?location:null){return e?new URLSearchParams(e.search).get(Ue):null}function Z({win:e,doc:t,parentOrigin:r}={}){if(e=e||(typeof window<"u"?window:null),t=t||(typeof document<"u"?document:null),!e||!t||(r=r||oe(e.location),!r))return;let o=()=>Ce({win:e,doc:t,parentOrigin:r});t.readyState==="loading"?t.addEventListener("DOMContentLoaded",o,{once:!0}):o()}function Ce({win:e,doc:t,parentOrigin:r}){let o;try{o=_(g,t.body)}catch(f){return K(e,r,f)}if(!o)return K(e,r,new Error("helper-mode: no rules tag in v2 document"));let n=o.rules,s=je(t,"hyper-version"),c=!!H(),i=f=>{if(f.source!==e.parent||f.origin!==r)return;let a=f.data;if(!(!a||a.type!=="hha:upgrade-data")){e.removeEventListener("message",i);try{let u=De({doc:t,rules:n,v1Data:a.v1Data});e.parent.postMessage({type:"hha:upgrade-result",html:u.html,summary:u.summary},r)}catch(u){K(e,r,u)}}};e.addEventListener("message",i),e.parent.postMessage({type:"hha:upgrade-ready",rules:n,version:s,hasTransform:c},r)}function De({doc:e,rules:t,v1Data:r}){let o=H(),n=r,s=!1;o&&(n=o(r),s=!0);let{data:c,summary:i}=U(n,t);L(g,e.body,t,c);let f=A(g,e.body,t);return{html:`<!DOCTYPE html>
2
- `+e.documentElement.outerHTML,summary:{...i,transformApplied:s,appliedFieldCount:Q(f)}}}function K(e,t,r){e.parent.postMessage({type:"hha:upgrade-error",name:r?.name||"Error",message:r?.message||String(r)},t)}function je(e,t){let r=e.querySelector(`meta[name="${t}"]`);return r?r.getAttribute("content"):null}function Q(e){return e==null?0:Array.isArray(e)?e.reduce((t,r)=>t+Q(r),0):typeof e=="object"?Object.values(e).reduce((t,r)=>t+Q(r),0):1}var se={extract:(e,t)=>A(g,e,t),apply:(e,t,r)=>L(g,e,t,r),findRulesIn:e=>_(g,e),parseStrict:P,parseRelaxed:J,errors:D,DOM_PROPERTIES:C},ie={},fe={registerUpgrade:V,run:z,shapeMatch:U,isHelperMode:q};typeof window<"u"&&q(window.location)&&Z({win:window,doc:document});var ke={engine:se,cms:ie,upgrade:fe},qe=ke;return de(Be);})();
1
+ var HyperHtmlApi=(()=>{var Ee=Object.defineProperty;var ht=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var gt=Object.prototype.hasOwnProperty;var Se=(e,t)=>{for(var r in t)Ee(e,r,{get:t[r],enumerable:!0})},yt=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of mt(t))!gt.call(e,o)&&o!==r&&Ee(e,o,{get:()=>t[o],enumerable:!(n=ht(t,o))||n.enumerable});return e};var bt=e=>yt(Ee({},"__esModule",{value:!0}),e);var yr={};Se(yr,{cms:()=>dt,default:()=>gr,engine:()=>ft,upgrade:()=>pt});var ce=["textContent","innerText","innerHTML","outerHTML","value","checked","selected","disabled","readOnly","type","tagName","nodeName","nodeType","nodeValue","childElementCount","id","className","classList","baseURI","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","dataset","currentSrc","duration","paused","title","documentURI","contentType"],ve=new Set(ce),Ke=new Set(["textContent","innerText","innerHTML","value","checked","selected","disabled","readOnly","type","id","className","title"]),ze=new Set(["tagName","nodeName","nodeType","nodeValue","childElementCount","classList","baseURI","documentURI","contentType","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","currentSrc","duration","paused","dataset"]);var ue={};Se(ue,{EmptyListInsert:()=>Z,MAX_RULE_DEPTH:()=>J,MaxRuleDepthExceeded:()=>U,RuleTargetReadOnly:()=>ee,RulesParseError:()=>z,ShapeMismatch:()=>X,UnknownRulesVersion:()=>Q,UpgradeAlreadyRegistered:()=>te});var z=class extends Error{constructor(t,r){super(t),this.name="RulesParseError",this.cause=r}},Q=class extends Error{constructor(t){super(`unknown rules version: ${t}. Library supports "1".`),this.name="UnknownRulesVersion",this.version=t}},J=20,U=class extends Error{constructor(t){super(`rule depth exceeded ${J} at path: ${t.join(".")}`),this.name="MaxRuleDepthExceeded",this.path=t}},X=class extends Error{constructor(t){super(`shape mismatch: ${t.length} field(s) failed validation`),this.name="ShapeMismatch",this.mismatches=t}},Z=class extends Error{constructor(t){super(`cannot add items to empty list at "${t.join(".")}" \u2014 no sibling to clone as template. Seed the list with a hidden item first.`),this.name="EmptyListInsert",this.path=t}},ee=class extends Error{constructor(t){super(`cannot write to read-only DOM property "${t}"`),this.name="RuleTargetReadOnly",this.target=t}},te=class extends Error{constructor(){super("upgrade transform already registered; only one registration is allowed per page."),this.name="UpgradeAlreadyRegistered"}};function B(e,t,r,n={}){return xe(e,t,r,{depth:0,path:[]},n)}function xe(e,t,r,n,o){if(n.depth>J)throw new U(n.path);if(typeof r=="string")return At(e,t,r,o);if(Array.isArray(r)){let[i,u]=r;return e.find(t,i,o).map((a,M)=>xe(e,a,u,{depth:n.depth+1,path:[...n.path,M]},o))}if(typeof r=="object"&&r!==null){let i={};for(let[u,s]of Object.entries(r))i[u]=xe(e,t,s,{depth:n.depth+1,path:[...n.path,u]},o);return i}return null}function At(e,t,r,n){if(r.endsWith("[]")){let i=r.slice(0,-2);return e.find(t,i,n).map(u=>e.text(u))}if(r.startsWith("@"))return Je(e,t,r.slice(1));if(r.includes("@")){let i=r.lastIndexOf("@"),u=r.slice(0,i),s=r.slice(i+1),a=u?e.find(t,u,n):[t];return a.length===0?null:Je(e,a[0],s)}if(r===".")return e.text(t);let o=e.find(t,r,n);return o.length===0?null:e.text(o[0])}function Je(e,t,r){if(ve.has(r)){let o=e.prop(t,r);return o==null?null:String(o)}let n=e.attr(t,r);return n||null}var Mt=.5;function we(e,t,r,n,o,i,u,s={}){let a=e.find(t,r,s);if(o.length===0){a.forEach(S=>e.remove(S));return}let M=o.length>a.length,w=a[0]||null;if(M&&!w&&(w=wt(e,t,r,s),!w))throw new Z(i.path);let b=a.map(S=>Et(e,S,n,s)),h=null;if(w){h=e.clone(w),s.templateAttr&&e.removeAttr(h,s.templateAttr);let S=e.stripIds(h);S>0&&console.warn(`[hyper-html-api] stripped ${S} id attribute(s) from cloned template at "${i.path.join(".")||"(root)"}"`)}let R=St(o,b,n),N=a[0]||w,k=e.parent(N),m=a.length>0?xt(e,k,N):0,O=new Set,v=o.map((S,x)=>{let E=R[x];if(E>=0)return O.add(E),a[E];let d=e.clone(h);return e.stripIds(d),d});a.forEach((S,x)=>{O.has(x)||e.remove(S)}),v.forEach((S,x)=>{let E=m+x;e.children(k).findIndex(c=>e.sameNode(c,S))!==E&&e.insertAt(k,S,E)}),v.forEach((S,x)=>{if(n===null){let E=o[x],d=E==null?"":String(E);e.text(S)!==d&&e.text(S,d)}else{let E=u(e,S,n,o[x],{depth:i.depth+1,path:[...i.path,x]},s);E&&E!==S&&(v[x]=E)}})}function Et(e,t,r,n){return r===null?e.text(t):B(e,t,r,n)}function St(e,t,r){let n=new Array(e.length).fill(-1),o=new Set;return e.forEach((i,u)=>{let s=-1,a=-1;t.forEach((M,w)=>{if(o.has(w))return;let b=vt(i,M,r),h=b===a&&s>=0?Math.abs(w-u)<Math.abs(s-u):!1;(b>a||h)&&(a=b,s=w)}),a>=Mt&&(n[u]=s,o.add(s))}),n}function vt(e,t,r){if(r===null)return e===t?1:0;let n=Object.keys(r||{});if(n.length===0)return 0;let o=0;for(let i of n)JSON.stringify(e?.[i])===JSON.stringify(t?.[i])&&o++;return o/n.length}function xt(e,t,r){let n=e.children(t);for(let o=0;o<n.length;o++)if(e.sameNode(n[o],r))return o;return-1}function wt(e,t,r,n){if(!n.templateAttr)return null;let o=t;for(;o;){let i=e.find(o,r,{includeRulesTag:!1});for(let u of i)if(e.attr(u,n.templateAttr)!=null)return u;o=e.parent(o)}return null}var Ye=new Set(["checked","selected","disabled","readOnly","paused"]);function W(e,t,r,n,o={}){let i=[];if(Te(r,n,[],i),i.length)throw new X(i);le(e,t,r,n,{depth:0,path:[]},o)}function le(e,t,r,n,o,i={}){if(o.depth>J)throw new U(o.path);if(n===void 0)return t;if(typeof r=="string")return Tt(e,t,r,n,o,i);if(Array.isArray(r)){let[u,s]=r;return we(e,t,u,s,n,o,le,i),t}if(typeof r=="object"&&r!==null){for(let[u,s]of Object.entries(r)){let a=le(e,t,s,n==null?n:n[u],{depth:o.depth+1,path:[...o.path,u]},i);a&&a!==t&&(t=a)}return t}return t}function Tt(e,t,r,n,o,i){if(r.endsWith("[]")){let s=r.slice(0,-2);return we(e,t,s,null,n,o,le,i),t}if(r.startsWith("@"))return Ge(e,t,r.slice(1),n);if(r.includes("@")){let s=r.lastIndexOf("@"),a=r.slice(0,s),M=r.slice(s+1),w=a?e.find(t,a,i):[t];return w.length===0||Ge(e,w[0],M,n),t}if(r===".")return e.text(t,n==null?"":String(n)),t;let u=e.find(t,r,i);return u.length===0||e.text(u[0],n==null?"":String(n)),t}function Ge(e,t,r,n){if(ze.has(r))throw new ee(r);if(r==="outerHTML"){let o=n==null?"":String(n);return e.replaceWith(t,o)}return Ke.has(r)?(e.prop(t,r,Rt(r,n)),t):(e.attr(t,r,n==null?"":String(n)),t)}function Rt(e,t){return t==null?Ye.has(e)?!1:"":Ye.has(e)?!!t:t}function Te(e,t,r,n){if(t!==void 0){if(typeof e=="string"){if(e.endsWith("[]")){Array.isArray(t)?t.forEach((o,i)=>{typeof o=="object"&&o!==null&&n.push({path:ne([...r,i]),expected:"scalar",got:re(o)})}):n.push({path:ne(r),expected:"array",got:re(t)});return}t!==null&&typeof t=="object"&&n.push({path:ne(r),expected:"scalar",got:re(t)});return}if(Array.isArray(e)){if(!Array.isArray(t)){n.push({path:ne(r),expected:"array",got:re(t)});return}let o=e[1];t.forEach((i,u)=>Te(o,i,[...r,u],n));return}if(typeof e=="object"&&e!==null){if(t===null||Array.isArray(t)||typeof t!="object"){n.push({path:ne(r),expected:"object",got:re(t)});return}for(let[o,i]of Object.entries(e))Te(i,t[o],[...r,o],n)}}}function re(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function ne(e){return e.join(".")}function Re(e){try{return JSON.parse(e)}catch(t){throw new z(`Invalid strict JSON: ${t.message}`,t)}}function oe(e){try{return JSON.parse(e)}catch{}let t={BRACE_OPEN:"{",BRACE_CLOSE:"}",BRACKET_OPEN:"[",BRACKET_CLOSE:"]",COLON:":",COMMA:",",STRING:"STRING",SELECTOR:"SELECTOR",IDENTIFIER:"IDENTIFIER",NUMBER:"NUMBER",BOOLEAN:"BOOLEAN"};function r(o){let i=[],u=0;for(;u<o.length;){let s=o[u];if(/\s/.test(s)){u++;continue}if("{}".includes(s)){i.push({type:s,value:s}),u++;continue}if(s==="["){let b=!1,h=u+1;for(;h<o.length&&/\s/.test(o[h]);)h++;if(h<o.length&&/[a-zA-Z_]/.test(o[h])&&(b=!0),!b){i.push({type:s,value:s}),u++;continue}}if(s==="]"){i.push({type:s,value:s}),u++;continue}if(s===":"){i.push({type:t.COLON,value:s}),u++;continue}if(s===","){i.push({type:t.COMMA,value:s}),u++;continue}if(s==='"'||s==="'"){let b=s,h=u+1;for(;h<o.length&&o[h]!==b;)o[h]==="\\"&&h++,h++;i.push({type:t.STRING,value:o.substring(u+1,h),quoted:!0,sourceQuote:b}),u=h+1;continue}let a=u,M;for(;a<o.length&&!/[{},]/.test(o[a]);)if(o[a]===":"){let b=[":first",":last",":nth-child",":nth-of-type",":first-child",":last-child",":first-of-type",":last-of-type",":only-child",":only-of-type",":hover",":focus",":active",":visited",":disabled",":enabled",":checked",":empty",":root",":target",":not",":before",":after",":nth-last-child",":nth-last-of-type"],h=!1;for(let R of b){let N=R.substring(1);if(o.substring(a+1,a+1+N.length)===N){h=!0,a+=N.length;break}}if(!h)break}else if(o[a]==="["){for(a++;a<o.length&&o[a]!=="]";){if(o[a]==='"'||o[a]==="'"){let b=o[a];for(a++;a<o.length&&o[a]!==b;)o[a]==="\\"&&a++,a++}a++}a<o.length&&o[a]==="]"&&a++}else a++;M=o.substring(u,a);let w=t.IDENTIFIER;/^-?\d+(\.\d+)?$/.test(M)?w=t.NUMBER:M==="true"||M==="false"||M==="null"?w=t.BOOLEAN:/^[.#@\[]|[.#@\[]| /.test(M)&&(w=t.SELECTOR),i.push({type:w,value:M,quoted:!1}),u=a}return i}function n(o){let i="";for(let u=0;u<o.length;u++){let s=o[u];if("{}".includes(s.type)||"[]".includes(s.type)){i+=s.value;continue}if(s.type===t.COLON){i+=s.value;continue}if(s.type===t.COMMA){let a=o[u+1];if(a&&(a.type==="}"||a.type==="]"))continue;i+=s.value;continue}if(s.type===t.STRING&&s.quoted){let a=s.value;s.sourceQuote==="'"&&(a=a.replace(/\\'/g,"'"),a=a.replace(/(\\*)"/g,(M,w)=>w.length%2===0?w+'\\"':M)),i+=`"${a}"`;continue}if(s.type===t.NUMBER||s.type===t.BOOLEAN){i+=s.value;continue}if(s.type===t.SELECTOR||s.type===t.IDENTIFIER){i+=`"${s.value}"`;continue}i+=`"${s.value}"`}return i}try{let o=r(e),i=n(o);return JSON.parse(i)}catch(o){throw new z("Invalid extraction rules syntax: "+o.message,o)}}var Nt="1",Qe=/^[a-zA-Z0-9_-]+$/;function q(e,t,r){let n;if(r===void 0)n="script[data-rules-name]";else{if(typeof r!="string"||!Qe.test(r))throw new Error(`hyper-html-api: invalid rules token ${JSON.stringify(r)} (must match ${Qe})`);n=`script[data-rules-name~="${r}"]`}let o=e.find(t,n,{includeRulesTag:!0});if(o.length===0)return null;r!==void 0&&o.length>1&&console.warn(`hyper-html-api: ${o.length} rules tags match data-rules-name~="${r}"; using the first.`);let i=o[0],u=e.attr(i,"data-rules-version");if(u!==Nt)throw new Q(u);return{rules:oe(e.text(i)),tagNode:i}}function Ne(e,t,r){if(r&&typeof r=="object")return{rules:r,tagNode:null};if(typeof r=="string"){let n=t&&t.ownerDocument?t.ownerDocument:t;return q(e,n,r)}return null}function Xe(e,t,r,n){let o=Ne(e,t,r);if(!o){let s=typeof r=="string"?`data-rules-name~="${r}"`:"the provided rules object";throw new Error(`hyper-html-api: could not resolve rules for ${s}`)}let{rules:i,tagNode:u}=o;return{rules:i,tagNode:u,get:()=>B(e,t,i,n),set:s=>W(e,t,i,s,n)}}var de={};Se(de,{fromString:()=>fe,getRuleAtPath:()=>Oe,getValueAtPath:()=>ie,parseConfigKey:()=>kt,setAtPath:()=>F,toConfigKey:()=>It,toString:()=>_});function _(e){return e.map(String).join(".")}function It(e){return e.map(t=>typeof t=="number"?"*":String(t)).join(".")}function kt(e){return e===""?[]:e.split(".")}function fe(e){return e===""?[]:e.split(".").map(t=>/^\d+$/.test(t)?Number(t):t)}function Oe(e,t){let r=e;for(let n of t){if(r==null||typeof r=="string")return;if(Array.isArray(r)){if(typeof n!="number"&&n!=="*")return;r=r[1];continue}if(typeof r=="object"){if(typeof n=="number"||!(n in r))return;r=r[n];continue}return}return r}function ie(e,t){let r=e;for(let n of t){if(r==null)return;r=r[n]}return r}function F(e,t,r){if(t.length===0)return r;let[n,...o]=t;if(typeof n=="number"){let i=Array.isArray(e)?[...e]:[];return i[n]=F(i[n],o,r),i}return{...e&&typeof e=="object"?e:{},[n]:F((e||{})[n],o,r)}}function Y(e){if(typeof e=="string")return e.endsWith("[]")?[]:"";if(Array.isArray(e))return[];if(typeof e=="object"&&e!==null){let t={};for(let[r,n]of Object.entries(e))t[r]=Y(n);return t}return""}var pe=new WeakMap;var Lt=new Set(["checked","selected","disabled","readOnly","paused"]);function Ie({rules:e,data:t,appRoot:r,cmsRoot:n}){let o=document.createDocumentFragment(),i={rules:e,appRoot:r,cmsRoot:n};return o.appendChild(Le({rule:e,value:t,path:[],ctx:i})),o}function ke(e,{rules:t,getData:r,onChange:n}){e.setAttribute("data-hha-form-root",""),tt.set(e,{rules:t,getData:r,onChange:n}),Ct()}var tt=new WeakMap,Ze=!1;function Ct(){Ze||(document.addEventListener("input",et,!0),document.addEventListener("change",et,!0),document.addEventListener("click",Ht,!0),Ze=!0)}function rt(e){if(!(e instanceof Element))return null;let t=e.closest("[data-hha-form-root]");return t&&tt.get(t)||null}function Ht(e){if(!(e.target instanceof Element))return;let t=e.target.closest("[data-hha-action]");if(!t||e.defaultPrevented)return;let r=rt(t);if(!r)return;let{rules:n,getData:o,onChange:i}=r,u=t.getAttribute("data-hha-action"),s=fe(t.getAttribute("data-hha-path")||"");if(u==="scalar-array-add"){let a=ie(o(),s)||[];i(F(o(),s,[...a,""]),{structural:!0});return}if(u==="object-array-add"){let a=Oe(n,s);if(!Array.isArray(a))return;let M=ie(o(),s)||[];i(F(o(),s,[...M,Y(a[1])]),{structural:!0});return}if(u==="array-remove"){if(s.length===0)return;let a=s.slice(0,-1),M=s[s.length-1],w=ie(o(),a)||[];if(typeof M!="number")return;let b=w.filter((h,R)=>R!==M);i(F(o(),a,b),{structural:!0})}}function et(e){let t=e.target;if(!t?.matches?.("input, textarea, select"))return;let r=rt(t);if(!r)return;let{getData:n,onChange:o}=r,i=t.closest("[data-hha-path]");if(!i)return;let u=fe(i.getAttribute("data-hha-path")||""),s=t.type==="checkbox"?t.checked:t.value;o(F(n(),u,s),{structural:!1})}function Le({rule:e,value:t,path:r,ctx:n}){if(typeof e=="string")return e.endsWith("[]")?Dt({rule:e,value:t,path:r,ctx:n}):_t({rule:e,value:t,path:r,ctx:n});if(Array.isArray(e))return jt({rule:e,value:t,path:r,ctx:n});if(typeof e=="object"&&e!==null)return Pt({rule:e,value:t,path:r,ctx:n});let o=document.createElement("span");return o.textContent="(unsupported rule)",o}function Pt({rule:e,value:t,path:r,ctx:n}){let o=document.createElement("div");if(o.className="form-section",o.setAttribute("data-hha-path",_(r)),r.length>0){let i=document.createElement("div");i.className="form-section-label",i.textContent=he(r[r.length-1]),o.appendChild(i)}for(let[i,u]of Object.entries(e)){let s=[...r,i],a=t?.[i];o.appendChild(Le({rule:u,value:a,path:s,ctx:n}))}return o}function _t({rule:e,value:t,path:r,ctx:n}){let o=document.createElement("div");o.className="field-row",o.setAttribute("data-hha-path",_(r));let i=document.createElement("div");i.className="field-body";let u=document.createElement("label");u.className="field-label",u.textContent=he(r[r.length-1]||".")+Wt(e);let s=Bt(e,n.appRoot),a=$t(s,{value:t,rule:e,path:r,appRoot:n.appRoot}),M=a.el;return M.classList.add(s.type==="textarea"?"field-textarea":"field-input"),i.appendChild(u),i.appendChild(M),o.appendChild(i),pe.set(o,a),o}function Dt({rule:e,value:t,path:r,ctx:n}){let o=document.createElement("div");o.className="form-section",o.setAttribute("data-hha-path",_(r));let i=document.createElement("div");i.className="form-section-label",i.textContent=he(r[r.length-1]),o.appendChild(i);let u=Array.isArray(t)?t:[],s=document.createElement("div");o.appendChild(s),u.forEach((M,w)=>{let b=[...r,w],h=document.createElement("div");h.className="scalar-array-row",h.setAttribute("data-hha-path",_(b));let R=document.createElement("input");R.type="text",R.className="field-input",R.value=M==null?"":String(M);let N=document.createElement("button");N.type="button",N.className="array-remove",N.textContent="\xD7",N.title="remove",N.setAttribute("data-hha-action","array-remove"),N.setAttribute("data-hha-path",_(b)),h.appendChild(R),h.appendChild(N),s.appendChild(h)});let a=document.createElement("button");return a.type="button",a.className="array-add",a.textContent="+ add",a.setAttribute("data-hha-action","scalar-array-add"),a.setAttribute("data-hha-path",_(r)),o.appendChild(a),o}function jt({rule:e,value:t,path:r,ctx:n}){let[,o]=e,i=Array.isArray(t)?t:[],u=document.createElement("div");u.className="form-section",u.setAttribute("data-hha-path",_(r));let s=document.createElement("div");s.className="form-section-label",s.textContent=he(r[r.length-1]),u.appendChild(s),i.forEach((M,w)=>{let b=[...r,w],h=document.createElement("div");h.className="array-card",h.setAttribute("data-hha-path",_(b));let R=document.createElement("button");R.type="button",R.className="array-remove",R.textContent="\xD7",R.title="remove item",R.setAttribute("data-hha-action","array-remove"),R.setAttribute("data-hha-path",_(b)),h.appendChild(R);let N=Le({rule:o,value:M,path:b,ctx:n});N.querySelector(".form-section-label")?.remove(),h.appendChild(N),u.appendChild(h)});let a=document.createElement("button");return a.type="button",a.className="array-add",a.textContent="+ add",a.setAttribute("data-hha-action","object-array-add"),a.setAttribute("data-hha-path",_(r)),u.appendChild(a),u}function $t(e,t){let r=Ut(e);if(e.type==="select"&&e.options)for(let n of e.options){let o=document.createElement("option");o.value=n.value,o.textContent=n.text,String(t.value)===n.value&&(o.selected=!0),r.appendChild(o)}else e.type==="checkbox"?r.checked=t.value===!0||t.value==="true"||t.value==="checked":(e.type,r.value=t.value==null?"":String(t.value));return{el:r,destroy(){},focus(){r.focus()},validate(){}}}function Bt(e,t){let r=null;if(e.startsWith("@")?r=e.slice(1):e.includes("@")&&(r=e.split("@")[1]||null),r&&Lt.has(r))return{type:"checkbox"};if(r==="innerHTML")return{type:"textarea"};let n=Ft(e,t);if(!n)return{type:"text"};let o=(n.tagName||"").toLowerCase();if(o==="textarea")return{type:"textarea"};if(o==="select")return{type:"select",options:Array.from(n.querySelectorAll("option")).map(s=>({value:s.getAttribute("value")||s.textContent,text:s.textContent.trim()||s.getAttribute("value")||""}))};if(o==="input"){let u=(n.getAttribute("type")||"text").toLowerCase();if(u==="checkbox"||u==="radio")return{type:"checkbox"};if(u==="number")return{type:"number"}}let i=(n.textContent||"").trim();return i.length>60||i.includes(`
2
+ `)?{type:"textarea"}:{type:"text"}}function Ft(e,t){if(!t||e==="."||e===""||e.startsWith("@"))return null;let r=e.includes("@")?e.split("@")[0]:e;if(!r)return null;try{return t.querySelector(r)}catch{return null}}function Ut(e){if(e.type==="textarea")return document.createElement("textarea");if(e.type==="select")return document.createElement("select");let t=document.createElement("input");return t.type=e.type==="checkbox"?"checkbox":e.type==="number"?"number":"text",t}function he(e){return typeof e=="number"?`#${e+1}`:String(e).replace(/([a-z])([A-Z])/g,"$1 $2").replace(/[_-]+/g," ").replace(/^\w/,t=>t.toUpperCase())}function Wt(e){return` \xB7 ${e}`}var nt={includeClasses:!0,includeAttributes:["href","src","name","type","role","aria-label","alt","title"],excludeAttributePrefixes:["data-morph-","data-hyper-","data-im-"],textHintLength:64,excludeIds:!0,maxPathDepth:4,landmarks:["HEADER","NAV","MAIN","ASIDE","FOOTER","SECTION","ARTICLE"],weights:{signature:100,pathSegment:10,textMatch:20,textMismatch:25,uniqueCandidate:50,positionPenalty:1,slotMatch:30},minConfidence:101};function qt(e){let t=5381;for(let r=0;r<e.length;r++)t=(t<<5)+t^e.charCodeAt(r);return Math.abs(t).toString(36)}function Vt(e){if(e.classList&&e.classList.length>0)return Array.from(e.classList).sort().join(" ");let t=e.getAttribute?.("class");return t?t.split(/\s+/).filter(Boolean).sort().join(" "):""}function Kt(e,t){let r=[];for(let n of e.attributes||[]){let o=n.name;o==="id"||o==="class"||t.excludeAttributePrefixes.some(i=>o.startsWith(i))||t.includeAttributes.includes(o)&&r.push(`${o}=${n.value}`)}return r.sort().join("|")}function zt(e,t){return(e.textContent||"").replace(/\s+/g," ").trim().slice(0,t.textHintLength)}function Jt(e,t){let r=[e.tagName];return t.includeClasses&&r.push(Vt(e)),r.push(Kt(e,t)),qt(r.join("|"))}function Yt(e){let t=e.tagName,r=1,n=e.previousElementSibling;for(;n;)n.tagName===t&&r++,n=n.previousElementSibling;return r}function Gt(e,t){return e.id||e.getAttribute?.("role")?!0:t.landmarks.includes(e.tagName)}function Qt(e){if(e.id)return`#${e.id}`;let t=e.getAttribute?.("role");return t?`@${t}`:e.tagName}function Xt(e,t){let r=[],n=e;for(;n&&n.tagName&&r.length<t.maxPathDepth;){let o=`${n.tagName}:${Yt(n)}`;if(r.unshift(o),n!==e&&Gt(n,t)){r.unshift(Qt(n));break}n=n.parentElement}return r}function Zt(e,t){let r=0,n=e.length-1,o=t.length-1;for(;n>=0&&o>=0&&e[n]===t[o];)r++,n--,o--;return r}function j(e,t,r){if(r.has(e))return r.get(e);let n={signature:Jt(e,t),path:Xt(e,t),textHint:zt(e,t)};return r.set(e,n),n}function at(e,t,r,n){if(n.has(e))return n.get(e);let o=new Map,i=e.querySelectorAll("*"),u=0;for(let s of i){let a=j(s,t,r);a.domIndex=u++,o.has(a.signature)||o.set(a.signature,[]),o.get(a.signature).push(s)}return n.set(e,o),o}function er(e,t,r){r.delete(e),t.delete(e);let n=e.querySelectorAll("*");for(let o of n)t.delete(o)}function Ce(e,t,r,n,o){let i=j(e,r,n),u=j(t,r,n),s=r.weights,a={},M=0;if(i.signature!==u.signature)return{score:0,breakdown:{rejected:"signature mismatch"}};M+=s.signature,a.signature=s.signature;let b=Zt(i.path,u.path)*s.pathSegment;M+=b,a.path=b;let h=!0;if(i.textHint&&u.textHint?i.textHint===u.textHint?(M+=s.textMatch,a.text=s.textMatch):(M-=s.textMismatch,a.text=-s.textMismatch,h=!1):i.textHint!==u.textHint&&(M-=s.textMismatch,a.text=-s.textMismatch,h=!1),o.candidateCount===1&&h&&(M+=s.uniqueCandidate,a.unique=s.uniqueCandidate),typeof i.domIndex=="number"&&typeof u.domIndex=="number"){let R=Math.abs(i.domIndex-u.domIndex),N=Math.min(R*s.positionPenalty,20);M-=N,a.drift=-N}return{score:M,breakdown:a}}function ot(e,t,r,n,o){if(r.excludeIds&&e.id)return null;let i=at(t,r,n,o),u=j(e,r,n);if(typeof u.domIndex!="number"){let h=0,R=e.previousElementSibling;for(;R;)h++,R=R.previousElementSibling;u.domIndex=h}let s=i.get(u.signature)||[],a=r.excludeIds?s.filter(h=>!h.id):s;if(a.length===0)return null;let M=null,w=0,b=null;for(let h of a){let{score:R,breakdown:N}=Ce(e,h,r,n,{candidateCount:a.length});R>w&&(w=R,M=h,b=N)}return w<r.minConfidence?null:{element:M,confidence:w,breakdown:b}}function tr(e,t,r,n){let o=[],i=r.weights.signature+r.weights.slotMatch,u={slot:i};function s(b){if(b.children)return b.children;let h=b.childNodes;if(!h)return[];let R=[];for(let N=0;N<h.length;N++)h[N].nodeType===1&&R.push(h[N]);return R}function a(b,h){let R=s(b),N=s(h);if(R.length===N.length)for(let k=0;k<R.length;k++){let m=R[k],O=N[k];if(r.excludeIds&&(m.id||O.id)||m.tagName!==O.tagName)continue;let v=j(m,r,n).signature,S=j(O,r,n).signature;v!==S&&o.push({newEl:m,oldEl:O,score:i,breakdown:u}),a(m,O)}}function M(b,h){for(;;){if(b.tagName===h.tagName)return[b,h];let R=s(b);if(!b.tagName&&R.length===1){b=R[0];continue}let N=s(h);if(N.length===1&&N[0].tagName===b.tagName){h=N[0];continue}return null}}let w=M(e,t);return w&&a(w[0],w[1]),o}function it(e,t,r,n,o){let i=t.querySelectorAll("*"),u=at(e,r,n,o),s=0;for(let b of i){let h=j(b,r,n);h.domIndex=s++}let a=[];for(let b of i){if(r.excludeIds&&b.id)continue;let h=j(b,r,n),R=u.get(h.signature)||[],N=r.excludeIds?R.filter(k=>!k.id):R;for(let k of N){let{score:m,breakdown:O}=Ce(b,k,r,n,{candidateCount:N.length});m>=r.minConfidence&&a.push({newEl:b,oldEl:k,score:m,breakdown:O})}}if(r.weights.slotMatch>0){let b=tr(t,e,r,n);for(let h of b)a.push(h)}a.sort((b,h)=>h.score-b.score);let M=new Map,w=new Set;for(let{newEl:b,oldEl:h}of a)M.has(b)||w.has(h)||(M.set(b,h),w.add(h));return M}function st(e,t,r,n){let o=j(e,r,n),i=j(t,r,n),{score:u,breakdown:s}=Ce(e,t,r,n,{candidateCount:1});return{matches:u>=r.minConfidence,score:u,breakdown:s,newMeta:{signature:o.signature,path:o.path,textHint:o.textHint},oldMeta:{signature:i.signature,path:i.path,textHint:i.textHint}}}function ct(e={}){let t={...nt,...e,weights:{...nt.weights,...e.weights}},r=new WeakMap,n=new WeakMap;return{findMatch:(o,i)=>ot(o,i,t,r,n),computeMatches:(o,i)=>it(o,i,t,r,n),explain:(o,i)=>st(o,i,t,r),invalidate:o=>er(o,r,n),session:()=>{let o=new WeakMap,i=new WeakMap;return{findMatch:(u,s)=>ot(u,s,t,o,i),computeMatches:(u,s)=>it(u,s,t,o,i),explain:(u,s)=>st(u,s,t,o)}},getConfig:()=>({...t})}}var rr=ct(),He=function(){"use strict";let e=()=>{};function t(m){if(!(m instanceof Element))return!1;if(m.hasAttribute("save-ignore"))return!0;if(m.tagName==="LINK"||m.tagName==="SCRIPT"){let O=m.getAttribute("src")||m.getAttribute("href")||"";if(O.startsWith("chrome-extension://")||O.startsWith("moz-extension://")||O.startsWith("safari-web-extension://"))return!0}return!1}function r(m,O){if(O!=="smart")return m.outerHTML;let v=m.getAttribute("src"),S=m.getAttribute("type")||"text/javascript";if(v)try{let x=new URL(v,window.location.href);return`ext:${S}:${x.origin}${x.pathname}${x.search}`}catch{return`ext:${S}:${v}`}else{let x=m.textContent.trim(),E=5381;for(let d=0;d<x.length;d++)E=(E<<5)+E^x.charCodeAt(d);return`inline:${S}:${Math.abs(E).toString(36)}`}}let n={morphStyle:"outerHTML",callbacks:{beforeNodeAdded:e,afterNodeAdded:e,beforeNodeMorphed:e,afterNodeMorphed:e,beforeNodeRemoved:e,afterNodeRemoved:e,beforeAttributeUpdated:e},head:{style:"merge",shouldPreserve:m=>m.getAttribute("im-preserve")==="true",shouldReAppend:m=>m.getAttribute("im-re-append")==="true",shouldRemove:e,afterHeadMorphed:e},scripts:{handle:!1,matchMode:"outerHTML",shouldPreserve:m=>m.getAttribute("im-preserve")==="true",shouldReAppend:m=>m.getAttribute("im-re-append")==="true",shouldRemove:e,afterScriptsHandled:e},restoreFocus:!0},o={computeMatches(m,O){let{computeMatches:v}=rr.session();return v(m,O)}};function i(m,O,v={}){m=N(m);let S=k(O),x=R(m,S,v),E=x.scripts.matchMode,d=new Set(Array.from(m.querySelectorAll("script")).map(l=>r(l,E))),y=s(x,()=>w(x,m,S,l=>l.morphStyle==="innerHTML"?(a(l,m,S),Array.from(m.childNodes)):u(l,m,S)));x.pantry.remove();let c=h(m,d,x);return c.length>0?y instanceof Promise?y.then(l=>Promise.all(c).then(()=>l)):Promise.all(c).then(()=>y):y}function u(m,O,v){let S=k(O);return a(m,S,v,O,O.nextSibling),Array.from(S.childNodes)}function s(m,O){if(!m.config.restoreFocus)return O();let v=document.activeElement;if(!(v instanceof HTMLInputElement||v instanceof HTMLTextAreaElement))return O();let{id:S,selectionStart:x,selectionEnd:E}=v,d=O();return S&&S!==document.activeElement?.getAttribute("id")&&(v=m.target.querySelector(`[id="${S}"]`),v?.focus()),v&&!v.selectionEnd&&E!=null&&v.setSelectionRange(x,E),d}let a=function(){function m(c,l,p,f=null,g=null){l instanceof HTMLTemplateElement&&p instanceof HTMLTemplateElement&&(l=l.content,p=p.content),f||=l.firstChild;for(let A of p.childNodes){if(t(A))continue;if(f&&f!=g){let I=v(c,A,f,g);if(I){I!==f&&x(c,f,I),M(I,A,c),f=I.nextSibling;continue}}if(A instanceof Element){let I=A.getAttribute("id");if(c.persistentIds.has(I)){let L=E(l,I,f,c);M(L,A,c),f=L.nextSibling;continue}if(!c.idMap.has(A)){let L=c.hyperMatches.get(A);if(L&&!c.idMap.has(L)){y(l,L,f),M(L,A,c),f=L.nextSibling;continue}}}let T=O(l,A,f,c);T&&(f=T.nextSibling)}for(;f&&f!=g;){let A=f;f=f.nextSibling,t(A)||S(c,A)}}function O(c,l,p,f){if(f.callbacks.beforeNodeAdded(l)===!1)return null;if(f.idMap.has(l)){let g=document.createElement(l.tagName);return c.insertBefore(g,p),M(g,l,f),f.callbacks.afterNodeAdded(g),g}else{let g=document.importNode(l,!0);return c.insertBefore(g,p),f.callbacks.afterNodeAdded(g),g}}let v=function(){function c(f,g,A,T){let I=g instanceof Element&&!f.idMap.has(g)?f.hyperMatches.get(g):null,L=null,D=g.nextSibling,G=0,C=A;for(;C&&C!=T;){if(p(C,g)){if(l(f,C,g)||C===I&&!f.idMap.has(C))return C;if(L===null){let V=C instanceof Element&&f.hyperMatchedOldElements.has(C);!f.idMap.has(C)&&!V&&(L=C)}}if(L===null&&D&&p(C,D)&&(G++,D=D.nextSibling,G>=2&&(L=void 0)),f.activeElementAndParents.includes(C))break;C=C.nextSibling}return L||null}function l(f,g,A){let T=f.idMap.get(g),I=f.idMap.get(A);if(!I||!T)return!1;for(let L of T)if(I.has(L))return!0;return!1}function p(f,g){let A=f,T=g;return A.nodeType===T.nodeType&&A.tagName===T.tagName&&(!A.getAttribute?.("id")||A.getAttribute?.("id")===T.getAttribute?.("id"))}return c}();function S(c,l){let p=l instanceof Element&&c.hyperMatchedOldElements.has(l)&&!c.idMap.has(l);if(c.idMap.has(l)||p)y(c.pantry,l,null);else{if(c.callbacks.beforeNodeRemoved(l)===!1)return;l.parentNode?.removeChild(l),c.callbacks.afterNodeRemoved(l)}}function x(c,l,p){let f=l;for(;f&&f!==p;){let g=f;f=f.nextSibling,t(g)||S(c,g)}return f}function E(c,l,p,f){let g=f.target.getAttribute?.("id")===l&&f.target||f.target.querySelector(`[id="${l}"]`)||f.pantry.querySelector(`[id="${l}"]`);return d(g,f),y(c,g,p),g}function d(c,l){let p=c.getAttribute("id");for(;c=c.parentNode;){let f=l.idMap.get(c);f&&(f.delete(p),f.size||l.idMap.delete(c))}}function y(c,l,p){if(c.moveBefore)try{c.moveBefore(l,p)}catch{c.insertBefore(l,p)}else c.insertBefore(l,p)}return m}(),M=function(){function m(d,y,c){return c.ignoreActive&&d===document.activeElement?null:(c.callbacks.beforeNodeMorphed(d,y)===!1||(d instanceof HTMLHeadElement&&c.head.ignore||(d instanceof HTMLHeadElement&&c.head.style!=="morph"?b(d,y,c):(O(d,y,c),E(d,c)||a(c,d,y))),c.callbacks.afterNodeMorphed(d,y)),d)}function O(d,y,c){let l=y.nodeType;if(l===1){let p=d,f=y,g=p.attributes,A=f.attributes;for(let T of A)x(T.name,p,"update",c)||p.getAttribute(T.name)!==T.value&&p.setAttribute(T.name,T.value);for(let T=g.length-1;0<=T;T--){let I=g[T];if(I&&!f.hasAttribute(I.name)){if(x(I.name,p,"remove",c))continue;p.removeAttribute(I.name)}}E(p,c)||v(p,f,c)}(l===8||l===3)&&d.nodeValue!==y.nodeValue&&(d.nodeValue=y.nodeValue)}function v(d,y,c){if(d instanceof HTMLInputElement&&y instanceof HTMLInputElement&&y.type!=="file"){let l=y.value,p=d.value;S(d,y,"checked",c),S(d,y,"disabled",c),c.formStateSync==="property"?p!==l&&(x("value",d,"update",c)||(d.value=l)):y.hasAttribute("value")?p!==l&&(x("value",d,"update",c)||(d.setAttribute("value",l),d.value=l)):x("value",d,"remove",c)||(d.value="",d.removeAttribute("value"))}else if(d instanceof HTMLOptionElement&&y instanceof HTMLOptionElement)S(d,y,"selected",c);else if(d instanceof HTMLTextAreaElement&&y instanceof HTMLTextAreaElement){let l=y.value,p=d.value;if(x("value",d,"update",c))return;l!==p&&(d.value=l),d.firstChild&&d.firstChild.nodeValue!==l&&(d.firstChild.nodeValue=l)}}function S(d,y,c,l){let p=y[c],f=d[c];if(p!==f){let g=x(c,d,"update",l);if(g||(d[c]=y[c]),l.formStateSync==="property")return;p?g||d.setAttribute(c,""):x(c,d,"remove",l)||d.removeAttribute(c)}}function x(d,y,c,l){return d==="value"&&l.ignoreActiveValue&&y===document.activeElement?!0:l.callbacks.beforeAttributeUpdated(d,y,c)===!1}function E(d,y){return!!y.ignoreActiveValue&&d===document.activeElement&&d!==document.body}return m}();function w(m,O,v,S){if(m.head.block){let x=O.querySelector("head"),E=v.querySelector("head");if(x&&E){let d=b(x,E,m);return Promise.all(d).then(()=>{let y=Object.assign(m,{head:{block:!1,ignore:!0}});return S(y)})}}return S(m)}function b(m,O,v){let S=[],x=[],E=[],d=[],y=v.scripts.matchMode,c=f=>{if(f.tagName==="SCRIPT")return r(f,y);if(f.tagName==="LINK"&&y==="smart"){let g=f.getAttribute("href");if(g)try{let A=new URL(g,window.location.href);return`link:${f.getAttribute("rel")||""}:${A.origin}${A.pathname}${A.search}`}catch{}}return f.outerHTML},l=new Map;for(let f of O.children)t(f)||l.set(c(f),f);for(let f of m.children){let g=c(f),A=l.has(g),T=v.head.shouldReAppend(f),I=v.head.shouldPreserve(f);A||I?T?x.push(f):(l.delete(g),E.push(f)):v.head.style==="append"?T&&(x.push(f),d.push(f)):v.head.shouldRemove(f)!==!1&&!t(f)&&x.push(f)}d.push(...l.values());let p=[];for(let f of d){let g=document.createRange().createContextualFragment(f.outerHTML).firstChild;if(v.callbacks.beforeNodeAdded(g)!==!1){if("href"in g&&g.href||"src"in g&&g.src){let A,T=new Promise(function(I){A=I});g.addEventListener("load",function(){A()}),p.push(T)}m.appendChild(g),v.callbacks.afterNodeAdded(g),S.push(g)}}for(let f of x)v.callbacks.beforeNodeRemoved(f)!==!1&&(m.removeChild(f),v.callbacks.afterNodeRemoved(f));return v.head.afterHeadMorphed(m,{added:S,kept:E,removed:x}),p}function h(m,O,v){if(!v.scripts.handle)return[];let S=[],x=[],E=[],d=[],y=v.scripts.matchMode,c=Array.from(m.querySelectorAll("script"));for(let p of c){let f=r(p,y),g=O.has(f),A=v.scripts.shouldPreserve(p),T=v.scripts.shouldReAppend(p);g||A?T?(x.push(p),d.push(p)):E.push(p):d.push(p)}for(let p of O){let f=c.some(g=>g.outerHTML===p)}let l=[];for(let p of d){if(v.callbacks.beforeNodeAdded(p)===!1)continue;let f=document.createRange().createContextualFragment(p.outerHTML).firstChild;if(f.src){let g,A=new Promise(function(T){g=T});f.addEventListener("load",function(){g()}),f.addEventListener("error",function(){g()}),l.push(A)}p.replaceWith(f),v.callbacks.afterNodeAdded(f),S.push(f)}return v.scripts.afterScriptsHandled(m,{added:S,kept:E,removed:x}),l}let R=function(){function m(c,l,p){let{persistentIds:f,idMap:g}=d(c,l),A=o.computeMatches(c,l);if(typeof p.key=="function"){let D=new Map,G=new Set,C=H=>{let P=p.key(H);P!=null&&(D.has(P)?G.add(P):D.set(P,H))};c instanceof Element&&C(c);for(let H of c.querySelectorAll("*"))C(H);for(let H of G)D.delete(H);let V=new Map;for(let[H,P]of A)V.set(P,H);let be=l.__hyperMorphRoot||l,ae=new Map,qe=new Set,Ve=H=>{let P=p.key(H);P!=null&&(ae.has(P)?qe.add(P):ae.set(P,H))};be instanceof Element&&Ve(be);for(let H of be.querySelectorAll("*"))Ve(H);for(let H of qe)ae.delete(H);for(let[H,P]of ae){let K=D.get(H);if(!K||K.tagName!==P.tagName)continue;let Ae=V.get(K);Ae&&Ae!==P&&A.delete(Ae);let Me=A.get(P);Me&&Me!==K&&V.delete(Me),A.set(P,K),V.set(K,P)}}let T=new Set;for(let D of A.values())T.add(D);let I=O(p),L=I.morphStyle||"outerHTML";if(!["innerHTML","outerHTML"].includes(L))throw`Do not understand how to morph style ${L}`;return{target:c,newContent:l,config:I,morphStyle:L,ignoreActive:I.ignoreActive,ignoreActiveValue:I.ignoreActiveValue,restoreFocus:I.restoreFocus,formStateSync:I.formStateSync||"attribute",idMap:g,persistentIds:f,hyperMatches:A,hyperMatchedOldElements:T,pantry:v(),activeElementAndParents:S(c),callbacks:I.callbacks,head:I.head,scripts:I.scripts}}function O(c){let l=Object.assign({},n);return Object.assign(l,c),l.callbacks=Object.assign({},n.callbacks,c.callbacks),l.head=Object.assign({},n.head,c.head),l.scripts=Object.assign({},n.scripts,c.scripts),l}function v(){let c=document.createElement("div");return c.hidden=!0,document.body.insertAdjacentElement("afterend",c),c}function S(c){let l=[],p=document.activeElement;if(p?.tagName!=="BODY"&&c.contains(p))for(;p&&(l.push(p),p!==c);)p=p.parentElement;return l}function x(c){let l=Array.from(c.querySelectorAll("[id]"));return c.getAttribute?.("id")&&l.push(c),l}function E(c,l,p,f){for(let g of f){let A=g.getAttribute("id");if(l.has(A)){let T=g;for(;T;){let I=c.get(T);if(I==null&&(I=new Set,c.set(T,I)),I.add(A),T===p)break;T=T.parentElement}}}}function d(c,l){let p=x(c),f=x(l),g=y(p,f),A=new Map;E(A,g,c,p);let T=l.__hyperMorphRoot||l;return E(A,g,T,f),{persistentIds:g,idMap:A}}function y(c,l){let p=new Set,f=new Map;for(let{id:A,tagName:T}of c)f.has(A)?p.add(A):f.set(A,T);let g=new Set;for(let{id:A,tagName:T}of l)g.has(A)?p.add(A):f.get(A)===T&&g.add(A);for(let A of p)g.delete(A);return g}return m}(),{normalizeElement:N,normalizeParent:k}=function(){let m=new WeakSet;function O(E){return E instanceof Document?E.documentElement:E}function v(E){if(E==null)return document.createElement("div");if(typeof E=="string")return v(x(E));if(m.has(E))return E;if(E instanceof Node){if(E.parentNode)return new S(E);{let d=document.createElement("div");return d.append(E),d}}else{let d=document.createElement("div");for(let y of[...E])d.append(y);return d}}class S{constructor(d){this.originalNode=d,this.realParentNode=d.parentNode,this.previousSibling=d.previousSibling,this.nextSibling=d.nextSibling}get childNodes(){let d=[],y=this.previousSibling?this.previousSibling.nextSibling:this.realParentNode.firstChild;for(;y&&y!=this.nextSibling;)d.push(y),y=y.nextSibling;return d}querySelectorAll(d){return this.childNodes.reduce((y,c)=>{if(c instanceof Element){c.matches(d)&&y.push(c);let l=c.querySelectorAll(d);for(let p=0;p<l.length;p++)y.push(l[p])}return y},[])}insertBefore(d,y){return this.realParentNode.insertBefore(d,y)}moveBefore(d,y){return this.realParentNode.moveBefore(d,y)}get __hyperMorphRoot(){return this.originalNode}}function x(E){let d=new DOMParser,y=E.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim,"");if(y.match(/<\/html>/)||y.match(/<\/head>/)||y.match(/<\/body>/)){let c=d.parseFromString(E,"text/html");if(y.match(/<\/html>/))return m.add(c),c;{let l=c.firstChild;return l&&m.add(l),l}}else{let l=d.parseFromString("<body><template>"+E+"</template></body>","text/html").body.querySelector("template").content;return m.add(l),l}}return{normalizeElement:O,normalizeParent:v}}();return{morph:i,defaults:n}}();var Qr=He.morph,Xr=He.defaults,ut=He;function Pe(e,t,{onWidgetRemoved:r}={}){ut.morph(e,t,{morphStyle:"innerHTML",ignoreActiveValue:!0,restoreFocus:!0,formStateSync:"property",callbacks:{beforeNodeRemoved(n){let o=pe.get(n);o?.destroy&&o.destroy(),r?.(n)}}})}var _e=null;function De(e){if(typeof e!="function")throw new TypeError("registerUpgrade expects a function (v1Data) => v2Data");if(_e)throw new te;_e=e}function me(){return _e}function se(e,t){let r={carriedOver:0,discarded:0,listItems:0},n=je(t,e,r);return $e(t,e,r),{data:n,summary:r}}function je(e,t,r){if(typeof e=="string")return e.endsWith("[]")?Array.isArray(t)?(r.listItems+=t.length,r.carriedOver+=t.length,t):void 0:t==null?void 0:(r.carriedOver++,t);if(Array.isArray(e)){let[,n]=e;return Array.isArray(t)?(r.listItems+=t.length,t.map(o=>je(n,o,r))):void 0}if(typeof e=="object"&&e!==null){let n={};for(let[o,i]of Object.entries(e)){let u=je(i,t?.[o],r);u!==void 0&&(n[o]=u)}return n}}function $e(e,t,r){if(t!=null){if(typeof e=="object"&&e!==null&&!Array.isArray(e)){if(typeof t!="object"||Array.isArray(t))return;let n=new Set(Object.keys(e));for(let o of Object.keys(t))n.has(o)?$e(e[o],t[o],r):r.discarded+=ge(t[o]);return}if(Array.isArray(e)&&Array.isArray(t)){let n=e[1];t.forEach(o=>$e(n,o,r));return}typeof e=="string"&&!e.endsWith("[]")&&typeof t=="object"&&t!==null&&(r.discarded+=ge(t))}}function ge(e){return e==null?0:Array.isArray(e)?e.reduce((t,r)=>t+ge(r),0):typeof e=="object"?Object.values(e).reduce((t,r)=>t+ge(r),0):1}async function Be({sourceUrl:e,v1Data:t,v1Version:r=null,parent:n=typeof window<"u"?window:null,timeoutMs:o=15e3,hidden:i=!0}={}){if(!n)throw new Error("upgrade.run requires a window context");if(!e)throw new Error("upgrade.run requires sourceUrl");let u=or(e,n.location.origin),s=new URL(u,n.location.href).origin,a=n.document.createElement("iframe");i&&(a.style.cssText="position:absolute;left:-9999px;top:-9999px;width:1px;height:1px;border:0;"),a.setAttribute("aria-hidden","true"),a.src=u,n.document.body.appendChild(a);let M=()=>{};try{return await new Promise((w,b)=>{let h=setTimeout(()=>{b(new Error(`upgrade.run: helper iframe timed out after ${o}ms`))},o),R=N=>{if(N.source!==a.contentWindow||N.origin!==s)return;let k=N.data;if(!(!k||typeof k!="object")){if(k.type==="hha:upgrade-ready"){a.contentWindow.postMessage({type:"hha:upgrade-data",v1Data:t,v1Version:r},s);return}if(k.type==="hha:upgrade-result"){clearTimeout(h),w({html:k.html,summary:k.summary});return}if(k.type==="hha:upgrade-error"){clearTimeout(h);let m=new Error(k.message||"helper error");m.name=k.name||"UpgradeHelperError",b(m);return}}};n.addEventListener("message",R),M=()=>{n.removeEventListener("message",R),clearTimeout(h),a.parentNode&&a.parentNode.removeChild(a)}})}finally{M()}}function or(e,t){let r=new URL(e,typeof location<"u"?location.href:void 0);return r.searchParams.set("_hyperHtmlApi","upgrade-helper"),r.searchParams.set("parentOrigin",t),r.toString()}function ir(e){return e&&e.nodeType===1&&e.tagName==="SCRIPT"&&e.hasAttribute&&e.hasAttribute("data-rules-name")}function sr(e){return e?(e.nodeType===9||e.nodeType===11,e):null}var ar={find(e,t,r={}){let n=sr(e);if(!n||!n.querySelectorAll)return[];let o=Array.from(n.querySelectorAll(t));r.includeRulesTag||(o=o.filter(u=>!ir(u)));let i=[];if(r.skip&&i.push(r.skip),r.templateAttr&&i.push("["+r.templateAttr+"]"),i.length){let u=i.join(", ");o=o.filter(s=>!s.closest||!s.closest(u))}return o},parent(e){return e?e.parentElement:null},children(e){return e?Array.from(e.children):[]},text(e,t){if(t===void 0)return(e.textContent||"").trim();e.textContent=t},attr(e,t,r){if(r===void 0)return e.hasAttribute&&e.hasAttribute(t)?e.getAttribute(t):null;e.setAttribute(t,r)},removeAttr(e,t){e&&e.removeAttribute&&e.removeAttribute(t)},prop(e,t,r){if(r===void 0){let n=e?e[t]:void 0;return n!==void 0?n:null}e[t]=r},clone(e){return e.cloneNode(!0)},insertAt(e,t,r){let n=e.children[r]||null;e.insertBefore(t,n)},remove(e){e&&e.parentNode&&e.parentNode.removeChild(e)},replaceWith(e,t){if(!e||!e.parentNode)throw new Error("dom.replaceWith: node has no parent");let n=e.ownerDocument.createElement("template");n.innerHTML=t;let o=n.content.firstElementChild;if(!o)throw new Error("dom.replaceWith: html did not parse to an element");return e.parentNode.replaceChild(o,e),o},stripIds(e){let t=0;return e.id&&(e.removeAttribute("id"),t++),(e.querySelectorAll?e.querySelectorAll("[id]"):[]).forEach(n=>{n.removeAttribute("id"),t++}),t},sameNode(e,t){return e===t}},$=ar;var cr="_hyperHtmlApi",ur="upgrade-helper",lr="parentOrigin";function ye(e=typeof location<"u"?location:null){if(!e)return!1;try{return new URLSearchParams(e.search).get(cr)===ur}catch{return!1}}function lt(e=typeof location<"u"?location:null){return e?new URLSearchParams(e.search).get(lr):null}function We({win:e,doc:t,parentOrigin:r}={}){if(e=e||(typeof window<"u"?window:null),t=t||(typeof document<"u"?document:null),!e||!t||(r=r||lt(e.location),!r))return;let n=()=>fr({win:e,doc:t,parentOrigin:r});t.readyState==="loading"?t.addEventListener("DOMContentLoaded",n,{once:!0}):n()}function fr({win:e,doc:t,parentOrigin:r}){let n;try{n=q($,t.body)}catch(a){return Fe(e,r,a)}if(!n)return Fe(e,r,new Error("helper-mode: no rules tag in v2 document"));let o=n.rules,i=pr(t,"hyper-version"),u=!!me(),s=a=>{if(a.source!==e.parent||a.origin!==r)return;let M=a.data;if(!(!M||M.type!=="hha:upgrade-data")){e.removeEventListener("message",s);try{let w=dr({doc:t,rules:o,v1Data:M.v1Data});e.parent.postMessage({type:"hha:upgrade-result",html:w.html,summary:w.summary},r)}catch(w){Fe(e,r,w)}}};e.addEventListener("message",s),e.parent.postMessage({type:"hha:upgrade-ready",rules:o,version:i,hasTransform:u},r)}function dr({doc:e,rules:t,v1Data:r}){let n=me(),o=r,i=!1;n&&(o=n(r),i=!0);let{data:u,summary:s}=se(o,t);W($,e.body,t,u);let a=B($,e.body,t);return{html:`<!DOCTYPE html>
3
+ `+e.documentElement.outerHTML,summary:{...s,transformApplied:i,appliedFieldCount:Ue(a)}}}function Fe(e,t,r){e.parent.postMessage({type:"hha:upgrade-error",name:r?.name||"Error",message:r?.message||String(r)},t)}function pr(e,t){let r=e.querySelector(`meta[name="${t}"]`);return r?r.getAttribute("content"):null}function Ue(e){return e==null?0:Array.isArray(e)?e.reduce((t,r)=>t+Ue(r),0):typeof e=="object"?Object.values(e).reduce((t,r)=>t+Ue(r),0):1}var ft={extract:(e,t,r)=>B($,e,t,r),apply:(e,t,r,n)=>W($,e,t,r,n),findRulesIn:(e,t)=>q($,e,t),findRules:(e,t)=>Ne($,e,t),bind:(e,t,r)=>Xe($,e,t,r),parseStrict:Re,parseRelaxed:oe,errors:ue,DOM_PROPERTIES:ce},dt={buildForm:Ie,bindFormEvents:ke,scaffold:Y,morphForm:Pe,path:de},pt={registerUpgrade:De,run:Be,shapeMatch:se,isHelperMode:ye};typeof window<"u"&&ye(window.location)&&We({win:window,doc:document});var mr={engine:ft,cms:dt,upgrade:pt},gr=mr;return bt(yr);})();
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "apply",
10
10
  "CMS"
11
11
  ],
12
- "version": "0.1.0",
12
+ "version": "0.2.0",
13
13
  "homepage": "https://github.com/panphora/hyper-html-api",
14
14
  "bugs": {
15
15
  "url": "https://github.com/panphora/hyper-html-api/issues"
@@ -27,6 +27,7 @@
27
27
  "exports": {
28
28
  ".": "./src/hyper-html-api.js",
29
29
  "./engine": "./src/engine/index.js",
30
+ "./cms": "./src/cms/index.js",
30
31
  "./cheerio": "./src/adapters/cheerio.js",
31
32
  "./dom": "./src/adapters/dom.js"
32
33
  },
@@ -42,8 +43,8 @@
42
43
  "test:webkit": "web-test-runner --playwright --browsers webkit",
43
44
  "test:all": "web-test-runner --concurrency 1 --playwright --browsers chromium firefox webkit",
44
45
  "test:node": "node --test 'test-node/**/*.test.js'",
45
- "test:ci": "npm run test:node && npm run test:all -- --fail-only && node test/lib/ensure-full-coverage.js",
46
- "test:coverage": "npm run test:chrome && node test/lib/ensure-full-coverage.js",
46
+ "test:ci": "npm run test:node && npm run test:all -- --fail-only && node test/lib/ensure-full-coverage.cjs",
47
+ "test:coverage": "npm run test:chrome && node test/lib/ensure-full-coverage.cjs",
47
48
  "format": "prettier --write .",
48
49
  "format:check": "prettier --check ."
49
50
  },
@@ -51,6 +52,9 @@
51
52
  "type": "git",
52
53
  "url": "git+https://github.com/panphora/hyper-html-api.git"
53
54
  },
55
+ "dependencies": {
56
+ "hyper-morph": "^0.3.0"
57
+ },
54
58
  "devDependencies": {
55
59
  "@web/test-runner": "^0.20.0",
56
60
  "@web/test-runner-playwright": "^0.11.0",
@@ -1,10 +1,8 @@
1
- const RULES_TAG_ID = 'hyper-html-api'
2
-
3
1
  function isRulesTag(node) {
4
2
  if (!node || !node.attr) return false
5
- if (node.attr('id') !== RULES_TAG_ID) return false
6
3
  const tag = node.prop ? node.prop('tagName') : ''
7
- return String(tag || '').toUpperCase() === 'SCRIPT'
4
+ if (String(tag || '').toUpperCase() !== 'SCRIPT') return false
5
+ return node.attr('data-rules-name') !== undefined
8
6
  }
9
7
 
10
8
  function toWrappers(cheerioSet) {
@@ -16,9 +14,16 @@ function toWrappers(cheerioSet) {
16
14
  const cheerioAdapter = {
17
15
  find(ctx, selector, opts = {}) {
18
16
  if (!ctx || !ctx.find) return []
19
- const matches = toWrappers(ctx.find(selector))
20
- if (opts.includeRulesTag) return matches
21
- return matches.filter((n) => !isRulesTag(n))
17
+ let matches = toWrappers(ctx.find(selector))
18
+ if (!opts.includeRulesTag) matches = matches.filter((n) => !isRulesTag(n))
19
+ const skipParts = []
20
+ if (opts.skip) skipParts.push(opts.skip)
21
+ if (opts.templateAttr) skipParts.push('[' + opts.templateAttr + ']')
22
+ if (skipParts.length) {
23
+ const combined = skipParts.join(', ')
24
+ matches = matches.filter((n) => !n.closest || n.closest(combined).length === 0)
25
+ }
26
+ return matches
22
27
  },
23
28
 
24
29
  parent(node) {
@@ -45,14 +50,49 @@ const cheerioAdapter = {
45
50
  node.attr(name, value)
46
51
  },
47
52
 
53
+ removeAttr(node, name) {
54
+ if (node) node.removeAttr(name)
55
+ },
56
+
48
57
  prop(node, name, value) {
49
58
  if (value === undefined) {
59
+ // Cheerio's .prop() doesn't expose innerHTML/textContent/className as
60
+ // proper properties. Route reads through the matching cheerio API so
61
+ // they're symmetric with the writes below (and with the DOM adapter).
62
+ if (name === 'innerHTML') return node.html()
63
+ if (name === 'textContent' || name === 'innerText') return node.text()
64
+ if (name === 'className') {
65
+ const v = node.attr('class')
66
+ return v !== undefined ? v : null
67
+ }
50
68
  const v = node.prop(name)
51
69
  return v !== undefined ? v : null
52
70
  }
71
+ // Cheerio's .prop() setter writes a literal attribute named `name`; it
72
+ // does NOT mutate the underlying property (cheerio has no live DOM).
73
+ // For names that have semantic write meaning, route through the right
74
+ // cheerio API instead.
75
+ const v = value == null ? '' : String(value)
76
+ if (name === 'innerHTML') return node.html(v)
77
+ if (name === 'textContent' || name === 'innerText') return node.text(v)
78
+ if (name === 'className') return node.attr('class', v)
53
79
  node.prop(name, value)
54
80
  },
55
81
 
82
+ replaceWith(node, html) {
83
+ // Capture the parent + index before detaching, then reparse the html
84
+ // and replace. Returns a fresh cheerio wrapper around the new node so
85
+ // callers can keep operating on it.
86
+ const parent = node.parent()
87
+ if (!parent || !parent.length) {
88
+ // Detached node — nothing meaningful we can do. Mirror DOM throwing.
89
+ throw new Error('cheerio.replaceWith: node has no parent')
90
+ }
91
+ const idx = parent.children().index(node[0])
92
+ node.replaceWith(html)
93
+ return parent.children().eq(idx)
94
+ },
95
+
56
96
  clone(node) {
57
97
  return node.clone()
58
98
  },
@@ -1,7 +1,6 @@
1
- const RULES_TAG_ID = 'hyper-html-api'
2
-
3
1
  function isRulesTag(node) {
4
- return node && node.nodeType === 1 && node.id === RULES_TAG_ID && node.tagName === 'SCRIPT'
2
+ return node && node.nodeType === 1 && node.tagName === 'SCRIPT'
3
+ && node.hasAttribute && node.hasAttribute('data-rules-name')
5
4
  }
6
5
 
7
6
  function resolveSearchRoot(ctx) {
@@ -15,9 +14,16 @@ const dom = {
15
14
  find(ctx, selector, opts = {}) {
16
15
  const root = resolveSearchRoot(ctx)
17
16
  if (!root || !root.querySelectorAll) return []
18
- const all = Array.from(root.querySelectorAll(selector))
19
- if (opts.includeRulesTag) return all
20
- return all.filter((n) => !isRulesTag(n))
17
+ let all = Array.from(root.querySelectorAll(selector))
18
+ if (!opts.includeRulesTag) all = all.filter((n) => !isRulesTag(n))
19
+ const skipParts = []
20
+ if (opts.skip) skipParts.push(opts.skip)
21
+ if (opts.templateAttr) skipParts.push('[' + opts.templateAttr + ']')
22
+ if (skipParts.length) {
23
+ const combined = skipParts.join(', ')
24
+ all = all.filter((n) => !n.closest || !n.closest(combined))
25
+ }
26
+ return all
21
27
  },
22
28
 
23
29
  parent(node) {
@@ -40,6 +46,10 @@ const dom = {
40
46
  node.setAttribute(name, value)
41
47
  },
42
48
 
49
+ removeAttr(node, name) {
50
+ if (node && node.removeAttribute) node.removeAttribute(name)
51
+ },
52
+
43
53
  prop(node, name, value) {
44
54
  if (value === undefined) {
45
55
  const v = node ? node[name] : undefined
@@ -61,6 +71,21 @@ const dom = {
61
71
  if (node && node.parentNode) node.parentNode.removeChild(node)
62
72
  },
63
73
 
74
+ replaceWith(node, html) {
75
+ if (!node || !node.parentNode) {
76
+ throw new Error('dom.replaceWith: node has no parent')
77
+ }
78
+ const doc = node.ownerDocument
79
+ const template = doc.createElement('template')
80
+ template.innerHTML = html
81
+ const newNode = template.content.firstElementChild
82
+ if (!newNode) {
83
+ throw new Error('dom.replaceWith: html did not parse to an element')
84
+ }
85
+ node.parentNode.replaceChild(newNode, node)
86
+ return newNode
87
+ },
88
+
64
89
  stripIds(node) {
65
90
  let count = 0
66
91
  if (node.id) {