hyper-html-api 0.8.0 → 0.8.1

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.
@@ -1,2 +1,2 @@
1
- var hyperHtmlApiUpgrade=(()=>{var Y=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var $e=Object.prototype.hasOwnProperty;var ae=(e,t)=>{for(var n in t)Y(e,n,{get:t[n],enumerable:!0})},Ue=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Ce(t))!$e.call(e,r)&&r!==n&&Y(e,r,{get:()=>t[r],enumerable:!(o=Le(t,r))||o.enumerable});return e};var He=e=>Ue(Y({},"__esModule",{value:!0}),e);var pt={};ae(pt,{default:()=>at,engine:()=>le,upgrade:()=>De});var F=["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"],Q=new Set(F),pe=new Set(["textContent","innerText","innerHTML","value","checked","selected","disabled","readOnly","type","id","className","title"]),de=new Set(["tagName","nodeName","nodeType","nodeValue","childElementCount","classList","baseURI","documentURI","contentType","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","currentSrc","duration","paused","dataset"]);var J={};ae(J,{EmptyListInsert:()=>L,MAX_RULE_DEPTH:()=>_,MaxRuleDepthExceeded:()=>T,RuleTargetReadOnly:()=>C,RulesParseError:()=>j,ShapeMismatch:()=>k,UnknownRulesVersion:()=>S});var j=class extends Error{constructor(t,n){super(t),this.name="RulesParseError",this.cause=n}},S=class extends Error{constructor(t){super(`unknown rules version: ${t}. Library supports "1".`),this.name="UnknownRulesVersion",this.version=t}},_=20,T=class extends Error{constructor(t){super(`rule depth exceeded ${_} at path: ${t.join(".")}`),this.name="MaxRuleDepthExceeded",this.path=t}},k=class extends Error{constructor(t){super(`shape mismatch: ${t.length} field(s) failed validation`),this.name="ShapeMismatch",this.mismatches=t}},L=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}},C=class extends Error{constructor(t){super(`cannot write to read-only DOM property "${t}"`),this.name="RuleTargetReadOnly",this.target=t}};function O(e){let t=0,n=null,o=-1;for(let r=0;r<e.length;r++){let i=e[r];i==="\\"?r++:n?i===n&&(n=null):i==='"'||i==="'"?n=i:i==="["||i==="("?t++:i==="]"||i===")"?t>0&&t--:i==="@"&&t===0&&(o=r)}return o}function Z(e){let t=O(e);return t===-1?{selector:e,prop:null}:{selector:e.slice(0,t),prop:e.slice(t+1)||null}}function x(e,t,n,o={}){return ee(e,t,n,{depth:0,path:[]},o)}function ee(e,t,n,o,r){if(o.depth>_)throw new T(o.path);if(typeof n=="string")return We(e,t,n,o,r);if(Array.isArray(n)){let[i,l]=n,s=e.find(t,i,r);return me(r,o,s),s.map((c,f)=>ee(e,c,l,{depth:o.depth+1,path:[...o.path,f]},r))}if(typeof n=="object"&&n!==null){let i={};for(let[l,s]of Object.entries(n))i[l]=ee(e,t,s,{depth:o.depth+1,path:[...o.path,l]},r);return i}return null}function We(e,t,n,o,r){if(n.endsWith("[]")){let s=n.slice(0,-2),c=e.find(t,s,r);return me(r,o,c),c.map(f=>e.text(f))}if(n.startsWith("@"))return he(e,t,n.slice(1));let i=O(n);if(i!==-1){let s=n.slice(0,i),c=n.slice(i+1),f=s?e.find(t,s,r):[t];return f.length===0?null:he(e,f[0],c)}if(n===".")return e.text(t);let l=e.find(t,n,r);return l.length===0?null:e.text(l[0])}function me(e,t,n){if(typeof e.onRowsRead=="function")try{e.onRowsRead(t.path.slice(),n)}catch(o){console.warn(`[hyper-html-api] onRowsRead threw at "${t.path.join(".")||"(root)"}"`,o)}}function he(e,t,n){if(Q.has(n)){let r=e.prop(t,n);return r==null?null:String(r)}let o=e.attr(t,n);return o||null}function Ee(e,t,n,o){let r=e.length,i=t.length,l=new Array(r).fill(-1);if(o){let d=new Set;for(let h=0;h<r;h++){let m=o[h];!(m>=0&&m<i)||d.has(m)||(l[h]=m,d.add(m))}}if(r===0||i===0)return l;let s=e.map(d=>ye(d,n)),c=t.map(d=>ye(d,n)),f=new Array(i).fill(!1);for(let d of l)d>=0&&(f[d]=!0);let u=new Map;c.forEach((d,h)=>{f[h]||u.set(d,u.has(d)?-1:h)});let a=new Map;s.forEach((d,h)=>{l[h]>=0||a.set(d,(a.get(d)||0)+1)}),s.forEach((d,h)=>{if(l[h]>=0||a.get(d)!==1)return;let m=u.get(d);m===void 0||m===-1||f[m]||(l[h]=m,f[m]=!0)});let p=[];for(let d=0;d<r;d++)l[d]<0&&p.push(d);let y=[];for(let d=0;d<i;d++)f[d]||y.push(d);if(p.length===0||y.length===0)return l;let g=r*i+1,w=(d,h)=>Be(e[d],t[h],n)*g+Math.abs(d-h);for(let[d,h]of Fe(p,y,w))l[d]=h;return l}var Re=e=>typeof e=="object"&&e!==null;function ye(e,t){if(!Re(t))return e==null?" null":String(e);let n=Object.keys(t);return JSON.stringify(n.map(o=>{let r=JSON.stringify(e?.[o]);return r===void 0?" undef":r}))}function Be(e,t,n){if(!Re(n))return e===t?0:1;let o=Object.keys(n);if(o.length===0)return 0;let r=0;for(let i of o){let l=JSON.stringify(e?.[i]),s=JSON.stringify(t?.[i]);l!==s&&r++}return r}function Fe(e,t,n){return e.length<=t.length?ge(e,t,n,!1):ge(t,e,(o,r)=>n(r,o),!0)}function ge(e,t,n,o){let r=e.length,i=t.length,l=[];for(let a=0;a<=r;a++)l.push(new Float64Array(i+1).fill(1/0));let s=[];for(let a=0;a<=r;a++)s.push(new Uint8Array(i+1));for(let a=0;a<=i;a++)l[r][a]=0;for(let a=r-1;a>=0;a--)for(let p=i-1;p>=0;p--){let y=n(e[a],t[p])+l[a+1][p+1],g=l[a][p+1];y<=g?(l[a][p]=y,s[a][p]=1):l[a][p]=g}let c=[],f=0,u=0;for(;f<r&&u<i;)s[f][u]&&(c.push(o?[t[u],e[f]]:[e[f],t[u]]),f++),u++;return c}function ne(e,t,n,o,r,i,l,s={}){let c=e.find(t,n,s);if(r.length===0){c.forEach(E=>e.remove(E)),te(s,"onRowsApplied",i.path,[]);return}let f=r.length>c.length,u=c[0]||null;if(f&&!u&&(u=ve(e,t,n,s),!u))throw new L(i.path);let a=c.map(E=>qe(e,E,o,s)),p=null;if(f&&u){p=e.clone(u),s.templateAttr&&e.removeAttr(p,s.templateAttr);let E=e.stripIds(p);E>0&&console.warn(`[hyper-html-api] stripped ${E} id attribute(s) from cloned template at "${i.path.join(".")||"(root)"}"`)}let y=Ee(r,a,o,Je(e,c,r,i,s)),g=c[0]||u,w=e.parent(g),d=c.length>0?we(e,w,g):0,h=Ve(e,c),m=new Set,z=[],B=r.map((E,D)=>{let M=y[D];if(M>=0)return m.add(M),z.push(!1),c[M];z.push(!0);let X=e.clone(p);return e.stripIds(X),X});c.forEach((E,D)=>{m.has(D)||e.remove(E)}),h?B.forEach((E,D)=>{let M=d+D;e.children(w).findIndex(ke=>e.sameNode(ke,E))!==M&&e.insertAt(w,E,M)}):Ge(e,B,z,w,d),Ke(e,B,o,r,i,l,s),te(s,"onRowsApplied",i.path,B)}function te(e,t,n,o){if(typeof e[t]=="function")try{return e[t](n.slice(),o)}catch(r){console.warn(`[hyper-html-api] ${t} threw at "${n.join(".")||"(root)"}"`,r);return}}function Je(e,t,n,o,r){let i=te(r,"identifyRows",o.path,n);if(!Array.isArray(i))return null;let l=new Array(n.length).fill(-1),s=new Set;for(let c=0;c<n.length;c++)if(i[c]){for(let f=0;f<t.length;f++)if(!(s.has(f)||!e.sameNode(t[f],i[c]))){l[c]=f,s.add(f);break}}return l}function Ke(e,t,n,o,r,i,l){t.forEach((s,c)=>{if(n===null){let f=o[c],u=f==null?"":String(f);e.text(s)!==u&&e.text(s,u)}else{let f=i(e,s,n,o[c],{depth:r.depth+1,path:[...r.path,c]},l);f&&f!==s&&(t[c]=f)}})}function qe(e,t,n,o){return n===null?e.text(t):x(e,t,n,o.onRowsRead?{...o,onRowsRead:void 0}:o)}function we(e,t,n){let o=e.children(t);for(let r=0;r<o.length;r++)if(e.sameNode(o[r],n))return r;return-1}function ve(e,t,n,o){if(!o.templateAttr)return null;let r=t;for(;r;){let i=e.find(r,n,{includeRulesTag:!1,templateAttr:null});for(let l of i)if(e.attr(l,o.templateAttr)!=null)return l;r=e.parent(r)}return null}function Ve(e,t){if(t.length<=1)return!0;let n=e.parent(t[0]);if(!n)return!1;let o=e.children(n),r=[];for(let i of t){let l=o.findIndex(s=>e.sameNode(s,i));if(l===-1)return!1;r.push(l)}return r.sort((i,l)=>i-l),r[r.length-1]-r[0]===r.length-1}function Ge(e,t,n,o,r){let i=null,l=r;for(let s=0;s<t.length;s++){if(!n[s]){i=t[s];continue}let c=i?e.parent(i):o;if(!c)continue;let f=i?we(e,c,i)+1:l++;e.insertAt(c,t[s],f),i=t[s]}}var xe=new Set(["checked","selected","disabled","readOnly","paused"]);function b(e,t,n,o,r={}){let i=[];if(re(n,o,[],i),i.length)throw new k(i);K(e,t,n,o,{depth:0,path:[]},r)}function K(e,t,n,o,r,i={}){if(r.depth>_)throw new T(r.path);if(o===void 0)return t;if(typeof n=="string")return ze(e,t,n,o,r,i);if(Array.isArray(n)){let[l,s]=n;return ne(e,t,l,s,o,r,K,i),t}if(typeof n=="object"&&n!==null){for(let[l,s]of Object.entries(n)){let c=K(e,t,s,o==null?o:o[l],{depth:r.depth+1,path:[...r.path,l]},i);c&&c!==t&&(t=c)}return t}return t}function ze(e,t,n,o,r,i){if(n.endsWith("[]")){let c=n.slice(0,-2);return ne(e,t,c,null,o,r,K,i),t}if(n.startsWith("@"))return Oe(e,t,n.slice(1),o);let l=O(n);if(l!==-1){let c=n.slice(0,l),f=n.slice(l+1),u=c?e.find(t,c,i):[t];return u.length===0||Oe(e,u[0],f,o),t}if(n===".")return Ae(e,t,o),t;let s=e.find(t,n,i);return s.length===0||Ae(e,s[0],o),t}function Ae(e,t,n){let o=n==null?"":String(n);e.text(t)!==o&&e.text(t,o)}function Oe(e,t,n,o){if(de.has(n))throw new C(n);if(n==="outerHTML"){let r=o==null?"":String(o);return e.replaceWith(t,r)}return pe.has(n)?(e.prop(t,n,Xe(n,o)),t):(e.attr(t,n,o==null?"":String(o)),t)}function Xe(e,t){return t==null?xe.has(e)?!1:"":xe.has(e)?t==="false"?!1:!!t:t}function re(e,t,n,o){if(t!==void 0){if(typeof e=="string"){if(e.endsWith("[]")){Array.isArray(t)?t.forEach((r,i)=>{typeof r=="object"&&r!==null&&o.push({path:U([...n,i]),expected:"scalar",got:$(r)})}):o.push({path:U(n),expected:"array",got:$(t)});return}t!==null&&typeof t=="object"&&o.push({path:U(n),expected:"scalar",got:$(t)});return}if(Array.isArray(e)){if(!Array.isArray(t)){o.push({path:U(n),expected:"array",got:$(t)});return}let r=e[1];t.forEach((i,l)=>re(r,i,[...n,l],o));return}if(typeof e=="object"&&e!==null){if(t===null||Array.isArray(t)||typeof t!="object"){o.push({path:U(n),expected:"object",got:$(t)});return}for(let[r,i]of Object.entries(e))re(i,t[r],[...n,r],o)}}}function $(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function U(e){return e.join(".")}function oe(e){try{return JSON.parse(e)}catch(t){throw new j(`Invalid strict JSON: ${t.message}`,t)}}function I(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 n(r){let i=[],l=0;for(;l<r.length;){let s=r[l];if(/\s/.test(s)){l++;continue}if("{}".includes(s)){i.push({type:s,value:s}),l++;continue}if(s==="["){let a=!1,p=l+1;for(;p<r.length&&/\s/.test(r[p]);)p++;if(p<r.length&&/[a-zA-Z_]/.test(r[p])&&(a=!0),!a){i.push({type:s,value:s}),l++;continue}}if(s==="]"){i.push({type:s,value:s}),l++;continue}if(s===":"){i.push({type:t.COLON,value:s}),l++;continue}if(s===","){i.push({type:t.COMMA,value:s}),l++;continue}if(s==='"'||s==="'"){let a=s,p=l+1;for(;p<r.length&&r[p]!==a;)r[p]==="\\"&&p++,p++;i.push({type:t.STRING,value:r.substring(l+1,p),quoted:!0,sourceQuote:a}),l=p+1;continue}let c=l,f;for(;c<r.length&&!/[{},]/.test(r[c]);)if(r[c]===":"){let a=[":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"],p=!1;for(let y of a){let g=y.substring(1);if(r.substring(c+1,c+1+g.length)===g){p=!0,c+=g.length;break}}if(!p)break}else if(r[c]==="["){for(c++;c<r.length&&r[c]!=="]";){if(r[c]==='"'||r[c]==="'"){let a=r[c];for(c++;c<r.length&&r[c]!==a;)r[c]==="\\"&&c++,c++}c++}c<r.length&&r[c]==="]"&&c++}else c++;f=r.substring(l,c);let u=t.IDENTIFIER;/^-?\d+(\.\d+)?$/.test(f)?u=t.NUMBER:f==="true"||f==="false"||f==="null"?u=t.BOOLEAN:/^[.#@\[]|[.#@\[]| /.test(f)&&(u=t.SELECTOR),i.push({type:u,value:f,quoted:!1}),l=c}return i}function o(r){let i="";for(let l=0;l<r.length;l++){let s=r[l];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 c=r[l+1];if(c&&(c.type==="}"||c.type==="]"))continue;i+=s.value;continue}if(s.type===t.STRING&&s.quoted){let c=s.value;s.sourceQuote==="'"&&(c=c.replace(/\\'/g,"'"),c=c.replace(/(\\*)"/g,(f,u)=>u.length%2===0?u+'\\"':f)),i+=`"${c}"`;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 r=n(e),i=o(r);return JSON.parse(i)}catch(r){throw new j("Invalid extraction rules syntax: "+r.message,r)}}var ie="1",Se=/^[a-zA-Z0-9_-]+$/;function H(e,t,n){let o;if(n===void 0)o="script[data-rules-name]";else{if(typeof n!="string"||!Se.test(n))throw new Error(`hyper-html-api: invalid rules token ${JSON.stringify(n)} (must match ${Se})`);o=`script[data-rules-name~="${n}"]`}let r=e.find(t,o,{includeRulesTag:!0});if(r.length===0)return null;n!==void 0&&r.length>1&&console.warn(`hyper-html-api: ${r.length} rules tags match data-rules-name~="${n}"; using the first.`);let i=r[0],l=e.attr(i,"data-rules-version");if(l!==ie)throw new S(l);return{rules:I(e.text(i)),tagNode:i}}function se(e,t,n){if(n&&typeof n=="object")return{rules:n,tagNode:null};if(typeof n=="string"){let o=t&&t.ownerDocument?t.ownerDocument:t;return H(e,o,n)}return null}function Te(e,t,n,o){let r=se(e,t,n);if(!r){let s=typeof n=="string"?`data-rules-name~="${n}"`:"the provided rules object";throw new Error(`hyper-html-api: could not resolve rules for ${s}`)}let{rules:i,tagNode:l}=r;return{rules:i,tagNode:l,get:()=>x(e,t,i,o),set:s=>b(e,t,i,s,o)}}function Qe(e){return e&&e.nodeType===1&&e.tagName==="SCRIPT"&&e.hasAttribute&&e.hasAttribute("data-rules-name")}function Ze(e){return e?(e.nodeType===9||e.nodeType===11,e):null}var et={find(e,t,n={}){let o=Ze(e);if(!o||!o.querySelectorAll)return[];let r=Array.from(o.querySelectorAll(t));n.includeRulesTag||(r=r.filter(s=>!Qe(s)));let i=[];n.skip&&i.push(n.skip);let l=n.templateAttr===null?null:n.templateAttr||"cms-template";if(l&&i.push("["+l+"]"),i.length){let s=i.join(", ");r=r.filter(c=>!c.closest||!c.closest(s))}return r},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,n){if(n===void 0)return e.hasAttribute&&e.hasAttribute(t)?e.getAttribute(t):null;e.setAttribute(t,n)},removeAttr(e,t){e&&e.removeAttribute&&e.removeAttribute(t)},prop(e,t,n){if(n===void 0){let o=e?e[t]:void 0;return o!==void 0?o:null}e[t]=n},clone(e){return e.cloneNode(!0)},insertAt(e,t,n){let o=e.children[n]||null;e.insertBefore(t,o)},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 o=e.ownerDocument.createElement("template");o.innerHTML=t;let r=o.content.firstElementChild;if(!r)throw new Error("dom.replaceWith: html did not parse to an element");return e.parentNode.replaceChild(r,e),r},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}},R=et;var le={extract:(e,t,n)=>x(R,e,t,n),apply:(e,t,n,o)=>b(R,e,t,n,o),findRulesIn:(e,t)=>H(R,e,t),findRules:(e,t)=>se(R,e,t),bind:(e,t,n)=>Te(R,e,t,n),parseStrict:oe,parseRelaxed:I,ruleAttrIndex:O,splitRule:Z,errors:J,DOM_PROPERTIES:F};var tt="hha:upgrade-check:";function A(e,t){let n=e.querySelector(`meta[name="${t}"]`),o=n?n.getAttribute("content"):null;return o&&o.trim()?o.trim():null}function be(e){if(typeof e!="string")return null;let t=e.trim().replace(/^v/,"");return/^\d+(\.\d+)*$/.test(t)?t.split(".").map(Number):null}function nt(e,t){let n=be(e),o=be(t);if(!n||!o)return!1;let r=Math.max(n.length,o.length);for(let i=0;i<r;i++){let l=n[i]||0,s=o[i]||0;if(l!==s)return l>s}return!1}function rt(e){try{let t=globalThis.localStorage.getItem(e);return t?JSON.parse(t):null}catch{return null}}function ot(e,t){try{globalThis.localStorage.setItem(e,JSON.stringify(t))}catch{}}async function Ie({force:e=!1,doc:t,loc:n,fetchFn:o,now:r,ttlMs:i=864e5}={}){if(t=t||(typeof document<"u"?document:null),n=n||(typeof location<"u"?location:null),o=o||(p=>fetch(p)),r=r??Date.now(),!t)return null;let l=A(t,"hyper-source");if(!l)return null;let s=A(t,"hyper-version"),c;try{c=new URL(l,n?n.href:void 0)}catch{return null}if(n&&c.origin===n.origin&&c.pathname===n.pathname)return null;let f=`${tt}${c.href}:${s||"none"}`,u,a=e?null:rt(f);if(a&&typeof a.checkedAt=="number"&&r-a.checkedAt<i)u=a.sourceVersion;else{try{let p=await o(c.href);if(!p.ok)throw new Error(`HTTP ${p.status}`);let y=await p.text(),g=new DOMParser().parseFromString(y,"text/html");u=A(g,"hyper-version")}catch{u=null}ot(f,{checkedAt:r,sourceVersion:u})}return u?{available:nt(u,s||"0.0.0"),currentVersion:s,sourceVersion:u,sourceUrl:c.href}:null}var it="script[data-rules-name]";function st(e){return typeof e=="string"?e.trim().replace(/\s+/g," "):""}function q(e,t){let n=e.find(t,it,{includeRulesTag:!0}),o=new Set,r=[];for(let i of n){let l=st(e.attr(i,"data-rules-name"));if(!l)continue;if(o.has(l)){console.warn(`hyper-html-api: duplicate rules tag name "${l}"; using the first.`);continue}let s=e.attr(i,"data-rules-version");if(s!==ie)throw new S(s);o.add(l),r.push({name:l,rules:I(e.text(i))})}return r}function ce(e,t){let n={};for(let{name:o,rules:r}of q(e,t))n[o]=x(e,t,r);return n}function Ne(e){let t=e||document,n=t.nodeType===9?t:t.ownerDocument||t;return{dataByName:ce(R,t),version:A(n,"hyper-version")}}var W=class extends Error{constructor(t,n){super(`could not fetch upgrade source: ${t}`),this.name="UpgradeSourceUnreachable",this.sourceUrl=t,this.cause=n}},v=class extends Error{constructor(t){super(`upgrade source has no rules tags; refusing to drop all existing data: ${t}`),this.name="UpgradeSourceHasNoRules",this.sourceUrl=t}},N=class extends Error{constructor(t,n){super(t),this.name="UpgradeTransformInvalid",this.cause=n}},V=class extends Error{constructor(t){super(`found ${t} script[type="text/hyper-upgrade"] tags; only one is allowed per document.`),this.name="UpgradeMultipleTransforms",this.count=t}};var lt="text/hyper-upgrade";function Me(e,t){let n=e.find(t,`script[type="${lt}"]`);if(n.length===0)return null;if(n.length>1)throw new V(n.length);return e.text(n[0])||null}var ct=new Function("url","return import(url)");async function je(e){let t=new Blob([e],{type:"text/javascript"}),n=URL.createObjectURL(t),o;try{o=await ct(n)}catch(r){throw new N(`transform failed to load: ${r&&r.message?r.message:r}`,r)}finally{URL.revokeObjectURL(n)}if(typeof o.default!="function")throw new N("transform must `export default` a function");return o.default}function G(e,t){let n={carriedOver:0,discarded:0,listItems:0},o=fe(t,e,n);return ue(t,e,n),{data:o,summary:n}}function fe(e,t,n){if(typeof e=="string")return e.endsWith("[]")?Array.isArray(t)?(n.listItems+=t.length,n.carriedOver+=t.length,t):void 0:t==null||typeof t=="object"?void 0:(n.carriedOver++,t);if(Array.isArray(e)){let[,o]=e;return Array.isArray(t)?(n.listItems+=t.length,t.map(r=>fe(o,r,n))):void 0}if(typeof e=="object"&&e!==null){let o={};for(let[r,i]of Object.entries(e)){let l=fe(i,t?.[r],n);l!==void 0&&(o[r]=l)}return o}}function ue(e,t,n){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 r of Object.keys(t))o.has(r)?ue(e[r],t[r],n):n.discarded+=P(t[r]);return}if(Array.isArray(e)&&Array.isArray(t)){let o=e[1];t.forEach(r=>ue(o,r,n));return}typeof e=="string"&&!e.endsWith("[]")&&typeof t=="object"&&t!==null&&(n.discarded+=P(t))}}function P(e){return e==null?0:Array.isArray(e)?e.reduce((t,n)=>t+P(n),0):typeof e=="object"?Object.values(e).reduce((t,n)=>t+P(n),0):1}function _e(e,t,n){let o=q(e,t),r={carriedOver:0,discarded:0,listItems:0},i={},l=new Set;for(let{name:s,rules:c}of o){if(l.add(s),!Object.prototype.hasOwnProperty.call(n,s)){i[s]={carriedOver:0,discarded:0,listItems:0};continue}let{data:f,summary:u}=G(n[s],c);b(e,t,c,f),i[s]=u,r.carriedOver+=u.carriedOver,r.discarded+=u.discarded,r.listItems+=u.listItems}for(let s of Object.keys(n))l.has(s)||(r.discarded+=P(n[s]));return{totals:r,byName:i,rulesTagCount:o.length}}async function Pe({sourceUrl:e,dataByName:t,fromVersion:n,doc:o,loc:r,fetchFn:i}={}){if(o=o||(typeof document<"u"?document:null),r=r||(typeof location<"u"?location:null),i=i||(h=>fetch(h)),!o)throw new Error("upgrade.run requires a document context");if(e=e||A(o,"hyper-source"),!e)throw new Error("upgrade.run: no sourceUrl given and no hyper-source meta tag found");let l=new URL(e,r?r.href:void 0);n=n!==void 0?n:A(o,"hyper-version"),t=t||ce(R,o);let s;try{s=await i(l.href)}catch(h){throw new W(l.href,h)}if(!s.ok)throw new W(l.href,new Error(`HTTP ${s.status}`));let c=await s.text(),f=new DOMParser().parseFromString(c,"text/html"),u=A(f,"hyper-version"),a=t,p=!1,y=Me(R,f);if(y){let m=await(await je(y))(a,{fromVersion:n,toVersion:u});if(!m||typeof m!="object"||Array.isArray(m))throw new N("transform must return a plain object map of { rulesName: data }");a=m,p=!0}let{totals:g,byName:w,rulesTagCount:d}=_e(R,f,a);if(d===0&&Object.keys(a).length>0)throw new v(l.href);return{html:ft(f),fromVersion:n,toVersion:u,summary:{transformApplied:p,totals:g,byName:w}}}function ft(e){return`<!DOCTYPE ${e.doctype&&e.doctype.name?e.doctype.name:"html"}>
2
- `+e.documentElement.outerHTML}var De={checkForUpdate:Ie,run:Pe,extractAll:Ne,shapeMatch:G};var ut={engine:le,upgrade:De},at=ut;return He(pt);})();
1
+ var hyperHtmlApiUpgrade=(()=>{var te=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var Ve=Object.getOwnPropertyNames;var Je=Object.prototype.hasOwnProperty;var Ee=(e,t)=>{for(var n in t)te(e,n,{get:t[n],enumerable:!0})},Ye=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Ve(t))!Je.call(e,r)&&r!==n&&te(e,r,{get:()=>t[r],enumerable:!(o=Ke(t,r))||o.enumerable});return e};var Ge=e=>Ye(te({},"__esModule",{value:!0}),e);var St={};Ee(St,{default:()=>bt,engine:()=>pe,upgrade:()=>ze});var J=["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"],ne=new Set(J),we=new Set(["textContent","innerText","innerHTML","value","checked","selected","disabled","readOnly","type","id","className","title"]),re=new Set(["tagName","nodeName","nodeType","nodeValue","childElementCount","classList","baseURI","documentURI","contentType","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","currentSrc","duration","paused","dataset"]);var Y={};Ee(Y,{EmptyListInsert:()=>U,MAX_RULE_DEPTH:()=>_,MaxRuleDepthExceeded:()=>I,RuleTargetReadOnly:()=>H,RulesParseError:()=>k,ShapeMismatch:()=>v,UnknownRulesVersion:()=>j});var k=class extends Error{constructor(t,n){super(t),this.name="RulesParseError",this.cause=n}},j=class extends Error{constructor(t){super(`unknown rules version: ${t}. Library supports "1".`),this.name="UnknownRulesVersion",this.version=t}},_=20,I=class extends Error{constructor(t){super(`rule depth exceeded ${_} at path: ${t.join(".")}`),this.name="MaxRuleDepthExceeded",this.path=t}},v=class extends Error{constructor(t){super(`shape mismatch: ${t.length} field(s) failed validation`),this.name="ShapeMismatch",this.mismatches=t}},U=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}},H=class extends Error{constructor(t){super(`cannot write to read-only DOM property "${t}"`),this.name="RuleTargetReadOnly",this.target=t}};function N(e){let t=0,n=null,o=-1;for(let r=0;r<e.length;r++){let i=e[r];i==="\\"?r++:n?i===n&&(n=null):i==='"'||i==="'"?n=i:i==="["||i==="("?t++:i==="]"||i===")"?t>0&&t--:i==="@"&&t===0&&(o=r)}return o}function oe(e){let t=N(e);return t===-1?{selector:e,prop:null}:{selector:e.slice(0,t),prop:e.slice(t+1)||null}}function M(e,t,n,o={}){if(Object.prototype.hasOwnProperty.call(o,"exclude")&&e.semanticExclude===!1)throw new Error("This adapter does not support semantic exclude queries; omit exclude or use the DOM adapter.");return ie(e,t,n,{depth:0,path:[]},o)}function ie(e,t,n,o,r){if(o.depth>_)throw new I(o.path);if(typeof n=="string")return Xe(e,t,n,o,r);if(Array.isArray(n)){let[i,c]=n,s=e.find(t,i,r);return xe(r,o,s),s.map((l,a)=>ie(e,l,c,{depth:o.depth+1,path:[...o.path,a]},r))}if(typeof n=="object"&&n!==null){let i={};for(let[c,s]of Object.entries(n))i[c]=ie(e,t,s,{depth:o.depth+1,path:[...o.path,c]},r);return i}return null}function Xe(e,t,n,o,r){if(n.endsWith("[]")){let s=n.slice(0,-2),l=e.find(t,s,r);return xe(r,o,l),l.map(a=>e.text(a))}if(n.startsWith("@"))return Te(e,t,n.slice(1));let i=N(n);if(i!==-1){let s=n.slice(0,i),l=n.slice(i+1),a=s?e.find(t,s,r):[t];return a.length===0?null:Te(e,a[0],l)}if(n===".")return e.text(t);let c=e.find(t,n,r);return c.length===0?null:e.text(c[0])}function xe(e,t,n){if(typeof e.onRowsRead=="function")try{e.onRowsRead(t.path.slice(),n)}catch(o){console.warn(`[hyper-html-api] onRowsRead threw at "${t.path.join(".")||"(root)"}"`,o)}}function Te(e,t,n){if(ne.has(n)){let r=e.prop(t,n);return r==null?null:String(r)}let o=e.attr(t,n);return o||null}function be(e,t,n,o){let r=e.length,i=t.length,c=new Array(r).fill(-1);if(o){let u=new Set;for(let p=0;p<r;p++){let g=o[p];!(g>=0&&g<i)||u.has(g)||(c[p]=g,u.add(g))}}if(r===0||i===0)return c;let s=e.map(u=>Oe(u,n)),l=t.map(u=>Oe(u,n)),a=new Array(i).fill(!1);for(let u of c)u>=0&&(a[u]=!0);let f=new Map;l.forEach((u,p)=>{a[p]||f.set(u,f.has(u)?-1:p)});let y=new Map;s.forEach((u,p)=>{c[p]>=0||y.set(u,(y.get(u)||0)+1)}),s.forEach((u,p)=>{if(c[p]>=0||y.get(u)!==1)return;let g=f.get(u);g===void 0||g===-1||a[g]||(c[p]=g,a[g]=!0)});let d=[];for(let u=0;u<r;u++)c[u]<0&&d.push(u);let T=[];for(let u=0;u<i;u++)a[u]||T.push(u);if(d.length===0||T.length===0)return c;let h=r*i+1,m=(u,p)=>Qe(e[u],t[p],n)*h+Math.abs(u-p);for(let[u,p]of Ze(d,T,m))c[u]=p;return c}var Se=e=>typeof e=="object"&&e!==null;function Oe(e,t){if(!Se(t))return e==null?" null":String(e);let n=Object.keys(t);return JSON.stringify(n.map(o=>{let r=JSON.stringify(e?.[o]);return r===void 0?" undef":r}))}function Qe(e,t,n){if(!Se(n))return e===t?0:1;let o=Object.keys(n);if(o.length===0)return 0;let r=0;for(let i of o){let c=JSON.stringify(e?.[i]),s=JSON.stringify(t?.[i]);c!==s&&r++}return r}function Ze(e,t,n){return e.length<=t.length?Ae(e,t,n,!1):Ae(t,e,(o,r)=>n(r,o),!0)}function Ae(e,t,n,o){let r=e.length,i=t.length,c=[];for(let y=0;y<=r;y++)c.push(new Float64Array(i+1).fill(1/0));let s=[];for(let y=0;y<=r;y++)s.push(new Uint8Array(i+1));for(let y=0;y<=i;y++)c[r][y]=0;for(let y=r-1;y>=0;y--)for(let d=i-1;d>=0;d--){let T=n(e[y],t[d])+c[y+1][d+1],h=c[y][d+1];T<=h?(c[y][d]=T,s[y][d]=1):c[y][d]=h}let l=[],a=0,f=0;for(;a<r&&f<i;)s[a][f]&&(l.push(o?[t[f],e[a]]:[e[a],t[f]]),a++),f++;return l}function le(e,t,n,o,r,i,c,s={}){let l=e.find(t,n,s);if(r.length===0){l.forEach(E=>e.remove(E)),se(s,"onRowsApplied",i.path,[]);return}let a=r.length>l.length,f=l[0]||null;if(a&&!f&&(f=rt(e,t,n,s),!f))throw new U(i.path);let y=l.map(E=>nt(e,E,o,s)),d=null;if(a&&f){d=e.clone(f),s.templateAttr&&e.removeAttr(d,s.templateAttr);let E=e.stripIds(d);E>0&&console.warn(`[hyper-html-api] stripped ${E} id attribute(s) from cloned template at "${i.path.join(".")||"(root)"}"`)}let T=be(r,y,o,et(e,l,r,i,s)),h=l[0]||f,m=e.parent(h),u=l.length>0?Re(e,m,h):0,p=ot(e,l),g=new Set,A=[],O=r.map((E,x)=>{let w=T[x];if(w>=0)return g.add(w),A.push(!1),l[w];A.push(!0);let R=e.clone(d);return e.stripIds(R),R});l.forEach((E,x)=>{g.has(x)||e.remove(E)}),p?O.forEach((E,x)=>{let w=u+x;e.children(m).findIndex(Fe=>e.sameNode(Fe,E))!==w&&e.insertAt(m,E,w)}):it(e,O,A,m,u),tt(e,O,o,r,i,c,s),se(s,"onRowsApplied",i.path,O)}function se(e,t,n,o){if(typeof e[t]=="function")try{return e[t](n.slice(),o)}catch(r){console.warn(`[hyper-html-api] ${t} threw at "${n.join(".")||"(root)"}"`,r);return}}function et(e,t,n,o,r){let i=se(r,"identifyRows",o.path,n);if(!Array.isArray(i))return null;let c=new Array(n.length).fill(-1),s=new Set;for(let l=0;l<n.length;l++)if(i[l]){for(let a=0;a<t.length;a++)if(!(s.has(a)||!e.sameNode(t[a],i[l]))){c[l]=a,s.add(a);break}}return c}function tt(e,t,n,o,r,i,c){t.forEach((s,l)=>{if(n===null){let a=o[l],f=a==null?"":String(a);e.text(s)!==f&&e.text(s,f)}else{let a=i(e,s,n,o[l],{depth:r.depth+1,path:[...r.path,l]},c);a&&a!==s&&(t[l]=a)}})}function nt(e,t,n,o){return n===null?e.text(t):M(e,t,n,o.onRowsRead?{...o,onRowsRead:void 0}:o)}function Re(e,t,n){let o=e.children(t);for(let r=0;r<o.length;r++)if(e.sameNode(o[r],n))return r;return-1}function rt(e,t,n,o){if(!o.templateAttr)return null;let r=t;for(;r;){let i=e.find(r,n,{includeRulesTag:!1,templateAttr:null});for(let c of i)if(e.attr(c,o.templateAttr)!=null)return c;r=e.parent(r)}return null}function ot(e,t){if(t.length<=1)return!0;let n=e.parent(t[0]);if(!n)return!1;let o=e.children(n),r=[];for(let i of t){let c=o.findIndex(s=>e.sameNode(s,i));if(c===-1)return!1;r.push(c)}return r.sort((i,c)=>i-c),r[r.length-1]-r[0]===r.length-1}function it(e,t,n,o,r){let i=null,c=r;for(let s=0;s<t.length;s++){if(!n[s]){i=t[s];continue}let l=i?e.parent(i):o;if(!l)continue;let a=i?Re(e,l,i)+1:c++;e.insertAt(l,t[s],a),i=t[s]}}var Me=new Set(["checked","selected","disabled","readOnly","paused"]);function P(e,t,n,o,r={}){if(Object.prototype.hasOwnProperty.call(r,"exclude")&&e.semanticExclude===!1)throw new Error("This adapter does not support semantic exclude queries; omit exclude or use the DOM adapter.");let i=[];if(ce(n,o,[],i),i.length)throw new v(i);G(e,t,n,o,{depth:0,path:[]},r)}function G(e,t,n,o,r,i={}){if(r.depth>_)throw new I(r.path);if(o===void 0)return t;if(typeof n=="string")return st(e,t,n,o,r,i);if(Array.isArray(n)){let[c,s]=n;return le(e,t,c,s,o,r,G,i),t}if(typeof n=="object"&&n!==null){for(let[c,s]of Object.entries(n)){let l=G(e,t,s,o==null?o:o[c],{depth:r.depth+1,path:[...r.path,c]},i);l&&l!==t&&(t=l)}return t}return t}function st(e,t,n,o,r,i){if(n.endsWith("[]")){let l=n.slice(0,-2);return le(e,t,l,null,o,r,G,i),t}if(n.startsWith("@"))return Ne(e,t,n.slice(1),o);let c=N(n);if(c!==-1){let l=n.slice(0,c),a=n.slice(c+1),f=l?e.find(t,l,i):[t];return f.length===0||Ne(e,f[0],a,o),t}if(n===".")return Ce(e,t,o),t;let s=e.find(t,n,i);return s.length===0||Ce(e,s[0],o),t}function Ce(e,t,n){let o=n==null?"":String(n);e.text(t)!==o&&e.text(t,o)}function Ne(e,t,n,o){if(re.has(n))throw new H(n);if(n==="outerHTML"){let i=o==null?"":String(o);return e.replaceWith(t,i)}if(we.has(n)){let i=lt(n,o);return e.prop(t,n)!==i&&e.prop(t,n,i),t}let r=o==null?"":String(o);return e.attr(t,n)!==r&&e.attr(t,n,r),t}function lt(e,t){return t==null?Me.has(e)?!1:"":Me.has(e)?t==="false"?!1:!!t:t}function ce(e,t,n,o){if(t!==void 0){if(typeof e=="string"){if(e.endsWith("[]")){Array.isArray(t)?t.forEach((r,i)=>{typeof r=="object"&&r!==null&&o.push({path:q([...n,i]),expected:"scalar",got:W(r)})}):o.push({path:q(n),expected:"array",got:W(t)});return}t!==null&&typeof t=="object"&&o.push({path:q(n),expected:"scalar",got:W(t)});return}if(Array.isArray(e)){if(!Array.isArray(t)){o.push({path:q(n),expected:"array",got:W(t)});return}let r=e[1];t.forEach((i,c)=>ce(r,i,[...n,c],o));return}if(typeof e=="object"&&e!==null){if(t===null||Array.isArray(t)||typeof t!="object"){o.push({path:q(n),expected:"object",got:W(t)});return}for(let[r,i]of Object.entries(e))ce(i,t[r],[...n,r],o)}}}function W(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function q(e){return e.join(".")}function fe(e){try{return JSON.parse(e)}catch(t){throw new k(`Invalid strict JSON: ${t.message}`,t)}}function L(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 n(r){let i=[],c=0;for(;c<r.length;){let s=r[c];if(/\s/.test(s)){c++;continue}if("{}".includes(s)){i.push({type:s,value:s}),c++;continue}if(s==="["){let y=!1,d=c+1;for(;d<r.length&&/\s/.test(r[d]);)d++;if(d<r.length&&/[a-zA-Z_]/.test(r[d])&&(y=!0),!y){i.push({type:s,value:s}),c++;continue}}if(s==="]"){i.push({type:s,value:s}),c++;continue}if(s===":"){i.push({type:t.COLON,value:s}),c++;continue}if(s===","){i.push({type:t.COMMA,value:s}),c++;continue}if(s==='"'||s==="'"){let y=s,d=c+1;for(;d<r.length&&r[d]!==y;)r[d]==="\\"&&d++,d++;i.push({type:t.STRING,value:r.substring(c+1,d),quoted:!0,sourceQuote:y}),c=d+1;continue}let l=c,a;for(;l<r.length&&!/[{},]/.test(r[l]);)if(r[l]===":"){let y=[":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"],d=!1;for(let T of y){let h=T.substring(1);if(r.substring(l+1,l+1+h.length)===h){d=!0,l+=h.length;break}}if(!d)break}else if(r[l]==="["){for(l++;l<r.length&&r[l]!=="]";){if(r[l]==='"'||r[l]==="'"){let y=r[l];for(l++;l<r.length&&r[l]!==y;)r[l]==="\\"&&l++,l++}l++}l<r.length&&r[l]==="]"&&l++}else l++;a=r.substring(c,l);let f=t.IDENTIFIER;/^-?\d+(\.\d+)?$/.test(a)?f=t.NUMBER:a==="true"||a==="false"||a==="null"?f=t.BOOLEAN:/^[.#@\[]|[.#@\[]| /.test(a)&&(f=t.SELECTOR),i.push({type:f,value:a,quoted:!1}),c=l}return i}function o(r){let i="";for(let c=0;c<r.length;c++){let s=r[c];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 l=r[c+1];if(l&&(l.type==="}"||l.type==="]"))continue;i+=s.value;continue}if(s.type===t.STRING&&s.quoted){let l=s.value;s.sourceQuote==="'"&&(l=l.replace(/\\'/g,"'"),l=l.replace(/(\\*)"/g,(a,f)=>f.length%2===0?f+'\\"':a)),i+=`"${l}"`;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 r=n(e),i=o(r);return JSON.parse(i)}catch(r){throw new k("Invalid extraction rules syntax: "+r.message,r)}}var ue="1",je=/^[a-zA-Z0-9_-]+$/;function B(e,t,n){let o;if(n===void 0)o="script[data-rules-name]";else{if(typeof n!="string"||!je.test(n))throw new Error(`hyper-html-api: invalid rules token ${JSON.stringify(n)} (must match ${je})`);o=`script[data-rules-name~="${n}"]`}let r=e.find(t,o,{includeRulesTag:!0});if(r.length===0)return null;n!==void 0&&r.length>1&&console.warn(`hyper-html-api: ${r.length} rules tags match data-rules-name~="${n}"; using the first.`);let i=r[0],c=e.attr(i,"data-rules-version");if(c!==ue)throw new j(c);return{rules:L(e.text(i)),tagNode:i}}function ae(e,t,n){if(n&&typeof n=="object")return{rules:n,tagNode:null};if(typeof n=="string"){let o=t&&t.ownerDocument?t.ownerDocument:t;return B(e,o,n)}return null}var Ie=Object.freeze({data:Object.freeze({tokens:["no-data"],bundles:["editor-ui"]}),save:Object.freeze({tokens:["no-save"],bundles:["editor-ui"]}),snapshot:Object.freeze({tokens:["no-snapshot"],bundles:["editor-ui"]}),watch:Object.freeze({tokens:["no-watch"],bundles:["editor-ui"]}),undo:Object.freeze({tokens:["no-undo"],bundles:["editor-ui"]}),history:Object.freeze({tokens:[],bundles:["editor-ui"]})}),ft=Object.freeze({"editor-ui":Object.freeze(["no-data","no-save","no-snapshot","no-watch","no-undo"])}),rn=Object.freeze(["no-save","no-snapshot","no-trigger-autosave","no-dirty","no-watch","no-undo","no-data","freeze","editor-ui"]);function de(e,t){if(!e||e.nodeType!==1)return!1;let n=e.getAttribute?.("clay");return!!(n&&n.split(/\s+/).includes(t)||e.hasAttribute?.(t))}function ut(e,t){if(de(e,t))return!0;for(let[n,o]of Object.entries(ft))if(o.includes(t)&&de(e,n))return!0;return!1}function z(e){let t=Ie[e];if(!t)throw new Error(`Unknown region capability: ${e}`);return[...t.tokens,...t.bundles].flatMap(n=>[`[clay~="${n}"]`,`[${n}]`]).join(", ")}function at(e,t){let n=e&&e.nodeType===1?e:e?.parentElement;for(;n&&n.nodeType===1;){let o=Ie[t];if(!o)throw new Error(`Unknown region capability: ${t}`);if(o.tokens.some(r=>ut(n,r))||o.bundles.some(r=>de(n,r)))return n;n=n.parentElement}return null}function Pe(e,t){return!!at(e,t)}var dt=/:(?:focus(?:-within|-visible)?|hover|active|visited|defined)\b/i;function Le(e,t){if(!/^(INPUT|TEXTAREA|SELECT|OPTION)$/.test(e.tagName||""))return;let n=(e.getAttribute?.("type")||"").toLowerCase();if("value"in e&&"value"in t&&e.tagName!=="OPTION"&&n!=="checkbox"&&n!=="radio"&&(t.value=e.value),"checked"in e&&"checked"in t&&(t.checked=e.checked),"selected"in e&&"selected"in t&&(t.selected=e.selected),e.tagName==="SELECT")for(let o=0;o<e.options.length;o++)t.options[o].selected=e.options[o].selected;"indeterminate"in e&&"indeterminate"in t&&(t.indeterminate=e.indeterminate)}function De(e,t,n,o){if(o)return!!e.closest?.(t);let r=e;for(;r?.nodeType===1;){if(r.matches(t))return!0;if(r===n)break;r=r.parentElement}return!1}function ke(e,t,n,o,r,i,c,s){if(e.nodeType===1&&((c?Pe(e,n):De(e,o,i,!1))||r&&De(e,r,i,c)))return null;let l=t.importNode(e,!1);s.cloneToLive.set(l,e),s.liveToClone.set(e,l);let a=e.nodeType===1&&e.tagName==="TEMPLATE"?e.content:e,f=l.nodeType===1&&l.tagName==="TEMPLATE"?l.content:l;a!==e&&(s.cloneToLive.set(f,a),s.liveToClone.set(a,f));for(let y of a.childNodes||[]){let d=ke(y,t,n,o,r,i,c,s);d&&(f.appendChild(d),y.nodeType===1&&Le(y,d))}return e.nodeType===1&&Le(e,l),l}function F(e,{capability:t="data",exclude:n=null,inherit:o=!0}={}){if(!e)throw new TypeError("createContentView requires a DOM context");let r=e.nodeType===9?e:e.ownerDocument;if(!r?.implementation?.createHTMLDocument)throw new TypeError("createContentView requires an HTML DOM implementation");let i=r.implementation.createHTMLDocument(""),c=new WeakMap,s=new WeakMap,l=e.nodeType===9?e.documentElement:e;n&&i.documentElement.matches(n);let a=z(t),f=ke(l,i,t,a,n,l,o,{cloneToLive:c,liveToClone:s});e.nodeType===9&&f&&(i.replaceChild(f,i.documentElement),s.set(e,i),c.set(i,e));let y=d=>{if(dt.test(d))throw new Error(`Filtered content queries do not support stateful selector: ${d}`)};return{root:f,document:i,capability:t,selector:z(t),cloneToLive:c,liveToClone:s,original(d){return c.get(d)||null},cloneOf(d){return s.get(d)||null},query(d,T=f){return y(d),Array.from(T.querySelectorAll(d),h=>c.get(h)||h)},text(d=f){return(d===f?f:s.get(d))?.textContent||""},html(d=f){return(d===f?f:s.get(d))?.innerHTML??""},clone(d=f){let T=d===f?f:s.get(d);return T?i.importNode(T,!0):null}}}function _e(e){return e&&e.nodeType===1&&e.tagName==="SCRIPT"&&e.hasAttribute&&e.hasAttribute("data-rules-name")}function pt(e){return e?(e.nodeType===9||e.nodeType===11,e):null}var b={semanticExclude:!0,find(e,t,n={}){let o=pt(e);if(!o||!o.querySelectorAll)return[];let r=Array.from(o.querySelectorAll(t));n.includeRulesTag||(r=r.filter(s=>!_e(s)));let i=[];n.skip&&i.push(n.skip);let c=n.templateAttr===null?null:n.templateAttr||"cms-template";if(c&&i.push("["+c+"]"),i.length){let s=i.join(", ");r=r.filter(l=>!l.closest||!l.closest(s))}return r},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,n){if(n===void 0)return e.hasAttribute&&e.hasAttribute(t)?e.getAttribute(t):null;e.setAttribute(t,n)},removeAttr(e,t){e&&e.removeAttribute&&e.removeAttribute(t)},prop(e,t,n){if(n===void 0){let o=e?e[t]:void 0;return o!==void 0?o:null}e[t]=n},clone(e){return e.cloneNode(!0)},insertAt(e,t,n){let o=e.children[n]||null;e.insertBefore(t,o)},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 o=e.ownerDocument.createElement("template");o.innerHTML=t;let r=o.content.firstElementChild;if(!r)throw new Error("dom.replaceWith: html did not parse to an element");return e.parentNode.replaceChild(r,e),r},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}};function K(e,t={}){if(t.exclude===null)return b;let n=[z("data"),t.exclude].filter(Boolean).join(", "),o=e.nodeType===9?e:e.ownerDocument||e,r=e.nodeType===9?e.documentElement:e;if(!t._write&&!r?.matches?.(n)&&!r?.querySelector?.(n)&&!o?.querySelector?.(n))return b;let i=e.nodeType===9||!e.isConnected?e:e.ownerDocument,c=e.nodeType===9?e:e.ownerDocument,s=null,l=()=>s||(s=F(i,{capability:"data",exclude:t.exclude||null})),a=h=>{let m=l();return h===e?m.cloneOf(e):m.cloneOf(h)||h},f=h=>s?.original(h)||h,y=(h,m)=>{l().liveToClone.set(h,m),l().cloneToLive.set(m,h);let u=h.childNodes||[],p=m.childNodes||[];for(let g=0;g<Math.min(u.length,p.length);g++)y(u[g],p[g])},d=(h,m,u,p)=>{let g=Array.from(h.childNodes).filter(w=>s.cloneOf(w)),O=g[0];for(;O&&g.includes(O);)O=O.nextSibling;for(let w of g)w.remove();if(u==="innerHTML"){let w=c.createElement("template");w.innerHTML=p;for(let R of Array.from(w.content.childNodes))h.insertBefore(R,O||null)}else h.insertBefore(c.createTextNode(p),O||null);let E=F(h,{capability:"data",exclude:t.exclude||null});m.replaceChildren(...Array.from(E.root?.childNodes||[]));let x=w=>{let R=E.original(w);R&&(s.liveToClone.set(R,w),s.cloneToLive.set(w,R));for(let ge of Array.from(w.childNodes||[]))x(ge)};for(let w of Array.from(m.childNodes))x(w)},T={...b,find(h,m,u={}){let p=a(h);if(!p?.querySelectorAll)return[];let g=l().query(m,p);u.includeRulesTag||(g=g.filter(E=>!_e(E)));let A=[];u.skip&&A.push(u.skip);let O=u.templateAttr===null?null:u.templateAttr||"cms-template";if(O&&A.push(`[${O}]`),A.length){let E=A.join(", ");g=g.filter(x=>!x.closest?.(E))}return g},parent(h){let m=a(h)?.parentElement;return m?f(m):null},children(h){return Array.from(a(h)?.children||[],f)},text(h,m){if(m===void 0){let g=f(h);return!g?.matches?.(n)&&!g?.querySelector?.(n)?b.text(g):(a(h)?.textContent||"").trim()}let u=f(h);if(!u?.matches?.(n)&&!u?.querySelector?.(n)&&!s){b.text(u,m);return}let p=l().cloneOf(u);p?d(u,p,"textContent",m):b.text(u,m)},attr(h,m,u){let p=f(h);if(u===void 0)return b.attr(p,m);b.attr(p,m,u);let g=s?.cloneOf(p);g&&(b.attr(g,m,u),F(p,{capability:"data",exclude:t.exclude||null}).root===null&&(g.remove(),s.liveToClone.delete(p),s.cloneToLive.delete(g)))},removeAttr(h,m){let u=f(h);b.removeAttr(u,m);let p=s?.cloneOf(u);p&&b.removeAttr(p,m)},prop(h,m,u){let p=f(h);if(u===void 0)return m==="innerHTML"||m==="outerHTML"||m==="textContent"||m==="innerText"?b.prop(a(p),m):b.prop(p,m);let g=m==="innerHTML"||m==="textContent"||m==="innerText",A=g?l().cloneOf(p):s?.cloneOf(p);A&&g?d(p,A,m,u):(b.prop(p,m,u),A&&b.prop(A,m,u))},clone(h){let m=a(h);return m===h?b.clone(h):c.importNode(m,!0)},insertAt(h,m,u){let p=f(h),A=T.children(p)[u]||(()=>{for(let x=p.children.length-1;x>=0;x--){let w=p.children[x];if(l().cloneOf(w))return w.nextElementSibling}return p.firstElementChild})(),O=f(m);p.insertBefore(O,A||null);let E=l().cloneOf(p);if(E){let x=l().cloneOf(O);x||(x=c.importNode(O,!0),y(O,x));let w=Array.from(E.children);E.insertBefore(x,w[u]||null)}},remove(h){let m=f(h),u=l().cloneOf(m);b.remove(m),u&&b.remove(u)},replaceWith(h,m){let u=f(h),p=l().cloneOf(u),g=b.replaceWith(u,m);if(p){let A=F(g,{capability:"data",exclude:t.exclude||null});if(!A.root)p.remove();else{p.replaceWith(A.root);let O=E=>{let x=A.original(E);x&&(s.liveToClone.set(x,E),s.cloneToLive.set(E,x));for(let w of Array.from(E.childNodes||[]))O(w)};O(A.root)}}return g}};return T}var S=b;var pe={extract:(e,t,n={})=>M(K(e,n),e,t,n),apply:(e,t,n,o={})=>P(K(e,{...o,_write:!0}),e,t,n,o),findRulesIn:(e,t)=>B(S,e,t),findRules:(e,t)=>ae(S,e,t),bind:(e,t,n={})=>{let o=ae(S,e,t);if(!o){let r=typeof t=="string"?`data-rules-name~="${t}"`:"the provided rules object";throw new Error(`hyper-html-api: could not resolve rules for ${r}`)}return{...o,get:()=>M(K(e,n),e,o.rules,n),set:r=>P(K(e,{...n,_write:!0}),e,o.rules,r,n)}},parseStrict:fe,parseRelaxed:L,ruleAttrIndex:N,splitRule:oe,errors:Y,DOM_PROPERTIES:J};var ht="hha:upgrade-check:";function C(e,t){let n=e.querySelector(`meta[name="${t}"]`),o=n?n.getAttribute("content"):null;return o&&o.trim()?o.trim():null}function $e(e){if(typeof e!="string")return null;let t=e.trim().replace(/^v/,"");return/^\d+(\.\d+)*$/.test(t)?t.split(".").map(Number):null}function mt(e,t){let n=$e(e),o=$e(t);if(!n||!o)return!1;let r=Math.max(n.length,o.length);for(let i=0;i<r;i++){let c=n[i]||0,s=o[i]||0;if(c!==s)return c>s}return!1}function yt(e){try{let t=globalThis.localStorage.getItem(e);return t?JSON.parse(t):null}catch{return null}}function gt(e,t){try{globalThis.localStorage.setItem(e,JSON.stringify(t))}catch{}}async function ve({force:e=!1,doc:t,loc:n,fetchFn:o,now:r,ttlMs:i=864e5}={}){if(t=t||(typeof document<"u"?document:null),n=n||(typeof location<"u"?location:null),o=o||(d=>fetch(d)),r=r??Date.now(),!t)return null;let c=C(t,"hyper-source");if(!c)return null;let s=C(t,"hyper-version"),l;try{l=new URL(c,n?n.href:void 0)}catch{return null}if(n&&l.origin===n.origin&&l.pathname===n.pathname)return null;let a=`${ht}${l.href}:${s||"none"}`,f,y=e?null:yt(a);if(y&&typeof y.checkedAt=="number"&&r-y.checkedAt<i)f=y.sourceVersion;else{try{let d=await o(l.href);if(!d.ok)throw new Error(`HTTP ${d.status}`);let T=await d.text(),h=new DOMParser().parseFromString(T,"text/html");f=C(h,"hyper-version")}catch{f=null}gt(a,{checkedAt:r,sourceVersion:f})}return f?{available:mt(f,s||"0.0.0"),currentVersion:s,sourceVersion:f,sourceUrl:l.href}:null}var Et="script[data-rules-name]";function wt(e){return typeof e=="string"?e.trim().replace(/\s+/g," "):""}function X(e,t){let n=e.find(t,Et,{includeRulesTag:!0}),o=new Set,r=[];for(let i of n){let c=wt(e.attr(i,"data-rules-name"));if(!c)continue;if(o.has(c)){console.warn(`hyper-html-api: duplicate rules tag name "${c}"; using the first.`);continue}let s=e.attr(i,"data-rules-version");if(s!==ue)throw new j(s);o.add(c),r.push({name:c,rules:L(e.text(i))})}return r}function he(e,t){let n={};for(let{name:o,rules:r}of X(e,t))n[o]=M(e,t,r);return n}function Ue(e){let t=e||document,n=t.nodeType===9?t:t.ownerDocument||t;return{dataByName:he(S,t),version:C(n,"hyper-version")}}var V=class extends Error{constructor(t,n){super(`could not fetch upgrade source: ${t}`),this.name="UpgradeSourceUnreachable",this.sourceUrl=t,this.cause=n}},Q=class extends Error{constructor(t){super(`upgrade source has no rules tags; refusing to drop all existing data: ${t}`),this.name="UpgradeSourceHasNoRules",this.sourceUrl=t}},D=class extends Error{constructor(t,n){super(t),this.name="UpgradeTransformInvalid",this.cause=n}},Z=class extends Error{constructor(t){super(`found ${t} script[type="text/hyper-upgrade"] tags; only one is allowed per document.`),this.name="UpgradeMultipleTransforms",this.count=t}};var Tt="text/hyper-upgrade";function He(e,t){let n=e.find(t,`script[type="${Tt}"]`);if(n.length===0)return null;if(n.length>1)throw new Z(n.length);return e.text(n[0])||null}var xt=new Function("url","return import(url)");async function We(e){let t=new Blob([e],{type:"text/javascript"}),n=URL.createObjectURL(t),o;try{o=await xt(n)}catch(r){throw new D(`transform failed to load: ${r&&r.message?r.message:r}`,r)}finally{URL.revokeObjectURL(n)}if(typeof o.default!="function")throw new D("transform must `export default` a function");return o.default}function ee(e,t){let n={carriedOver:0,discarded:0,listItems:0},o=me(t,e,n);return ye(t,e,n),{data:o,summary:n}}function me(e,t,n){if(typeof e=="string")return e.endsWith("[]")?Array.isArray(t)?(n.listItems+=t.length,n.carriedOver+=t.length,t):void 0:t==null||typeof t=="object"?void 0:(n.carriedOver++,t);if(Array.isArray(e)){let[,o]=e;return Array.isArray(t)?(n.listItems+=t.length,t.map(r=>me(o,r,n))):void 0}if(typeof e=="object"&&e!==null){let o={};for(let[r,i]of Object.entries(e)){let c=me(i,t?.[r],n);c!==void 0&&(o[r]=c)}return o}}function ye(e,t,n){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 r of Object.keys(t))o.has(r)?ye(e[r],t[r],n):n.discarded+=$(t[r]);return}if(Array.isArray(e)&&Array.isArray(t)){let o=e[1];t.forEach(r=>ye(o,r,n));return}typeof e=="string"&&!e.endsWith("[]")&&typeof t=="object"&&t!==null&&(n.discarded+=$(t))}}function $(e){return e==null?0:Array.isArray(e)?e.reduce((t,n)=>t+$(n),0):typeof e=="object"?Object.values(e).reduce((t,n)=>t+$(n),0):1}function qe(e,t,n){let o=X(e,t),r={carriedOver:0,discarded:0,listItems:0},i={},c=new Set;for(let{name:s,rules:l}of o){if(c.add(s),!Object.prototype.hasOwnProperty.call(n,s)){i[s]={carriedOver:0,discarded:0,listItems:0};continue}let{data:a,summary:f}=ee(n[s],l);P(e,t,l,a),i[s]=f,r.carriedOver+=f.carriedOver,r.discarded+=f.discarded,r.listItems+=f.listItems}for(let s of Object.keys(n))c.has(s)||(r.discarded+=$(n[s]));return{totals:r,byName:i,rulesTagCount:o.length}}async function Be({sourceUrl:e,dataByName:t,fromVersion:n,doc:o,loc:r,fetchFn:i}={}){if(o=o||(typeof document<"u"?document:null),r=r||(typeof location<"u"?location:null),i=i||(p=>fetch(p)),!o)throw new Error("upgrade.run requires a document context");if(e=e||C(o,"hyper-source"),!e)throw new Error("upgrade.run: no sourceUrl given and no hyper-source meta tag found");let c=new URL(e,r?r.href:void 0);n=n!==void 0?n:C(o,"hyper-version"),t=t||he(S,o);let s;try{s=await i(c.href)}catch(p){throw new V(c.href,p)}if(!s.ok)throw new V(c.href,new Error(`HTTP ${s.status}`));let l=await s.text(),a=new DOMParser().parseFromString(l,"text/html"),f=C(a,"hyper-version"),y=t,d=!1,T=He(S,a);if(T){let g=await(await We(T))(y,{fromVersion:n,toVersion:f});if(!g||typeof g!="object"||Array.isArray(g))throw new D("transform must return a plain object map of { rulesName: data }");y=g,d=!0}let{totals:h,byName:m,rulesTagCount:u}=qe(S,a,y);if(u===0&&Object.keys(y).length>0)throw new Q(c.href);return{html:Ot(a),fromVersion:n,toVersion:f,summary:{transformApplied:d,totals:h,byName:m}}}function Ot(e){return`<!DOCTYPE ${e.doctype&&e.doctype.name?e.doctype.name:"html"}>
2
+ `+e.documentElement.outerHTML}var ze={checkForUpdate:ve,run:Be,extractAll:Ue,shapeMatch:ee};var At={engine:pe,upgrade:ze},bt=At;return Ge(St);})();
package/package.json CHANGED
@@ -9,13 +9,14 @@
9
9
  "apply",
10
10
  "CMS"
11
11
  ],
12
- "version": "0.8.0",
12
+ "version": "0.8.1",
13
13
  "homepage": "https://github.com/panphora/hyper-html-api",
14
14
  "bugs": {
15
15
  "url": "https://github.com/panphora/hyper-html-api/issues"
16
16
  },
17
17
  "license": "MIT-0",
18
18
  "files": [
19
+ "packed-contract.json",
19
20
  "LICENSE",
20
21
  "README.md",
21
22
  "src/**/*.js",
@@ -61,7 +62,7 @@
61
62
  "url": "git+https://github.com/panphora/hyper-html-api.git"
62
63
  },
63
64
  "dependencies": {
64
- "hyper-morph": "^0.5.1"
65
+ "hyper-morph": "^0.5.3"
65
66
  },
66
67
  "devDependencies": {
67
68
  "@web/test-runner": "^0.20.0",
@@ -0,0 +1 @@
1
+ {"load":["hyper-html-api","hyper-html-api/cheerio","hyper-html-api/cms","hyper-html-api/data","hyper-html-api/dom","hyper-html-api/engine","hyper-html-api/upgrade"]}
@@ -12,7 +12,11 @@ function toWrappers(cheerioSet) {
12
12
  }
13
13
 
14
14
  const cheerioAdapter = {
15
+ semanticExclude: false,
15
16
  find(ctx, selector, opts = {}) {
17
+ if (Object.prototype.hasOwnProperty.call(opts, 'exclude')) {
18
+ throw new Error('Cheerio does not support semantic exclude queries; omit exclude or use the DOM adapter.')
19
+ }
16
20
  if (!ctx || !ctx.find) return []
17
21
  let matches = toWrappers(ctx.find(selector))
18
22
  if (!opts.includeRulesTag) matches = matches.filter((n) => !isRulesTag(n))
@@ -1,3 +1,6 @@
1
+ import { createContentView } from '../lib/content-dom.js'
2
+ import { capabilitySelector } from '../lib/region-capabilities.js'
3
+
1
4
  function isRulesTag(node) {
2
5
  return node && node.nodeType === 1 && node.tagName === 'SCRIPT'
3
6
  && node.hasAttribute && node.hasAttribute('data-rules-name')
@@ -11,6 +14,7 @@ function resolveSearchRoot(ctx) {
11
14
  }
12
15
 
13
16
  const dom = {
17
+ semanticExclude: true,
14
18
  find(ctx, selector, opts = {}) {
15
19
  const root = resolveSearchRoot(ctx)
16
20
  if (!root || !root.querySelectorAll) return []
@@ -110,4 +114,191 @@ const dom = {
110
114
  },
111
115
  }
112
116
 
117
+ export function createDomAdapter(operationRoot, opts = {}) {
118
+ if (opts.exclude === null) return dom
119
+ const semanticSelector = [capabilitySelector('data'), opts.exclude].filter(Boolean).join(', ')
120
+ const searchContext = operationRoot.nodeType === 9 ? operationRoot : (operationRoot.ownerDocument || operationRoot)
121
+ const rootElement = operationRoot.nodeType === 9 ? operationRoot.documentElement : operationRoot
122
+ if (!opts._write && !rootElement?.matches?.(semanticSelector) && !rootElement?.querySelector?.(semanticSelector) &&
123
+ !searchContext?.querySelector?.(semanticSelector)) return dom
124
+ const ownerContext = operationRoot.nodeType === 9 || !operationRoot.isConnected
125
+ ? operationRoot
126
+ : operationRoot.ownerDocument
127
+ const outputDocument = operationRoot.nodeType === 9 ? operationRoot : operationRoot.ownerDocument
128
+ let view = null
129
+ const contentView = () => view || (view = createContentView(ownerContext, { capability: 'data', exclude: opts.exclude || null }))
130
+ const projected = node => {
131
+ const current = contentView()
132
+ return node === operationRoot ? current.cloneOf(operationRoot) : (current.cloneOf(node) || node)
133
+ }
134
+ const live = node => view?.original(node) || node
135
+ const mapParallel = (liveNode, cloneNode) => {
136
+ contentView().liveToClone.set(liveNode, cloneNode)
137
+ contentView().cloneToLive.set(cloneNode, liveNode)
138
+ const liveKids = liveNode.childNodes || []
139
+ const cloneKids = cloneNode.childNodes || []
140
+ for (let i = 0; i < Math.min(liveKids.length, cloneKids.length); i++) mapParallel(liveKids[i], cloneKids[i])
141
+ }
142
+ const replaceProjectedContent = (target, copy, name, value) => {
143
+ const included = Array.from(target.childNodes).filter(node => view.cloneOf(node))
144
+ const first = included[0]
145
+ let anchor = first
146
+ while (anchor && included.includes(anchor)) anchor = anchor.nextSibling
147
+ for (const node of included) node.remove()
148
+ if (name === 'innerHTML') {
149
+ const template = outputDocument.createElement('template')
150
+ template.innerHTML = value
151
+ for (const child of Array.from(template.content.childNodes)) target.insertBefore(child, anchor || null)
152
+ } else {
153
+ target.insertBefore(outputDocument.createTextNode(value), anchor || null)
154
+ }
155
+ const filteredView = createContentView(target, { capability: 'data', exclude: opts.exclude || null })
156
+ copy.replaceChildren(...Array.from(filteredView.root?.childNodes || []))
157
+ const mapFiltered = cloneNode => {
158
+ const liveNode = filteredView.original(cloneNode)
159
+ if (liveNode) {
160
+ view.liveToClone.set(liveNode, cloneNode)
161
+ view.cloneToLive.set(cloneNode, liveNode)
162
+ }
163
+ for (const child of Array.from(cloneNode.childNodes || [])) mapFiltered(child)
164
+ }
165
+ for (const child of Array.from(copy.childNodes)) mapFiltered(child)
166
+ }
167
+
168
+ const adapter = {
169
+ ...dom,
170
+ find(ctx, selector, findOpts = {}) {
171
+ const projectedContext = projected(ctx)
172
+ if (!projectedContext?.querySelectorAll) return []
173
+ let matches = contentView().query(selector, projectedContext)
174
+ if (!findOpts.includeRulesTag) matches = matches.filter(node => !isRulesTag(node))
175
+ const skipParts = []
176
+ if (findOpts.skip) skipParts.push(findOpts.skip)
177
+ const tplAttr = findOpts.templateAttr === null ? null : (findOpts.templateAttr || 'cms-template')
178
+ if (tplAttr) skipParts.push(`[${tplAttr}]`)
179
+ if (skipParts.length) {
180
+ const combined = skipParts.join(', ')
181
+ matches = matches.filter(node => !node.closest?.(combined))
182
+ }
183
+ return matches
184
+ },
185
+ parent(node) {
186
+ const result = projected(node)?.parentElement
187
+ return result ? live(result) : null
188
+ },
189
+ children(node) {
190
+ return Array.from(projected(node)?.children || [], live)
191
+ },
192
+ text(node, value) {
193
+ if (value === undefined) {
194
+ const target = live(node)
195
+ if (!target?.matches?.(semanticSelector) && !target?.querySelector?.(semanticSelector)) return dom.text(target)
196
+ return (projected(node)?.textContent || '').trim()
197
+ }
198
+ const target = live(node)
199
+ if (!target?.matches?.(semanticSelector) && !target?.querySelector?.(semanticSelector) && !view) {
200
+ dom.text(target, value)
201
+ return
202
+ }
203
+ const copy = contentView().cloneOf(target)
204
+ if (copy) replaceProjectedContent(target, copy, 'textContent', value)
205
+ else dom.text(target, value)
206
+ },
207
+ attr(node, name, value) {
208
+ const target = live(node)
209
+ if (value === undefined) return dom.attr(target, name)
210
+ dom.attr(target, name, value)
211
+ const copy = view?.cloneOf(target)
212
+ if (copy) {
213
+ dom.attr(copy, name, value)
214
+ if (createContentView(target, { capability: 'data', exclude: opts.exclude || null }).root === null) {
215
+ copy.remove()
216
+ view.liveToClone.delete(target)
217
+ view.cloneToLive.delete(copy)
218
+ }
219
+ }
220
+ },
221
+ removeAttr(node, name) {
222
+ const target = live(node)
223
+ dom.removeAttr(target, name)
224
+ const copy = view?.cloneOf(target)
225
+ if (copy) dom.removeAttr(copy, name)
226
+ },
227
+ prop(node, name, value) {
228
+ const target = live(node)
229
+ if (value === undefined) {
230
+ if (name === 'innerHTML' || name === 'outerHTML' || name === 'textContent' || name === 'innerText') {
231
+ return dom.prop(projected(target), name)
232
+ }
233
+ return dom.prop(target, name)
234
+ }
235
+ const semanticContent = name === 'innerHTML' || name === 'textContent' || name === 'innerText'
236
+ const copy = semanticContent ? contentView().cloneOf(target) : view?.cloneOf(target)
237
+ if (copy && semanticContent) {
238
+ replaceProjectedContent(target, copy, name, value)
239
+ } else {
240
+ dom.prop(target, name, value)
241
+ if (copy) dom.prop(copy, name, value)
242
+ }
243
+ },
244
+ clone(node) {
245
+ const copy = projected(node)
246
+ return copy === node ? dom.clone(node) : outputDocument.importNode(copy, true)
247
+ },
248
+ insertAt(parent, node, index) {
249
+ const targetParent = live(parent)
250
+ const contentChildren = adapter.children(targetParent)
251
+ const ref = contentChildren[index] || (() => {
252
+ for (let i = targetParent.children.length - 1; i >= 0; i--) {
253
+ const child = targetParent.children[i]
254
+ if (contentView().cloneOf(child)) return child.nextElementSibling
255
+ }
256
+ return targetParent.firstElementChild
257
+ })()
258
+ const targetNode = live(node)
259
+ targetParent.insertBefore(targetNode, ref || null)
260
+ const parentCopy = contentView().cloneOf(targetParent)
261
+ if (parentCopy) {
262
+ let nodeCopy = contentView().cloneOf(targetNode)
263
+ if (!nodeCopy) {
264
+ nodeCopy = outputDocument.importNode(targetNode, true)
265
+ mapParallel(targetNode, nodeCopy)
266
+ }
267
+ const copyContentChildren = Array.from(parentCopy.children)
268
+ parentCopy.insertBefore(nodeCopy, copyContentChildren[index] || null)
269
+ }
270
+ },
271
+ remove(node) {
272
+ const target = live(node)
273
+ const copy = contentView().cloneOf(target)
274
+ dom.remove(target)
275
+ if (copy) dom.remove(copy)
276
+ },
277
+ replaceWith(node, html) {
278
+ const target = live(node)
279
+ const copy = contentView().cloneOf(target)
280
+ const replacement = dom.replaceWith(target, html)
281
+ if (copy) {
282
+ const filteredView = createContentView(replacement, { capability: 'data', exclude: opts.exclude || null })
283
+ if (!filteredView.root) {
284
+ copy.remove()
285
+ } else {
286
+ copy.replaceWith(filteredView.root)
287
+ const mapFiltered = cloneNode => {
288
+ const liveNode = filteredView.original(cloneNode)
289
+ if (liveNode) {
290
+ view.liveToClone.set(liveNode, cloneNode)
291
+ view.cloneToLive.set(cloneNode, liveNode)
292
+ }
293
+ for (const child of Array.from(cloneNode.childNodes || [])) mapFiltered(child)
294
+ }
295
+ mapFiltered(filteredView.root)
296
+ }
297
+ }
298
+ return replacement
299
+ },
300
+ }
301
+ return adapter
302
+ }
303
+
113
304
  export default dom
package/src/dom-api.js CHANGED
@@ -1,15 +1,26 @@
1
1
  import * as engineMod from './engine/index.js'
2
- import domAdapter from './adapters/dom.js'
2
+ import domAdapter, { createDomAdapter } from './adapters/dom.js'
3
3
 
4
4
  // The DOM-bound engine: every engine call pre-wired with the DOM adapter. Lives
5
5
  // here (instead of inline in hyper-html-api.js) so both the full CDN bundle and
6
6
  // the lean `data.js` entry share one definition.
7
7
  export const engine = {
8
- extract: (root, rules, opts) => engineMod.extract(domAdapter, root, rules, opts),
9
- apply: (root, rules, data, opts) => engineMod.apply(domAdapter, root, rules, data, opts),
8
+ extract: (root, rules, opts = {}) => engineMod.extract(createDomAdapter(root, opts), root, rules, opts),
9
+ apply: (root, rules, data, opts = {}) => engineMod.apply(createDomAdapter(root, { ...opts, _write: true }), root, rules, data, opts),
10
10
  findRulesIn: (root, token) => engineMod.findRulesIn(domAdapter, root, token),
11
11
  findRules: (root, source) => engineMod.resolveRules(domAdapter, root, source),
12
- bind: (root, source, opts) => engineMod.bind(domAdapter, root, source, opts),
12
+ bind: (root, source, opts = {}) => {
13
+ const found = engineMod.resolveRules(domAdapter, root, source)
14
+ if (!found) {
15
+ const what = typeof source === 'string' ? `data-rules-name~="${source}"` : 'the provided rules object'
16
+ throw new Error(`hyper-html-api: could not resolve rules for ${what}`)
17
+ }
18
+ return {
19
+ ...found,
20
+ get: () => engineMod.extract(createDomAdapter(root, opts), root, found.rules, opts),
21
+ set: data => engineMod.apply(createDomAdapter(root, { ...opts, _write: true }), root, found.rules, data, opts),
22
+ }
23
+ },
13
24
  parseStrict: engineMod.parseStrict,
14
25
  parseRelaxed: engineMod.parseRelaxed,
15
26
  // Adapter-free, like the parsers above: a consumer that has to split a rule
@@ -48,7 +59,7 @@ function autodetect(root) {
48
59
  export function extractData(a, b) {
49
60
  const root = isNode(a) ? a : document
50
61
  const source = isNode(a) ? b : a
51
- if (source === undefined) return engineMod.extract(domAdapter, root, autodetect(root))
62
+ if (source === undefined) return engineMod.extract(createDomAdapter(root), root, autodetect(root))
52
63
  return engine.bind(root, source).get()
53
64
  }
54
65
 
@@ -59,7 +70,7 @@ export function applyData(root, data, source) {
59
70
  if (!isNode(root)) {
60
71
  throw new Error('hyper-html-api: applyData(root, data, source?) needs a DOM root as the first argument.')
61
72
  }
62
- if (source === undefined) engineMod.apply(domAdapter, root, autodetect(root), data)
73
+ if (source === undefined) engineMod.apply(createDomAdapter(root), root, autodetect(root), data)
63
74
  else engine.bind(root, source).set(data)
64
75
  return root
65
76
  }
@@ -14,6 +14,9 @@ import { ruleAttrIndex } from './rule-syntax.js'
14
14
  const BOOLEAN_PROPS = new Set(['checked', 'selected', 'disabled', 'readOnly', 'paused'])
15
15
 
16
16
  export function apply(adapter, root, rules, data, opts = {}) {
17
+ if (Object.prototype.hasOwnProperty.call(opts, 'exclude') && adapter.semanticExclude === false) {
18
+ throw new Error('This adapter does not support semantic exclude queries; omit exclude or use the DOM adapter.')
19
+ }
17
20
  const mismatches = []
18
21
  validateShape(rules, data, [], mismatches)
19
22
  if (mismatches.length) throw new ShapeMismatch(mismatches)
@@ -109,11 +112,20 @@ function writePropOrAttr(adapter, node, name, value) {
109
112
  const html = value == null ? '' : String(value)
110
113
  return adapter.replaceWith(node, html)
111
114
  }
115
+ // Compare before writing, exactly as writeText does. A property write of an
116
+ // identical value is not a no-op: assigning innerHTML destroys and rebuilds
117
+ // every child, and setting an attribute to the value it already has still
118
+ // emits a mutation record. The CMS re-applies the whole page on each
119
+ // keystroke, so without this every rich-text region on the page was torn
120
+ // down per keystroke (losing the caret, restarting an embedded video or
121
+ // iframe) and every attribute rule emitted a record to undo and live sync.
112
122
  if (DOM_PROPERTIES_WRITE_SET.has(name)) {
113
- adapter.prop(node, name, coercePropValue(name, value))
123
+ const next = coercePropValue(name, value)
124
+ if (adapter.prop(node, name) !== next) adapter.prop(node, name, next)
114
125
  return node
115
126
  }
116
- adapter.attr(node, name, value == null ? '' : String(value))
127
+ const next = value == null ? '' : String(value)
128
+ if (adapter.attr(node, name) !== next) adapter.attr(node, name, next)
117
129
  return node
118
130
  }
119
131
 
@@ -3,6 +3,9 @@ import { MaxRuleDepthExceeded, MAX_RULE_DEPTH } from './errors.js'
3
3
  import { ruleAttrIndex } from './rule-syntax.js'
4
4
 
5
5
  export function extract(adapter, root, rules, opts = {}) {
6
+ if (Object.prototype.hasOwnProperty.call(opts, 'exclude') && adapter.semanticExclude === false) {
7
+ throw new Error('This adapter does not support semantic exclude queries; omit exclude or use the DOM adapter.')
8
+ }
6
9
  return extractAt(adapter, root, rules, { depth: 0, path: [] }, opts)
7
10
  }
8
11
 
@@ -8,7 +8,7 @@ export { findRulesIn } from './rules-tag.js'
8
8
  export { parseStrict, parseRelaxed } from './rules.js'
9
9
  export { ruleAttrIndex, splitRule } from './rule-syntax.js'
10
10
  export * as errors from './errors.js'
11
- export { DOM_PROPERTIES, DOM_PROPERTIES_SET } from './dom-properties.js'
11
+ export { DOM_PROPERTIES, DOM_PROPERTIES_SET, DOM_PROPERTIES_READ_ONLY_SET } from './dom-properties.js'
12
12
 
13
13
  // source: object literal → use as-is (no tag); string → look up by token.
14
14
  // For an element root, search the whole document (root.ownerDocument) so a
@@ -0,0 +1,110 @@
1
+ // GENERATED from clayjs/src/lib/content-dom.js. Edit ClayJS and run `npm run propagate:foundation`.
2
+
3
+ import { capabilitySelector, hasCapability } from './region-capabilities.js'
4
+
5
+ const UNSUPPORTED_SELECTOR = /:(?:focus(?:-within|-visible)?|hover|active|visited|defined)\b/i
6
+
7
+ function copyControlState(source, copy) {
8
+ if (!/^(INPUT|TEXTAREA|SELECT|OPTION)$/.test(source.tagName || '')) return
9
+ const type = (source.getAttribute?.('type') || '').toLowerCase()
10
+ if ('value' in source && 'value' in copy && source.tagName !== 'OPTION' && type !== 'checkbox' && type !== 'radio') copy.value = source.value
11
+ if ('checked' in source && 'checked' in copy) copy.checked = source.checked
12
+ if ('selected' in source && 'selected' in copy) copy.selected = source.selected
13
+ if (source.tagName === 'SELECT') {
14
+ for (let i = 0; i < source.options.length; i++) copy.options[i].selected = source.options[i].selected
15
+ }
16
+ if ('indeterminate' in source && 'indeterminate' in copy) copy.indeterminate = source.indeterminate
17
+ }
18
+
19
+ function matchesWithin(node, selector, boundary, inherit) {
20
+ if (inherit) return !!node.closest?.(selector)
21
+ let current = node
22
+ while (current?.nodeType === 1) {
23
+ if (current.matches(selector)) return true
24
+ if (current === boundary) break
25
+ current = current.parentElement
26
+ }
27
+ return false
28
+ }
29
+
30
+ function importTree(source, targetDocument, capability, capabilityMatch, exclude, boundary, inherit, maps) {
31
+ if (source.nodeType === 1 && (
32
+ (inherit ? hasCapability(source, capability) : matchesWithin(source, capabilityMatch, boundary, false)) ||
33
+ (exclude && matchesWithin(source, exclude, boundary, inherit))
34
+ )) return null
35
+ const copy = targetDocument.importNode(source, false)
36
+ maps.cloneToLive.set(copy, source)
37
+ maps.liveToClone.set(source, copy)
38
+ const sourceChildren = source.nodeType === 1 && source.tagName === 'TEMPLATE' ? source.content : source
39
+ const copyChildren = copy.nodeType === 1 && copy.tagName === 'TEMPLATE' ? copy.content : copy
40
+ if (sourceChildren !== source) {
41
+ maps.cloneToLive.set(copyChildren, sourceChildren)
42
+ maps.liveToClone.set(sourceChildren, copyChildren)
43
+ }
44
+ for (const child of sourceChildren.childNodes || []) {
45
+ const childCopy = importTree(child, targetDocument, capability, capabilityMatch, exclude, boundary, inherit, maps)
46
+ if (childCopy) {
47
+ copyChildren.appendChild(childCopy)
48
+ if (child.nodeType === 1) copyControlState(child, childCopy)
49
+ }
50
+ }
51
+ if (source.nodeType === 1) copyControlState(source, copy)
52
+ return copy
53
+ }
54
+
55
+ export function createContentView(context, { capability = 'data', exclude = null, inherit = true } = {}) {
56
+ if (!context) throw new TypeError('createContentView requires a DOM context')
57
+ const sourceDocument = context.nodeType === 9 ? context : context.ownerDocument
58
+ if (!sourceDocument?.implementation?.createHTMLDocument) {
59
+ throw new TypeError('createContentView requires an HTML DOM implementation')
60
+ }
61
+ const inertDocument = sourceDocument.implementation.createHTMLDocument('')
62
+ const cloneToLive = new WeakMap()
63
+ const liveToClone = new WeakMap()
64
+ const sourceRoot = context.nodeType === 9 ? context.documentElement : context
65
+ if (exclude) inertDocument.documentElement.matches(exclude)
66
+ const capabilityMatch = capabilitySelector(capability)
67
+ const root = importTree(sourceRoot, inertDocument, capability, capabilityMatch, exclude, sourceRoot, inherit, { cloneToLive, liveToClone })
68
+ if (context.nodeType === 9 && root) {
69
+ inertDocument.replaceChild(root, inertDocument.documentElement)
70
+ liveToClone.set(context, inertDocument)
71
+ cloneToLive.set(inertDocument, context)
72
+ }
73
+
74
+ const assertSelector = selector => {
75
+ if (UNSUPPORTED_SELECTOR.test(selector)) {
76
+ throw new Error(`Filtered content queries do not support stateful selector: ${selector}`)
77
+ }
78
+ }
79
+
80
+ return {
81
+ root,
82
+ document: inertDocument,
83
+ capability,
84
+ selector: capabilitySelector(capability),
85
+ cloneToLive,
86
+ liveToClone,
87
+ original(node) { return cloneToLive.get(node) || null },
88
+ cloneOf(node) { return liveToClone.get(node) || null },
89
+ query(selector, queryRoot = root) {
90
+ assertSelector(selector)
91
+ return Array.from(queryRoot.querySelectorAll(selector), node => cloneToLive.get(node) || node)
92
+ },
93
+ text(node = root) {
94
+ const projected = node === root ? root : liveToClone.get(node)
95
+ return projected?.textContent || ''
96
+ },
97
+ html(node = root) {
98
+ const projected = node === root ? root : liveToClone.get(node)
99
+ return projected?.innerHTML ?? ''
100
+ },
101
+ clone(node = root) {
102
+ const projected = node === root ? root : liveToClone.get(node)
103
+ return projected ? inertDocument.importNode(projected, true) : null
104
+ },
105
+ }
106
+ }
107
+
108
+ export function cleanContentClone(node, options) {
109
+ return createContentView(node, options).root
110
+ }