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.
- package/README.md +10 -0
- package/dist/hyper-html-api.engine.min.js +1 -1
- package/dist/hyper-html-api.min.js +4 -4
- package/dist/hyper-html-api.upgrade.min.js +2 -2
- package/package.json +3 -2
- package/packed-contract.json +1 -0
- package/src/adapters/cheerio.js +4 -0
- package/src/adapters/dom.js +191 -0
- package/src/dom-api.js +17 -6
- package/src/engine/apply.js +14 -2
- package/src/engine/extract.js +3 -0
- package/src/engine/index.js +1 -1
- package/src/lib/content-dom.js +110 -0
- package/src/lib/region-capabilities.js +71 -0
|
@@ -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
|
|
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.
|
|
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.
|
|
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"]}
|
package/src/adapters/cheerio.js
CHANGED
|
@@ -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))
|
package/src/adapters/dom.js
CHANGED
|
@@ -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(
|
|
9
|
-
apply: (root, rules, data, opts) => engineMod.apply(
|
|
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) =>
|
|
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(
|
|
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(
|
|
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
|
}
|
package/src/engine/apply.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
package/src/engine/extract.js
CHANGED
|
@@ -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
|
|
package/src/engine/index.js
CHANGED
|
@@ -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
|
+
}
|